【OpenCV】人脸检测和识别


前言

人脸检测有几种方法,主要讲2种,一种是基于Haar,另外一种基于深度学习,从效果上看肯定是后者效果较好,但是前者简单。
人脸识别讲4种方法,EigenFaces、FisherFaces和LBPH以及Dlib方法。


一、人脸检测

1.基于Haar的人脸检测

import cv2
img=cv2.imread('E:\VSCode\CSDN\my.jpg')    
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)  #转换为灰度图像
#加载人脸检测器
face = cv2.CascadeClassifier('E:\VSCode\CSDN\haarcascade_frontalface_default.xml')
eye = cv2.CascadeClassifier('E:\VSCode\CSDN\haarcascade_eye.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)#绘制矩形标注人脸
    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,255,0),1)
cv2.imshow('faces',img)     
cv2.waitKey(0)

在这里插入图片描述
通过这张图片发现人脸识别效果一般。

基于视频的代码:

import cv2
capture = cv2.VideoCapture(0)   #创建视频捕捉器对象
face = cv2.CascadeClassifier('E:\VSCode\CSDN\haarcascade_frontalface_default.xml')#加载人脸检测器
eye = cv2.CascadeClassifier('E:\VSCode\CSDN\haarcascade_eye.xml')#加载眼睛检测器
while True:
    ret, frame = capture.read()                             
    gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)           #转换为灰度图像    
    faces = face.detectMultiScale(gray)                     #执行人脸检测
    for x,y,w,h in faces:
        cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,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(frame[y:y+h, x:x+w],(int(ex+ew/2),
                 int(ey+eh/2)),int(max(ew,eh)/2),(0,255,0),2)  
    cv2.imshow('faces',frame)                        
    key = cv2.waitKey(20)
    if key == 27:    
        break

2.基于深度学习的人脸检测

opencv的深度神经网络(DNN)模块提供了基于深度学习的人脸检测器。DNN使用的深度学习框架包括Caffe、TensorFlow、Torch等。OpenCV提供了2个预训练的人脸检测模型,Caffee和Tensorflow模型。
以下为代码:

import cv2
import numpy as np
from matplotlib import pyplot as plt
#加载训练好的模型,可以选择使用Caffee或者Tensorflow模型,加载的2个文件不一样。
#dnnnet = cv2.dnn.readNetFromCaffe("E:\VSCode\CSDN\deploy.prototxt", "E:\VSCode\CSDN\res10_300x300_ssd_iter_140000_fp16.caffemodel")
dnnnet = cv2.dnn.readNetFromTensorflow("E:\VSCode\CSDN\opencv_face_detector_uint8.pb", "E:\VSCode\CSDN\opencv_face_detector.pbtxt")
img = cv2.imread("E:\VSCode\CSDN\hello.jpg")        #读取图像
h, w = img.shape[:2]                                #获得图像尺寸
blobs = cv2.dnn.blobFromImage(img, 1.0, (300, 300), #创建图像的块数据
                       [104., 117., 123.], False, False)
dnnnet.setInput(blobs)                                 #将块数据设置为输入
detections = dnnnet.forward()                          #执行计算,获得检测结果
faces = 0
for i in range(0, detections.shape[2]): #迭代,输出可信度高的人脸检测结果
    confidence = detections[0, 0, i, 2] #获得可信度
    if confidence > 0.6:                #输出可行度高于60%的结果
        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, y),cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 2)#输出可信度
cv2.imshow('faces',img)
cv2.waitKey(0)

deploy.prototxt 文件定义模型结构配置文件。
res10_300x300_ssd_iter_140000_fp16.caffemodel 包含实际权重训练模型文件。
opencv_face_detector_uint8.pb 包含实际权重训练模型文件。
opencv_face_detector.pbtxt 定义模型结构配置文件

函数cv2.dnn.blobFromImage(image[, scalefactor[, size[, mean[, swapRB[, crop[, ddepth]]]]]])
作用:对图像进行预处理,包括减均值,比例缩放,裁剪,交换通道等,返回一个4通道的blob(blob可以简单理解为一个N维的数组,用于神经网络的输入)

参数:
image:输入图像(1、3或者4通道)
可选参数
scalefactor:图像各通道数值的缩放比例
size:输出图像的空间尺寸,如size=(200,300)表示高h=300,宽w=200
mean:用于各通道减去的值,以降低光照的影响(e.g. image为bgr3通道的图像,mean=[104.0, 177.0, 123.0],表示b通道的值-104,g-177,r-123)
swapRB:交换RB通道,默认为False.(cv2.imread读取的是彩图是bgr通道)
crop:图像裁剪,默认为False.当值为True时,先按比例缩放,然后从中心裁剪成size尺寸
ddepth:输出的图像深度,可选CV_32F 或者 CV_8U.
在这里插入图片描述

二、人脸识别

1.特征脸EigenFaces

代码如下(示例):

