【机器学习】基于 dlib 面部关键点的多表情分类
文章目录完整代码一览一、环境准备与模型文件二、核心原理三个关键指标1. EAR眼睛纵横比—— 判断睁眼/闭眼2. MAR嘴巴纵横比—— 判断嘴巴张开程度3. MJR嘴宽脸宽比—— 判断嘴巴拉宽程度三、逐行代码详解1. 导入库与定义指标函数MAR 函数MJR 函数辅助函数中文绘制 cv2AddChineseText绘制眼睛轮廓 drawEye3. 主程序结构4. 主循环提取关键点并计算指标表情判定逻辑绘制与显示完整代码一览import numpy as np import dlib import cv2 from sklearn.metrics.pairwise import euclidean_distances from PIL import Image,ImageDraw,ImageFont#MAR嘴巴纵横比defMAR(shape):Aeuclidean_distances(shape[50].reshape(1,2),shape[58].reshape(1,2))Beuclidean_distances(shape[51].reshape(1,2),shape[57].reshape(1,2))Ceuclidean_distances(shape[52].reshape(1,2),shape[56].reshape(1,2))Deuclidean_distances(shape[48].reshape(1,2),shape[54].reshape(1,2))return((ABC)/3)/D#EAR眼睛纵横比defeye_aspect_ratio(eye):Aeuclidean_distances(eye[1].reshape(1,2),eye[5].reshape(1,2))Beuclidean_distances(eye[2].reshape(1,2),eye[4].reshape(1,2))Ceuclidean_distances(eye[0].reshape(1,2),eye[3].reshape(1,2))ear((AB)/2.0)/Creturnear#MJR嘴宽/脸宽比值defMJR(shape):Meuclidean_distances(shape[48].reshape(1,2),shape[54].reshape(1,2))Jeuclidean_distances(shape[3].reshape(1,2),shape[13].reshape(1,2))returnM/J#OpenCV 中文绘制defcv2AddChineseText(img,text,position,textColor(255,0,0),textSize30):ifisinstance(img,np.ndarray):imgImage.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))drawImageDraw.Draw(img)fontImageFont.truetype(simhei.ttf,textSize,encodingutf-8)draw.text(position,text,textColor,fontfont)returncv2.cvtColor(np.array(img),cv2.COLOR_RGB2BGR)defdrawEye(eye):eyeHullcv2.convexHull(eye)cv2.drawContours(frame,[eyeHull],-1,(0,255,0),2)detectordlib.get_frontal_face_detector()predictordlib.shape_predictor(shape_predictor_68_face_landmarks.dat)capcv2.VideoCapture(0)COUNTER0whileTrue:ret,framecap.read()ifnot ret:breakfacesdetector(frame,0)forface in faces:shapepredictor(frame,face)shapenp.array([[p.x,p.y]forp in shape.parts()])rightEyeshape[36:42]leftEyeshape[42:48]rightEAReye_aspect_ratio(rightEye)leftEAReye_aspect_ratio(leftEye)ear(leftEARrightEAR)/2.0marMAR(shape)mjrMJR(shape)print(mar,mar,\tmjr,mjr)result正常ifmar0.5:result大笑elif mjr0.45:result微笑elif mar0.45and ear0.3:COUNTER1ifCOUNTER30:result哭elif ear0.35:result愤怒else:COUNTER0drawEye(leftEye)drawEye(rightEye)infoEAR: {:.2f}.format(ear[0][0])framecv2AddChineseText(frame,info,(0,30))framecv2AddChineseText(frame,result,(50,100))mouthHullcv2.convexHull(shape[48:61])cv2.drawContours(frame,[mouthHull],-1,(0,255,0),1)cv2.imshow(Frame,frame)ifcv2.waitKey(1)27:breakcap.release()cv2.destroyAllWindows()一、环境准备与模型文件在运行代码之前请确保已安装以下库pip install dlib opencv-python scikit-learn Pillow并下载 dlib 的 68 点关键点模型文件下载地址解压后得到 shape_predictor_68_face_landmarks.dat放在脚本同一目录。中文绘制需要字体文件本代码使用 simhei.ttf黑体你可以从 Windows 系统字体文件夹C:\Windows\Fonts复制或使用其他中文字体如 msyh.ttc并修改代码中的字体名称。二、核心原理三个关键指标1. EAR眼睛纵横比—— 判断睁眼/闭眼我们在上一篇文章中已经详细介绍过它基于眼睛 6 个点睁眼时 EAR ≈ 0.25~0.3闭眼时接近 0。用于区分“愤怒”眼睛睁圆EAR 较大和“哭”眼睛闭合EAR 很小。2. MAR嘴巴纵横比—— 判断嘴巴张开程度MAR 是 Mouth Aspect Ratio 的缩写基于嘴巴 6 个点内唇上下和宽度嘴巴张开大笑、惊讶时MAR 明显增大 0.5。嘴巴闭合时MAR 较小 0.4。3. MJR嘴宽脸宽比—— 判断嘴巴拉宽程度MJR 是 Mouth-to-Jaw Ratio即嘴巴宽度与下颌宽度脸部宽度的比值微笑时嘴巴会向两侧拉宽MJR 增大 0.45。正常表情时MJR 较小。通过这三个指标的组合我们可以区分多种表情。三、逐行代码详解1. 导入库与定义指标函数import numpy as np import dlib import cv2 from sklearn.metrics.pairwise import euclidean_distances #提供欧氏距离计算 from PIL import Image,ImageDraw,ImageFont #中文绘制MAR 函数defMAR(shape):Aeuclidean_distances(shape[50].reshape(1,2),shape[58].reshape(1,2))Beuclidean_distances(shape[51].reshape(1,2),shape[57].reshape(1,2))Ceuclidean_distances(shape[52].reshape(1,2),shape[56].reshape(1,2))Deuclidean_distances(shape[48].reshape(1,2),shape[54].reshape(1,2))return((ABC)/3)/Dshape 是 68 个点的坐标数组索引 48~60 是嘴巴区域。50/58、51/57、52/56 是三对垂直方向上的内唇点取平均得到嘴巴高度48 和 54 是嘴角两端代表嘴巴宽度。MAR 平均高度 / 宽度张嘴时增大。MJR 函数defMJR(shape):Meuclidean_distances(shape[48].reshape(1,2),shape[54].reshape(1,2))# 嘴宽 Jeuclidean_distances(shape[3].reshape(1,2),shape[13].reshape(1,2))# 下颌宽度returnM/Jshape[48] 和 shape[54] 是嘴角其距离即嘴宽。shape[3] 和 shape[13] 是下巴轮廓两端的点相当于脸部宽度。微笑时嘴巴变宽比值增大。辅助函数中文绘制 cv2AddChineseTextdefcv2AddChineseText(img,text,position,textColor(255,0,0),textSize30):ifisinstance(img,np.ndarray):imgImage.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))drawImageDraw.Draw(img)fontImageFont.truetype(simhei.ttf,textSize,encodingutf-8)draw.text(position,text,textColor,fontfont)returncv2.cvtColor(np.array(img),cv2.COLOR_RGB2BGR)将 OpenCV 图像转为 PIL 图像绘制文字后再转回 OpenCV BGR 格式。绘制眼睛轮廓 drawEyedefdrawEye(eye):eyeHullcv2.convexHull(eye)cv2.drawContours(frame,[eyeHull],-1,(0,255,0),2)3. 主程序结构detectordlib.get_frontal_face_detector()predictordlib.shape_predictor(shape_predictor_68_face_landmarks.dat)capcv2.VideoCapture(0)COUNTER0初始化检测器、预测器、摄像头COUNTER 用于连续闭眼帧计数。4. 主循环whileTrue:ret,framecap.read()ifnot ret:breakfacesdetector(frame,0)逐帧读取检测人脸。提取关键点并计算指标forface in faces:shapepredictor(frame,face)shapenp.array([[p.x,p.y]forp in shape.parts()])rightEyeshape[36:42]leftEyeshape[42:48]rightEAReye_aspect_ratio(rightEye)leftEAReye_aspect_ratio(leftEye)ear(leftEARrightEAR)/2.0marMAR(shape)mjrMJR(shape)print(mar,mar,\tmjr,mjr)获取 68 点截取左右眼和嘴巴计算三个指标。print 输出到控制台便于调试。表情判定逻辑result正常ifmar0.5:result大笑elif mjr0.45:result微笑elif mar0.45and ear0.3:COUNTER1ifCOUNTER30:result哭elif ear0.35:result愤怒else:COUNTER0采用级联判断如果 MAR 0.5判定为“大笑”嘴巴张得很大。否则如果 MJR 0.45判定为“微笑”嘴巴拉宽但未张很大。否则如果 MAR 0.45 且 EAR 0.3嘴巴张开且眼睛闭合可能是“哭”需要连续 30 帧确认与疲劳检测类似。否则如果 EAR 0.35眼睛睁得很圆判定为“愤怒”。否则为“正常”。绘制与显示drawEye(leftEye)drawEye(rightEye)infoEAR: {:.2f}.format(ear[0][0])framecv2AddChineseText(frame,info,(0,30))framecv2AddChineseText(frame,result,(50,100))mouthHullcv2.convexHull(shape[48:61])cv2.drawContours(frame,[mouthHull],-1,(0,255,0),1)绘制眼睛和嘴巴的凸包轮廓绿色显示 EAR 值和表情结果。最后显示画面按 ESC 退出。

