基于OpenCV的实时视觉检测:年龄性别识别与疲劳检测实战

在计算机视觉领域,实时人脸相关检测技术广泛应用于安防、车载、智能交互等场景。本文将分享两个实用的视觉检测项目------实时年龄性别检测和驾驶员疲劳检测,从技术原理到代码实现,带你快速掌握基于OpenCV的视觉检测开发。

一、项目背景与技术栈

1. 核心技术栈

• OpenCV:用于图像/视频读取、预处理、人脸检测、绘图等核心操作

• DNN模块:加载预训练模型实现年龄和性别预测

• dlib:人脸关键点检测(疲劳检测核心)

• NumPy:数值计算,处理坐标和矩阵运算

• PIL:解决OpenCV中文显示乱码问题

2. 应用场景

• 年龄性别检测:智能门禁、客流分析、个性化推荐

• 疲劳检测:车载安全系统、工业操作岗监控、防疲劳驾驶

二、实战1:实时年龄与性别检测

技术原理
  1. 人脸检测:通过OpenCV的DNN模块加载预训练的人脸检测模型,定位画面中的人脸区域(人脸包围框);

  2. 特征提取与预测:将检测到的人脸区域预处理后,输入预训练的年龄/性别分类模型,输出预测结果;

  3. 结果可视化:在人脸区域上方绘制中文标注,实时展示性别和年龄区间。

核心代码解析
  1. 模型加载与参数配置
python 复制代码
import cv2
from PIL import Image, ImageDraw, ImageFont
import numpy as np

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

# 加载DNN网络
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)  # 模型输入均值(标准化用)
  1. 人脸检测函数

通过DNN模型检测人脸,返回绘制了人脸框的画面和人脸坐标列表:

python 复制代码
def getBoxes(net,frame):
    frameHeight,frameWidth = frame.shape[:2]
    # 将图像转换为DNN输入的blob格式
    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),int(round(frameHeight/150)),6)
    return frame, faceBoxes
  1. 中文显示解决(OpenCV原生不支持中文)
python 复制代码
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)
    # 加载宋体字体(需确保系统有simsun.ttc文件)
    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)
  1. 主循环(实时检测)
python 复制代码
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)
        genderOuts = genderNet.forward()
        gender = genderList[genderOuts[0].argmax()]
        # 年龄预测
        ageNet.setInput(blob)
        ageOuts = ageNet.forward()
        age = ageList[ageOuts[0].argmax()]
        # 绘制结果
        result = f"{gender},{age}"
        frame = cv2AddChineseText(frame,result,(x1,y1-30))
    cv2.imshow("年龄性别检测",frame)
    if cv2.waitKey(1) == 27:  # ESC键退出
        break
cv2.destroyAllWindows()
cap.release()
运行注意事项
  1. 需下载预训练模型文件(opencv_face_detector系列、age_net、gender_net),放在model1目录下;

  2. 确保系统有simsun.ttc字体文件(Windows默认有,Linux需手动安装);

  3. 摄像头权限需开启,且无其他程序占用。

三、实战2:驾驶员疲劳检测

技术原理

疲劳检测的核心是眼睛纵横比(EAR):

• 眼睛睁开时,EAR值较高;闭眼时,EAR值会骤降;

• 当EAR值持续低于阈值(如0.3),判定为疲劳状态,触发警报。

  1. EAR计算函数
python 复制代码
import numpy as np
import dlib
import cv2
from sklearn.metrics.pairwise import euclidean_distances

def eye_aspect_ratio(eye):
    # 计算垂直方向两点距离
    A = euclidean_distances(np.array(eye[1]), np.array(eye[5]))
    B = euclidean_distances(np.array(eye[2]), np.array(eye[4]))
    # 计算水平方向两点距离
    C = euclidean_distances(np.array(eye[0]), np.array(eye[3]))
    # EAR公式:垂直距离均值 / 水平距离
    ear = ((A + B) / 2.0) / C
    return ear
  1. 人脸关键点检测与疲劳判断
python 复制代码
# 初始化dlib检测器和关键点预测器
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")

