文章目录
- 引言
- 一、技术原理
- 二、代码实现
- 2.1 关键代码解析
- 2.1.1 模型加载
- 2.1.2 图像翻转
- 2.1.3 人脸检测 + 微笑检测
- 2.2 显示效果
- 三、参数调优建议
- 四、总结
引言
在计算机视觉领域,人脸检测和表情识别一直是热门的研究方向。今天我将分享一个使用Python和OpenCV实现的实时人脸微笑检测系统。这个系统能够通过摄像头捕捉视频流,实时检测人脸并识别微笑表情,非常适合初学者学习计算机视觉的基础应用。
一、技术原理
本实现主要基于OpenCV提供的Haar级联分类器,使用了两个预训练模型:
- haarcascade_frontalface_default.xml - 用于人脸检测
- haarcascade_smile.xml - 用于微笑检测
Haar级联分类器是一种基于机器学习的物体检测方法,由Paul Viola和Michael Jones在2001年提出。它通过训练大量正负样本,学习物体的特征模式,从而实现快速检测。
二、代码实现
import cv2
# 加载预训练模型
faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
smile = cv2.CascadeClassifier("haarcascade_smile.xml")
cap = cv2.VideoCapture('smile.mp4') #初始化摄像头
while True: #处理每一帧
ret,image = cap.read() #读取一帧
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=15,
minSize=(5,5) )
# 处理每个人脸
for (x,y,w,h) in faces:
cv2.rectangle(image,(x,y),(x + w,y + h),(0,255,0),2)
# 提取人脸ROI区域(灰度)
roi_gray_face = gray[y:y+h,x:x+w]
cv2.imshow('Face ROI',roi_gray_face)
# 微笑检测,仅在人脸区域内检测
smiles = smile.detectMultiScale(roi_gray_face,
scaleFactor=1.5,
minNeighbors=2,
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)
# 显示"smile"文字
cv2.putText(image,"smile",(x,y),cv2.FONT_HERSHEY_COMPLEX_SMALL,1,
(0,255,255),thickness=2)
# 显示结果
cv2.imshow("Smile Detection",image)
key = cv2.waitKey(25)
if key ==27: # ESC键退出
break
# 释放资源
cap.release()
cv2.destroyAllWindows()
2.1 关键代码解析
2.1.1 模型加载
faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
smile = cv2.CascadeClassifier("haarcascade_smile.xml")
这两行代码加载了OpenCV提供的预训练Haar级联分类器模型。
2.1.2 图像翻转
image = cv2.flip(image, 1)
-
cv2.flip()函数
- 作用:翻转输入图像(水平、垂直或同时翻转)。
- 参数:
- 第1个参数
image
:输入的图像(NumPy数组)。 - 第2个参数
1
:翻转模式的标志。0
:垂直翻转(沿x轴翻转)。1
:水平翻转(沿y轴翻转,即镜像效果)。-1
:同时水平和垂直翻转。
- 第1个参数
-
flipCode=1 的效果
假设原图为:
原图: [A B C] → 翻转后: [C B A]
[D E F] [F E D]
- 每一行的元素顺序被反转,但行的顺序不变。
2.1.3 人脸检测 + 微笑检测
for (x,y,w,h) in faces:
cv2.rectangle(image,(x,y),(x + w,y + h),(0,255,0),2)
# 提取人脸所在区域,多通道形式
# roiColorFace = image(y:y+h,x:x+w)
# 提取人脸所在区域,单通道形式
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=2,
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)
# 显示文字“smile” 表示微笑了
cv2.putText(image,"smile",(x,y),cv2.FONT_HERSHEY_COMPLEX_SMALL,1,
(0,255,255),thickness=2)
这段代码是一个 人脸检测 + 微笑检测 的程序,主要使用了 OpenCV 的 Haar 级联分类器(detectMultiScale
)来检测人脸和微笑。以下是详细解析:
代码功能概述
- 检测人脸(在
faces
中存储的人脸矩形框)。 - 提取人脸区域(灰度图
roi_gray_face
)。 - 在人脸区域内检测微笑(
smiles
)。 - 绘制人脸框和微笑框,并标注文字“smile”。
代码逐行解析
1. 遍历检测到的人脸
for (x, y, w, h) in faces:
faces
是一个包含人脸矩形框的列表,每个框由(x, y, w, h)
表示:(x, y)
:人脸左上角坐标。(w, h)
:人脸的宽度和高度。
2. 绘制人脸矩形框
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
- 在原始图像
image
上绘制绿色矩形框(RGB(0,255,0)
),线宽为2
。
3. 提取人脸区域(灰度图)
roi_gray_face = gray[y:y+h, x:x+w]
cv2.imshow('lian', roi_gray_face)
gray
是灰度图像(单通道)。roi_gray_face
是从gray
中截取的人脸区域。cv2.imshow('lian', roi_gray_face)
显示人脸区域的灰度图(窗口名'lian'
)。
4. 在人脸区域内检测微笑
smiles = smile.detectMultiScale(
roi_gray_face,
scaleFactor=1.5,
minNeighbors=2,
minSize=(50, 50)
)
smile
是一个训练好的 Haar 级联分类器(用于微笑检测)。- 参数说明:
scaleFactor=1.5
:每次图像缩放的比例(越大检测越快,但可能漏检)。minNeighbors=2
:候选框至少需要多少个邻近检测才被确认(越小误检越多)。minSize=(50, 50)
:微笑区域的最小尺寸(小于该尺寸的忽略)。
5. 遍历检测到的微笑区域
for (sx, sy, sw, sh) in smiles:
smiles
包含微笑矩形框(sx, sy, sw, sh)
,坐标是相对于roi_gray_face
(人脸区域)的。
6. 绘制微笑框(蓝色)
a = x + sx # 转换到原始图像的坐标
b = y + sy
cv2.rectangle(image, (a, b), (a + sw, b + sh), (255, 0, 0), 2)
(a, b)
是微笑框在原始图像image
中的左上角坐标。- 绘制蓝色矩形框(RGB
(255,0,0)
),线宽2
。
7. 标注文字“smile”
cv2.putText(image, "smile", (x, y), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (0, 255, 255), 2)
- 在人脸框左上角
(x, y)
处显示黄色文字“smile”:- 字体:
cv2.FONT_HERSHEY_COMPLEX_SMALL
。 - 字号:
1
。 - 颜色:
(0, 255, 255)
(黄色)。 - 线宽:
2
。
- 字体:
代码执行流程
- 输入图像 → 检测人脸 → 绘制绿色人脸框。
- 提取人脸区域 → 检测微笑 → 绘制蓝色微笑框。
- 标注“smile”文字 → 显示结果。
注意事项
- 依赖 Haar 级联分类器:
faces
和smiles
是由cv2.CascadeClassifier
检测得到的。- 通常需要加载预训练模型:
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') smile_cascade = cv2.CascadeClassifier('haarcascade_smile.xml')
- 参数调优:
scaleFactor
和minNeighbors
影响检测精度和速度,需根据实际场景调整。
- 坐标转换:
- 微笑检测是在人脸区域 (
roi_gray_face
) 内进行的,绘制时需要转换回原始图像坐标。
- 微笑检测是在人脸区域 (
2.2 显示效果
# 显示结果
cv2.imshow("dect",image)
key = cv2.waitKey(25)
if key ==27:
break
cap.release()
cv2.destroyAllWindows()
- 显示效果如下,我们插入一段视频,在视频中对人物进行微笑检测,并画出检测框:
三、参数调优建议
-
人脸检测参数:
minNeighbors
值越大,检测越严格,但可能漏检scaleFactor
通常在1.01-1.5之间
-
微笑检测参数:
- 由于微笑区域相对较小,
minSize
不宜设置过大 minNeighbors
可以适当调小以避免漏检
- 由于微笑区域相对较小,
四、总结
本文介绍了一个基于OpenCV Haar级联分类器的实时微笑检测系统。虽然Haar级联分类器在复杂场景下可能表现不佳,但它的计算效率高,非常适合初学者学习和快速原型开发。通过调整参数和优化流程,可以在实际应用中获得不错的效果。