20 KiB
人脸检测参数配置指南
本文档详细说明人脸检测节点(ai_face_det, ai_scrfd, ai_scrfd_sliding)中的核心后处理参数及其对检测结果的影响。
参数概览
| 参数名 | 类型 | 默认值 | 范围 | 说明 |
|---|---|---|---|---|
conf_thresh |
float | 0.5/0.6/0.7 | 0.0 ~ 1.0 | 置信度阈值,过滤低置信度候选框 |
nms_thresh |
float | 0.4 | 0.0 ~ 1.0 | NMS IoU 阈值,控制重复框去重力度 |
max_faces |
int | 10/50 | ≥ 1 | 单帧最大返回人脸数 |
1. conf_thresh (置信度阈值)
含义
模型对检测到的人脸的置信度(confidence score)阈值。神经网络在推理时会对每个候选框输出一个置信度分数,表示该位置存在人脸的确定性程度。
对检测结果的影响
| 设置 | 效果 | 适用场景 |
|---|---|---|
| 调高 (如 0.7) | 减少误检,只保留高置信度人脸 | 高精度需求场景(门禁、考勤) |
| 调低 (如 0.2) | 增加检出率,更多弱特征人脸被检测 | 弱光、远距离、小目标场景 |
注意事项
- 值过高可能导致漏检:模糊人脸、侧脸、小人脸可能被过滤
- 值过低可能导致误检:背景中的类似人脸的纹理可能被误判
代码实现
在 SCRFD 后处理中 (ai_scrfd_node.cpp:282):
if (score < cfg_.conf_thresh) continue;
在 RetinaFace 后处理中 (ai_face_det_node.cpp:784):
if (score < cfg.conf_thresh) continue;
2. nms_thresh (NMS IoU 阈值)
含义
非极大值抑制(Non-Maximum Suppression)的 IoU(Intersection over Union,交并比)阈值。
NMS 的作用:同一个真实人脸可能被多个 anchor/候选框检测到,NMS 用于去除重叠的重复检测框,只保留最优的一个。
IoU 计算:
IoU = 两个框的交集面积 / 两个框的并集面积
对检测结果的影响
| 设置 | 效果 | 适用场景 |
|---|---|---|
| 调高 (如 0.6) | 保留更多重叠框,对密集人脸友好 | 多人密集场景(会议室、教室) |
| 调低 (如 0.3) | 严格去重,只保留最优框 | 单人场景、需要精确框选 |
注意事项
- 值过高:同一人脸可能返回多个重叠框
- 值过低:密集人脸场景可能误删相邻的不同人脸
代码实现
在 SCRFD 后处理中 (ai_scrfd_node.cpp:172):
detections = ApplyNMS(detections, cfg_.nms_thresh);
NMS 算法逻辑 (ai_face_det_node.cpp:156-167):
void NmsSorted(const std::vector<Rect>& boxes, const std::vector<float>& scores,
float nms_thresh, std::vector<int>& keep) {
for (...) {
bool suppressed = false;
for (int kept : keep) {
if (IoU(boxes[idx], boxes[kept]) > nms_thresh) {
suppressed = true; // 被已保留的框抑制
break;
}
}
if (!suppressed) keep.push_back(idx);
}
}
3. max_faces (最大人脸数)
含义
单帧图像中最多返回的人脸检测数量限制。
对检测结果的影响
| 设置 | 效果 | 性能影响 |
|---|---|---|
| 调高 (如 50) | 可检测更多人脸,不遗漏密集场景目标 | 增加后处理开销,RGA/OSD 绘制负载增大 |
| 调低 (如 5) | 仅保留置信度最高的前几个人脸 | 减少计算量,提升实时性 |
注意事项
- 当画面中出现超过
max_faces数量的人脸时,系统会按置信度排序,只保留前 N 个 - 设置过大可能导致 RGA 任务堆积,引起 OSD 绘制卡顿
代码实现
在 SCRFD 后处理中 (ai_scrfd_node.cpp:174-176):
if (detections.size() > static_cast<size_t>(cfg_.max_faces)) {
detections.resize(cfg_.max_faces);
}
在 RetinaFace 后处理中 (ai_face_det_node.cpp:840):
const int out_n = std::min<int>(cfg.max_faces, static_cast<int>(keep.size()));
推荐配置
按应用场景
| 场景 | conf_thresh | nms_thresh | max_faces | 说明 |
|---|---|---|---|---|
| 高精度门禁/考勤 | 0.6 ~ 0.7 | 0.4 | 5 ~ 10 | 减少误识别,确保准确率 |
| 多人大场景 (会议室/教室) | 0.4 ~ 0.5 | 0.4 ~ 0.5 | 20 ~ 50 | 平衡检出率和去重效果 |
| 实时性优先 | 0.5 | 0.4 | 10 | 减少后处理开销 |
| 弱光/远距离/小目标 | 0.3 ~ 0.4 | 0.3 | 10 ~ 20 | 提高检出率,但需容忍一定误检 |
| 单人视频通话 | 0.6 | 0.4 | 1 ~ 3 | 最小化处理开销 |
按硬件性能
| 设备性能 | max_faces 建议 | 优化策略 |
|---|---|---|
| RK3588 高性能模式 | 20 ~ 50 | 可同时处理多路高清视频 |
| RK3588 平衡模式 | 10 ~ 20 | 适当降低分辨率和检测频率 |
| RK3566/RK3568 | 5 ~ 10 | 降低输入分辨率,提高 conf_thresh 减少候选框 |
参数联动关系
这三个参数需要协同调整:
- 提高
conf_thresh→ 候选框数量减少 → 可降低max_faces→ NMS 压力减小 - 降低
conf_thresh→ 候选框数量增加 → 可能需要提高max_faces→ NMS 压力增大 - 密集场景:适当提高
nms_thresh避免误删相邻人脸,同时确保max_faces足够大
配置示例
SCRFD 配置 (ai_scrfd 节点)
{
"type": "ai_scrfd",
"model_path": "./models/scrfd_500m_640.rknn",
"conf_thresh": 0.5,
"nms_thresh": 0.4,
"max_faces": 50,
"output_landmarks": true,
"input_format": "rgb"
}
RetinaFace 配置 (ai_face_det 节点)
{
"type": "ai_face_det",
"model_path": "./models/RetinaFace_mobile320.rknn",
"conf": 0.7,
"nms": 0.4,
"max_faces": 10,
"output_landmarks": true,
"input_format": "rgb"
}
分区域检测配置 (ai_face_det_zoned 节点)
{
"type": "ai_face_det_zoned",
"model_path": "./models/RetinaFace_mobile320.rknn",
"conf": 0.6,
"nms": 0.4,
"max_faces": 10,
"output_landmarks": true
}
调试建议
- 先调 conf_thresh:从默认值开始,观察是否漏检或误检
- 再调 nms_thresh:在密集人脸场景测试,确保既不重复框选也不漏检
- 最后调 max_faces:根据实际场景人数和硬件性能调整
日志查看
启动时节点会打印当前参数:
[ai_face_det] start id=face_det conf=0.7 nms=0.4 max_faces=10
[ai_scrfd] start id=scrfd conf=0.5 nms=0.4 max_faces=50
常见问题
Q1: 为什么检测到的人脸框会抖动/闪烁?
可能原因:
conf_thresh设置过低,边缘候选框置信度波动导致时有时无nms_thresh过低,相邻帧选择不同的 anchor
解决方法:适当提高 conf_thresh 或调整 nms_thresh
Q2: 密集场景漏检严重怎么办?
解决方法:
- 降低
conf_thresh到 0.4 左右 - 提高
max_faces到 30 以上 - 适当提高
nms_thresh到 0.5,避免相邻人脸被抑制
Q3: OSD 绘制卡顿,RGA 任务堆积?
解决方法:
- 降低
max_faces减少绘制负载 - 提高
conf_thresh减少检测数量
四、人脸识别参数 (ai_face_recog)
ai_face_recog 节点接收人脸检测结果,提取人脸特征向量并与特征库进行比对,完成人脸识别。
4.1 参数概览
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
align |
bool | true | 是否使用5点关键点进行人脸对齐 |
emit_embedding |
bool | false | 是否输出特征向量(用于调试) |
max_faces |
int | 10 | 单帧最大处理人脸数 |
input_format |
string | "rgb" | 输入图像格式:rgb/bgr |
input_dtype |
string | "uint8" | 输入数据类型:uint8/float |
threshold.accept |
float | 0.45 | 识别通过阈值,相似度超过此值才接受 |
threshold.margin |
float | 0.05 | 边距阈值,最佳与次佳匹配的差距要求 |
gallery.backend |
string | "sqlite" | 人脸库后端类型 |
gallery.path |
string | "./models/face_gallery.db" | 人脸库文件路径 |
4.2 align (人脸对齐)
含义
是否使用检测到的5个面部关键点(眼睛、鼻子、嘴角)进行人脸对齐变换。
对识别效果的影响
| 设置 | 效果 | 适用场景 |
|---|---|---|
| true | 对齐后人脸姿态归一化,提高识别准确率 | 高位摄像头、角度倾斜、侧脸场景 |
| false | 直接裁剪人脸区域,计算量略小 | 正面、固定位置场景 |
对齐原理
使用5点关键点与标准模板进行相似变换(Similarity Transform):
- 标准模板坐标(112x112输入):左眼(38.29,51.70)、右眼(73.53,51.50)、鼻尖(56.02,71.74)、左嘴角(41.55,92.37)、右嘴角(70.73,92.20)
- 代码实现:
ai_face_recog_node.cpp:851-865
if (cfg->align && face.has_landmarks && model_w_ == 112 && model_h_ == 112) {
const std::array<Point2f, 5> dst = { ... }; // 标准模板
SimilarityTransform t;
InvTransform inv;
if (ComputeSimilarity(face.landmarks, dst, t) && InvertSimilarity(t, inv)) {
WarpFace(src, w, h, stride, inv, face_buf_.data(), model_w_, model_h_, need_swap);
}
}
4.3 threshold.accept (接受阈值)
含义
特征向量相似度阈值,范围 0.0 ~ 1.0。只有当待识别人脸与库中某人的相似度超过此值时,才认为是匹配成功。
对识别结果的影响
| 设置 | 效果 | 误识率 | 拒识率 |
|---|---|---|---|
| 调高 (如 0.55) | 更严格,只接受高度相似 | 低 | 高 |
| 调低 (如 0.35) | 更宽松,容易匹配 | 高 | 低 |
推荐值
| 场景 | 推荐值 | 说明 |
|---|---|---|
| 高安全性场景 | 0.50 ~ 0.55 | 门禁、支付,严格控制误识 |
| 一般场景 | 0.45 ~ 0.50 | 考勤、签到,平衡准确率和体验 |
| 快速通行场景 | 0.40 ~ 0.45 | 闸机、通道,减少拒识 |
代码实现
const bool accept = (sr.best_person_id >= 0) &&
(sr.best_sim >= cfg->thr_accept) &&
((cfg->thr_margin <= 0.0f) || ((sr.best_sim - sr.second_sim) >= cfg->thr_margin));
4.4 threshold.margin (边距阈值)
含义
要求最佳匹配与次佳匹配的相似度差距至少达到此值,用于排除模糊匹配(如两个人都很像的情况)。设为 0 或负数可禁用此检查。
作用示例
假设待识别人脸与库中人员相似度如下:
- 张三(最佳): 0.62
- 李四(次佳): 0.58
- 差距: 0.04
如果 margin = 0.05,则 0.04 < 0.05,匹配失败(标记为 unknown)
如果 margin = 0.03,则 0.04 > 0.03,匹配成功(识别为张三)
推荐值
- 0.05(默认):适合大多数人脸库
- 0.00 或负数:禁用边距检查,只依赖 accept 阈值
4.5 max_faces (最大处理人脸数)
含义
单帧最多处理的人脸数量。由于特征提取需要 NPU 推理,此参数直接影响处理延迟。
与检测节点 max_faces 的关系
实际处理数 = min(face_det.max_faces, face_recog.max_faces)
建议两个节点的 max_faces 保持一致或识别节点略小。
4.6 gallery (人脸库配置)
参数说明
| 参数 | 默认值 | 说明 |
|---|---|---|
backend |
"sqlite" | 后端类型,目前仅支持 sqlite |
path |
"./models/face_gallery.db" | 人脸库数据库文件路径 |
load_on_start |
true | 启动时加载到内存 |
expected_dim |
512 | 特征向量维度(MobileFaceNet 为 512) |
dtype |
"auto" | 数据类型,auto/float32 |
人脸库管理
人脸库使用 SQLite 存储,包含以下信息:
person_id:人员唯一IDname:人员名称embedding:特征向量(512维浮点数)- 可通过 Web 管理接口或脚本添加/删除/更新人脸
4.7 normalize (输入归一化)
两种归一化方式
方式一:缩放+偏移(简单)
{
"normalize": {
"scale": 0.0078125,
"bias": 0.0
}
}
公式:output = input * scale + bias
方式二:均值+标准差(标准)
{
"normalize": {
"mean": [127.5, 127.5, 127.5],
"std": [128.0, 128.0, 128.0]
}
}
公式:output = (input - mean) / std
默认值
MobileFaceNet 模型通常使用:
scale: 1.0(不对 uint8 输入做缩放,由模型内部处理)- 或
mean: [127.5,127.5,127.5], std: [127.5,127.5,127.5]归一化到 [-1, 1]
4.8 人脸识别配置示例
{
"id": "face_recog",
"type": "ai_face_recog",
"role": "filter",
"enable": true,
"model_path": "./models/mobilefacenet_arcface.rknn",
"align": true,
"emit_embedding": false,
"max_faces": 50,
"input_format": "rgb",
"input_dtype": "uint8",
"threshold": {
"accept": 0.45,
"margin": 0.05
},
"gallery": {
"backend": "sqlite",
"path": "./models/face_gallery.db",
"load_on_start": true,
"expected_dim": 512,
"dtype": "auto"
}
}
4.9 检测+识别完整流程配置
{
"graphs": [{
"nodes": [
{
"id": "scrfd",
"type": "ai_scrfd",
"conf_thresh": 0.3,
"nms_thresh": 0.4,
"max_faces": 50,
"output_landmarks": true
},
{
"id": "face_recog",
"type": "ai_face_recog",
"align": true,
"max_faces": 50,
"threshold": { "accept": 0.45, "margin": 0.05 },
"gallery": { "path": "./models/face_gallery.db" }
},
{
"id": "osd",
"type": "osd",
"draw_face_det": true,
"draw_face_bbox": true
}
],
"edges": [
["scrfd", "face_recog"],
["face_recog", "osd"]
]
}]
}
五、滑动窗口检测参数 (ai_scrfd_sliding)
ai_scrfd_sliding 是专为高分辨率视频设计的滑动窗口检测节点,通过将画面分割成多个窗口分别检测,有效提升远处小目标的检出率。
5.1 节点特性
| 特性 | 说明 |
|---|---|
| 原始分辨率输入 | 直接接收原始图像,保留更多细节 |
| 滑动窗口检测 | 将画面分割成多个窗口,分别检测后合并结果 |
| 保持宽高比 | 每个窗口 resize 到 640x640,轻微变形但可接受 |
| 窗口可配置 | 支持自定义窗口数量和位置 |
5.2 参数说明
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
model_path |
string | - | SCRFD 模型路径 |
conf_thresh |
float | 0.3 | 置信度阈值 |
nms_thresh |
float | 0.4 | NMS IoU 阈值 |
max_faces |
int | 50 | 最大检测人脸数 |
output_landmarks |
bool | true | 是否输出5点关键点 |
windows |
array | 自动计算 | 窗口配置数组 |
5.3 窗口配置 (windows)
如果不配置 windows,节点会根据输入分辨率自动计算窗口。
窗口格式:
{
"x": 0, // 窗口左上角 X 坐标
"y": 0, // 窗口左上角 Y 坐标
"w": 960, // 窗口宽度
"h": 1080 // 窗口高度
}
窗口设计原则:
- 窗口之间应有适当重叠,避免漏检
- 窗口尺寸建议接近 640x640 的倍数(resize 后变形较小)
- 对于 16:9 视频,水平分割效果较好
5.4 不同分辨率配置参考
1080p (1920×1080) - 推荐2窗口
{
"windows": [
{"x": 0, "y": 0, "w": 960, "h": 1080},
{"x": 960, "y": 0, "w": 960, "h": 1080}
]
}
说明:
- 窗口 0:左半边 960x1080
- 窗口 1:右半边 960x1080
- 正好覆盖 1920 宽度,无重叠
- 每个窗口 resize 到 640x640,比例 0.89:1
1440p (2560×1440) - 推荐2窗口
{
"windows": [
{"x": 0, "y": 0, "w": 1280, "h": 1440},
{"x": 1280, "y": 0, "w": 1280, "h": 1440}
]
}
说明:
- 窗口 0:左半边 1280x1440
- 窗口 1:右半边 1280x1440
- 比例 0.89:1,与 1080p 一致
更高分辨率 - 增加窗口数
对于 4K (3840×2160) 等更高分辨率,可以增加窗口数量:
{
"windows": [
{"x": 0, "y": 0, "w": 1280, "h": 1080},
{"x": 1280, "y": 0, "w": 1280, "h": 1080},
{"x": 2560, "y": 0, "w": 1280, "h": 1080}
]
}
5.5 配置示例
{
"id": "scrfd_sliding",
"type": "ai_scrfd_sliding",
"role": "filter",
"enable": true,
"model_path": "./models/scrfd_500m_640.rknn",
"conf_thresh": 0.3,
"nms_thresh": 0.4,
"max_faces": 50,
"output_landmarks": true,
"windows": [
{"x": 0, "y": 0, "w": 960, "h": 1080},
{"x": 960, "y": 0, "w": 960, "h": 1080}
]
}
5.6 性能考量
- 窗口数 = 推理次数:2 个窗口 = 2 次模型推理
- 分辨率越高,窗口数越多:需要在检测效果和性能之间平衡
- 建议窗口数:
- 1080p:2 个窗口
- 1440p:2 个窗口(或 4 个窗口用于更精细检测)
- 4K:3-4 个窗口
5.7 滑动窗口检测常见问题
Q7: 窗口边缘的人脸被分割成两半?
解决方法:
- 增加窗口重叠区域(如窗口 0 结束于 1000,窗口 1 开始于 900)
- NMS 会自动合并重复检测
Q8: 远处人脸还是检测不到?
解决方法:
- 增加窗口数量,让每个窗口覆盖更小区域
- 降低
conf_thresh让更多候选框通过 - 考虑使用更高分辨率摄像头
Q9: 检测延迟增加?
解决方法:
- 减少窗口数量
- 降低
max_faces减少后处理负担 - 使用更高性能硬件
六、综合配置建议
6.1 场景配置速查表
| 场景 | 检测节点 | 关键参数 | 说明 |
|---|---|---|---|
| 门禁/考勤 | ai_face_det |
conf=0.7, max_faces=5 | 近距离,高精度 |
| 车间/厂房 | ai_scrfd_sliding |
2窗口 | 高位摄像头,大透视 |
| 会议室 | ai_scrfd |
conf=0.4, max_faces=50 | 多人场景 |
| 户外/街道 | ai_scrfd_sliding |
2-4窗口 | 远距离检测 |
6.2 分辨率配置对照表
| 分辨率 | 检测节点 | 输入处理 | 建议 |
|---|---|---|---|
| 720p | ai_scrfd |
前置缩放至640 | 通用配置 |
| 1080p | ai_scrfd_sliding |
2窗口(960x1080) | 滑动窗口检测 |
| 1440p | ai_scrfd_sliding |
2窗口(1280x1440) | 滑动窗口检测 |
| 4K | ai_scrfd_sliding |
3-4窗口 | 更多窗口提升精度 |
七、常见问题汇总
Q1: 检测框抖动/闪烁
可能原因:
conf_thresh设置过低,边缘候选框置信度波动nms_thresh过低,相邻帧选择不同 anchor
解决方法:适当提高 conf_thresh 或调整 nms_thresh
Q2: 密集场景漏检严重?
解决方法:
- 降低
conf_thresh到 0.4 左右 - 提高
max_faces到 30 以上 - 适当提高
nms_thresh到 0.5
Q3: OSD 绘制卡顿?
解决方法:
- 降低
max_faces减少绘制负载 - 提高
conf_thresh减少检测数量
Q4: 识别准确率不高?
可能原因及解决方法:
- 对齐问题:确保
align: true,且检测节点output_landmarks: true - 阈值不合适:调整
threshold.accept,根据实际测试确定最佳值 - 人脸库质量:确保库中人脸照片清晰、正面、光线均匀
- 检测框质量:适当提高检测
conf_thresh,过滤低质量检测框
Q5: 远距离/小目标识别效果差?
解决方法:
- 提高检测
conf_thresh,让只有清晰的人脸进入识别 - 检查摄像头分辨率,确保人脸区域至少 60x60 像素
- 考虑使用更高清的摄像头或调整安装角度
Q6: 识别延迟高?
优化方法:
- 降低
max_faces,减少单帧处理数量 - 提高检测
conf_thresh,减少候选框 - 确保
gallery.load_on_start: true,避免运行时查询数据库