add readme
This commit is contained in:
227
README.md
Normal file
227
README.md
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
# FaceRecognition — 实时网络视频流人脸检测
|
||||||
|
|
||||||
|
基于 CNN 的人脸检测应用:从 HTTP 网络视频流实时抓帧,调用 `libfacedetection` 进行人脸检测与关键点定位,并在窗口中绘制结果。
|
||||||
|
|
||||||
|
- 作者:Liu zhenyu
|
||||||
|
- 语言标准:C++11
|
||||||
|
- 构建系统:CMake ≥ 3.10
|
||||||
|
- 人脸检测核心:[libfacedetection](https://github.com/ShiqiYu/libfacedetection)(BSD 3-Clause,原作者 Shiqi Yu)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
FaceRecognition/
|
||||||
|
├── CMakeLists.txt # 顶层 CMake:SIMD 选项 + 依赖查找 + 子模块
|
||||||
|
├── app/ # 主可执行程序
|
||||||
|
│ ├── CMakeLists.txt
|
||||||
|
│ └── src/main.cpp # 编排:收帧 -> 检测 -> 显示
|
||||||
|
├── libfacedetection/ # 人脸检测动态库 (SHARED)
|
||||||
|
│ ├── CMakeLists.txt
|
||||||
|
│ ├── include/
|
||||||
|
│ │ ├── facedetectcnn.h
|
||||||
|
│ │ └── facedetection_export.h
|
||||||
|
│ └── src/ # CNN 模型与推理实现
|
||||||
|
├── network_camera_receiver/ # 网络抓帧静态库 (STATIC)
|
||||||
|
│ ├── CMakeLists.txt
|
||||||
|
│ ├── include/network_camera_receiver.h
|
||||||
|
│ └── src/network_camera_receiver.cpp
|
||||||
|
└── resources/ # 测试资源
|
||||||
|
```
|
||||||
|
|
||||||
|
### 三个子模块
|
||||||
|
|
||||||
|
| 模块 | 类型 | 职责 |
|
||||||
|
|------|------|------|
|
||||||
|
| `libfacedetection` | SHARED 动态库 | CNN 人脸检测(含 5 个关键点),仅导出 `facedetect_cnn` |
|
||||||
|
| `network_camera_receiver` | STATIC 静态库 | 后台线程从 HTTP 视频流持续抓取最新帧,不包含检测逻辑 |
|
||||||
|
| `app` | 可执行程序 `face_detection_app` | 编排:拉帧 → 检测 → 绘制 → 显示 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
|
||||||
|
- **实时检测**:后台线程抓帧,主线程检测显示,互不阻塞。
|
||||||
|
- **CNN 人脸检测**:输出人脸框 + 置信度 + 5 个面部关键点(双眼、鼻尖、嘴角)。
|
||||||
|
- **SIMD 加速**:支持 AVX2 / AVX512 / NEON,CMake 选项一键开关并自动配置编译标志。
|
||||||
|
- **OpenMP 加速**:卷积运算可选多线程并行。
|
||||||
|
- **置信度过滤**:仅显示置信度 > 60 的人脸,降低误检。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 依赖
|
||||||
|
|
||||||
|
- **OpenCV**(必需,视频采集与图像显示)
|
||||||
|
- **CMake ≥ 3.10**
|
||||||
|
- **C++11** 兼容编译器(GCC / Clang / MSVC)
|
||||||
|
- **OpenMP**(可选,加速检测)
|
||||||
|
- **Threads**(必需,后台抓帧线程)
|
||||||
|
|
||||||
|
Ubuntu / Debian 安装示例:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt-get install build-essential cmake libopencv-dev
|
||||||
|
# 可选 OpenMP 通常随 gcc 自带
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 构建
|
||||||
|
|
||||||
|
### 1. 默认构建(启用 AVX2)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd FaceRecognition
|
||||||
|
cmake -S . -B build -DENABLE_AVX2=ON
|
||||||
|
cmake --build build -j
|
||||||
|
```
|
||||||
|
|
||||||
|
生成的可执行文件:`build/app/face_detection_app`
|
||||||
|
|
||||||
|
### 2. SIMD 加速选项
|
||||||
|
|
||||||
|
`ENABLE_AVX2` / `ENABLE_AVX512` / `ENABLE_NEON` 三者**互斥**,最多开启一个。
|
||||||
|
|
||||||
|
| 选项 | 适用平台 | 默认 |
|
||||||
|
|------|----------|------|
|
||||||
|
| `ENABLE_AVX2` | X86/X64 CPU | ON |
|
||||||
|
| `ENABLE_AVX512` | 较新 X64 CPU | OFF |
|
||||||
|
| `ENABLE_NEON` | ARM CPU | OFF |
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# AVX512(切换前先把默认的 AVX2 关掉)
|
||||||
|
cmake -S . -B build -DENABLE_AVX2=OFF -DENABLE_AVX512=ON
|
||||||
|
|
||||||
|
# ARM NEON
|
||||||
|
cmake -S . -B build -DENABLE_AVX2=OFF -DENABLE_NEON=ON
|
||||||
|
```
|
||||||
|
|
||||||
|
> ⚠️ 开启 CPU 不支持的指令集(如在不支持 AVX512 的机器上开 `ENABLE_AVX512`)能编译通过,但运行时会 `SIGILL` 崩溃。开启前先查询:
|
||||||
|
> ```bash
|
||||||
|
> grep -oE 'avx512[a-z]*|avx2|fma' /proc/cpuinfo | sort -u
|
||||||
|
> ```
|
||||||
|
|
||||||
|
### 3. 运行时依赖
|
||||||
|
|
||||||
|
`libfacedetection` 是动态库,运行时需能找到 `libfacedetection.so`。若未安装到系统路径,可:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export LD_LIBRARY_PATH=/home/hongshaorou/lzy_demo/FaceRecognition/build/libfacedetection:$LD_LIBRARY_PATH
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 使用方法
|
||||||
|
|
||||||
|
### 1. 准备视频流
|
||||||
|
|
||||||
|
程序默认连接 `http://127.0.0.1:5000/video`(HTTP MJPEG 流)。可使用任意能产出该接口的工具,例如 Python Flask + 摄像头:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# send.py —— 简易 MJPEG 推流端(示例)
|
||||||
|
from flask import Flask, Response
|
||||||
|
import cv2
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
cap = cv2.VideoCapture(0) # 本机摄像头
|
||||||
|
|
||||||
|
def gen():
|
||||||
|
while True:
|
||||||
|
ok, frame = cap.read()
|
||||||
|
if not ok: continue
|
||||||
|
_, jpg = cv2.imencode('.jpg', frame)
|
||||||
|
yield (b'--frame\r\n'
|
||||||
|
b'Content-Type: image/jpeg\r\n\r\n' + jpg.tobytes() + b'\r\n')
|
||||||
|
|
||||||
|
@app.route('/video')
|
||||||
|
def video():
|
||||||
|
return Response(gen(), mimetype='multipart/x-mixed-replace; boundary=frame')
|
||||||
|
|
||||||
|
app.run(host='0.0.0.0', port=5000)
|
||||||
|
```
|
||||||
|
|
||||||
|
推流端也可换成树莓派、IP 摄像头等任何能提供 `/video` MJPEG 接口的设备。
|
||||||
|
|
||||||
|
### 2. 修改目标 IP(可选)
|
||||||
|
|
||||||
|
如需连接远端主机,编辑 `app/src/main.cpp`:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
std::string host_ip = "127.0.0.1"; // 改为推流主机 IP
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 运行
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./build/app/face_detection_app
|
||||||
|
```
|
||||||
|
|
||||||
|
窗口将实时显示检测到的人脸框、置信度及 5 个关键点。按 **ESC** 退出。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 检测结果解析
|
||||||
|
|
||||||
|
`facedetect_cnn` 返回的缓冲区布局(关键,写错会导致"只能检测一张脸"):
|
||||||
|
|
||||||
|
- `buffer[0..3]`:人脸数量(`int`)
|
||||||
|
- `buffer[4..]` 起:每张人脸占 `FACEDETECTION_RESULT_STRIDE_SHORTS = 16` 个 `short`(32 字节)
|
||||||
|
|
||||||
|
每个人脸 16 个 short 字段:
|
||||||
|
|
||||||
|
| 索引 | 含义 |
|
||||||
|
|------|------|
|
||||||
|
| `p[0]` | 置信度(score × 100) |
|
||||||
|
| `p[1..4]` | 人脸框 x, y, w, h |
|
||||||
|
| `p[5..14]` | 5 个关键点(x, y 交替) |
|
||||||
|
| `p[15]` | 对齐填充 |
|
||||||
|
|
||||||
|
正确遍历写法(见 `app/src/main.cpp`):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
short* p = ((short*)(pResults + 1)) + FACEDETECTION_RESULT_STRIDE_SHORTS * i;
|
||||||
|
```
|
||||||
|
|
||||||
|
> ⚠️ 经典版 libfacedetection(uint8 模型)每个结果占 142 字节,网上示例常写 `+ 142 * i`;在本重构版(float 模型)上会导致第 1 张起全部错位读到垃圾数据。务必使用 `FACEDETECTION_RESULT_STRIDE_SHORTS`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 项目架构流程
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────┐ 最新帧 ┌──────────────────────┐
|
||||||
|
│ network_camera_ │ ─────────> │ app (main.cpp) │
|
||||||
|
│ receiver (STATIC) │ getLatest │ ┌──────────────────┐ │
|
||||||
|
│ 后台线程抓帧 │ Frame() │ │ facedetect_cnn() │ │
|
||||||
|
└─────────────────────┘ │ │ (libfacedetect)│ │
|
||||||
|
▲ │ └────────┬─────────┘ │
|
||||||
|
│ HTTP MJPEG │ v │
|
||||||
|
│ /video │ 绘制框/关键点/置信度 │
|
||||||
|
┌───────┴──────────────┐ │ cv::imshow │
|
||||||
|
│ 推流端 (Flask/摄像头) │ └───────────────────────┘
|
||||||
|
└──────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
**Q: 编译报 `target specific option mismatch`?**
|
||||||
|
A: 开了 `_ENABLE_AVX*` 宏但没加对应 `-m` 编译标志。本项目已通过 CMake 选项自动同步两者,使用 `-DENABLE_AVX2=ON` 即可,不要手动改头文件宏。
|
||||||
|
|
||||||
|
**Q: 运行时 `SIGILL` 崩溃?**
|
||||||
|
A: 开了 CPU 不支持的指令集(如 AVX512)。用 `grep avx /proc/cpuinfo` 确认后重新 cmake。
|
||||||
|
|
||||||
|
**Q: 只能检测到一张脸?**
|
||||||
|
A: 结果 buffer stride 写错,必须用 `FACEDETECTION_RESULT_STRIDE_SHORTS`,不要用旧版的 142。
|
||||||
|
|
||||||
|
**Q: 连接视频流失败?**
|
||||||
|
A: 确认推流端已启动并监听对应端口;检查 `host_ip` 与端口是否正确;确认 `/video` 路由返回 `multipart/x-mixed-replace` 流。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 许可证
|
||||||
|
|
||||||
|
- 本项目业务代码(`app/`、`network_camera_receiver/`)版权归 Liu zhenyu 所有。
|
||||||
|
- `libfacedetection` 遵循 BSD 3-Clause 许可证,版权归原作者 Shiqi Yu 所有,详见 `libfacedetection/include/facedetectcnn.h` 头部。
|
||||||
Reference in New Issue
Block a user