【OpenCV-Python】——Haar人脸检测&深度学习人脸检测&EigenFaces/FisherFaces/LBPH人脸识别

目录

前言:

1、人脸检测

1.1 基于Haar的人脸检测

1.2 基于深度学习的人脸检测

2、人脸识别

2.1 EigenFaces人脸识别

2.2 FisherFaces人脸识别

2.3 LBPH人脸识别

总结:


前言:

人脸检测是人脸定位的过程;人脸识别是在人脸检测的基础上进一步判断人的身份。

1、人脸检测

1.1 基于Haar的人脸检测

OpenCV源代码中的"data\haarcascades"文件夹中包含训练好的Haar级联分类器文件:包含人眼、眼镜、猫脸、人脸(alt和default)、侧脸检测等文件。

①cv2.CascadeClassifier()函数用于加载分类器:

faceClassifier=cv2.CascadeClassifier(filename)
faceClassifier是返回的级联分类器对象。参数是文件名

②级联分类器的detectMultiScale()方法用于执行检测:

objects=faceClassifier.detectMultiScale(image,scaleFactor,minNeighbors,
                                        flags,minSize,maxSize)

objects是返回的目标矩形,矩形中是人脸。image通常输入的是灰度图。后面的都是可选参数(flags在高版本中省略):图像缩放比例、构成目标矩形的最少相邻矩形个数、目标矩形的最小尺寸、目标矩形的最大尺寸。

检测图像中的人脸示例:

import cv2
img=cv2.imread('friends.png')
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
face=cv2.CascadeClassifier("./haarcascade_frontalface_default.xml")#加载人脸识别器
eye=cv2.CascadeClassifier("./haarcascade_eye.xml")  #加载眼镜识别器
faces=face.detectMultiScale(gray)  #执行人脸识别
for x,y,w,h in faces:
    cv2.rectangle(img,(x,y),(x+w,y+h), (0,255,0),2)  #绘制矩形标注人脸
    roi_eye=gray[y:y+h,x:x+w]  #根据人脸获得眼睛的检测范围
    eyes=eye.detectMultiScale(roi_eye)  #在人脸范围内检测眼睛
    for (ex,ey,ew,eh) in eyes:   #标注眼睛
        cv2.circle(img[y:y+h,x:x+w],(int(ex+ew/2),int(ey+eh/2)),
                    int(max(ew,eh)/2),(0,0,255),2)
