当前位置: 首页 > article >正文

《OpenCV》——dlib(人脸应用实例)

文章目录

    • dlib库
    • dlib库——人脸应用实例——表情识别
    • dlib库——人脸应用实例——疲劳检测

dlib库

dlib库的基础用法介绍可以参考这篇文章:https://blog.csdn.net/lou0720/article/details/145968062?spm=1011.2415.3001.5331,故此这篇文章只介绍dlib的人脸应用实例。

dlib库——人脸应用实例——表情识别

在这里插入图片描述
代码:

import numpy as np
import cv2
import dlib
from sklearn.metrics.pairwise import euclidean_distances
from PIL import Image, ImageDraw, ImageFont

def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=20):
    """ 向图片中添加中文 """
    # 判断输入的 img 是否为 OpenCV 格式的图片(即 numpy.ndarray 类型)
    if isinstance(img, np.ndarray):
        # 如果是 OpenCV 格式,将其从 BGR 颜色空间转换为 RGB 颜色空间,
        # 因为 PIL 库使用 RGB 颜色空间,而 OpenCV 使用 BGR 颜色空间
        img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))

    # 在 img 图片上创建一个绘图对象,用于后续绘制文本
    draw = ImageDraw.Draw(img)

    # 定义字体的格式,使用 "simsun.ttc" 字体文件,指定字体大小为 textSize,
    # 并设置编码为 UTF - 8 以支持中文显示
    fontStyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8")

    # 在指定的 position 位置,使用指定的 textColor 颜色和 fontStyle 字体绘制文本
    draw.text(position, text, textColor, font=fontStyle)

    # 将绘制好文本的 PIL 图片转换回 numpy.ndarray 类型,并将颜色空间从 RGB 转换回 BGR,
    # 以符合 OpenCV 的要求
    return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)

def MAR(shape):
    """
    计算嘴巴纵横比(Mouth Aspect Ratio)
    :param shape: 68 个人脸特征点的坐标数组
    :return: 嘴巴纵横比
    """
    # 计算嘴巴上下部分特定点之间的欧氏距离
    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

def MJR(shape):
    """
    计算嘴巴与下巴宽度比(Mouth to Jaw Ratio)
    :param shape: 68 个人脸特征点的坐标数组
    :return: 嘴巴与下巴宽度比
    """
    # 计算嘴巴左右两侧特定点之间的欧氏距离
    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

def MBR(shape):
    """
    计算眉毛间距比(Mouth to Brow Ratio)
    :param shape: 68 个人脸特征点的坐标数组
    :return: 眉毛间距比
    """
    # 计算左右眉毛内侧特定点之间的欧氏距离
    F = euclidean_distances(shape[21].reshape(1, 2), shape[22].reshape(1, 2))
    # 计算左右眉毛外侧特定点之间的欧氏距离
    I = euclidean_distances(shape[17].reshape(1, 2), shape[26].reshape(1, 2))
    # 计算眉毛间距比
    return F / I

# 打开默认摄像头,用于实时视频捕获
cap = cv2.VideoCapture(0)
# 加载预训练的 68 点人脸特征预测模型
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
# 创建人脸检测器对象
detector = dlib.get_frontal_face_detector()

while True:
    # 从摄像头读取一帧视频
    ret, frame = cap.read()
    # 水平翻转视频帧,使画面看起来更自然
    frame = cv2.flip(frame, 1)
    # 如果读取失败,跳出循环
    if ret is None:
        break
    # 检测视频帧中的人脸
    faces = detector(frame, 0)
    for face in faces:
        # 预测人脸的 68 个特征点
        shape = predictor(frame, face)
        # 将特征点转换为 numpy 数组
        shape = np.array([[p.x, p.y] for p in shape.parts()])
        # 计算嘴巴纵横比
        mar = MAR(shape)
        # 计算嘴巴与下巴宽度比
        mjr = MJR(shape)
        # 计算眉毛间距比
        mbr = MBR(shape)
        # 初始化表情结果为正常
        result = '正常'
        # 打印各个比值
        print("mar", mar, '\tmjr', mjr, 'mbr', mbr)
        # 根据比值判断表情
        if mar > 0.5:
            result = "大笑"
        elif mjr > 0.45:
            result = '微笑'
        elif mbr < 0.15:
            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('img', frame)
    # 等待用户按键,等待时间为 1 毫秒
    key = cv2.waitKey(1)
    # 如果用户按下 ESC 键(ASCII 码为 27),跳出循环
    if key == 27:
        break
# 释放摄像头资源
cap.release()
# 关闭所有 OpenCV 窗口
cv2.destroyAllWindows()

在这里插入图片描述

dlib库——人脸应用实例——疲劳检测

在这里插入图片描述

当闭眼时间长时,发出危险警告。

代码:

import numpy as np
import cv2
import dlib
from sklearn.metrics.pairwise import euclidean_distances
from PIL import Image, ImageDraw, ImageFont

def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=20):
    """ 向图片中添加中文 """
    # 判断输入的 img 是否为 OpenCV 格式的图片(即 numpy.ndarray 类型)
    if isinstance(img, np.ndarray):
        # 如果是 OpenCV 格式,将其从 BGR 颜色空间转换为 RGB 颜色空间,
        # 因为 PIL 库使用 RGB 颜色空间,而 OpenCV 使用 BGR 颜色空间
        img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))

    # 在 img 图片上创建一个绘图对象,用于后续绘制文本
    draw = ImageDraw.Draw(img)

    # 定义字体的格式,使用 "simsun.ttc" 字体文件,指定字体大小为 textSize,
    # 并设置编码为 UTF - 8 以支持中文显示
    fontStyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8")

    # 在指定的 position 位置,使用指定的 textColor 颜色和 fontStyle 字体绘制文本
    draw.text(position, text, textColor, font=fontStyle)

    # 将绘制好文本的 PIL 图片转换回 numpy.ndarray 类型,并将颜色空间从 RGB 转换回 BGR,
    # 以符合 OpenCV 的要求
    return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)

