196 lines
5.0 KiB
Markdown
196 lines
5.0 KiB
Markdown
# 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) |
|
||
|
||
## 输入规格
|
||
|
||
```python
|
||
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) 生成
|
||
|
||
```python
|
||
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。
|
||
|
||
## 后处理流程
|
||
|
||
1. **Score筛选**: 对每个anchor,检查 `score > conf_thresh`
|
||
2. **BBox解码**: anchor中心 + 相对偏移 + exp解码宽高
|
||
3. **Kps解码**: 5个面部关键点,相对anchor中心
|
||
4. **坐标映射**: 从640x640映射回原图分辨率
|
||
5. **NMS**: IoU阈值去重
|
||
|
||
## 配置参数
|
||
|
||
```json
|
||
{
|
||
"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
|
||
|
||
## 调试命令
|
||
|
||
```bash
|
||
# 检查模型版本
|
||
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`
|
||
|
||
## 参考
|
||
|
||
- [SCRFD Paper](https://arxiv.org/abs/2105.04714)
|
||
- [InsightFace SCRFD](https://github.com/deepinsight/insightface/tree/master/detection/scrfd)
|
||
- [RKNN API文档](https://github.com/rockchip-linux/rknpu2)
|