OpenCV-Python实战(19)——LBPH人脸识别

环境要求: 

pip install opencv-contrib-python

下载OpenCV已经训练好的分类器到本地 :

一、 LBPH人脸识别算法概述

        OpenCV库自带的人脸级联分级器具有很好的人脸检测和人脸追踪效果,它是一个基于Haar特征的Adaboost级联分类器。特别注意,OpenCV库虽然自带人脸级联分级器,但是识别效率一般。本项目使用的是OpenCV提供的人脸识别算法LBPH(Local Binary Pattern Histogram),即局部二进制模式直方图,它属于OpenCV拓展库opencv-contrib的一部分,需要另外单独安装opencv-contrib-python-4.1.2。
       LBPH人脸识别算法思路如下:将检测到的人脸分为小单元如下图1所示,并将其与模型中的对应单元进行比较,对每个区域的匹配值产生一个直方图,如图2所示,通过对直方图的比较,算法将能够识别图像的边缘和角,能够识别直方图中哪些代表人的主要特征,比如眼睛的颜色、嘴巴的形状等等,这个算法的基本理论也就是基于直方图的创建和比较。由于这种方法通过比较不同人脸图像LBP编码直方图达到人脸识别的目的,其优点是不会受到光照、缩放、旋转和平移的影响。

提示:二进制是将中间的数值“90”与四周数值进行对比,大于为1,小于为0,然后绕四周逆时针得出二进制10001101 

*参考文档:

1.基于OpenCV提供的人脸识别算法LBPH实现人脸识别_lbph人脸识别-优快云博客  
2.使用LBPH算法理解人脸识别
3.LBPH人脸识别

二、 人脸识别

        本项目将实现人脸识别分为以下3个小任务,通过3个步骤来完成人脸采集与检测、人脸模型训练、人脸识别。 

相关文件:  

Facedata:保存人脸数据的文件夹,(只需建立Facedata的文件夹即可)。

opencv-master:github上下载的opencv源码,里面含有已训练好的分类器。

face_get:基于摄像头的人脸数据采集代码。

face_model:人脸识别模型的建立与保存。

face_predict:对摄像头实时拍摄到的图像进行人脸识别。 

2.1 人脸数据的采集 

import cv2
import os


def GetFace(name):
    # 获取haarcascades分类器
    face_cascade = cv2.CascadeClassifier(r'E:/PycharmProjects/exercise\opencv-master/data/haarcascades/haarcascade_frontalface_default.xml')
    if not os.path.exists('Facedata'): # 如果不存在'Facedata',就创建'Facedata'文件夹
        os.mkdir('Facedata')
    # 创建一个针对单个name的face图像存储文件夹
    if os.path.exists('Facedata\\'+name):
        print('此人脸数据已存在!')
    else:
        os.mkdir('Facedata\\'+name)
        camera = cv2.VideoCapture(0)  #  0: 笔记本内置摄像头; 1: USB摄像头
        total = 5  # 单个name的人脸取样数
        num = 1    # 目前取样进度
        while(camera.isOpened()): # 判断摄像头是否正常打开
            success,img = camera.read()  # 读取图片帧
            # 检测人脸
            faces = face_cascade.detectMultiScale(img,1.1,3,minSize=(20,20))
            for (x,y,w,h) in faces:
                cv2.rectangle(img,(x,y),(x+w,x+h),(255,0,0),2) # 蓝色方框框住人脸
            cv2.imshow('camera',img)  # 展示框住后的图像
            if success==True:
                key = cv2.waitKey(100) # 图片刷新速度,每张图片展示多少秒
                if key==ord('a') or key==ord('A'):  # 如果感觉取样可以就按a/A键保存
                    image_crop = img[y:y+h,x:x+w]  # 截取人脸部分
                    imageResize = cv2.resize(image_crop,(160,160))  # 重置人脸大小
                    faceName = 'Facedata\\'+name+'\\'+name+str(num)+'.jpg'   # 人脸保存位置
                    cv2.imwrite(faceName,imageResize)  # 保存
                    if num >=total:  # 如果num >=total就会中断人脸采样
                        if num == total:
                            print('拍摄第{}次人脸成功'.format(num))
                        break
                    print('拍摄第{}次人脸成功'.format(num))
                    num+=1
        camera.release()  # 关闭摄像机
        cv2.destroyAllWindows()  # 关闭图片显示窗口