相关新闻

Ollama 的并发模型深度分析:从请求队列到 GPU Stream 的任务分派与同步机制

Ollama 的并发模型深度分析:从请求队列到 GPU Stream 的任务分派与同步机制

Ollama 的并发模型深度分析:从请求队列到 GPU Stream 的任务分派与同步机制 一、多用户并发推理时 GPU 利用率不饱和的根因追问 Ollama 作为本地 LLM 推理的流行方案,单用户场景下表现良好。但部署为内部推理服务后,多用户并发访问时 GPU 利用…

2026/7/28 2:23:32 阅读更多 →
Raft 集群的性能退化诊断:日志复制延迟的 flamegraph 分析与网络层优化方案

Raft 集群的性能退化诊断:日志复制延迟的 flamegraph 分析与网络层优化方案

Raft 集群的性能退化诊断:日志复制延迟的 flamegraph 分析与网络层优化方案 一、节点数增长时集群吞吐不升反降的诡异现象 在分布式系统中,直觉上增加节点应该提升吞吐量——更多节点意味着更多并行处理单元。然而 Raft 集群的实际表现恰恰相反&#xff…

2026/7/28 14:49:45 阅读更多 →
Rust 程序的内存泄漏排查:使用 heaptrack、valgrind 与自定义 Allocator 追踪分配路径

