《深度学习》OpenCV 人脸检测、微笑检测 原理及案例解析

目录

一、人脸检测

1、如何实现人脸识别

2、haar特征

1)什么是哈尔特征

2)工作原理

3)关于预先定义的哈尔特征矩形框

• 矩形框位置

• 矩形框大小

• 矩形框类型

4)举例

3、级联分类器

4、级联分类器的使用

二、人脸检测、微笑检测 案例实现

1、人脸检测完整代码

运行结果:

2、使用摄像头来直接检测

3、人脸微笑检测

完整代码:


一、人脸检测

1、如何实现人脸识别

        调用 OpenCV 中训练好的分类器实现人脸检测。OpenCV 提供了训练好的haar 级联分类器,OpenCV 还提供了使用 HOG 特征(主要用于行人检测)和 LBP 算法级联分类器。

2、haar特征

        1)什么是哈尔特征

                哈尔特征(Haar-like features)是一种基于图像亮度差异的特征描述符,通常用于描述图像的局部特征。这些特征通常是矩形区域的亮度差异,例如眼睛周围的黑色和白色区域。哈尔特征可以捕捉到目标的边缘线条纹理等信息,从而可以用来区分目标和背景。

        2)工作原理

                通过对图像中的不同位置尺度的窗口应用一组预先定义的哈尔特征,然后计算这些特征的加权和,根据加权和的值来判断窗口中是否包含感兴趣的目标。

        3)关于预先定义的哈尔特征矩形框
                • 矩形框位置

                        矩形框要逐像素点地划过(遍历) 整个图像获取每个位置的特征值。

                • 矩形框大小

                        矩形的大小可以根据需要进行任意调整。

                • 矩形框类型

                        包含垂直、水平、对角等不同类型,如下所示。

                特征值 = ∑特征区域中白色区域的像素值-黑色区域像素值(Haar特征反映的是图像的灰度变化)

        4)举例

        有上述多个人脸的灰度图,以及haar特征预先定义的矩形框,这些矩形框对这张图片进行扫描,即从开头位置开始,设置好矩形框大小以及步长,从左到右依次扫描,然后每次扫描得到的灰度值进行处理,矩形框中分为黑白区域,对每个扫描出来的灰度值进行白色区域减去黑色区域,然后求和得到扫描出来的特征值。

        

3、级联分类器

        在实际应用中,哈尔特征分类器通常与级联分类器(Cascade Classifier)结合使用。级联分类器是由大量的弱分类器组成的级联结构,每个弱分类器用于检测图像的一个特定特征。通过级联的方式,可以逐步筛选出可能包含目标的区域,从而提高了检测的准确性和效率。级联分类器能够快速排除非目标区域,减少计算量,提高检测速度。

        例如,在识别一个动物是狗(正类)还是其他动物(负类)时,直接根据多个条件进行判断,流程是非常烦琐的。如果先判断该动物有几条腿。有四条腿的动物被判断为可能为狗,并对此范围内的对象继续进行分析和判断。没有四条腿的动物直接被否决,即不可能是狗。只通过比较腿的数目就能排除样本集中大量的负类(如鸡、鸭、鹅等不是狗的动物的实例)。级联分类器就是基于这种思路将多个简单的分类器按照一定的顺序级联而成的。

4、级联分类器的使用

        OpenCV 提供了opencv_createsamples.exeopencv_traincascade.exe 文件,这两个 exe 文件需要去手动下载来说使用,他们可以用来训练级联分类器,训练级联分类器很耗时,如果训练的数据量较大,可能需要几天才能完成。

        OpenCV 提供了一些训练好的级联分类器供用户使用。这些分类器可以用来检测人脸、脸部特征(眼睛、鼻子)、人类和其他物体。这些级联分类器以XML 文件的形式存放在 OpenCV 源文件的 data 目录下,因为在我们pip安装时已经下载好了,加载不同级联分类器的 XML 文件就可以实现对不同对象的检测。

二、人脸检测、微笑检测 案例实现

1、人脸检测完整代码

import cv2
image = cv2.imread('people2.png')   # 导入待检测图像
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)  # 转变成灰度图

"""加载分类器"""
faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')    # 将data文件下的分类器复制到代码同目录下
"""分类器检测人脸"""

