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

news2025/4/21 14:18:56

文章目录

    • 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.coloradmin.cn/o/2310183.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

tauri2+typescript+vue+vite+leaflet等的简单联合使用(一)

项目目标 主要的目的是学习tauri。 流程 1、搭建项目 2、简单的在项目使用leaflet 3、打包 准备项目 环境准备 废话不多说&#xff0c;直接开始 需要有准备能运行Rust的环境和Node&#xff0c;对于Rust可以参考下面这位大佬的文章&#xff0c;Node不必细说。 Rust 和…

本地部署阿里万象2.1文生视频模型(Wan2.1-T2V)完全指南

在生成式AI技术爆发式发展的今天,阿里云开源的万象2.1(Wan2.1)视频生成模型,为创作者提供了从文字/图像到高清视频的一站式解决方案。本文针对消费级显卡用户,以RTX 4060 Ti 16G为例,详解本地部署全流程与性能调优方案,涵盖环境配置、多模型选择策略、显存优化技巧及实战…

【Vue CLI脚手架开发】——3.组件交互props配置

文章目录 前言一、props数据接收方式二、代码实现1. 父组件2.子组件 三、分析 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a;随着人工智能的不断发展&#xff0c;机器学习这门技术也越来越重要&#xff0c;很多人都开启了学习机器学习…

FPGA之USB通信实战:基于FX2芯片的Slave FIFO回环测试详解

FPGA之Usb数据传输 Usb 通信 你也许会有疑问&#xff0c;明明有这么多通信方式和数据传输&#xff08;SPI、I2C、UART、以太网&#xff09;为什么偏偏使用USB呢? 原因有很多&#xff0c;如下&#xff1a; 1. 高速数据传输能力 高带宽&#xff1a;USB接口提供了较高的数据传…

【Office-Word】如何自动生成中英文目录

1.目录介绍 Word这个自动生成目录非常强大&#xff0c;涉及的功能很琐碎&#xff0c;想要完美的生成目录不仅仅是只会目录这么简单&#xff0c;前后涉及到的大纲级别、目标样式和域代码等操作是比较头疼的。 下面就一步一步开始介绍 2.多级标题级别编号设置 目录想要设置好…

CentOS 7 安装Nginx-1.26.3

无论安装啥工具、首先认准了就是官网。Nginx Nginx官网下载安装包 Windows下载&#xff1a; http://nginx.org/download/nginx-1.26.3.zipLinxu下载 wget http://nginx.org/download/nginx-1.26.3.tar.gzLinux安装Nginx-1.26.3 安装之前先安装Nginx依赖包、自行选择 yum -y i…

家政预约小程序用例图分析

在和客户进行需求沟通的时候&#xff0c;除了使用常规的问答的形式&#xff0c;我还使用图形化工具更深入的沟通。比如借助UML的用例图来开展系统分析&#xff0c;并且按照角色详细拆解了家政预约小程序的各个用例。在分析阶段思考的越多&#xff0c;沟通的越多&#xff0c;在系…

112页精品PPT | DeepSeek行业应用实践报告

这份文件是一份关于DeepSeek行业应用实践的报告&#xff0c;以PPT形式呈现&#xff0c;共112页&#xff0c;详细介绍了DeepSeek及其核心产品DeepSeek-R1的技术特点、市场表现、应用路径以及在多领域的实践案例。报告展示了DeepSeek在市场上的快速崛起&#xff0c;包括其日活用户…

计算机毕业设计SpringBoot+Vue.js航空机票预定系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

C语言学习笔记-初阶(27)操作符详解1:位操作

1. 操作符的分类 上述的操作符&#xff0c;我们已经学过算术操作符、赋值操作符、逻辑操作符、条件操作符和部分的单目操作符&#xff0c;今天继续介绍⼀部分&#xff0c;操作符中有一些操作符和二进制有关系&#xff0c;我们先铺垫一下二进制的和进制转换的知识。 2. 二进制、…

网络安全需要学多久才能入门?

