5.0 KiB
5.0 KiB
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=1,RKNN 自动反量化,输出已是 FP32。
后处理流程
- Score筛选: 对每个anchor,检查
score > conf_thresh - BBox解码: anchor中心 + 相对偏移 + exp解码宽高
- Kps解码: 5个面部关键点,相对anchor中心
- 坐标映射: 从640x640映射回原图分辨率
- 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