目录
一、基础理论
1、基于特征的算法
2、基于图像的算法
3、Haar特征
4、adaboost级联决策器
二、人脸识别(图片)
1、图片灰度化
2、训练一组数据
3、检测人脸
4、遍历人脸,画出矩形框并显示
出错的情况
总代码
三、摄像头人脸识别
1、打开摄像头
2、按帧读取视频
3、图像左右翻转
4、识别每一帧图像
5、退出设置(必要步骤)
总代码
参考资料
人脸检测算法按照方法可以被分为两大类,基于特征的算法、基于图像的算法。
基于特征的算法就是通过提取图像中的特征和人脸特征进行匹配,如果匹配上了就说明是人脸,反之则不是。提取的特征是人为设计的特征,例如Haar,FHOG,特征提取完之后,再利用分类器去进行判断。通俗的说就是采用模板匹配,就是用人脸的模板图像与待检测的图像中的各个位置进行匹配,匹配的内容就是提取的特征,然后再利用分类器进行判断是否有人脸。
基于图像的算法,将图像分为很多小窗口,然后分别判断每个小窗是否有人脸。通常基于图像的方法依赖于统计分析和机器学习,通过统计分析或者学习的过程来找到人脸和非人脸之间的统计关系来进行人脸检测。最具代表性的就是CNN,CNN用来做人脸检测也是目前效果最好,速度最快的。
我们使用机器学习的方法完成人脸检测,首先需要大量的正样本图像(面部图像)和负样本图像〈不含面部的图像)来训练分类器。我们需要从其中提取特征。下图中的 Haar特征会被使用,就像我们的卷积核,每一个特征是一个值,这个值等于黑色矩形中的像素值之和减去白色矩形中的像素值之和。
Haar特征:
Haar特征值反映了图像的灰度变化情况。例如︰脸部的一些特征能由矩形特征简单的描述,眼睛要比脸颊颜色要深,鼻梁两侧比鼻梁颜色要深,嘴巴比周围颜色要深等。
Haar特征可用于于图像任意位置,大小也可以任意改变,所以矩形特征值是矩形模版类别、矩形位置和矩形大小这三个因素的函数。故类别、大小和位置的变化,使得很小的检测窗口含有非常多的矩形特征。
得到图像的特征后,训练一个决策树构建的adaboost级联决策器来识别是否为人脸。
人脸检测,把图像分成一个个小块,对每一个小块判断是否是人脸,假如一张图被分成了5000块,则速度非常慢。为了提高效率,OpenCV 提供 cascades 来避免这种情况。提供了一系列的xml文件。(cascades :级联)
cascade 对于每个数据块,它都进行一个简单快速的检测。若过,会再进行一个更仔细的检测。该算法有 30 到 50 个这样的阶段,或者说 cascade。只有通过全部阶段,cascade才会判断检测到人脸。这样做的好处是:大多数小块都会在前几步就产生否定反馈,节约时间。
# 1、转灰度图
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
cv2.imshow("gray", gray)
级联分类器CascadeClassifier:
CascadeClassifier是用来做目标检测的级联分类器的一个类 。
face_detector = cv2.CascadeClassifier(src)
src:待训练数据的地址。
这里用来训练一组人脸数据,xml文件中会描述人体各个部位的Haar特征值。包括人脸、眼睛、嘴唇等等。
# 1、训练一组人脸
face_detector = cv2.CascadeClassifier("D:/Software/OpenCV/opencv/sources/data/haarcascades/haarcascade_frontalface_alt_tree.xml")
检测API,detectMultiScale :
在灰度图上检测人脸,输出是人脸区域的外接矩形框。
faces = face_cascade.detectMultiScale(self, image: Any, scaleFactor: Any = None, minNeighbors: Any = None, flags: Any = None, minSize: Any = None, maxSize: Any = None) -> None
参数:
1.image:表示的是要检测的输入图像
2.scaleFactor:表示每次图像尺寸减小的比例
3. minNeighbors:至少检测次数。若为3,表示每一个目标至少要被检测到3次才算是真的目标(因为周围的像素和不同的窗口大小都可以检测到人脸)
4.flags,要么使用默认值,要么使用CV_HAAR_DO_CANNY_PRUNING,如果设置为CV_HAAR_DO_CANNY_PRUNING,那么函数将会使用Canny边缘检测来排除边缘过多或过少的区域,因此这些区域通常不会是人脸所在区域
5.minSize为目标的最小尺寸
6.minSize为目标的最大尺寸
返回:
返回检测到的区域矩形坐标(4个角)。
# 2、检测人脸(用灰度图检测,返回人脸矩形坐标(4个角))
faces_rect = face_detector.detectMultiScale(gray, 1.05, 3)
# 灰度图 图像尺寸缩小比例 至少检测次数(若为3,表示一个目标至少检测到3次才是真正目标)
得到结果:
# 3、遍历每个人脸,画出矩形框
dst = img.copy()
for x, y, w, h in faces_rect:
cv2.rectangle(dst, (x, y), (x + w, y + h), (0, 0, 255), 3) #画出矩形框
# 显示
cv2.imshow("dst", dst)
可以发现这个侧脸识别失败,我们降低要求,把最小检测次数换成1次:
# 2、检测人脸(用灰度图检测,返回人脸矩形坐标(4个角))
faces_rect = face_detector.detectMultiScale(gray, 1.05, 1)
# 灰度图 图像尺寸缩小比例 至少检测次数(若为3,表示一个目标至少检测到3次才是真正目标)
# 人脸识别
import cv2
# 图片中人脸识别
def Face_Detect_Pic(image):
# 1、转灰度图
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
cv2.imshow("gray", gray)
# 2、训练一组人脸
face_detector = cv2.CascadeClassifier("D:/Software/OpenCV/opencv/sources/data/haarcascades/haarcascade_frontalface_alt.xml")
# 3、检测人脸(用灰度图检测,返回人脸矩形坐标(4个角))
faces_rect = face_detector.detectMultiScale(gray, 1.05, 3)
# 灰度图 图像尺寸缩小比例 至少检测次数(若为3,表示一个目标至少检测到3次才是真正目标)
print("人脸矩形坐标faces_rect:", faces_rect)
# 4、遍历每个人脸,画出矩形框
dst = img.copy()
for x, y, w, h in faces_rect:
cv2.rectangle(dst, (x, y), (x + w, y + h), (0, 0, 255), 3) #画出矩形框
# 显示
cv2.imshow("dst", dst)
if __name__ == "__main__":
# 读取图片
img = cv2.imread("Resource/faces.jpg")
cv2.imshow("img", img)
Face_Detect_Pic(img) #人脸识别(图片)
cv2.waitKey(0)
注:这里把最低检测次数改成了7 ,否则会错误检测。
# 打开摄像头
capture = cv2.VideoCapture(0) #0:本地摄像头 1:外接摄像头
while (True):
# 1、按帧读取视频
ret, frame = capture.read() #frame为每一帧的图像
需要左右翻转,否则向左右移动的时候,对象右左移动,反着移。
# 2、左右翻转(否则向左右移动的时候,对象右左移动,反着移)
frame = cv2.flip(frame, 1)
对每一帧提取的图像调用人脸识别函数,进行人脸识别。
# 3、对每一帧图像人脸识别
result = Face_Detect_Pic(frame)
# q键退出
if cv2.waitKey(1) & 0XFF == ord("q"):
break
# 人脸识别(图片、摄像头)
import cv2
# 图片中人脸识别
def Face_Detect_Pic(image):
# 1、转灰度图
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
cv2.imshow("gray", gray)
# 2、训练一组人脸
face_detector = cv2.CascadeClassifier("D:/Software/OpenCV/opencv/sources/data/haarcascades/haarcascade_frontalface_alt.xml")
# 3、检测人脸(用灰度图检测,返回人脸矩形坐标(4个角))
faces_rect = face_detector.detectMultiScale(gray, 1.05, 7)
# 灰度图 图像尺寸缩小比例 至少检测次数(若为3,表示一个目标至少检测到3次才是真正目标)
# print("人脸矩形坐标faces_rect:", faces_rect)
# 4、遍历每个人脸,画出矩形框
dst = image.copy()
for x, y, w, h in faces_rect:
cv2.rectangle(dst, (x, y), (x + w, y + h), (0, 0, 255), 3) #画出矩形框
# 显示
cv2.imshow("dst", dst)
return dst
# 摄像头中人脸识别
def Face_Detect_Cam():
# 打开摄像头
capture = cv2.VideoCapture(0) #0:本地摄像头 1:外接摄像头
while (True):
# 1、按帧读取视频
ret, frame = capture.read() #frame为每一帧的图像
# 2、左右翻转(否则向左右移动的时候,对象右左移动,反着移)
frame = cv2.flip(frame, 1)
# 3、对每一帧图像人脸识别
result = Face_Detect_Pic(frame)
# q键退出
if cv2.waitKey(1) & 0XFF == ord("q"):
break
if __name__ == "__main__":
# 读取图片
img = cv2.imread("Resource/faces.jpg")
cv2.imshow("img", img)
Face_Detect_Pic(img) #人脸识别(图片)
Face_Detect_Cam() #人脸识别(视频)
cv2.waitKey(0)
黑马程序员人工智能教程_10小时学会图像处理OpenCV入门教程_哔哩哔哩_bilibili
python-opencv人脸检测和识别实现(有代码和资源)_总裁余(余登武)博客-CSDN博客
【OpenCV】⚠️实战⚠️ 人脸识别 ☢️建议手收藏☢️_我是小白呀的博客-CSDN博客
Python实现人脸识别_yan_dk的专栏-CSDN博客_python人脸识别