网络安全是一个复杂且不断发展的领域&#xff0c;想要入行该领域&#xff0c;我们需要付出足够多的时间和精力好好学习相关知识&#xff0c;才可以获得一份不错的工作&#xff0c;那么网络安全需要学多久才能入门?我们通过这篇文章来了解一下。 学习网络安全的入门时间因个人的…

20250304学习记录

第一部分&#xff0c;先来了解一下各种论文期刊吧&#xff0c;毕竟也是这把岁数了&#xff0c;还什么都不懂呢 国际期刊&#xff1a; EI收集的主要有两种&#xff0c; JA&#xff1a;EI源刊 CA&#xff1a;EI会议 CPCI也叫 ISTP 常说的SCI分区是指&#xff0c;JCR的一区、…

【星云 Orbit • STM32F4】08. 用判断数据头来接收据的串口通用程序框架

【星云 Orbit • STM32F4】08. 用判断数据头来接收据的串口通用程序框架 1. 引言 本教程旨在帮助嵌入式开发小白从零开始&#xff0c;学习如何在STM32F407微控制器上实现一个基于串口的数据接收程序。该程序能够通过判断数据头来接收一串数据&#xff0c;并将其存储到缓冲区中…

文件上传复现

文件上传漏洞的概念 在现代互联网的web应用程序中&#xff0c;上传文件是一种常见的功能&#xff0c;因为它有助于提高业务效率&#xff0c;比如社交 网站中&#xff0c;允许用户上传图片、视频、头像和许多其他类型的文件。然而向用户提供的功能越多&#xff0c; web应 用受到…

Redis——缓存穿透、击穿、雪崩

缓存穿透 什么是缓存穿透 缓存穿透说简单点就是大量请求的 key 根本不存在于缓存中&#xff0c;导致请求直接到了数据库上&#xff0c;根本没有经过缓存这一层。举个例子&#xff1a;某个黑客故意制造我们缓存中不存在的 key 发起大量请求&#xff0c;导致大量请求落到数据库…

HMC7043和HMC7044芯片配置使用

一,HMC7043芯片 MC7043独特的特性是对14个通道分别进行独立灵活的相位管理。所有14个通道均支持频率和相位调整。这些输出还可针对50 Ω或100 Ω内部和外部端接选项进行编程。HMC7043器件具有RF SYNC功能,支持确定性同步多个HMC7043器件,即确保所有时钟输出从同一时钟沿开始…

VSCode知名主题带毒 安装量900万次

目前微软已经从 Visual Studio Marketplace 中删除非常流行的主题扩展 Material Theme Free 和 Material Theme Icons&#xff0c;微软称这些主题扩展包含恶意代码。 统计显示这些扩展程序的安装总次数近 900 万次&#xff0c;在微软实施删除后现在已安装这些扩展的开发者也会…

mybatis映射文件相关的知识点总结

mybatis映射文件相关的知识点总结 mybatis官网地址 英文版&#xff1a;https://mybatis.org/mybatis-3/index.html 中文版&#xff1a;https://mybatis.p2hp.com/ 搭建环境 /* SQLyog Ultimate v10.00 Beta1 MySQL - 8.0.30 : Database - mybatis-label *****************…

【UCB CS 61B SP24】Lecture 21: Data Structures 5: Priority Queues and Heaps 学习笔记

本文介绍了优先队列与堆&#xff0c;分析了最小堆的插入与删除过程&#xff0c;并用 Java 实现了一个通用类型的最小堆。 1. 优先队列 1.1 介绍 优先队列是一种抽象数据类型&#xff0c;其元素按照优先级顺序被处理。不同于普通队列的先进先出&#xff08;FIFO&#xff09;&…

爬虫系列之发送请求与响应《一》

一、请求组成 1.1 请求方式&#xff1a;GET和POST请求 GET:从服务器获取&#xff0c;请求参数直接附在URL之后&#xff0c;便于查看和分享&#xff0c;常用于获取数据和查询操作 POST&#xff1a;用于向服务器提交数据&#xff0c;其参数不会显示在URL中&#xff0c;而是包含在…