Rust 程序的内存泄漏排查:使用 heaptrack、valgrind 与自定义 Allocator 追踪分配路径

Rust 程序的内存泄漏排查:使用 heaptrack、valgrind 与自定义 Allocator 追踪分配路径 一、生产环境中的"温水煮青蛙"式内存增长 Rust 的所有权模型在编译期消除了 Use-After-Free 和 Double-Free,但这并不意味着内存泄漏从此绝缘。引用计数循…

2026/7/27 3:40:53 阅读更多 →

最新新闻

小程序——单列和多列picker选择器(二)

小程序——单列和多列picker选择器(二)

在我的另一篇博文中已经提到了要解决的第一个问题:在未选择时展示引导内容,在下拉栏选择后显示选择内容 现在来解决第二个问题:存入值为文本值而不是角标 一、单列选择器 和多列选择器相比,单列选择器的处理相对简单些 我们先看…

2026/7/28 16:50:39 阅读更多 →
功率计读数偏低?先别送修,查查探头校准

功率计读数偏低?先别送修,查查探头校准

做射频测试的人都遇到过这种情况:功率计测出来的数值,怎么比预期低了好几个 dB?换个信号源还是低,换根电缆还是低,甚至换台主机都一样 —— 难道探头坏了?很多人第一反应是 "功率计不准了,得送修"。但实际…

2026/7/28 16:50:39 阅读更多 →
Blueman蓝牙管理器:Linux桌面蓝牙管理的终极解决方案

Blueman蓝牙管理器:Linux桌面蓝牙管理的终极解决方案

Blueman蓝牙管理器:Linux桌面蓝牙管理的终极解决方案 【免费下载链接】blueman Blueman is a GTK Bluetooth Manager 项目地址: https://gitcode.com/gh_mirrors/bl/blueman 在Linux桌面环境中管理蓝牙设备常常让人感到头疼,特别是当你需要连接音…

2026/7/28 16:50:39 阅读更多 →
高帧率视频素材哪里找?2026年适合高频创作团队的5个网站

高帧率视频素材哪里找?2026年适合高频创作团队的5个网站

引言:视频产量提高后,素材效率比单纯数量更重要IAB在2026年行业研究中指出,接近三分之二的数字视频广告买家已经在创意制作中使用生成式AI,高于2025年的约一半;与此同时,93%的买家认为直播内容具有更高价值…

2026/7/28 16:50:39 阅读更多 →
NBM5100A与TM4C1294协同设计优化物联网设备电源管理

NBM5100A与TM4C1294协同设计优化物联网设备电源管理

1. 项目背景与核心挑战在便携式电子设备和物联网终端设计中,电池寿命和瞬时大电流供给能力一直是工程师面临的两大核心矛盾。传统方案中,设备遇到脉冲负载时(如无线模块发射信号、电机启动等),直接由电池提供瞬态大电流…

2026/7/28 16:50:39 阅读更多 →
AI Agent Skill 工程化 10:Skill 治理——Owner、清单、发布与季度复盘

AI Agent Skill 工程化 10:Skill 治理——Owner、清单、发布与季度复盘

Skill 一多,新问题就不是「怎么改」,而是「谁有权改、改坏了找谁」,尤其团队的Skill管理尤其重要 。这篇文章讲治理。工具很少,规矩很多——而且这些规矩,你们仓库里其实已经有一半雏形了。前言一句话:让 S…

2026/7/28 16:49:38 阅读更多 →

日新闻

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生 【免费下载链接】OmenSuperHub Control Omen laptop performance, fan speeds, and keyboard lighting, and unlock power limits. 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 你是否也曾为官方Om…

2026/7/28 0:00:43 阅读更多 →
RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

做 RAG 的人应该都踩过这个致命的坑:把几百页的财报、法规、技术手册扔给向量库,问一个具体问题,搜出来的全是沾边但没用的内容 —— 关键信息要么被硬切块拆碎了,要么藏在几十条结果的最下面。语义相似≠真正相关,这个…

2026/7/28 0:00:43 阅读更多 →
抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

2026年做短视频运营,从抖音上扒文案早就不是偷偷抄笔记的事了。我刚开始做内容的时候,每天刷半小时抖音,手动把爆款视频的口播敲进备忘录,一条2分钟的视频得花十来分钟,碰到语速快的还要反复回听。后来试了一圈工具&am…

2026/7/28 0:00:43 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/28 12:04:22 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/28 8:29:16 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/28 5:03:42 阅读更多 →

月新闻