if __name__ == '__main__':
    # 请输入您的name和id
    name = input('Please input your name:')
    GetFace(name)

结果: 

一次只能采集一个人的图片,放入输入的name文件夹中。 

2.2 训练人脸模型 

import glob
import os
import cv2
import numpy as np

nameList = []  # 人脸名称
faces_db = []  # 存储所有人脸,用于训练
labels = []    # 人脸标签编号,用于预测后,从nameList取值返回name
index = 0    # 编号索引
dirs = os.listdir('Facedata')   # 获取'Facedata'文件夹下所有文件名称
for d in dirs:
    if os.path.isdir('Facedata\\'+d): # 对应人脸的文件夹
        faces = glob.glob('Facedata\\'+d+'\\*.jpg')  # 对应人脸的图像
        for face in faces:
            img = cv2.imread(face,cv2.IMREAD_GRAYSCALE)  # 转灰度图
            faces_db.append(img)  # 人脸存入faces_db列表
            labels.append(index)  # 标签存入labels列表
        nameList.append(d)   # 将英文名字存入nameList列表
        index+=1
print('标签名称={}'.format(nameList))
print('标签序号={}'.format(labels))
# 存储人名,用于后续人脸识别
with open('Facedata\\name.txt','w') as f:
    f.write(','.join(nameList))
print('建立人脸识别数据库')
model = cv2.face.LBPHFaceRecognizer_create()  # 建立LBPH人脸识别对象
model.train(faces_db,np.array(labels))    # 训练
model.save('Facedata\\deepmind.yml')      # 保存模型
print('人脸识别数据库完成')

2.3 人脸识别 

import cv2


# 建立模型
face_cascade = cv2.CascadeClassifier(r'E:/PycharmProjects/exercise\opencv-master/data/haarcascades/haarcascade_frontalface_default.xml')
model = cv2.face.LBPHFaceRecognizer_create()
model.read('Facedata\\deepmind.yml')  # 读取已训练模型
# 名称列表
with open('Facedata\\name.txt','r') as f:
    names = f.readline().split(',')
'''===============基于摄像头取样的人脸识别==============='''
camera = cv2.VideoCapture(0)
while(camera.isOpened()):
    success,img = camera.read()
    faces = face_cascade.detectMultiScale(img,1.1,3,minSize=(20,20))
    for (x,y,w,h) in faces:
        cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
    cv2.imshow("face",img)
    if success == True:
        key = cv2.waitKey(100)  # 图片刷新速度,每张图片展示多少秒
        if key == ord('a') or key == ord('A'):  # 如果感觉取样可以就按a/A键保存
            image_crop = img[y:y + h, x:x + w]  # 截取人脸部分
            imageResize = cv2.resize(image_crop, (160, 160))  # 重置人脸大小
            cv2.imwrite("Facedata\\face.jpg", imageResize)  # 保存
            break
camera.release()  # 关闭摄像机
cv2.destroyAllWindows()  # 关闭图片显示窗口

# 读取上面获取的人脸
gray = cv2.imread("Facedata\\face.jpg",cv2.IMREAD_GRAYSCALE)
val = model.predict(gray)
if val[1] < 50:
    print('成功识别{}的人脸'.format(names[val[0]]))
    print('匹配值是{}'.format(val[1]))
else:
    print('人脸匹配失败')

总结: 

  1. 每个name可以采集多个人脸图像,正脸、侧脸、等。可以提高人脸识别准确率。
  2. 每个name的人脸单独使用文件夹存储,有利于数据的管理。
  3. 与商场的人脸识别储物箱的模式相同。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小码贾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值