COUNTER = 0  # 闭眼帧数计数器
cap = cv2.VideoCapture(0)
while True:
    ret, frame = cap.read()
    if not ret:
        break
    faces = detector(frame, 0)
    for rect in faces:
        # 获取68个人脸关键点
        shape = predictor(frame, rect)
        shape = np.matrix([[p.x, p.y] for p in shape.parts()])
        # 提取左右眼关键点(68点模型固定索引)
        rightEye = shape[36:42]
        leftEye = shape[42:48]
        # 计算EAR值
        rightEAR = eye_aspect_ratio(rightEye)
        leftEAR = eye_aspect_ratio(leftEye)
        ear = (leftEAR + rightEAR) / 2.0
        
        # 疲劳判断:EAR<0.3视为闭眼,累计50帧触发警报
        if ear < 0.30:
            COUNTER += 1
            if COUNTER >= 50:
                frame = cv2AddChineseText(frame, "!!!!危险!!!!", (250, 250), (0, 0, 255), 40)
        else:
            COUNTER = 0  # 睁眼则重置计数器
        
        # 绘制眼睛轮廓
        eyeHull = cv2.convexHull(leftEye)
        cv2.drawContours(frame, [eyeHull], -1, (0, 255, 0), 1)
        eyeHull = cv2.convexHull(rightEye)
        cv2.drawContours(frame, [eyeHull], -1, (0, 255, 0), 1)
        # 显示EAR值
        info = f"EAR: {ear[0][0]:.2f}"
        frame = cv2AddChineseText(frame, info, (0, 30))
    
    cv2.imshow("疲劳检测", frame)
    if cv2.waitKey(1) == 27:
        break
cv2.destroyAllWindows()
cap.release()
运行注意事项
  1. 需下载shape_predictor_68_face_landmarks.dat文件(dlib人脸关键点模型);

  2. EAR阈值可根据实际场景调整(如光线差的环境可适当降低);

  3. 帧数阈值(50帧)可根据摄像头帧率调整(默认25帧/秒,50帧约2秒)。

四、项目优化方向

  1. 性能优化:

◦ 降低图像分辨率(如640x480)减少计算量;

◦ 使用多线程/多进程分离检测和绘制逻辑;

  1. 精度提升:

◦ 年龄检测:增加更多年龄区间,或使用回归模型替代分类;

◦ 疲劳检测:结合嘴巴开合度(MAR)、头部姿态等多特征判断;

  1. 功能扩展:

◦ 年龄性别检测:添加人数统计、人脸识别绑定;

◦ 疲劳检测:增加声音警报、截图保存、远程推送等功能;

  1. 兼容性优化:

◦ 适配不同摄像头分辨率;

◦ 增加模型文件缺失的异常处理。

五、总结

本文通过两个实战项目,展示了OpenCV在实时视觉检测中的应用:年龄性别检测基于DNN预训练模型,核心是人脸检测+分类预测;疲劳检测基于人脸关键点的EAR特征,核心是行为特征提取+阈值判断。

这些技术不仅能快速落地到实际项目中,也能作为计算机视觉入门的经典案例。掌握这些基础后,可进一步探索更复杂的场景,如表情识别、行为分析、多目标追踪等。

相关推荐
taWSw5OjU8 小时前
从模型评估、梯度难题到科学初始化:一步步解析深度学习的训练问题
人工智能·深度学习
刘佬GEO8 小时前
【无标题】
网络·人工智能·搜索引擎·ai·语言模型
用户2018792831678 小时前
/export之一个程序员与AI的“破案笔记”
人工智能
Ricardo-Yang8 小时前
SCNP语义分割边缘logits策略
数据结构·人工智能·python·深度学习·算法
新缸中之脑8 小时前
微调BERT进行命名实体识别
人工智能·深度学习·bert
用户2018792831678 小时前
故事:小白的“无限循环”噩梦与大师的 /loop 魔法
人工智能
段小二8 小时前
Token 费用失控、VIP 用户体验一样烂:Context Engineering 才是关键
人工智能·后端
用户2018792831678 小时前
/branch 你点了一份代码,Cli 帮你分成了两碗
人工智能
kishu_iOS&AI8 小时前
机器学习 —— 线性回归
人工智能·机器学习·线性回归
阿里云大数据AI技术8 小时前
OpenClaw 长记忆增强:基于 Hologres + Mem0 的企业级方案
人工智能