基于 MediaPipe + PyTorch 的实时手势识别与面部表情分析系统
支持 19 种手势 · 7 种表情 · 3 种运行模式
使用 MediaPipe Hand Landmarker(21 关键点)和 Face Landmarker(478 关键点)提取高精度关键点,结合关节向量夹角分析与面部几何特征归一化,实现毫秒级实时识别。
┌──────────┐ ┌──────────────────┐ ┌────────────────┐
│ 摄像头 │───▶│ MediaPipe 推理 │───▶│ 分类 + 渲染 │───▶ 画面输出
│ 图片/视频 │ │ 手部21点/人脸478点 │ │ 19手势/7表情 │
└──────────┘ └──────────────────┘ └────────────────┘
| 特性 | 说明 |
|---|---|
| 🎯 高精度 | MediaPipe 关键点 + 关节向量夹角判定,识别精度 > 90% |
| ⚡ 实时性 | 端到端延迟 < 50ms,适合直播、互动场景 |
| 🌏 中文友好 | PIL 渲染中文标签 + 终端原生中文输出,无乱码 |
| 🖥️ 无头模式 | 自动检测 SSH/Docker 环境,无 GUI 也可运行 |
| 📸 截图录制 | 内置截图(S 键)和视频录制(R 键)功能 |
| 🔧 高度可配 | config.py 集中管理所有阈值、颜色、标签 |
| # | 英文 | 中文 | 手指状态 | # | 英文 | 中文 | 手指状态 |
|---|---|---|---|---|---|---|---|
| 1 | fist |
✊ 握拳 | 0 指 | 11 | thumbs_down |
👎 倒赞 | 仅拇指弯 |
| 2 | one |
☝️ 一指 | 食指伸 | 12 | pinch |
🤏 捏合 | 拇食指并拢 |
| 3 | two / peace |
✌️ 剪刀手 | 食+中分开 | 13 | call_me |
🤙 打电话 | 拇+小指伸 |
| 4 | three |
🤟 三指 | 食+中+无名 | 14 | spider_man |
🕷️ 蜘蛛侠 | 食+小指 |
| 5 | four |
🖖 四指 | 除拇指外 | 15 | ily |
🤟 我爱你 | 拇+食+小 |
| 6 | open_palm |
✋ 张开 | 5 指全伸 | 16 | heart |
🫶 比心 | 拇食指心形 |
| 7 | thumbs_up |
👍 点赞 | 仅拇指伸 | 17 | gun |
👉 枪手势 | 食+拇指 |
| 8 | ok |
👌 OK | 拇食圈 | 18 | double_point |
👆👆 双指指向 | 食+中并拢 |
| 9 | point |
👈 指向 | 仅食指 | 19 | pray |
🙏 祈祷 | 双手合十 |
| 10 | rock |
🤘 摇滚 | 食+小指 | — | — | — | — |
实际可用手势取决于 MediaPipe 关键点质量,光照良好时全部 19 种均可识别。
| # | 英文 | 中文 | 关键特征 |
|---|---|---|---|
| 1 | happy |
😊 开心 | 嘴角上扬、眼睛微眯 |
| 2 | sad |
😢 悲伤 | 嘴角下垂、眼睛缩小 |
| 3 | angry |
😠 生气 | 眉毛紧锁、嘴唇紧闭 |
| 4 | surprised |
😲 惊讶 | 嘴巴张大、眉毛抬高 |
| 5 | neutral |
😐 中性 | 面部放松、无显著变化 |
| 6 | fearful |
😨 恐惧 | 眼睛睁大、眉毛上抬 |
| 7 | disgusted |
🤢 厌恶 | 鼻子皱起、上唇抬起 |
# 1. 克隆项目
git clone https://github.com/anhaoking/gesture-recognition.git
cd gesture-recognition/recognition
# 2. 安装依赖
pip install -r requirements.txt
# 3. 预下载模型(可选,首次运行会自动下载)
python download_models.py
# 4. 启动实时识别
python main.py realtime💡 Windows 用户可直接双击根目录的
启动识别.bat
:: 双击运行,自动检测 Python 并安装依赖
setup.bat
:: 或手动安装
pip install -r requirements.txt -i https://mirrors.bfsu.edu.cn/pypi/web/simplechmod +x setup.sh
./setup.sh# 依赖安装
sudo apt install -y libgl1-mesa-glx libglib2.0-0 # 无头环境需要
# Python 依赖
pip install -r requirements.txt
# 无头模式运行
HEADLESS=1 python main.py video input.mp4 -o output.mp4 --no-showpython check_env.py检查 Python 版本、依赖包完整度、CUDA 可用性、摄像头状态。
| 参数 | 简写 | 默认值 | 说明 |
|---|---|---|---|
--camera |
-c |
0 |
摄像头设备 ID |
--width |
-W |
1280 |
画面宽度 |
--height |
-H |
720 |
画面高度 |
--record |
-r |
关 | 开关录制 |
--output |
-o |
realtime_output.mp4 |
录制文件路径 |
| 参数 | 简写 | 默认值 | 说明 |
|---|---|---|---|
image_path |
— | 必填 | 输入图片路径 |
--output |
-o |
output/images |
结果输出目录 |
--no-show |
— | 关 | 不弹出窗口 |
| 参数 | 简写 | 默认值 | 说明 |
|---|---|---|---|
video_path |
— | 必填 | 输入视频路径 |
--output |
-o |
不保存 | 输出视频路径 |
--skip |
-s |
2 |
跳帧间隔(越大越快) |
--max-frames |
-m |
全部 | 最大处理帧数 |
--no-show |
— | 关 | 不弹出窗口 |
| 按键 | 功能 | 说明 |
|---|---|---|
Q / ESC |
退出程序 | 安全释放摄像头 |
Space |
暂停/继续 | 画面冻结,可仔细观察 |
S |
截图 | 保存当前帧到 output/images/ |
R |
录制开关 | 开始/停止保存视频流 |
D |
调试模式 | 终端打印特征值与打分详情 |
F |
关键点显隐 | 切换手部骨架/面部网格显示 |
所有可调参数集中在 recognition/config.py,无需修改代码:
# 检测阈值
DETECT_CONF = 0.45 # 目标检测置信度(调高 = 更准但少检出)
IOU_THRESH = 0.45 # NMS 重叠阈值
# 可视化
LINE_THICKNESS = 2 # 骨架线宽
FONT_SCALE = 0.6 # 回退字体大小(PIL 模式下自动忽略)
KEYPOINT_RADIUS = 4 # 关键点半径
# 实时模式
CAMERA_ID = 0 # 默认摄像头
FRAME_WIDTH = 1280 # 水平分辨率
FRAME_HEIGHT = 720 # 垂直分辨率
FPS_DISPLAY = True # 显示帧率颜色映射
GESTURE_COLORS和EXPRESSION_COLORS支持自定义 BGR 色值。
┌──────────┐ ┌─────────────────┐ ┌──────────────┐ ┌──────────┐
│ 原始帧 │────▶│ MediaPipe │────▶│ 特征提取 │────▶│ 分类输出 │
│ BGR图像 │ │ 手部 21 关键点 │ │ 关节夹角(°) │ │ 手势标签 │
│ │ │ 面部 478 关键点 │ │ 几何比率 │ │ 表情标签 │
└──────────┘ └─────────────────┘ └──────────────┘ └──────────┘
- 关键点提取 — MediaPipe Hand Landmarker 输出 21 个手部关键点 (x, y, z)
- 关节夹角计算 — 取 PIP 关节三点的向量夹角:∠(MCP→PIP, PIP→TIP)
- 伸直时夹角 ≈ 180°,阈值 > 150° 判定为伸直
- 拇指阈值稍宽松:> 110° 即判定伸直(拇指天然略弯)
- 五维状态向量 — 生成
[拇指, 食指, 中指, 无名指, 小指]的 0/1 序列 - 规则匹配 — 将五维向量与 19 种预定义手势模式逐一比对
- 关键点提取 — MediaPipe Face Landmarker 输出 478 个面部网格点
- 归一化基准 — 取两眼内角间距(点 133 ↔ 362)作为尺度参考
- 特征计算(全部除以眼间距,与脸距离无关):
特征 计算方式 用途 嘴部开合比 嘴高 / 嘴宽 判断张嘴(惊讶)vs 闭嘴(生气) 嘴角上扬角 (上唇中点 Y - 嘴角中点 Y) / 眼间距 正=下垂(悲伤),负=上扬(开心) 眼睛纵横比 眼高 / 眼宽 < 0.18 眯眼(悲伤),> 0.30 瞪眼(惊讶/恐惧) 眉毛高度 (眼中心 Y - 眉 Y) / 眼间距 > 0.4 惊讶,< 0.05 悲伤 眉间距比 眉心距 / 眼间距 < 0.6 皱眉(生气) - 多特征打分 — 每个表情累加特征得分,取最高分输出
gesture-recognition/
│
├── src/ # Java 端(预留接口)
│ └── Main.java
│
├── recognition/ # Python 识别引擎
│ ├── main.py # CLI 主入口(argparse 子命令)
│ ├── config.py # 全局配置(阈值/颜色/标签/骨架)
│ ├── check_env.py # 环境自检工具
│ ├── download_models.py # 模型预下载脚本
│ ├── requirements.txt # Python 依赖清单
│ ├── run.bat / setup.bat / setup.sh # 启动/安装脚本
│ │
│ ├── detectors/ # 🔍 检测器模块
│ │ ├── hand_gesture.py # 手势检测:21点 → 关节角度 → 19分类
│ │ └── facial_expression.py # 表情检测:478点 → 几何特征 → 7分类
│ │
│ ├── modes/ # 🎬 运行模式
│ │ ├── image_recognition.py # 图片模式:单帧推理
│ │ ├── video_recognition.py # 视频模式:跳帧 + 进度条
│ │ └── realtime_recognition.py # 实时模式:摄像头 + 信息面板
│ │
│ ├── utils/ # 🛠 工具模块
│ │ ├── draw_utils.py # PIL 中文渲染(解决 cv2.putText 乱码)
│ │ ├── logger.py # 统一日志(文件 + 控制台)
│ │ └── headless.py # 无头环境适配
│ │
│ ├── models/ # 📦 模型文件(gitignore,需下载)
│ ├── output/images/ & videos/ # 📤 识别结果输出
│ ├── logs/ # 📝 运行日志
│ └── samples/ # 🖼 测试样本
│
├── 启动识别.bat # Windows 一键启动
├── .gitignore # Git 忽略规则
└── README.md # 本文件
| 包 | 版本 | 用途 |
|---|---|---|
mediapipe |
≥ 0.10 | 手部/面部关键点提取 |
opencv-python |
≥ 4.8 | 图像采集、处理、显示 |
torch |
≥ 2.0 | 深度学习推理后端 |
ultralytics |
≥ 8.3 | YOLOv11 模型加载 |
Pillow |
≥ 10.0 | 中文文本渲染 |
numpy |
≥ 1.24 | 数值/矩阵运算 |
Q: 首次运行报错"无法加载模型"?
A: 首次运行会从网络下载 YOLOv11 和 MediaPipe 模型文件(约 200MB),请确保网络畅通。可提前运行:
python download_models.pyQ: 摄像头打不开或黑屏?
A: 尝试以下步骤:
- 确认摄像头未被其他应用占用(关闭 Zoom、微信视频等)
- 切换设备 ID:
python main.py realtime --camera 1 - Windows 在设置 → 隐私 → 摄像头中允许 Python 访问
Q: 画面中文字是方框/乱码?
A: 程序使用 PIL 自动探测系统字体(微软雅黑 → 黑体 → 宋体)。如仍异常:
- Windows:确认
C:/Windows/Fonts/msyh.ttc存在 - macOS:系统自带苹方,无需额外配置
- Linux:
sudo apt install fonts-wqy-zenhei
Q: 服务器/Docker 环境无法运行?
A: 设置无头模式:
HEADLESS=1 python main.py video input.mp4 -o output.mp4 --no-showDocker 需额外安装 libgl1-mesa-glx libglib2.0-0
Q: 识别不准确,如何调优?
A:
- 保证光照充足、背景简洁,手掌正对摄像头
- 按
D键开启调试模式,观察特征值和打分细节 - 调整
config.py中的DETECT_CONF(降低 = 更容易检出) - 手势角度阈值在
hand_gesture.py的_FINGER_STRAIGHT_MIN中调整
Q: 如何提升 FPS?
A:
- 降低分辨率:
python main.py realtime --width 640 --height 480 - 视频模式加大跳帧:
--skip 3或--skip 4 - 关闭关键点显示:按
F键可实时切换 - 使用 GPU 推理(PyTorch CUDA 版本)
- 🐛 修复手势关节角度判断逻辑颠倒(伸直 180° 误判为弯曲)
- 🐛 修复表情特征未归一化(脸远近导致阈值失效)
- ✨ 新增 PIL 中文渲染,解决画面中文乱码
- ✨ 新增剪刀手 / 双指指向区分(指尖间距阈值)
- ✨ 新增 9 种手势支持(倒赞、捏合、打电话、蜘蛛侠、我爱你、比心、枪、双指指向、祈祷)
- 🎉 初始版本:10 种手势 + 7 种表情
- 📷 支持图片 / 视频 / 实时三种模式
- 🖥️ 无头模式支持
MIT © anhaoking
如果这个项目对你有帮助,请给个 ⭐ Star 支持一下!