Skip to main content

视觉 · 人脸检测

1. 模块概述

  • 主要功能:基于 YOLOv5-Face 的人脸检测,输出图像中每张人脸的边界框与置信度。仅做检测定位,不做身份识别(识别见 4.2.10-人脸识别)。
  • 规格或特性:
    • 支持模型:YOLOv5n-face
    • 输入尺寸:[1, 3, 640, 640]
    • 量化类型:int8
    • 输出:人脸边界框 + 置信度
    • 推理后端:ONNX Runtime + SpaceMITExecutionProvider
    • 接口形态:C++(vision_service.h)、Python(spacemit_vision wheel:VisionServiceNative
  • 相关目录结构:
examples/yolov5-face/
├── config/yolov5-face.yaml # 配置文件
├── cpp/yolov5_face.cpp # C++ 示例
├── python/yolov5_face.py # Python 示例
└── scripts/ # 模型下载脚本
src/deploy/yolov5_face/ # 部署实现(C++ / Python)

2. 环境准备

前置条件

SDK 源码获取和基础编译环境配置统一参考 2.3-构建编译。完成 SDK 初始化后,回到本文继续执行"构建编译"。

后续命令默认在 spacemit_robot SDK 根目录执行。

构建编译

系统缺少依赖时先安装:

sudo apt install python3-spacemit-ort opencv-spacemit libeigen3-dev spacemit-onnxruntime libyaml-cpp-dev

在 SDK 根目录加载构建环境后编译视觉组件:

source build/envsetup.sh
cd components/model_zoo/vision
mm

SDK 集成构建会把 yolov5-face 等示例程序安装到 output/staging/bin,加载 build/envsetup.sh 后可直接运行。

运行 Python 示例前,需先安装 spacemit_vision wheel:

cd components/model_zoo/vision
python3 -m pip install -U pybind11 build setuptools wheel
cmake -S . -B build && cmake --build build -j
python3 -m pip install --force-reinstall src/python/dist/*.whl
python3 -c "from spacemit_vision import VisionServiceNative; print('ok')"

模型权重默认存放路径为 ~/.cache/models/vision/yolov5-face/。须先手动执行下载脚本;缺失时程序会直接报错(Model file not found)。

3. 示例使用(从 0 跑通)

3.1 YOLOv5-Face 人脸检测(Python)

前置:见 §2。

步骤 1:下载模型

cd components/model_zoo/vision
bash examples/yolov5-face/scripts/download_models.sh

预期现象:模型文件下载至 ~/.cache/models/vision/yolov5-face/yolov5n-face_cut.q.onnx

步骤 2:下载测试素材

bash scripts/download_assets.sh

步骤 3:运行推理

python3 examples/yolov5-face/python/yolov5_face.py --config examples/yolov5-face/config/yolov5-face.yaml

步骤 4(可选):使用摄像头实时人脸检测

先确认摄像头设备号(--camera-id/dev/videoN 中的 N,默认 0):

v4l2-ctl --list-devices
ls /dev/video*

--camera-id 0 无法打开,请根据输出选择实际采集节点(例如 /dev/video20 对应 --camera-id 20)。需要时可执行 v4l2-ctl -d /dev/videoN --all 查看节点详情。

python3 examples/yolov5-face/python/yolov5_face.py --config examples/yolov5-face/config/yolov5-face.yaml --use-camera --camera-id 0

3.2 YOLOv5-Face 人脸检测(C++)

前置:见 §2,C++ 编译完成。

步骤 1:下载模型(同 §3.1 步骤 1)

步骤 2:运行推理

yolov5-face examples/yolov5-face/config/yolov5-face.yaml

步骤 3(可选):使用摄像头实时人脸检测

设备号查询方式见 §3.1 步骤 4。

yolov5-face examples/yolov5-face/config/yolov5-face.yaml --use-camera --camera-id 0

3.3 运行结果示例

终端输出示例

Detected 3 face(s):
face 1 score=0.812 box=[166.036,75.602,196.464,110.691]
face 2 score=0.799 box=[44.460,117.240,65.123,145.286]
face 3 score=0.748 box=[262.426,125.130,287.910,162.370]
Result saved to: result_face.jpg

可视化结果

YOLOv5-Face 人脸检测结果示例

图中展示了检测到的人脸边界框。

4. 应用开发

本章面向应用开发者,说明如何在自己的 C++ 或 Python 应用中集成人脸检测组件。完整接口定义以 include/vision_service.hsrc/python/spacemit_vision/vision_service_native.py 为准;本节介绍常用公开接口和典型调用方式。

4.1 接口说明

人脸检测组件的核心入口是 VisionService(C++)和 VisionServiceNative(Python,spacemit_vision wheel)。应用侧通过这些接口加载 YOLOv5-Face 模型,并发起图像或视频流的人脸检测请求。

4.1.1 常用数据结构

类型说明
VisionServiceResponse推理响应。resultsvision::ResultListstd::vector<vision::Result>,variant),ok 表示是否成功,error_message 为错误信息。
vision::Detection人脸检测结果具体类型,含 bboxvision::BoundingBox,字段 x1/y1/x2/y2)、scorelabel。可用 vision::get_bbox(result)vision::get_score(result)vision::get_label(result) 读取共有字段。
VisionServiceInferParams推理参数,包含置信度阈值、IOU 阈值、top_k、关键点阈值、掩码阈值、最大检测数等(字段 <= 0 表示使用 config 默认值)。

4.1.2 服务初始化

C++ 接口

接口说明参数返回值
VisionService::Create从 YAML 配置文件创建人脸检测服务实例config_path:YAML 配置文件路径VisionService 智能指针
VisionService::LastCreateError获取最近一次创建失败的错误信息错误描述字符串

Python 接口

接口说明参数返回值
VisionServiceNative.create从 YAML 配置文件创建服务实例config_path:YAML 路径;model_path_override:可选覆盖模型路径VisionServiceNative 实例
VisionServiceNative.last_create_error获取最近一次创建失败的错误信息错误描述字符串

4.1.3 人脸检测

C++ 接口

接口说明参数返回值
Infer对单张图像进行人脸检测image_path:图像文件路径;response:输出响应;params:可选推理参数VisionServiceStatus(VISION_SERVICE_OK 为成功)
Infer对 cv::Mat 图像进行人脸检测image:OpenCV Mat 对象;response:输出响应;params:可选推理参数VisionServiceStatus(VISION_SERVICE_OK 为成功)
Draw在图像上绘制检测结果(人脸边界框、置信度),无状态image:输入图像;response:检测响应;out_image:输出图像VisionServiceStatus
LastError获取最近一次推理的错误信息错误描述字符串

Python 接口

接口说明参数返回值
infer_image对图像进行推理image_or_path:BGR numpy 数组或图像路径;conf/iou:可选阈值(<=0 用 yaml 默认)(VisionServiceStatus, results 列表)
draw绘制最近一次推理结果image:BGR numpy 数组(VisionServiceStatus, 绘制后图像)
supports_draw当前模型是否支持 C++ 侧绘制bool
last_error获取最近一次推理错误错误描述字符串

4.1.4 性能监控

C++ 接口

接口说明参数返回值
SetTimingOptions启用/禁用性能计时options:VisionServiceTimingOptions(enabled、print_to_stdout)void
GetLastTiming获取最近一次推理的各阶段耗时VisionServiceTiming 结构体(preprocess_ms、model_infer_ms、postprocess_ms、infer_ms 等)

4.2 典型调用流程

4.2.1 C++ 单图人脸检测

#include "vision_service.h"
#include <opencv2/opencv.hpp>
#include <iostream>
#include <iomanip>

int main() {
// 1. 创建服务
auto service = VisionService::Create("examples/yolov5-face/config/yolov5-face.yaml");
if (!service) {
std::cerr << "Failed to create service: "
<< VisionService::LastCreateError() << std::endl;
return -1;
}

// 2. 启用性能计时(可选)
VisionServiceTimingOptions timing_options;
timing_options.enabled = true;
service->SetTimingOptions(timing_options);

// 3. 执行推理(支持文件路径或 cv::Mat 重载)
cv::Mat image = cv::imread("test.jpg");
VisionServiceResponse response;
VisionServiceStatus ret = service->Infer(image, &response);
if (ret != VISION_SERVICE_OK) {
std::cerr << "Inference failed: " << service->LastError() << std::endl;
return -1;
}

// 4. 处理结果(人脸检测结果类型为 vision::Detection)
std::cout << "Detected " << response.results.size() << " faces:" << std::endl;
for (const auto& r : response.results) {
const vision::BoundingBox box = vision::get_bbox(r);
std::cout << " Face - Score: " << std::fixed << std::setprecision(3)
<< vision::get_score(r)
<< ", Box: [" << box.x1 << "," << box.y1 << ","
<< box.x2 << "," << box.y2 << "]" << std::endl;
}

// 5. 绘制结果(无状态,需显式传入 response)
cv::Mat output;
service->Draw(image, response, &output);
cv::imwrite("result.jpg", output);

// 6. 查看性能指标(可选)
auto timing = service->GetLastTiming();
std::cout << "Preprocess: " << timing.preprocess_ms << " ms" << std::endl;
std::cout << "Inference: " << timing.model_infer_ms << " ms" << std::endl;
std::cout << "Postprocess: " << timing.postprocess_ms << " ms" << std::endl;

return 0;
}

4.2.2 C++ 视频流人脸检测

#include "vision_service.h"
#include <opencv2/opencv.hpp>

int main() {
auto service = VisionService::Create("examples/yolov5-face/config/yolov5-face.yaml");
cv::VideoCapture cap(0); // 打开摄像头
cv::Mat frame, output;

while (cap.read(frame)) {
VisionServiceResponse response;
if (service->Infer(frame, &response) != VISION_SERVICE_OK) {
continue;
}
service->Draw(frame, response, &output);

cv::imshow("Face Detection", output);
if (cv::waitKey(1) == 'q') break;
}

return 0;
}

4.2.3 Python 单图人脸检测

import cv2
from spacemit_vision import VisionServiceNative, VisionServiceStatus

svc = VisionServiceNative.create("examples/yolov5-face/config/yolov5-face.yaml")
image = cv2.imread("test.jpg")

status, results = svc.infer_image(image)
if status != VisionServiceStatus.OK:
raise RuntimeError(svc.last_error())

print(f"Detected {len(results)} faces:")
for i, r in enumerate(results):
print(f" Face {i+1} - Score: {r.score:.3f}, "
f"Box: [{r.x1:.0f},{r.y1:.0f},{r.x2:.0f},{r.y2:.0f}]")

if svc.supports_draw():
st, output = svc.draw(image)
if st == VisionServiceStatus.OK:
cv2.imwrite("result.jpg", output)

4.2.4 Python 视频流人脸检测

import cv2
from spacemit_vision import VisionServiceNative, VisionServiceStatus

svc = VisionServiceNative.create("examples/yolov5-face/config/yolov5-face.yaml")
cap = cv2.VideoCapture(0)

while True:
ret, frame = cap.read()
if not ret:
break
status, _ = svc.infer_image(frame)
if status != VisionServiceStatus.OK:
continue
output = frame
if svc.supports_draw():
st, output = svc.draw(frame)
cv2.imshow("Face Detection", output)
if cv2.waitKey(1) & 0xFF == ord('q'):
break

cap.release()
cv2.destroyAllWindows()

4.3 配置说明

YAML 配置文件是模型加载和推理参数的核心,以下是完整配置项说明:

# 模型文件路径(YOLOv5-Face 专用人脸检测模型)
model_path: ~/.cache/models/vision/yolov5-face/yolov5n-face_cut.q.onnx

# 测试图像路径(用于示例程序)
test_image: ~/.cache/assets/image/003_face0.png

# 模型输入尺寸 [height, width]
image_size: [640, 640]

# 部署类名(C++ 模型工厂注册名,Python 通过 yaml 路径间接使用)
class: deploy.yolov5_face.YOLOv5FaceDetector

# 推理参数
default_params:
# 置信度阈值(0.0-1.0),低于此值的检测框将被过滤
conf_threshold: 0.25

# IOU 阈值(0.0-1.0),用于 NMS 非极大值抑制
iou_threshold: 0.45

# 推理线程数(本模型示例默认 4;SpaceMIT EP 模型 intra-op 最大建议 8)
num_threads: 4

# 推理后端(优先使用 SpaceMITExecutionProvider)
providers:
- SpaceMITExecutionProvider
- CPUExecutionProvider # 备用后端

参数调优建议

  • conf_threshold:人脸检测建议使用 0.25-0.5,过低会增加误检(如将物体误识别为人脸)。
  • iou_threshold:默认 0.45 适用于大多数场景,密集人群场景可适当降低。
  • num_threads:本模型 yaml 默认为 4。若迁移到其他 SpaceMIT EP 检测模型,默认通常为 8,intra-op 最大建议 8,可按需调低。
  • providers:优先使用 SpaceMITExecutionProvider 以获得最佳性能。

4.4 性能监控

通过启用性能计时,可以分析推理各阶段的耗时,用于性能优化和瓶颈定位。

C++ 示例

VisionServiceTimingOptions timing_options;
timing_options.enabled = true;
service->SetTimingOptions(timing_options);

cv::Mat image = cv::imread("test.jpg");
VisionServiceResponse response;
service->Infer(image, &response);

auto timing = service->GetLastTiming();
std::cout << "Preprocess: " << timing.preprocess_ms << " ms" << std::endl;
std::cout << "Inference: " << timing.model_infer_ms << " ms" << std::endl;
std::cout << "Postprocess: " << timing.postprocess_ms << " ms" << std::endl;
std::cout << "Total: " << timing.infer_ms << " ms" << std::endl;

性能优化建议

  • 预处理耗时高:检查图像尺寸是否过大,考虑降低输入分辨率。
  • 推理耗时高:确认使用 SpaceMITExecutionProvider,检查线程数设置。
  • 后处理耗时高:适当提高 conf_threshold 可减少处理对象数量。

参考 demo 路径examples/yolov5-face/

  • 下游应用:人脸检测通常作为人脸识别(ArcFace)的前置步骤,先检测人脸区域再裁剪送入识别模型。参见 applications/emotion_detection/(表情检测应用)。

5. 调试指南

  • 启用计时:通过 SetTimingOptions 查看各阶段耗时
  • 检测不到人脸:降低 conf_threshold,确认输入图片中有正面或侧面人脸
  • 误检过多:提高 conf_threshold(如 0.5)

6. 常见问题

现象可能原因处理
Model file not found模型未下载执行 bash examples/yolov5-face/scripts/download_models.sh
No module named 'spacemit_vision'wheel 未安装按 §2 编译并 pip install src/python/dist/*.whl
检测结果为空图片中无人脸或阈值过高降低 conf_threshold,换用包含人脸的测试图片
小人脸漏检人脸在图片中占比过小裁剪感兴趣区域后再检测

附录:性能与测试数据

以下数据摘自 Vision 组件 README.md 附录「不包含前后处理」(纯 ONNX 模型推理,不含图像预处理与后处理)。为 K3 平台阶段性实测结果,完整表见 README。

K3 平台

具体模型输入大小数据类型帧率 (4核)帧率 (8核)
yolov5n-face[1,3,640,640]int832.141.1

复现方法:使用 onnxruntime_perf_test 工具(4 线程):

onnxruntime_perf_test ~/.cache/models/vision/yolov5-face/yolov5n-face_cut.q.onnx -e spacemit -r 20 -x 1 -S 1 -s -I -c 1 -i "SPACEMIT_EP_INTRA_THREAD_NUM|4"