【深度学习】OpenCV 实时微笑检测:摄像头人脸检测 + 微笑识别

文章目录


完整代码一览

c 复制代码
# 人脸微笑检测 (摄像头)
import cv2

xml_file = cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
faceCascade = cv2.CascadeClassifier(xml_file)
sml_file = cv2.data.haarcascades + "haarcascade_smile.xml"
smile = cv2.CascadeClassifier(sml_file)

cap = cv2.VideoCapture(0)  # 初始化摄像头

while True:  # 处理每一帧
    ret, image = cap.read()  # 读取一帧
    image = cv2.flip(image, flipCode=1)  # 图片翻转,水平翻转(镜像)
    if ret is None:  # 没有读到,直接退出
        break

    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)  # 灰度化

    faces = faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=15, minSize=(5, 5))
    
    # 处理每个人脸
    for (x, y, w, h) in faces:
        cv2.rectangle(image, pt1=(x, y), pt2=(x + w, y + h), color=(0, 255, 0), thickness=2)
        # 提取人脸所在区域(灰度图)
        roi_gray_face = gray[y:y + h, x:x + w]
        cv2.imshow('lian', roi_gray_face)

        # 微笑检测,仅在人脸区域内检测
        smiles = smile.detectMultiScale(roi_gray_face, scaleFactor=1.5, minNeighbors=15, minSize=(50, 50))
        for (sx, sy, sw, sh) in smiles:
            a = x + sx
            b = y + sy
            cv2.rectangle(image, (a, b), (a + sw, b + sh), (255, 0, 0), 2)
            cv2.putText(image, "smile", (x, y), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (0, 255, 255), 2)

    cv2.imshow("dect", image)
    key = cv2.waitKey(25)
    if key == 27:  # ESC键退出
        break

cap.release()
cv2.destroyAllWindows()

导入库与加载级联分类器

c 复制代码
import cv2

xml_file = cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
faceCascade = cv2.CascadeClassifier(xml_file)
sml_file = cv2.data.haarcascades + "haarcascade_smile.xml"
smile = cv2.CascadeClassifier(sml_file) # CascadeClassifier 是级联分类器类,加载后可用于检测目标。

cv2.data.haarcascades:OpenCV 内置的 Haar 级联分类器存放路径,自动定位。

加载两个模型:

haarcascade_frontalface_default.xml:正面人脸检测器。

haarcascade_smile.xml:微笑检测器(检测嘴巴的特定模式)。

初始化摄像头并循环读取帧

c 复制代码
cap = cv2.VideoCapture(0)  # 初始化摄像头

while True:
    ret, image = cap.read()  # 循环中不断读取帧,cap.read() 返回 (ret, image),ret 为布尔值表示是否成功。
    image = cv2.flip(image, flipCode=1)  # 水平翻转(镜像效果)
    if ret is None:  # 如果 ret 为None说明摄像头断开了或读取失败,退出循环
        break

灰度转换与人脸检测

c 复制代码
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    faces = faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=15, minSize=(5, 5))

将彩色帧转为灰度图,因为 Haar 分类器工作在灰度图像上。

detectMultiScale 参数说明:

  • scaleFactor=1.1:每次缩放比例 1.1,值越小检测越精细但速度慢。

  • minNeighbors=15:较高的值(15)大幅减少误报,适合实时场景,但可能漏检小脸。

  • minSize=(5,5):最小人脸尺寸为 5×5 像素(极小的脸也能检测,实际中通常调大以提升速度)。

返回值:

  • faces 是包含所有检测到的人脸矩形框的列表,每个框为 (x, y, w, h)。

遍历每个人脸,绘制人脸框并检测微笑

c 复制代码
    for (x, y, w, h) in faces:
        cv2.rectangle(image, pt1=(x, y), pt2=(x + w, y + h), color=(0, 255, 0), thickness=2) # 对每个人脸框,在原图上画绿色矩形
        roi_gray_face = gray[y:y + h, x:x + w]
        cv2.imshow('lian', roi_gray_face)
		# 微笑检测
        smiles = smile.detectMultiScale(roi_gray_face, scaleFactor=1.5, minNeighbors=15, minSize=(50, 50)) # 从灰度图 gray 中裁剪出人脸区域 roi_gray_face,这是微笑检测的输入。
        for (sx, sy, sw, sh) in smiles:
            a = x + sx
            b = y + sy
            cv2.rectangle(image, (a, b), (a + sw, b + sh), (255, 0, 0), 2)
            cv2.putText(image, "smile", (x, y), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (0, 255, 255), 2)

微笑检测参数:

scaleFactor=1.5:较大值加快检测,但可能漏检小微笑。

minNeighbors=15:同样高阈值来减少误报。

minSize=(50,50):微笑区域至少 50×50 像素(需根据人脸大小调整)。

如果检测到微笑,会返回一个或多个矩形框(嘴巴区域)。

将微笑框的坐标换算到原图(因为 roi_gray_face 的坐标是相对于人脸区域的,所以要加上 x, y 偏移)。

用蓝色矩形 (255,0,0) 绘制微笑框,并在人脸框上方显示黄色 "smile" 文字((0,255,255) 是黄色)。

显示结果与退出控制

c 复制代码
    cv2.imshow("dect", image)#  显示标注后的实时画面
    key = cv2.waitKey(25) # 等待 25 毫秒
    if key == 27:
        break

cap.release()
cv2.destroyAllWindows()# 循环结束后释放摄像头资源并关闭所有窗口