当前位置: 代码迷 >> 综合 >> 使用 Haar 级联人脸检测
  详细解决方案

使用 Haar 级联人脸检测

热度:70   发布时间:2023-10-28 07:05:51.0

Haar 级联概念

在进行图像分类和跟踪过程中,提取图像的细节很有用,这些细节也被称为特征,对于给定的图像,特征可能会因区域的大小而有所不同,区域大小也可被称为窗口大小。即使窗口大小不同,仅在尺度上大小不同的图像也应该有相似的特征。这种特征集合被称为级联。Haar 级联具有尺度不变性。OpenCV 提供了尺度不变Haar 级联的分类器和跟踪器。

需要注意的是, Haar 级联不具有旋转不变性,即不认为侧面照与正面照是相同的

获取 Haar 级联数据

OpnCV 原代码副本文件提供了OpenCV 人脸检测所需的XML文件

https://github.com/opencv/opencv/tree/master/data/haarcascades

从文件名可知这些级联用于什么跟踪。这些文件要求 直立的、正面的人脸图像,这些文件都是通过大量的机器学习,最终训练的结果,如果有很好的耐心,也可以创建自己的级联,并训练(train)这些级联用于检测不同的对象

静态图像中的人脸检测

使用图片:
在这里插入图片描述
进行人脸检测,主要部分为两部:

  1. 创建级联分类器 cv2.CascadeClassfier()
  2. 利用创建的级联分类器对图像进行多尺度检测 cv2.detectMultiScale()

cv2.detectMultiScale 主要参数:

在这些参数中,您需要更加关注其中的四个:

scaleFactor - 指定在每个图像比例下图像大小减少多少的参数。

基本上,比例因子用于创建比例金字塔。总之,作为描述在这里,你的模型训练过程中定义一个固定的大小,这是在XML可见。这意味着如果存在,则在图像中检测到这种尺寸的面部。但是,通过重新缩放输入图像,您可以将较大的面调整为较小的面,使其可被算法检测到。

1.05是一个很好的可能值,这意味着你使用一小步调整大小,即减小5%的大小,你增加了与检测模型匹配大小的机会。这也意味着算法运行得更慢,因为它更彻底。您可以将其增加到1.4以便更快地进行检测,并且可能会完全丢失一些面孔。

举例:假设训练好的眼睛特征大小 20 × 20 ,但是视频或者图像检测中,中代表眼睛的特征大小为 50 × 50 ,进行特征检测时可以看作训练好的特征对图片或者视频进行滑动比对,但是本例中如果保持这个大小是不可能成功检测的,这个时候就需要比例缩放了,假设设定为1.05 ,这里的数值为窗口扩大倍数,但是窗口实际是不能扩大的,可以看作图像相对窗口缩小了 5%,这样设定较小的值,就需要大量的计算才能准确的比对,但是检测结果应该更准,如果将其设定为更大的值,计算结果势必会更快,但是也相对会丢失一些检测机会,这就是检测多尺度变换detectMultiScale()的原理了

minNeighbors - 参数指定每个候选矩形应保留多少个邻居。此参数将影响检测到的面部的质量。值越高,检测越少,但质量越高。3~6对它来说是一个很好的价值。用作一个目标被多个窗口检测出来时起调节作用。

minSize - 最小可能的对象大小。小于该值的对象将被忽略。

maxSize - 最大可能的对象大小。大于此值的对象将被忽略。

下面创建一个实现人脸检测:

import cv2
img=cv2.imread('./img/face.jpg',cv2.IMREAD_UNCHANGED)
# 级联检测要求为灰度图
gray=cv2.cvtColor(img,cv2.COLOR_RGB2BGR)
# 创建级联分类器
face_cascade=cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml')
# 对图像进行检测
faces=face_cascade.detectMultiScale(gray,1.3,5)
# 检测结果是矩形框
for (x,y,w,h) in faces:cv2.rectangle(img,(x,y),(x+w,y+h),(255,255,0),2)cv2.imshow('face_cascade',img)
cv2.waitKey()
cv2.destroyAllWindows()

检测结果:
在这里插入图片描述
可以看到大多数都能检测到,但是第一个头像没有被检测到,这个时候我们调整一下检测的参数就能很好的检测到全部的头像了

视频中的人脸检测

视频中的人脸检测同静态图像,不同的时将图像变成 视频帧即可(frame),直接上代码

import cv2
def detect():face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml')eye_cascade=cv2.CascadeClassifier('./cascades/haarcascade_eye.xml')cameraCapture = cv2.VideoCapture(0)while True:success, frame = cameraCapture.read()gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)faces = face_cascade.detectMultiScale(gray, 1.02, 20)for (x, y, w, h) in faces:cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 255, 0), 2)roi_gray=gray[y:y+h,x:x+w]img=frame[y:y+h,x:x+w]eyes=eye_cascade.detectMultiScale(roi_gray,1.03,5,0)for (ex,ey,ew,eh) in eyes:cv2.rectangle(img,(ex,ey),(ex+ew,ey+eh),(0,255,255),2)cv2.imshow('camera', frame)if cv2.waitKey(1000 // 12) & 0xff == ord('q'):breakcameraCapture.release()cv2.destroyAllWindows()if __name__=='__main__':detect()

上面示例中的第二个for 循环用于在已检测好的人脸矩形框中检测眼睛并画出,在眼睛检测中多了几个参数,用于限制大小,因为眼睛是一个比较小的特征,很容易受其他因素的干扰,固指定带线啊哦,去掉假阳性。

其他

需要注意的是人脸检测与人脸识别是有区别的,opencv 中的人脸识别有三种Model

  1. Eigenfaces
  2. Fisherfaces
  3. Local Binary Pattern Histogram (LBPH)

你需要做的就是准备好训练数据(可以编写自己编写脚本存储获取图像),当作参数传递给这三个方法中的一个,然后使用 predict方法对你新获取的数据进行预测。