Files
FaceRecognition/README.md

8.0 KiB
Raw Permalink Blame History

FaceRecognition — 实时网络视频流人脸检测

基于 CNN 的人脸检测与特征提取应用:从 HTTP 网络视频流实时抓帧经运动粗筛后检测人脸与关键点完成对齐、SFace 特征提取和 IoU 跟踪。

  • 作者Liu zhenyu
  • 语言标准C++11
  • 构建系统CMake ≥ 3.10
  • 人脸检测核心:libfacedetectionBSD 3-Clause原作者 Shiqi Yu

目录结构

FaceRecognition/
├── CMakeLists.txt                  # 顶层 CMakeSIMD 选项 + 依赖查找 + 子模块
├── 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
├── face_pipeline/                  # 运动检测、跟踪、对齐、特征与消息接口
├── models/                         # 固定版本 SFace ONNX、许可证与校验信息
├── tests/                          # CTest 离线单元/模型测试
└── resources/                      # 测试资源

主要模块

模块 类型 职责
libfacedetection SHARED 动态库 CNN 人脸检测(含 5 个关键点),仅导出 facedetect_cnn
network_camera_receiver STATIC 静态库 后台线程从 HTTP 视频流持续抓取最新帧,不包含检测逻辑
face_pipeline STATIC 静态库 运动粗筛、检测、IoU 跟踪、对齐、SFace 特征和结果接口
app 可执行程序 face_detection_app 拉帧、提交任务并显示最新跟踪结果

功能特性

  • 低延迟流水线:采集与检测分线程,容量为 1 的 latest-wins mailbox 不积压旧帧。
  • 运动粗筛:有运动时触发检测;有人脸时每秒保活,无 track 时每 5 秒兜底扫描。
  • CNN 人脸检测:输出人脸框 + 置信度 + 5 个面部关键点(双眼、鼻尖、嘴角)。
  • 特征提取:五点相似变换对齐后,由 OpenCV SFace 输出 L2 归一化的 128 维向量。
  • 简单跟踪IoU 分配 track_id,每个 track 仅首次通过 ResultSink 发布。
  • SIMD 加速:支持 AVX2 / AVX512 / NEONCMake 选项一键开关并自动配置编译标志。
  • OpenMP 加速:卷积运算可选多线程并行。
  • 置信度过滤:仅显示置信度 > 60 的人脸,降低误检。

依赖

  • OpenCV(必需,视频采集与图像显示)
  • CMake ≥ 3.10
  • C++11 兼容编译器GCC / Clang / MSVC
  • OpenMP(可选,加速检测)
  • Threads(必需,后台抓帧线程)

Ubuntu / Debian 安装示例:

sudo apt-get install build-essential cmake libopencv-dev
# 可选 OpenMP 通常随 gcc 自带

构建

1. 默认构建(启用 AVX2

cd FaceRecognition
cmake -S . -B build -DENABLE_AVX2=ON
cmake --build build -j
ctest --test-dir build --output-on-failure

生成的可执行文件:build/app/face_detection_app。配置阶段会校验 models/face_recognition_sface_2021dec.onnx 的 SHA-256。

2. SIMD 加速选项

ENABLE_AVX2 / ENABLE_AVX512 / ENABLE_NEON 三者互斥,最多开启一个。

选项 适用平台 默认
ENABLE_AVX2 X86/X64 CPU ON
ENABLE_AVX512 较新 X64 CPU OFF
ENABLE_NEON ARM CPU OFF
# 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 崩溃。开启前先查询:

grep -oE 'avx512[a-z]*|avx2|fma' /proc/cpuinfo | sort -u

3. 运行时依赖

libfacedetection 是动态库,运行时需能找到 libfacedetection.so。若未安装到系统路径,可:

export LD_LIBRARY_PATH=/home/hongshaorou/lzy_demo/FaceRecognition/build/libfacedetection:$LD_LIBRARY_PATH

使用方法

1. 准备视频流

程序默认连接 http://127.0.0.1:5000/videoHTTP MJPEG 流)。可使用任意能产出该接口的工具,例如 Python Flask + 摄像头:

# 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

std::string host_ip = "127.0.0.1";  // 改为推流主机 IP

3. 运行

./build/app/face_detection_app

也可把兼容的 SFace 模型路径作为第一个参数传入。窗口显示人脸框、关键点和 track_id,按 ESC 退出。新 track 首次提取成功时输出一行 face_feature 日志,只记录元数据和特征维度,不打印完整向量。


检测结果解析

facedetect_cnn 返回的缓冲区布局(关键,写错会导致"只能检测一张脸"

  • buffer[0..3]:人脸数量(int
  • buffer[4..] 起:每张人脸占 FACEDETECTION_RESULT_STRIDE_SHORTS = 16short32 字节)

每个人脸 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

short* p = ((short*)(pResults + 1)) + FACEDETECTION_RESULT_STRIDE_SHORTS * i;

⚠️ 经典版 libfacedetectionuint8 模型)每个结果占 142 字节,网上示例常写 + 142 * i在本重构版float 模型)上会导致第 1 张起全部错位读到垃圾数据。务必使用 FACEDETECTION_RESULT_STRIDE_SHORTS


项目架构流程

HTTP MJPEG → 抓帧线程 → 主线程运动粗筛 → latest-wins mailbox
                                      ↓
                         检测 worker人脸检测 → IoU 跟踪
                                      ↓(仅未发布 track
                              五点对齐 → SFace → ResultSink

常见问题

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 头部。