文章目录
完整代码一览
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()# 循环结束后释放摄像头资源并关闭所有窗口