# 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) ## 关键代码片段 ```cpp // 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; ``` ## 配置参数 ```json { "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 个关键点