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

dlib库

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

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


代码:

python 复制代码
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库------人脸应用实例------疲劳检测

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

代码:

python 复制代码
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()
相关推荐
车载诊断技术2 小时前
人工智能AI在汽车设计领域的应用探索
数据库·人工智能·网络协议·架构·汽车·是诊断功能配置的核心
AuGuSt_813 小时前
【深度学习】Hopfield网络:模拟联想记忆
人工智能·深度学习
jndingxin4 小时前
OpenCV计算摄影学(6)高动态范围成像(HDR imaging)
人工智能·opencv·计算机视觉
数据攻城小狮子4 小时前
深入剖析 OpenCV:全面掌握基础操作、图像处理算法与特征匹配
图像处理·python·opencv·算法·计算机视觉
Sol-itude4 小时前
【文献阅读】Collective Decision for Open Set Recognition
论文阅读·人工智能·机器学习·支持向量机
没事偷着乐琅5 小时前
人工智能 pytorch篇
人工智能·pytorch·python
邪恶的贝利亚5 小时前
Pytorch常用函数
人工智能·pytorch·python
Ironben5 小时前
看好 MCP,但用不了 Claude,所以做了一款 MCP 客户端
人工智能·claude·mcp
佛州小李哥5 小时前
构建逻辑思维链(CoT)为金融AI消除幻觉(保险赔付篇)
人工智能·科技·ai·金融·云计算·aws·亚马逊云科技
xilu05 小时前
MCP与RAG:增强大型语言模型的两种路径
人工智能·llm·mcp