import cv2
import numpy as np
liudehua_img_1=cv2.imread('E:/VSCode/CSDN/liudehua1.jpg',cv2.IMREAD_GRAYSCALE))      #打开图像,灰度图
liudehua_img_2=cv2.imread('E:/VSCode/CSDN/liudehua2.jpg',cv2.IMREAD_GRAYSCALE))      
liudehua_img_3=cv2.imread('E:/VSCode/CSDN/liudehua3.jpg',cv2.IMREAD_GRAYSCALE))                         	
wangzuxian_img_1=cv2.imread('E:/VSCode/CSDN/wangzuxian1.jpg',cv2.IMREAD_GRAYSCALE))                         	
wangzuxian_img_2=cv2.imread('E:/VSCode/CSDN/wangzuxian2.jpg',cv2.IMREAD_GRAYSCALE))                         	
wangzuxian_img_3=cv2.imread('E:/VSCode/CSDN/wangzuxian3.jpg',cv2.IMREAD_GRAYSCALE))                         	

train_images=[liudehua_img_1,liudehua_img_2,liudehua_img_3,wangzuxian_img_1,wangzuxian_img_2,wangzuxian_img_3]   #创建训练图像数组
labels=np.array([0,0,0,1,1,1])  #创建标签数组,01表示对应的训练图像数组中人脸的身份
recognizer=cv2.face.EigenFaceRecognizer_create()#创建EigenFaces识别器
recognizer.train(train_images,labels)  #执行训练操作
testimg=cv2.imread('E:/VSCode/CSDN/test.jpg',0)  #打开测试图像
label,confidence=recognizer.predict(testimg)            #识别人脸
print('匹配标签:',label)
print('可信度:',confidence)

要求训练和预测图片的大小一致。可以使用在线图片处理网站将图片处理成同样大小。

train_images=[liudehua_img_1,liudehua_img_2,liudehua_img_3,wangzuxian_img_1,wangzuxian_img_2,wangzuxian_img_3]
labels=np.array([0,0,0,1,1,1])  

要求标签中的序号要和图片一一对应,比如刘德华照片是1,2,3,则labels中,前3个都是0号。后3张都是王祖贤,则序号都是1。
confidence表示置信度,值通常在0~20000之间,只要低于5000都被认为是相当可靠的识别结果。

2.人鱼脸FisherFaces

代码和前一种方法一样,只有一个地方不一样。

recognizer=cv2.face.FisherFaceRecognizer_create()#创建FisherFaces识别器

confidence表示置信度,值通常在0~20000之间,只要低于5000都被认为是相当可靠的识别结果。

3.局部二进制编码直方图LBPH

代码和第一种方法一样,只有一个地方不一样。

recognizer=cv2.face.LBPHFaceRecognizer_create()#创建LBPH识别器

confidence表示置信度,一个好的识别参考值要低于 50 , 任何高于 80 的参考值都会被认为是低的置信度评分。

4.DLIB

Dlib库的安装比较麻烦。这边创建了一个专门的环境给Dlib用。创建环境的方法请看。conda基本操作

先安装这两个库。

pip3 install cmake -i https://pypi.tuna.tsinghua.edu.cn/simple
pip3 install boost -i https://pypi.tuna.tsinghua.edu.cn/simple

在这里插入图片描述
dlib库直接PIP3安装的话基本都会报错,这里使用whl文件安装。
下载whl文件这个链接中只有python3.7和python3.8的版本。
选择你对应python版本的whl文件,然后执行
在这里插入图片描述
用绝对途径安装。这就安装成功了。

具体算法实现,参考此链接
也可以参考此篇。使用dlib库进行人脸识别

当然也可以使用Dlib来实现人脸识别,效果也很好。
以下是人脸检测(非识别)代码:

import cv2
import dlib
detector = dlib.get_frontal_face_detector()# Load the detector
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")# Load the predictor
cap = cv2.VideoCapture(0)

while True:
    _, frame = cap.read()
    # Convert image into grayscale
    gray = cv2.cvtColor(src=frame, code=cv2.COLOR_BGR2GRAY)
    # Use detector to find landmarks
    faces = detector(gray)

    for face in faces:
        x1 = face.left()  # left point
        y1 = face.top()  # top point
        x2 = face.right()  # right point
        y2 = face.bottom()  # bottom point

        # Create landmark object
        landmarks = predictor(image=gray, box=face)

        # Loop through all the points
        for n in range(0, 68):
            x = landmarks.part(n).x
            y = landmarks.part(n).y
            # Draw a circle
            cv2.circle(img=frame, center=(x, y), radius=3, color=(0, 255, 0), thickness=-1)
    # show the image
    cv2.imshow(winname="Face", mat=frame)
    # Exit when escape is pressed
    if cv2.waitKey(delay=1) == 27:
        break

# When everything done, release the video capture and video write objects
cap.release()
# Close all windows
cv2.destroyAllWindows()

shape_predictor_68_face_landmarks.da文件可留下邮箱获取也可以自行百度搜索。


总结

Dlib效果不错。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

粒子白

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

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

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

打赏作者

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

抵扣说明:

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

余额充值