目录
前言:
1、人脸检测
1.1基于Haar的人脸检测
1.2 基于深度学习的人脸检测
2、人脸识别
2.1 EigenFaces人脸识别
2.2FisherFaces人脸识别
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 cv2img=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 cv2img=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 cv2face_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'):breakcap.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 cv2import numpy as npfrom matplotlib import pyplot as pltdnnet=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=0for i in range(0,detections.shape[2]): #迭代,输出可信度高的人脸识别结果confidence=detections[0,0,i,2] #获得可信度if confidence >0.8:#输出可信度高于80%的结果faces += 1box = 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 cv2import numpy as npimg1=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.2FisherFaces人脸识别
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图像划分成多个单元格时,水平/垂直方向上的单元格的数量,默认是8threshold是人脸识别时采用的阈值
代码也只需改变创建识别器那一行即可,还是测试关晓彤,输出匹配结果标签和可信度:
recognizer=cv2.face.LBPHFaceRecognizer_create()
可信度没低于50,说明结果不是非常可靠,可能是由于训练图像太少的缘故。
总结:
由于是初学者可能很多地方没有总结完全或者有误,后续深入学习后会不断回来该删,也欢迎各位朋友指正!下次学习机器学习和深度学习基础!