实验准备

  硬件设备准备

  1. 旭日X3派一块

  2. USB数据线(tpye-c)

  3. USB摄像头(ANC狼魔)

  其他准备

  1. MpbaXterm

  2. Ubuntu20.04系统环境

  3. python3.8.10环境

  4. jupyterlab环境

  5. 笔记本电脑一台

一,基于Haar的人脸检测

在之前的博客中,博主做过摄像头驱动的实验,今天,我们在此基础上继续学习一下基于Haar的人脸检测

本次实验使用OpenCV提供的Haar级联分类器来进行人脸检测。在OpenCV源代码中的“data\haarcascades”文件夹中包含训练好的Haar级联分类器文件,示例如下

haarcascade_exe.xml  #人眼检测
haarcascade_eye_tree_eyeglasses  #眼镜检测
haarcascade_frontalcatface.xml  #猫脸检测
haarcascade_frontalface_alt.xml  #人脸检测
haarcascade_frontalface_default.xml  #人脸检测
haarcascade_profileface.xml  #侧脸检测

cv2.CascadeClassifier()函数用于加载分类器,其基本格式如下。

faceClassifier=cv2.CascadeClassifier(filename)

参数说明如下:

faceClassifier为返回的级联分类器对象

filename为级联分类器的文件名

级联分类器对象的detectMultiScale()方法用于执行检测,其基本格式如下。

objectsfaceClassifier.detectMultiScale(image[,scaleFactor[,minNeighbors[,flags[,maxSize]]]])

参数说明如下

objects问返回的目标矩形,矩形中为人脸。

image为输入图像,通常为灰度图像。

scaleFactor为图像缩放比例。

minNeighbors为构成目标矩形的最少相邻矩形个数。

flags在低版本的OpenCV1.x中使用,高版本中通常省略该参数。

minSize为目标矩形的最小尺寸。

maxSize为目标矩形的最大尺寸。

1.使用Haar级联分类器检测人脸

下面的代码使用haarcascade_frontalface_default.xml和haarcascade_eye.xml分类器检测图像中的人脸和眼睛。

#test9-1.py:使用Haar级联检测器检测人脸
#将用于眼睛和人脸检测的Harr级联检测器文件复制到程序文件位置
import cv2
img=cv2.imread('heard.jpg')                         	#打开输入图像
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),(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),2)
cv2.imshow('faces',img)                                   #显示检测结果
cv2.waitKey(0)

2.使用Haar级联分类器检测摄像头视频中的人脸

除了可以检测图片中的人脸,Haar级联分类器还可以用于检测视频中的人脸,默认的摄像头帧率为30帧,同时也可以自己设置摄像头帧率使用capture.set()函数定义。

#test9-3.py:检测摄像头视频中的人脸
import cv2
capture = cv2.VideoCapture(0)   #创建视频捕捉器对象
if not capture.isOpened:
    print('不能打开摄像头')
    exit(0)                     #不能打开摄像头时结束程序
#加载人脸检测器
face = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
#加载眼睛检测器
eye = cv2.CascadeClassifier('haarcascade_eye.xml')
while True:
    ret, frame = capture.read()                             #读摄像头的帧
    if frame is None:
        break
    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(30)
    if key == 27:                                           #按Esc键结束程序
        break

二,基于深度学习的人脸检测

OpenCV的深度神经网络( Deep Neural Network, DNN)模块提供了基于深度学习的人脸检测器。DNN模块中使用了广受欢迎的深度学习框架,包括Caffe、TensorFlow、Torch 和Darknet等。

OpenCV提供了两个预训练的人脸检测模型: Caffe 和TensorFlow模型。

Caffe模型需加载以下两个文件。

deploy.prototxt 定义模型结构的配置文件

res10_300*300_ssd_iter_140000_fp16.caffemodel  包含实际层权重的训练模型文件。

TensorFlow模型需加载以下两个文件。

opencv_ face_ detector.pbtxt 定义模型结构的配置文件

opencv_ face_ _detector _uint8.pb 包含实际层权重的训练模型文件

在OpenCV源代码的“sources\samples\dnn\face_detector”文件夹中提供了模型配置文件,但未提供训练模型文件。可运行该文件夹中的download—weights.py下载上述的两个训练模型文件。

使用预训练的模型执行人脸检测时主要包含下列步骤。

(1)调用Cv2 dn.derFromafe或cv2 dnrecn eromenroo函数加载模型,创建检测器。

(2)调用cv2.dnn.blobFromlmage()函数将待检测图像转换为图像块数据。

(3)调用检测器的setInput()方法将图像块数据设置为模型的输入数据。

(4)调用检测器的forward()方法执行计算,获得预测结果。

(5)将可信度高于指定值的预测结果作为检测结果,在原图像中标注人脸,同时输出可信度作为参考。

示例代码如下:

#test9-4.py:DNN人脸检测
import cv2
import numpy as np
from matplotlib import pyplot as plt
#dnnnet = cv2.dnn.readNetFromCaffe("deploy.prototxt", #加载训练好的模型
#                    "res10_300x300_ssd_iter_140000_fp16.caffemodel")
dnnnet = cv2.dnn.readNetFromTensorflow("opencv_face_detector_uint8.pb", "opencv_face_detector.pbtxt")
img = cv2.imread("heard.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
print("detections.shape[2]",detections.shape[2])
for i in range(0, detections.shape[2]): #迭代,输出可信度高的人脸检测结果
    confidence = detections[0, 0, i, 2] #获得可信度
    print("confidence", detections[0, 0, i, 2])
    if confidence > 0.6:                #输出可行度高于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, y),                        #输出可信度
                        cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 2)
cv2.imshow('faces',img)
cv2.waitKey(0)

程序运行结果如下: