safesight-edge/docs/scrfd_500m_640_spec.md

5.0 KiB
Raw Blame History

SCRFD 500M 640 模型完整规格

基本信息

属性
模型名称 SCRFD 500M 640
版本 1.4.1b16-dad86923
编译版本 1.4.1b13 (a06f28157@2022-11-26T05:23:21)
目标平台 RK3588 (RKNPU v2)
框架 ONNX
输入尺寸 640x640x3
输入格式 NHWC (RGB/BGR)

输入规格

shape: (1, 640, 640, 3)  # NHWC
format: UINT8 (pass_through=0, RKNN内部转INT8)
type: static_shape (非动态)

输出规格 (9个张量)

1. Scores (3个尺度)

索引 名称 形状 说明
0 score_8 (1, 12800, 1, 1) stride=8, 80x80x2 anchors
1 score_16 (1, 3200, 1, 1) stride=16, 40x40x2 anchors
2 score_32 (1, 800, 1, 1) stride=32, 20x20x2 anchors

关键发现: 每个anchor只输出1个前景分数不是2个通道

2. Bounding Boxes (3个尺度)

索引 名称 形状 说明
3 bbox_8 (1, 12800, 4, 1) [dx, dy, dw, dh] x 12800
4 bbox_16 (1, 3200, 4, 1) [dx, dy, dw, dh] x 3200
5 bbox_32 (1, 800, 4, 1) [dx, dy, dw, dh] x 800

解码公式:

cx = anchor_cx + dx * stride
cy = anchor_cy + dy * stride
w = exp(dw) * stride
h = exp(dh) * stride
x1 = cx - w/2
y1 = cy - h/2
x2 = cx + w/2
y2 = cy + h/2

3. Keypoints (3个尺度)

索引 名称 形状 说明
6 kps_8 (1, 12800, 10, 1) 5点x2坐标 x 12800
7 kps_16 (1, 3200, 10, 1) 5点x2坐标 x 3200
8 kps_32 (1, 800, 10, 1) 5点x2坐标 x 800

解码公式:

kps_x = anchor_cx + kps_dx * stride
kps_y = anchor_cy + kps_dy * stride

锚点 (Anchors) 生成

strides = [8, 16, 32]
num_anchors_per_location = 2

total_anchors = 80*80*2 + 40*40*2 + 20*20*2 = 16800

# anchor生成逻辑
for stride in [8, 16, 32]:
    grid_size = 640 // stride
    for y in range(grid_size):
        for x in range(grid_size):
            for a in range(2):  # 2 anchors per location
                anchor_cx = (x + 0.5) * stride
                anchor_cy = (y + 0.5) * stride

Anchor分布:

  • stride=8: 80x80 grid, 12800 anchors
  • stride=16: 40x40 grid, 3200 anchors
  • stride=32: 20x20 grid, 800 anchors

量化参数

张量 类型 Zero Point Scale
input INT8 -128 0.003921
score_8 INT8 -128 0.003534
score_16 INT8 -128 0.001638
score_32 INT8 -128 0.000163
bbox_8 INT8 -128 0.016671
bbox_16 INT8 -128 0.016227
bbox_32 INT8 -128 0.017979
kps_8 INT8 -7 0.020261
kps_16 INT8 -20 0.014725
kps_32 INT8 -11 0.014612

注意: 实际推理时使用 want_float=1RKNN 自动反量化,输出已是 FP32。

后处理流程

  1. Score筛选: 对每个anchor检查 score > conf_thresh
  2. BBox解码: anchor中心 + 相对偏移 + exp解码宽高
  3. Kps解码: 5个面部关键点相对anchor中心
  4. 坐标映射: 从640x640映射回原图分辨率
  5. NMS: IoU阈值去重

配置参数

{
  "model_path": "./models/scrfd_500m_640.rknn",
  "conf_thresh": 0.5,      // 置信度阈值 (0-1)
  "nms_thresh": 0.4,       // NMS IoU阈值
  "max_faces": 10,         // 最大检测人脸数
  "output_landmarks": true, // 输出5个关键点
  "input_format": "rgb"    // 输入格式: rgb/bgr
}

性能指标

指标
模型大小 ~1.5 MB
输入分辨率 640x640
Anchor数量 16800
输出张量数 9
关键点 5点 (双眼、鼻尖、嘴角)
总参数量 ~500K

版本兼容性

版本 状态 说明
1.4.1b16 推荐 静态形状C API完美支持
2.3.2 不兼容 动态形状C API崩溃

运行时库要求:

  • 最低: librknnrt 1.5.2
  • 推荐: librknnrt 2.3.2

调试命令

# 检查模型版本
strings models/scrfd_500m_640.rknn | grep "compiler version"

# 检查运行时版本  
strings /usr/lib/librknnrt.so | grep "librknnrt version"

# Python验证模型
python3 << 'PYEOF'
from rknnlite.api import RKNNLite
import numpy as np

rknn = RKNNLite()
rknn.load_rknn("models/scrfd_500m_640.rknn")
rknn.init_runtime()

img = np.zeros((1, 640, 640, 3), dtype=np.uint8)
outputs = rknn.inference(inputs=[img])

for i, out in enumerate(outputs):
    print(f"output[{i}]: shape={out.shape}")

rknn.release()
PYEOF

常见问题

1. 坐标错误

原因: Score张量误解为2通道实际只有1通道 修复: score = scores[i] 而不是 scores[i*2+1]

2. 模型崩溃

原因: 使用动态形状版本 (v2.3.2) 修复: 切换到静态形状版本 (v1.4.1b16)

3. RGA任务过多

原因: 检测到太多人脸OSD绘制任务堆积 修复: 降低 max_faces 或提高 conf_thresh

参考