OpenCV+Dlib实战:人脸检测 + 表情识别 + 年龄性别预测

一、前言

在计算机视觉入门项目中,人脸相关应用最容易上手、效果也最直观。本文基于 OpenCV + Dlib,分三部分实现:

  1. 实时表情识别(正常 / 微笑 / 大笑)
  2. 高精度人脸检测(Dlib CNN 检测器)
  3. 年龄与性别实时预测(OpenCV DNN 预训练模型)

二、环境配置

python 复制代码
pip install opencv-python numpy dlib pillow scikit-learn

模块一:基于 Dlib 关键点的实时表情识别

1. 实现思路

  • 使用 Dlib 68 点人脸关键点定位
  • 提取嘴部区域关键点
  • 计算两个比值:
    • MAR:嘴巴宽高比 → 判断是否大笑
    • MJR:嘴宽 / 脸颊宽 → 判断是否微笑
  • 绘制嘴部轮廓 + 实时显示表情结果
  • 解决 OpenCV 中文乱码问题

2. 完整代码

python 复制代码
import numpy as np
import dlib
import cv2
from sklearn.metrics.pairwise import euclidean_distances
from PIL import Image, ImageDraw, ImageFont

# 计算嘴的宽高比 MAR
def MAR(shape):
    A = euclidean_distances(shape[50].reshape(1, 2),shape[58].reshape(1, 2))
    B = euclidean_distances(shape[51].reshape(1, 2),shape[57].reshape(1, 2))
    C = euclidean_distances(shape[52].reshape(1, 2),shape[56].reshape(1, 2))
    D = euclidean_distances(shape[48].reshape(1, 2),shape[54].reshape(1, 2))
    return ((A+B+C)/3)/D

# 计算嘴宽度 / 脸颊宽度比值 MJR
def MJR(shape):
    M = euclidean_distances(shape[48].reshape(1, 2), shape[54].reshape(1, 2))
    J = euclidean_distances(shape[3].reshape(1, 2), shape[13].reshape(1, 2))
    return M/J

# OpenCV 显示中文
def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=30):
    if (isinstance(img, np.ndarray)):
        img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    draw = ImageDraw.Draw(img)
    fontStyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8")
    draw.text(position, text, textColor, font=fontStyle)
    return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)

# 初始化检测器
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")

cap = cv2.VideoCapture(0)

while True:
    ret, frame = cap.read()
    faces = detector(frame, 0)
    
    for face in faces:
        shape = predictor(frame, face)
        shape = np.array([[p.x, p.y] for p in shape.parts()])
        
        mar = MAR(shape)
        mjr = MJR(shape)
        result = "正常"
        
        if mar > 0.5:
            result = "大笑"
        elif mjr > 0.45:
            result = "微笑"
        
        # 绘制嘴部轮廓
        mouthHull = cv2.convexHull(shape[48:61])
        frame = cv2AddChineseText(frame, result, mouthHull[0,0])
        cv2.drawContours(frame, [mouthHull], -1, (0, 255, 0), 1)

    cv2.imshow("Frame", frame)
    if cv2.waitKey(1) == 27:
        break

cv2.destroyAllWindows()
cap.release()

3. 效果说明

  • 正常:无明显表情
  • 微笑:嘴角轻微上扬
  • 大笑:嘴巴明显张开
  • 实时绘制嘴部轮廓,支持多人脸

模块二:Dlib CNN 高精度人脸检测

1. 实现思路

  • 使用 Dlib 官方 CNN 人脸检测器:mmod_human_face_detector.dat
  • 对图片进行人脸检测
  • 绘制人脸矩形框
  • 适合复杂场景、侧脸、遮挡场景检测

2. 完整代码

python 复制代码
import dlib
import cv2

# 加载 CNN 人脸检测器
cnn_face_detector = dlib.cnn_face_detection_model_v1("mmod_human_face_detector.dat")

# 读取图片
img = cv2.imread("people1.png")

# 检测人脸
faces = cnn_face_detector(img, 0)

# 遍历绘制框
for d in faces:
    rect = d.rect
    left = rect.left()
    top = rect.top()
    right = rect.right()
    bottom = rect.bottom()
    cv2.rectangle(img, (left, top), (right, bottom), (0, 255, 0), 3)

