505 lines
16 KiB
Markdown
505 lines
16 KiB
Markdown
# 康达机器人人脸识别系统
|
||
|
||
## 项目简介
|
||
|
||
这是一个基于 CompreFace 的智能人脸识别系统,为康达新材的接待机器人提供实时人脸检测、识别和访客管理功能。系统通过 WebSocket 与机器人主控程序通信,支持视频展示、二维码引导和流媒体推送等多种功能。
|
||
|
||
## 核心功能
|
||
|
||
### 1. 人脸识别
|
||
- **实时检测**:基于 CompreFace API 进行高精度人脸检测
|
||
- **正脸检测**:使用姿态检测技术,获取人脸的yaw(偏航角)、pitch(俯仰角)、roll(翻滚角)数据,只识别正面人脸,有效过滤侧脸、抬头或低头
|
||
- **角度过滤**:通过REST API直接调用CompreFace的pose插件,设置±20°的角度阈值,确保只检测正脸
|
||
- **身份识别**:自动识别员工和访客,支持相似度阈值配置
|
||
- **防重复识别**:智能冷却机制,避免短时间内重复识别同一人
|
||
- **质量评估**:使用 Laplacian 方差评估图像清晰度
|
||
|
||
### 2. 访客引导
|
||
- **二维码展示**:陌生访客自动弹出访客预约流程二维码
|
||
- **SOTA 设计**:采用现代化 UI 设计,左侧二维码 + 右侧步骤说明
|
||
- **自动关闭**:可配置显示时长(默认 10 秒)
|
||
|
||
### 3. 展厅讲解
|
||
- **视频播放**:当机器人角色为"展厅讲解员"时自动播放展厅视频
|
||
- **状态叠加**:在视频上实时显示机器人状态(思考、倾听、讲话)
|
||
- **循环播放**:支持视频循环播放配置
|
||
|
||
### 4. WebSocket 通信
|
||
- **双向通信**:与机器人主控程序实时交互
|
||
- **状态同步**:获取机器人说话、思考、倾听状态
|
||
- **自动重连**:连接断开时自动重连,保证系统稳定性
|
||
|
||
### 5. 流媒体推送
|
||
- **RTMP/RTSP 推流**:支持将识别画面推送到流媒体服务器
|
||
- **异步推流**:独立线程处理推流,不影响主流程性能
|
||
- **自动重试**:推流失败自动重试,带冷却机制
|
||
|
||
### 6. 摄像头管理
|
||
- **自动重连**:摄像头断开时自动尝试重新连接
|
||
- **故障恢复**:连续失败达到阈值时触发完整重新初始化
|
||
|
||
## 技术架构
|
||
|
||
### 技术栈
|
||
- **Python 3.x**
|
||
- **OpenCV**:图像处理和摄像头控制
|
||
- **CompreFace**:人脸检测和识别服务
|
||
- **WebSocket**:实时通信
|
||
- **Pillow (PIL)**:中文字体渲染和图像合成
|
||
- **FFmpeg**:流媒体推送
|
||
- **asyncio**:异步事件循环
|
||
|
||
### 系统架构
|
||
```
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ 人脸识别系统主程序 │
|
||
│ (face_rec.py) │
|
||
├─────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||
│ │ 摄像头模块 │ │ 识别模块 │ │ 显示模块 │ │
|
||
│ │ │ │ │ │ │ │
|
||
│ │ - 视频采集 │ │ - 人脸检测 │ │ - 信息叠加 │ │
|
||
│ │ - 自动重连 │ │ - 身份识别 │ │ - 二维码显示 │ │
|
||
│ │ - 质量评估 │ │ - 角色判定 │ │ - 视频播放 │ │
|
||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||
│ │
|
||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||
│ │ WebSocket │ │ 推流模块 │ │ 日志模块 │ │
|
||
│ │ │ │ │ │ │ │
|
||
│ │ - 状态同步 │ │ - FFmpeg推流 │ │ - 日志记录 │ │
|
||
│ │ - 消息通信 │ │ - 异步队列 │ │ - 日志轮转 │ │
|
||
│ │ - 自动重连 │ │ - 错误恢复 │ │ │ │
|
||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||
└─────────────────────────────────────────────────────────┘
|
||
│ │ │
|
||
▼ ▼ ▼
|
||
┌─────────────┐ ┌──────────┐ ┌──────────┐
|
||
│ CompreFace │ │ 机器人主控│ │ 流媒体 │
|
||
│ 服务 │ │ 程序 │ │ 服务器 │
|
||
└─────────────┘ └──────────┘ └──────────┘
|
||
```
|
||
|
||
## 安装部署
|
||
|
||
### 环境要求
|
||
- Python 3.7+
|
||
- Linux 系统(推荐 Ubuntu 20.04+)
|
||
- 摄像头设备
|
||
- X11 显示服务器
|
||
|
||
### 依赖安装
|
||
```bash
|
||
pip install opencv-python
|
||
pip install websockets
|
||
pip install pyyaml
|
||
pip install numpy
|
||
pip install Pillow
|
||
pip install compreface-sdk
|
||
pip install screeninfo
|
||
pip install psutil # 可选,用于进程管理
|
||
```
|
||
|
||
### FFmpeg 安装(用于推流)
|
||
```bash
|
||
sudo apt-get update
|
||
sudo apt-get install ffmpeg
|
||
```
|
||
|
||
### 配置文件
|
||
|
||
编辑 `config.yaml` 配置系统参数:
|
||
|
||
```yaml
|
||
# CompreFace API 配置
|
||
compreface:
|
||
host: "http://10.0.0.202"
|
||
port: "8000"
|
||
recognition_api_key: "your_recognition_key"
|
||
detection_api_key: "your_detection_key"
|
||
|
||
# WebSocket 配置
|
||
websocket:
|
||
url: "ws://127.0.0.1:3344"
|
||
status_interval: 0.2
|
||
|
||
# 摄像头配置
|
||
camera:
|
||
device_id: 0 # 或使用设备路径
|
||
width: 1280
|
||
height: 720
|
||
fps: 30
|
||
|
||
# 人脸检测配置
|
||
face_detection:
|
||
frame_interval: 10 # 检测帧间隔(每N帧检测一次)
|
||
quality_threshold: 10 # 图像质量阈值(Laplacian方差)
|
||
min_face_size: 80 # 最小人脸尺寸(像素)
|
||
face_present_duration: 2.0 # 持续出现时长(秒)才触发识别
|
||
max_yaw: 20.0 # 最大允许的偏航角(度),超过此角度视为侧脸
|
||
max_pitch: 20.0 # 最大允许的俯仰角(度),超过此角度视为抬头或低头
|
||
|
||
# 人脸识别配置
|
||
face_recognition:
|
||
recognition_cooldown: 20.0 # 识别冷却时间(秒)
|
||
|
||
role_mapping:
|
||
stranger_threshold: 0.98 # 陌生人阈值
|
||
|
||
# 二维码配置
|
||
qrcode:
|
||
image_path: "preview_qrcode_sota.jpg"
|
||
display_duration: 30
|
||
|
||
# 视频配置
|
||
video:
|
||
path: "exhibition.mp4"
|
||
loop: true
|
||
|
||
# 推流配置(可选)
|
||
stream:
|
||
enabled: false # 是否启用推流
|
||
rtmp_url: "rtsp://127.0.0.1/live/video"
|
||
```
|
||
|
||
### 运行方式
|
||
|
||
#### 方式一:直接运行
|
||
```bash
|
||
python face_rec.py
|
||
```
|
||
|
||
#### 方式二:使用启动脚本
|
||
```bash
|
||
chmod +x start.sh
|
||
./start.sh
|
||
```
|
||
|
||
#### 方式三:系统服务(推荐生产环境)
|
||
```bash
|
||
# 复制服务文件
|
||
sudo cp face_rec.service /etc/systemd/system/
|
||
|
||
# 重载服务
|
||
sudo systemctl daemon-reload
|
||
|
||
# 启动服务
|
||
sudo systemctl start face_rec
|
||
|
||
# 设置开机自启
|
||
sudo systemctl enable face_rec
|
||
|
||
# 查看服务状态
|
||
sudo systemctl status face_rec
|
||
|
||
# 查看日志
|
||
sudo journalctl -u face_rec -f
|
||
```
|
||
|
||
## 核心模块说明
|
||
|
||
### 1. FaceRecognitionSystem 类
|
||
|
||
系统主类,包含以下核心方法:
|
||
|
||
#### 初始化相关
|
||
- `__init__()`: 初始化系统,加载配置
|
||
- `_init_camera()`: 初始化摄像头
|
||
- `_init_compreface()`: 初始化 CompreFace 服务
|
||
- `_init_ffmpeg_stream()`: 初始化推流
|
||
|
||
#### 人脸识别
|
||
- `detect_faces()`: 检测人脸
|
||
- `recognize_face()`: 识别人脸
|
||
- `assess_frame_quality()`: 评估图像质量
|
||
- `determine_role()`: 判定人员角色
|
||
- `should_recognize()`: 判断是否需要识别
|
||
|
||
#### 显示相关
|
||
- `_show_qrcode()`: 显示二维码
|
||
- `_show_video()`: 显示展厅视频
|
||
- `draw_info_on_frame()`: 在画面上绘制信息
|
||
- `_draw_robot_status_on_video()`: 在视频上绘制机器人状态
|
||
- `_build_qrcode_instruction_canvas()`: 构建二维码指引画布
|
||
|
||
#### WebSocket 通信
|
||
- `connect_websocket()`: 连接 WebSocket
|
||
- `send_websocket_message()`: 发送消息
|
||
- `handle_websocket_messages()`: 处理接收消息
|
||
- `query_robot_status()`: 查询机器人状态
|
||
|
||
#### 推流相关
|
||
- `_start_stream_thread()`: 启动推流线程
|
||
- `_stream_worker()`: 推流工作线程
|
||
- `_push_frame_to_stream()`: 推送帧到流媒体
|
||
- `_force_cleanup_ffmpeg()`: 清理 FFmpeg 资源
|
||
|
||
#### 主流程
|
||
- `process_video_stream()`: 处理视频流主循环
|
||
- `run()`: 系统运行入口
|
||
|
||
### 2. 工作流程
|
||
|
||
```
|
||
启动系统
|
||
↓
|
||
初始化配置、日志、CompreFace、摄像头
|
||
↓
|
||
连接 WebSocket(后台任务)
|
||
↓
|
||
启动推流(如果启用)
|
||
↓
|
||
┌─────────────────────────────────────┐
|
||
│ 主循环(异步) │
|
||
│ │
|
||
│ 1. 读取摄像头帧 │
|
||
│ 2. 检查机器人角色,控制视频播放 │
|
||
│ 3. 更新视频帧(如果正在播放) │
|
||
│ 4. 检查二维码超时 │
|
||
│ 5. 每 N 帧进行人脸检测 │
|
||
│ 6. 检测到人脸 → 持续出现 2 秒 │
|
||
│ 7. 触发人脸识别 │
|
||
│ 8. 判定角色(员工/访客/陌生人) │
|
||
│ 9. 发送识别结果到机器人 │
|
||
│ 10. 陌生人 → 显示二维码 │
|
||
│ 11. 绘制识别信息到画面 │
|
||
│ 12. 推送画面到流媒体(如果启用) │
|
||
│ 13. 显示画面 │
|
||
│ │
|
||
│ 按 'q' 退出 │
|
||
└─────────────────────────────────────┘
|
||
↓
|
||
清理资源(摄像头、推流、窗口)
|
||
↓
|
||
退出系统
|
||
```
|
||
|
||
## 文件说明
|
||
|
||
```
|
||
kanda-robot-facial-recognition/
|
||
├── face_rec.py # 主程序
|
||
├── config.yaml # 配置文件
|
||
├── start.sh # 启动脚本
|
||
├── face_rec.service # systemd 服务文件
|
||
├── preview_qrcode_sota.png # 二维码引导图片(新版)
|
||
├── qrcode.jpg # 二维码图片(旧版)
|
||
├── exhibition.mp4 # 展厅讲解视频
|
||
├── preview_qrcode.py # 二维码预览生成工具
|
||
├── face_recognition.log # 运行日志
|
||
├── 001保存摄像头流.py # 工具:保存摄像头视频流
|
||
├── 002查看摄像头id.py # 工具:查看摄像头设备 ID
|
||
├── 003查看GUI后端.py # 工具:查看 GUI 后端
|
||
└── README.md # 本文档
|
||
```
|
||
|
||
## 配置说明
|
||
|
||
### 人脸识别参数
|
||
|
||
- `frame_interval`: 检测帧间隔,建议 5-15
|
||
- `quality_threshold`: 图像质量阈值,建议 10-50
|
||
- `min_face_size`: 最小人脸尺寸(像素),建议 60-100
|
||
- `face_present_duration`: 持续出现时长(秒),建议 1.5-3.0
|
||
- `max_yaw`: 最大允许的偏航角(度),超过此角度视为侧脸,推荐 20°
|
||
- `max_pitch`: 最大允许的俯仰角(度),超过此角度视为抬头或低头,推荐 20°
|
||
- `stranger_threshold`: 陌生人阈值,建议 0.95-0.99
|
||
- `recognition_cooldown`: 识别冷却时间(秒),建议 15-30
|
||
|
||
### 摄像头设备 ID
|
||
|
||
**方式一:使用数字 ID**
|
||
```yaml
|
||
camera:
|
||
device_id: 0 # 通常是第一个摄像头
|
||
```
|
||
|
||
**方式二:使用设备路径(推荐,更稳定)**
|
||
```bash
|
||
# 查看可用摄像头
|
||
ls /dev/v4l/by-id/
|
||
|
||
# 使用设备路径
|
||
camera:
|
||
device_id: "/dev/v4l/by-id/usb-xxx-video-index0"
|
||
```
|
||
|
||
### WebSocket 消息格式
|
||
|
||
**发送识别结果**
|
||
```json
|
||
{
|
||
"type": "face_recognition",
|
||
"message": {
|
||
"person_name": "张三",
|
||
"person_role": "员工",
|
||
"similarity": 0.99,
|
||
"timestamp": "2025-12-18 10:30:00"
|
||
}
|
||
}
|
||
```
|
||
|
||
**接收机器人状态**
|
||
```json
|
||
{
|
||
"type": "status",
|
||
"message": {
|
||
"is_speaking": false,
|
||
"is_thinking": true,
|
||
"listening": false,
|
||
"role_name": "展厅讲解员"
|
||
}
|
||
}
|
||
```
|
||
|
||
## 常见问题
|
||
|
||
### Q1: 摄像头无法打开
|
||
**A:**
|
||
1. 检查摄像头是否被其他程序占用
|
||
2. 确认设备 ID 是否正确:`ls /dev/video*`
|
||
3. 检查用户权限:`sudo usermod -a -G video $USER`
|
||
4. 重启系统
|
||
|
||
### Q2: 无法显示中文
|
||
**A:**
|
||
1. 确认系统已安装中文字体
|
||
2. 修改 `config.yaml` 中的 `font_path` 配置
|
||
3. 常见字体路径:
|
||
- Ubuntu: `/usr/share/fonts/truetype/wqy/wqy-microhei.ttc`
|
||
- CentOS: `/usr/share/fonts/wqy-microhei/wqy-microhei.ttc`
|
||
|
||
### Q3: WebSocket 连接失败
|
||
**A:**
|
||
1. 确认机器人主控程序已启动
|
||
2. 检查 WebSocket URL 配置
|
||
3. 查看防火墙设置
|
||
4. 系统会自动重连,检查日志确认状态
|
||
|
||
### Q4: 推流失败
|
||
**A:**
|
||
1. 确认 FFmpeg 已安装:`ffmpeg -version`
|
||
2. 检查流媒体服务器是否运行
|
||
3. 验证 RTMP/RTSP URL 格式
|
||
4. 查看日志中的 FFmpeg 错误信息
|
||
|
||
### Q5: 识别准确率低
|
||
**A:**
|
||
1. 提高 `quality_threshold` 确保图像清晰
|
||
2. 调整 `stranger_threshold` 阈值
|
||
3. 确保光线充足
|
||
4. 在 CompreFace 中添加更多训练照片
|
||
|
||
### Q6: 侧脸也被识别了
|
||
**A:**
|
||
1. 调整 `max_yaw` 和 `max_pitch` 参数,降低角度阈值
|
||
2. 默认设置为 ±30 度,可改为 ±20 度提高严格程度
|
||
3. 检查 CompreFace 服务是否支持 pose 插件
|
||
4. 查看日志中的角度检查信息进行调试
|
||
|
||
### Q7: 系统服务无法启动
|
||
**A:**
|
||
1. 检查服务文件路径配置
|
||
2. 确认 Python 环境和依赖
|
||
3. 查看日志:`sudo journalctl -u face_rec -n 50`
|
||
4. 检查 DISPLAY 和 XAUTHORITY 环境变量
|
||
|
||
## 性能优化建议
|
||
|
||
1. **降低检测频率**:增大 `frame_interval` 值
|
||
2. **降低分辨率**:适当降低摄像头分辨率
|
||
3. **关闭推流**:生产环境不需要时关闭推流功能
|
||
4. **调整日志级别**:生产环境使用 INFO 或 WARNING
|
||
5. **使用 GPU**:如有 GPU,配置 OpenCV 使用 CUDA 加速
|
||
|
||
## 维护和监控
|
||
|
||
### 日志查看
|
||
```bash
|
||
# 查看应用日志
|
||
tail -f face_recognition.log
|
||
|
||
# 查看系统服务日志
|
||
sudo journalctl -u face_rec -f
|
||
|
||
# 查看启动脚本日志
|
||
tail -f /home/unitree/robot_face_rec/logs/face_rec/*.log
|
||
```
|
||
|
||
### 性能监控
|
||
```bash
|
||
# 查看 CPU 和内存占用
|
||
top -p $(pgrep -f face_rec.py)
|
||
|
||
# 查看 GPU 使用(如果使用 NVIDIA GPU)
|
||
nvidia-smi
|
||
|
||
# 查看进程状态
|
||
ps aux | grep face_rec
|
||
```
|
||
|
||
### 重启服务
|
||
```bash
|
||
# 重启服务
|
||
sudo systemctl restart face_rec
|
||
|
||
# 强制停止
|
||
sudo systemctl kill face_rec
|
||
|
||
# 完全重启(包括清理资源)
|
||
sudo systemctl stop face_rec
|
||
sleep 2
|
||
sudo systemctl start face_rec
|
||
```
|
||
|
||
## 开发和调试
|
||
|
||
### 调试模式
|
||
修改 `config.yaml`:
|
||
```yaml
|
||
logging:
|
||
level: "DEBUG"
|
||
```
|
||
|
||
### 测试工具
|
||
```bash
|
||
# 测试摄像头
|
||
python 001保存摄像头流.py
|
||
|
||
# 查看摄像头 ID
|
||
python 002查看摄像头id.py
|
||
|
||
# 预览二维码设计
|
||
python preview_qrcode.py
|
||
```
|
||
|
||
## 更新日志
|
||
|
||
### v1.1.0 (2025-12-18)
|
||
- ✅ 新增正脸检测功能,基于CompreFace姿态检测技术过滤侧脸
|
||
- ✅ 添加人脸角度阈值配置(max_yaw: 20°, max_pitch: 20°)
|
||
- ✅ 使用REST API直接调用CompreFace,绕过SDK限制获取pose数据
|
||
- ✅ 优化人脸识别准确性,适用于门禁场景,只识别正面人脸
|
||
- ✅ 二维码显示时间延长至30秒,方便访客操作
|
||
- ✅ 二维码指引界面改为全屏显示,提升用户体验
|
||
- ✅ 修复PIL兼容性问题,解决圆角矩形渲染错误
|
||
|
||
### v1.0.0 (2025-12-03)
|
||
- ✅ 完整的人脸检测和识别功能
|
||
- ✅ WebSocket 双向通信
|
||
- ✅ 二维码 SOTA 设计展示
|
||
- ✅ 展厅讲解视频播放
|
||
- ✅ 机器人状态叠加显示
|
||
- ✅ FFmpeg 流媒体推送
|
||
- ✅ 异步推流队列优化
|
||
- ✅ 摄像头自动重连机制
|
||
- ✅ 完善的日志系统
|
||
|
||
## 技术支持
|
||
|
||
如有问题,请联系开发团队或查看项目文档。
|
||
|
||
---
|
||
|
||
**泰奥理 © 2025**
|