# #image:待检测图像,通常为灰度图像
# #scaleFactor:表示在前后两次相继扫描中窗口的缩放比例。识別,扫描,按照不同比例来进行扫描
# #minNeighbors:表示构成检测目标的相邻矩形的最小个数。在默认情况下,该参数的值为3,表示有 3 个以上的检测标记存在时才认为存在人脸。如果希望提高检测的准确率可以将该参数的值设置得更大,但这样微可能会让一些入脸无法被检测到。
# # flags: 该参数通常被省略。在使用低版本 0penCV(openCV 1.X 版本)时,该参数可能会被设置为,CV HAAR_DO_CANNY_PRUNING,表示使用 Canny 边缘检测器拒绝一些区域。
# #minsize:目标的最小尺寸,小于这个尺寸的目标将被忽略。
# #maxSize: 目标的最大尺寸,大于这个尺寸的目标将被忽略。通常情况下,将该可选参数省略即可。
# # 若 maxsize 和 minsize 大小一致,则表示仅在一个尺度上査找目标。

faces = faceCascade.detectMultiScale(gray, scaleFactor=1.05,minNeighbors=10, minSize=(10,10))  # gray为待检测图像的灰度图,scaleFactor为图像缩放的比例因子,minNeighbors表示每个候选矩形区域需要有多少个相邻的矩形区域来保留该区域,minSize表示人脸可能的最小尺寸
# 返回检测到的所有的人脸坐标和大小的数组
print("发现{0}张人脸!".format(len(faces)))
print("其位置分别是:",faces)

"""--------------标注人脸及显示-------------------"""
for (x,y,w,h) in faces:   # 将检测出来的人脸的数组遍历出来,返回给x、y坐标,宽高
    cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2)   # 在三通道的原图上绘制矩形
cv2.imshow("result",image)
cv2.waitKey(0)
cv2.destroyAllWindows()
        运行结果:

2、使用摄像头来直接检测

        只需导入摄像头,遍历每一帧画面,对每一帧画面进行识别,然后对识别到的画面进行标注,完整代码如下:

import cv2

cap = cv2.VideoCapture(0)   # 确保摄像头是可以启动的状态
if not cap.isOpened():   # 打开失败
    print("Cannot open camera")
    exit()

while True:
    ret,image = cap.read()  # 如果正确读取帧,ret为True
    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    if not ret:  # 读取失败,则退出循环
        print("不能读取摄像头")
        break

    """加载分类器"""
    faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
    """分离器检测人脸"""

    faces = faceCascade.detectMultiScale(gray, scaleFactor=1.05,minNeighbors=40, minSize=(10,10))
    print("发现{0}张人脸!".format(len(faces)))
    print("其位置分别是:",faces)

    """--------------标注人脸及显示-------------------"""
    for (x,y,w,h) in faces:
        cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2)
    cv2.imshow("result",image)
    key = cv2.waitKey(10)
    if key==27:
        break

cap.release()  # 释放捕获器节省资源
cv2.destroyAllWindows()   # 关闭图像窗口

        检测结果自行实验。

3、人脸微笑检测

        同样需要将OpenCV根目录下的一个用来进行微笑检测的xml文件级联分类器复制到代码文件同目录下,首先检测人脸,然后再判断是否是微笑的脸

        完整代码:
import cv2

faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
smile = cv2.CascadeClassifier('haarcascade_smile.xml')
cap = cv2.VideoCapture(0)

while True:
    ret,image = cap.read()  # 如果正确读取帧,ret为True
    # image = cv2.flip(image,1)   # 图片翮转,水平翻转(镜像)
    if ret is None:  # 读取失败,则退出循环
        break
    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)   # 灰度图
    faces = faceCascade.detectMultiScale(gray, scaleFactor=1.1,minNeighbors=10, minSize=(5,5))  # 检测人脸
    print("发现{0}张人脸!".format(len(faces)))
    print("其位置分别是:",faces)

    """处理每个人脸"""
    for (x,y,w,h) in faces:
        cv2.rectangle(image,(x,y),(x + w,y + h),(0, 255,0), 2)  # 绘制每一张人脸的轮廓,用绿色标注,此处还未展示
        roi_gray_face = gray[y:y + h,x:x + w]   # 定位出来每个人脸的位置
        # 微笑检测,在人脸区域内检测
        smiles = smile.detectMultiScale(roi_gray_face,scaleFactor=1.5,minNeighbors=15,minSize=(50,50))  
        for (sx, sy, sw, sh) in smiles:
            # 使用putText绘制文字,显示文字smile"表示微笑了
            cv2.putText(image,"smile",(x,y),cv2.FONT_HERSHEY_COMPLEX_SMALL, 1,(0,255,255),thickness=2)

    # 显示结果
    cv2.imshow("dect", image)
    key = cv2.waitKey(25)
    if key == 27:
        break
cap.release()  # 释放捕获器
cv2.destroyAllWindows()   # 关闭图像窗口

上一篇:SpringBoot智能推荐:健康生活新选择


下一篇:红黑树的实现