cv2.imshow("result", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

3. 特点

  • 比传统 HOG 检测器更准
  • 对遮挡、小角度人脸更鲁棒
  • 适合静态图片高精度检测

模块三:基于 OpenCV DNN 的年龄与性别实时预测

1. 实现思路

  • 使用 OpenCV DNN 加载 Caffe 预训练模型
  • 先检测人脸区域
  • 对人脸区域分别预测性别与年龄
  • 实时在画面上标注中文结果
  • 支持摄像头实时检测

2. 完整代码

python 复制代码
import cv2
from PIL import Image, ImageDraw, ImageFont
import numpy as np

# ================== 模型路径 ==================
faceProto = "model/opencv_face_detector.pbtxt"
faceModel = "model/opencv_face_detector_uint8.pb"
ageProto = "model/deploy_age.prototxt"
ageModel = "model/age_net.caffemodel"
genderProto = "model/deploy_gender.prototxt"
genderModel = "model/gender_net.caffemodel"

# 加载网络
ageNet = cv2.dnn.readNet(ageModel, ageProto)
genderNet = cv2.dnn.readNet(genderModel, genderProto)
faceNet = cv2.dnn.readNet(faceModel, faceProto)

# 年龄与性别列表
ageList = ['0-2岁', '4-6岁', '8-12岁', '15-20岁', '25-32岁', '38-43岁', '48-53岁', '60-100岁']
genderList = ['男性', '女性']
mean = (78.4263377603, 87.7689143744, 114.895847746)

# 获取人脸框
def getBoxes(net, frame):
    frameHeight, frameWidth = frame.shape[:2]
    blob = cv2.dnn.blobFromImage(frame, 1.0, (300, 300), [104, 117, 123], True, False)
    net.setInput(blob)
    detections = net.forward()
    faceBoxes = []
    for i in range(detections.shape[2]):
        confidence = detections[0, 0, i, 2]
        if confidence > 0.7:
            x1 = int(detections[0, 0, i, 3] * frameWidth)
            y1 = int(detections[0, 0, i, 4] * frameHeight)
            x2 = int(detections[0, 0, i, 5] * frameWidth)
            y2 = int(detections[0, 0, i, 6] * frameHeight)
            faceBoxes.append([x1, y1, x2, y2])
            cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
    return frame, faceBoxes

# 中文显示
def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=30):
    if (isinstance(img, np.ndarray)):
        img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    draw = ImageDraw.Draw(img)
    fontStyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8")
    draw.text(position, text, textColor, font=fontStyle)
    return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)

# 打开摄像头
cap = cv2.VideoCapture(0)

while True:
    _, frame = cap.read()
    frame = cv2.flip(frame, 1)
    frame, faceBoxes = getBoxes(faceNet, frame)
    
    if not faceBoxes:
        print("当前镜头中没有人")
        continue

    for faceBox in faceBoxes:
        x1, y1, x2, y2 = faceBox
        face = frame[y1:y2, x1:x2]
        
        blob = cv2.dnn.blobFromImage(face, 1.0, (227, 227), mean)
        
        # 预测性别
        genderNet.setInput(blob)
        gender = genderList[genderNet.forward()[0].argmax()]
        
        # 预测年龄
        ageNet.setInput(blob)
        age = ageList[ageNet.forward()[0].argmax()]
        
        # 显示结果
        result = "{},{}".format(gender, age)
        frame = cv2AddChineseText(frame, result, (x1, y1 - 30))

    cv2.imshow("result", frame)
    if cv2.waitKey(1) == 27:
        break

cv2.destroyAllWindows()
cap.release()

3. 效果说明

  • 实时框选人脸
  • 显示:男性 / 女性 + 年龄段
  • 支持多人脸、实时摄像头
  • 中文清晰不乱码

三、项目总结

本文分三大模块完整实现:

  1. 表情识别:基于 68 关键点,判断正常、微笑、大笑
  2. 人脸检测:Dlib CNN 高精度检测,适合复杂场景
  3. 年龄性别预测:OpenCV DNN 预训练模型,实时预测
相关推荐
ting94520007 小时前
Tornado 全栈技术深度指南:从原理到实战
人工智能·python·架构·tornado
果汁华8 小时前
Browserbase Skills:让 Claude Agent 真正“看见“网页世界
人工智能·python
ZhengEnCi8 小时前
04-缩放点积注意力代码实现 💻
人工智能·python
HackTwoHub9 小时前
AI大模型网关存在SQL注入、附 POC 复现、影响版本LiteLLM 1.81.16~1.83.7(CVE-2026-42208)
数据库·人工智能·sql·网络安全·系统安全·网络攻击模型·安全架构
段一凡-华北理工大学9 小时前
【高炉炼铁领域炉温监测、预警、调控智能体设计与应用】~系列文章08:多模态数据融合:让数据更聪明
人工智能·python·高炉炼铁·ai赋能·工业智能体·高炉炉温
网络工程小王9 小时前
【LangChain 大模型6大调用指南】调用大模型篇
linux·运维·服务器·人工智能·学习
HIT_Weston9 小时前
63、【Agent】【OpenCode】用户对话提示词(示例)
人工智能·agent·opencode
CV-杨帆9 小时前
Phi-4-mini-flash-reasoning 部署安装与推理测试完整记录
人工智能
MediaTea10 小时前
AI 术语通俗词典:C4.5 算法
人工智能·算法
海兰10 小时前
【第27篇】Micrometer + Zipkin
人工智能·spring boot·alibaba·spring ai