人脸检测是指在图像中完成人脸定位的过程,OpenCV提供的Haar级联分类器可以用来进行人脸检测,在OpenCV源代码中的“datahaarcascades”文件中包含训练好的Haar级联分类器文件,这些文件包括:
haarcascade_eye.xml:人眼检测
haarcascade_eye——tree_eyeglasses.xml:眼镜检测
haarcascade_frontalcatface.xml:猫脸检测
haarcascade_frontalface_alt.xml:人脸检测
haarcascade_frontalface_default.xml:人脸检测
haarcascade_profileface.xml:侧脸检测
需要用到的函数函数有:
face=cv2.CascadeClassifier(filename)用于加载分类器。
参数说明:face为返回的级联分类器对象;filename为级联分类器的文件名。
faces=face.detectMultiScale(image[,scalFactor[,minNeighbors[,flags[,minSize[,maxSize]]]]])用于执行检测。
参数说明:faces为返回的目标矩形,矩形中为人脸
image为输入图像,通常为灰度图像
scaleFactor为图像的缩放比例
minNeighbors为构成目标矩形的最少相邻矩形个数
flags在低版本的OpenCV 1.x中使用,高版本中通常省略该参数
minSize为目标矩形的最小尺寸
maxSize为目标矩形的最大尺寸
1、 来看一下Haar级联分类器检测人脸的实现
import cv2
img = cv2.imread(r'xxx')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 加载人脸检测器
face = cv2.CascadeClassifier('xxxcv2datahaarcascade_frontalface_default.xml')
# 加载眼睛检测器
eye = cv2.CascadeClassifier('xxxcv2datahaarcascade_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('face', img)
cv2.waitKey(0)
程序中的级联分类器文件要根据自己的电脑写好绝对路径,需要找到它所在的位置,在Windows命令提示符中输入pip show opencv_python
在location这里找到OpenCV所在位置,并在文件夹中打开,接下来找到cv2—>data,在data文件下可以看到这些级联分类器文件:
把用到的文件的路径复制到程序中就可以了。
2、使用上述的分类器检测摄像头视频中的人脸,这里使用的默认摄像头是电脑的摄像头
import cv2
# 创建视频捕捉器对象
capture = cv2.VideoCapture(0)
if not capture.isOpened:
print('不能打开摄像头')
exit(0) # 不能打开摄像头时结束程序
# 加载人脸检测器
face = cv2.CascadeClassifier('xxxcv2datahaarcascade_frontalface_default.xml')
# 加载眼睛检测器
eye = cv2.CascadeClassifier('xxxcv2datahaarcascade_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:
break
颜值有限,结果就不展示了。
3、基于深度学习的人脸检测
OpenCV的深度神经网络(Deep Neural Network,DNN)模块提供了深度学习的人脸检测器。DNN模块中使用了多种深度学习框架,包括Caffe、TensorFlow、Torch等,OpenCV提供了两个预训练的人脸检测模型:Caffe和TensorFlow模型,使用时需要加载相应的文件。
Caffe模型需要加载以下两个文件:
deploy.prototxt:定义模型结构的配置文件;
res10_300x300_ssd_iter_140000.caffemodel:包含实际层权重的训练模型文件。
TensorFlow模型需要加载以下两个文件:
opencv_face_detector.pbtxt:定义模型结构的配置文件;
opencv_face_detector_uint8.pb:包含实际层权重的训练模型文件。
这些文件需要自行下载。
这里以Caffe模型为例,文件下载链接:https://pan.baidu.com/s/1LahJgvxPyUVJhdYARyGSRA
提取码:9dvb
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 加载训练好的模型
dnnnet = cv2.dnn.readNetFromCaffe(r"xxxdeploy.prototxt", r"xxxres10_300x300_ssd_iter_140000.caffemodel")
img = cv2.imread(r'xxx')
# 获得图像尺寸
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]
# 输出可信度大于80%的结果
if confidence > 0.8:
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)
cv2.dnn.blobFromImage(image[, scalefactor[, size[, mean[, swapRB[, crop[, ddepth]]]]]])
参数说明:
image:输入图像(1、3或者4通道)
scalefactor:图像各通道数值的缩放比例
size:输出图像的空间尺寸
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
返回值是一个4维的数组:原图各通道均值、输出blob各通道的均值、原图的shape、输出blob的shape。



