safesight-edge/docs/scrfd_500m_640_spec.md

196 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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)