def eye_aspect_ratio(eye):
    """
    计算眼睛的纵横比(Eye Aspect Ratio,EAR)
    :param eye: 眼睛的特征点坐标数组
    :return: 眼睛的纵横比
    """
    # 计算眼睛垂直方向上的距离
    A = euclidean_distances(eye[1].reshape(1, 2), eye[5].reshape(1, 2))
    B = euclidean_distances(eye[2].reshape(1, 2), eye[4].reshape(1, 2))
    # 计算眼睛水平方向上的距离
    C = euclidean_distances(eye[0].reshape(1, 2), eye[3].reshape(1, 2))
    # 计算眼睛纵横比,即垂直方向平均距离与水平距离的比值
    ear = ((A + B) / 2) / C
    return ear

def drawEye(eye):
    """
    在图像上绘制眼睛的轮廓
    :param eye: 眼睛的特征点坐标数组
    """
    # 计算眼睛特征点的凸包
    eyeHull = cv2.convexHull(eye)
    # 在图像 frame 上绘制眼睛的轮廓
    cv2.drawContours(frame, [eyeHull], -1, (0, 255, 0), 1)

# 初始化计数器,用于记录眼睛闭合的帧数
COUNTER = 0
# 创建人脸检测器对象,用于检测图像中的人脸
detector = dlib.get_frontal_face_detector()
# 打开默认摄像头,用于实时视频捕获
cap = cv2.VideoCapture(0)
# 加载预训练的 68 点人脸特征预测模型
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')

while True:
    # 从摄像头读取一帧视频
    ret, frame = cap.read()
    # 水平翻转视频帧,使画面看起来更自然
    frame = cv2.flip(frame, 1)
    # 如果读取失败,跳出循环
    if ret is None:
        break
    # 检测视频帧中的人脸
    faces = detector(frame, 0)
    for face in faces:
        # 预测人脸的 68 个特征点
        shape = predictor(frame, face)
        # 将特征点转换为 numpy 数组
        shape = np.array([[p.x, p.y] for p in shape.parts()])
        # 提取右眼的特征点
        rightEye = shape[36:42]
        # 提取左眼的特征点
        leftEye = shape[42:48]
        # 计算右眼的纵横比
        rightEAR = eye_aspect_ratio(rightEye)
        # 计算左眼的纵横比
        leftEAR = eye_aspect_ratio(leftEye)
        # 计算左右眼纵横比的平均值
        ear = (leftEAR + rightEAR) / 2

        # 如果眼睛纵横比小于 0.3,认为眼睛处于闭合状态
        if ear < 0.3:
            # 闭合帧数计数器加 1
            COUNTER += 1
            # 如果闭合帧数超过 50 帧,认为可能存在危险情况
            if COUNTER >= 50:
                # 在视频帧上添加中文提示信息
                frame = cv2AddChineseText(frame, "!!!危险!!!", (250, 250))
        else:
            # 如果眼睛处于睁开状态,将闭合帧数计数器重置为 0
            COUNTER = 0

        # 绘制左眼的轮廓
        drawEye(leftEye)
        # 绘制右眼的轮廓
        drawEye(rightEye)

        # 格式化眼睛纵横比信息,保留两位小数
        info = "EAR:{:.2f}".format(ear[0][0])
        # 在视频帧上添加眼睛纵横比信息
        frame = cv2AddChineseText(frame, info, (0, 30))

    # 显示处理后的视频帧
    cv2.imshow('Frame', frame)
    # 等待用户按键,等待时间为 1 毫秒
    key = cv2.waitKey(1)
    # 如果用户按下 ESC 键(ASCII 码为 27),跳出循环
    if key == 27:
        break

# 释放摄像头资源
cap.release()
# 关闭所有 OpenCV 窗口
cv2.destroyAllWindows()

在这里插入图片描述


http://www.kler.cn/a/571979.html

相关文章:

  • 机器学习相关知识概述
  • Leetcode 215 数组中的第K个最大元素
  • Libgdx游戏开发系列教程(4)——显示中文文字
  • Kubernetes教程(三)Docker容器命令
  • 股市现期驱动因子
  • go:windows环境下安装Go语言
  • AWS中使用CloudFront分发API Gateway
  • 计算机毕业设计SpringBoot+Vue.js工作流程管理系统(源码+文档+PPT+讲解)
  • 迷你世界脚本状态接口:Buff
  • 360图片爬虫|批量爬取图片
  • Vue05
  • QT-自定义参数设计框架软件
  • 爬虫(持续更新ing)
  • wordpress子分类调用父分类名称和链接的3种方法
  • Android 系统开发的指导文档
  • 奇安信天擎面试题
  • 未来经济范式争夺战:AR眼镜为何成为下一代交互终端的制高点?
  • 【TCP/IP协议栈】2. 网络接口层协议(以太网、令牌环、PPP 等)
  • 【STM32】TIM输入捕获-学习笔记
  • 2025年能源工作指导意见