cv2.imshow('face',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

 检测图像中的猫脸示例:

import cv2
img=cv2.imread('cat.png')
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
face=cv2.CascadeClassifier("./haarcascade_frontalcatface.xml")#加载猫脸识别器
faces=face.detectMultiScale(gray)  #执行猫脸识别
for x,y,w,h in faces:
    cv2.rectangle(img,(x,y),(x+w,y+h), (255,0,0),2)  #绘制矩形标注猫脸
cv2.imshow('face',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

 检测摄像头视频中的人脸示例:

import cv2
face_detector=cv2.CascadeClassifier("./haarcascade_frontalface_alt.xml")#cv2自带人脸识别器
cap=cv2.VideoCapture(0)#打开摄像头
while True:
    ret, frame = cap.read(0)#从摄像头中读取一帧数据,frame存储了此一帧数据
    gray = cv2.cvtColor(frame,code=cv2.COLOR_BGR2GRAY)#数据压缩——将获取到的数据灰度处理,减小内存增加处理速度
    faces = face_detector.detectMultiScale(gray)#算法返回下x,y,h,w四个参数
    for x,y,h,w in faces:
        #cv2.circle(frame,center = (x+w//2,y+h//2),radius = w//2, color =[0,0,255],thickness=2)
        cv2.rectangle(frame,(x,y),(x+w,y+h), color =[0,255,0],thickness=2)
        cv2.imshow('img',frame)
    key = cv2.waitKey(1000//24)#1000ms显示24张图片,最多等待1000//24毫秒,直到从键盘上按下一个按键或等待时间结束,key中保存了我们按下那个按键
    if key ==ord('q'):
        break
cap.release()#释放摄像头
cv2.destroyAllWindows()

1.2 基于深度学习的人脸检测

Opencv的深度神经网络(DNN)模块提供了基于深度学习的人脸检测器,DNN模块使用了Caffe、TensorFlow、Torch和Darknet等广受欢迎的深度学习框架。Opencv提供了Caffe、TensorFlow两个预训练的人脸检测模型。

①Caffe模型需要加载以下两个文件:

deploy.prototxt:定义模型结构的配置文件
res10.300x300_ssd_iter_140000_fb16.caffemodel:包含实际层权重的训练模型文件

②TensorFlow模型需要加载以下两个文件:

opencv_face_detector.pbtxt:定义模型结构的配置文件
opencv_face_detector_uint8.pb:包含实际层权重的训练模型文件

步骤:首先调用cv2.dnn.readNetFromCaffe()或cv2.dnn.readNetFromTensorFlow()函数加载模型,创建检测器;调用cv2.dnn.blobFromImage()函数将待检测图像转换为图像块数据;调用检测器的setInput()方法将图像块数据设置为模型的输入数据;调用检测器的forward()方法执行计算获得预测结果;将可信度高于指定值的预测结果作为检测结果,在原图像中标注人脸,同时输出可信度以作参考。

import cv2
import numpy as np
from matplotlib import pyplot as plt
dnnet=cv2.dnn.readNetFromCaffe("deploy.prototxt",#加载训练好的模型
                                "    " ) #缺少训练模型文件
img=cv2.imread("friends.png")
h,w=img.shape[: 2]
blobs=cv2.dnn.blobFromImage(img,1.0,(300,300),#创建图像的块数据
                            [104.,117.,123.],False,False)
dnnet.setInput(blobs)   #将块数据设置为输入数据
detections=dnnet.forward()  #执行计算,获得预测结果
faces=0
for i in range(0,detections.shape[2]):  #迭代,输出可信度高的人脸识别结果
    confidence=detections[0,0,i,2]    #获得可信度
    if confidence >0.8:               #输出可信度高于80%的结果
        faces += 1
        box = detections[0,0,i,3:7]*np.array([w,h,w,h])  #获得人脸在图像中的坐标
        x1,y1,x2,y2=box.astype("int")
        y=y1-10 if y1-10 >10 else y1+10    #计算可信度输出位置
        text="%.3f"%(confidence*100)+'%'
        cv2.rectangle(img,(x1,y1),(x2,y2),(255,0,0),2) #标注人脸范围
        cv2.putText(img,text,(x1+20,y),
                    cv2.FONT_HERSHEY_SIMPLEX,0.9,(0,0,255),2)  #输出可信度
cv2.imshow('faces',img)
cv2.waitKey(0)
cv2.destroyAllWindows()


2、人脸识别

Opencv提供了3种人脸识别方法:特征脸(EigenFaces)、人鱼脸(FisherFaces)和局部二进制编码直方图(Local Binary Patterns Histograms,LBPH)。

2.1 EigenFaces人脸识别

EigenFaces使用主要成分分析(PCA)方法将人脸数据从高维处理成低维后,获得人脸数据的主要成分信息,进而完成人脸识别。

步骤:首先调用cv2.face.EigenFaceRecognizer_create()方法创建EigenFaces识别器;然后调用识别器的train()方法以便使用已知图像训练模型;调用识别器的predict()方法以便使用未知图像进行识别,确认其身份。

①cv2.face.EigenFaceRecognizer_create()函数:

recognizer=cv2.face.EigenFaceRecognizer_create(num_components,threshold)
recognizer是返回的识别器对象;
参数都是可选参数:
num_components是分析时的分量个数;默认是0,表示根据实际输入决定;
threshold是人脸识别时采用的阈值

②EigenFaces识别器train()方法:

recognizer.train(src,labels)
src是用于训练的已知图像数组。所有图像都要是灰度图,且大小要相同;
labels是标签数组,与已知图像数组中的人脸一一对应,同一个人的脸标签应设置为相同值

③EigenFaces识别器predict()方法:

label,confidence=recognizer.predict(testimg)
testimg是未知的人脸图像,必须是灰度图,且与训练图像大小相同;
label是返回的标签值;
confidence是返回的可信度,表示未知人脸和模型中已知人脸之间的距离。
            0表示完全匹配,低于5000可认为是可靠的匹配结果。
import cv2
import numpy as np
img1=cv2.imread('face1.png',0)#打开图像,灰度图(0)——img1和img2是杨幂;img3和img4是关晓彤
img2=cv2.imread('face2.png',0)
img3=cv2.imread('face3.png',0)
img4=cv2.imread('face4.png',0)
print(img1.shape) #(161,157)
img2=cv2.resize(img2,(161,157))#训练图像需要大小相同
img3=cv2.resize(img3,(161,157))
img4=cv2.resize(img4,(161,157))

train_imgs=[img1,img2,img3,img4] #创建训练图像数组
labels=np.array([0,0,1,1])  #创建标签数组,0和1表示训练图像数组中人脸的身份(杨幂0和关晓彤1)
recognizer=cv2.face.EigenFaceRecognizer_create()  #创建EigenFaces识别器
recognizer.train(train_imgs,labels)  #执行训练操作
testimg=cv2.imread('testface1.png',0)  #打开测试图像(杨幂)
testimg=cv2.resize(testimg,(161,157))  #测试图像大小也要与训练图像相同
label,confidence=recognizer.predict(testimg)  #识别人脸
print('匹配标签:',label)  #输出识别结果
print('可信度:',confidence)

训练图像:        

测试图像和输出结果:  

2.2 FisherFaces人脸识别

FisherFaces使用线性判别分析(LDA)方法实现人脸识别。

步骤使用格式与EigenFaces相同:首先调用cv2.face.FisherFaceRecognizer_create()方法创建FisherFaces识别器;然后调用识别器的train()方法以便使用已知图像训练模型;调用识别器的predict()方法以便使用未知图像进行识别,确认其身份。

 所以代码就需要该一行创建识别器的代码:(这次测试下testface2关晓彤)

recognizer=cv2.face.FisherFaceRecognizer_create() 

 测试图像和输出结果:    

2.3 LBPH人脸识别

LBPH算法处理图像的基本原理:取像素x周围(邻域)的8个像素与其比较,像素值比像素x大的取0,小的取1。将8个像素对应的0、1连接得到一个8位二进制数,将其转换为十进制,作为像素x的LBP值。对所有像素同样操作得到整个LBP图像,该图像的直方图就是LBPH。

基本步骤与上面两个相似,只不过①创建识别器函数参数有所不同。②且predict()中confidence低于50可认为是非常可靠的匹配对象(不是5000了)。

cv2.face.LBPHFaceRecognizer_create(radius,neighbors,grid_x,grid_y,threshold)
参数都是可选参数:
radius是邻域的半径大小;
neighbors是邻域内像素点的数量,默认为8;
grid_x/grid_y是将LBP图像划分成多个单元格时,水平/垂直方向上的单元格的数量,默认是8
threshold是人脸识别时采用的阈值

 代码也只需改变创建识别器那一行即可,还是测试关晓彤,输出匹配结果标签和可信度:

recognizer=cv2.face.LBPHFaceRecognizer_create() 

可信度没低于50,说明结果不是非常可靠,可能是由于训练图像太少的缘故。


总结:

由于是初学者可能很多地方没有总结完全或者有误,后续深入学习后会不断回来该删,也欢迎各位朋友指正!下次学习机器学习和深度学习基础

猜你喜欢

转载自blog.csdn.net/weixin_51658186/article/details/130433940