OrangePi3588Media/docs/bugfix/002-scrfd-cpp-implementation.md

2.2 KiB
Raw Permalink Blame History

SCRFD C++ 实现完善

实现内容

完善了 ai_scrfd 插件的 C++ 实现,包括:

1. 输入预处理

  • 双线性插值 resize 到 640x640
  • 支持 RGB/BGR 格式转换
  • DMA 缓冲区同步

2. 推理流程

  • 使用 InferBorrowed 进行零拷贝推理
  • UINT8 输入RKNN 内部自动量化到 INT8
  • pass_through=0 让 RKNN 处理类型转换

3. 后处理逻辑

  • 维度处理: 适配 SCRFD 500M (v1.4.1) 的输出格式

    • scores: [1, 12800/3200/800, 1, 1] (2 channels: bg, fg)
    • bboxes: [1, 12800/3200/800, 4, 1] (dx, dy, dw, dh)
    • keypoints: [1, 12800/3200/800, 10, 1] (5 points x 2 coords)
  • 解码逻辑:

    • Score: sigmoid(bg_score - fg_score) 获取前景概率
    • BBox: anchor中心 + 偏移量exp(dw/dh) 解码宽高
    • Keypoints: anchor中心 + 相对偏移量
  • 坐标映射: 从 640x640 映射回原图分辨率

4. NMS (非极大值抑制)

  • 按置信度排序
  • IoU 阈值 0.4 去除重叠检测框
  • 限制最大检测数量 (默认 50)

关键代码片段

// Score解码 (sigmoid)
float score = 1.0f / (1.0f + std::exp(bg_score - fg_score));

// BBox解码 (相对于anchor)
float cx = anchor.cx + dx * stride;
float cy = anchor.cy + dy * stride;
float w = std::exp(dw) * stride;
float h = std::exp(dh) * stride;

配置参数

{
  "id": "scrfd",
  "type": "ai_scrfd",
  "model_path": "../models/face_det_scrfd_500m_640_rk3588.rknn",
  "conf_thresh": 0.5,
  "nms_thresh": 0.4,
  "max_faces": 50,
  "output_landmarks": true,
  "input_format": "rgb"
}

注意事项

  1. 模型版本: 使用 SCRFD 500M v1.4.1b16 (静态形状)

    • 新版本 v2.3.2 使用动态形状C API 不支持
  2. 输入格式:

    • 模型训练使用 BGR但代码默认使用 RGB
    • 通过 input_format 参数控制
  3. 性能:

    • 16800 个 anchor 需要遍历,后处理有一定开销
    • 可调整 conf_thresh 提前过滤低置信度候选框

测试结果

[ai_scrfd] Frame 1: detected 50 faces, best score=1.000000
[ai_scrfd] Frame 2: detected 50 faces, best score=1.000000
...
  • 推理正常,无崩溃
  • 检测到多个人脸(繁忙街道场景)
  • 输出包含 bbox 和 5 个关键点