代码诊断完成!找到帧率低的 3 个核心原因
代码分析
| 模块 | 当前实现 | 耗时估算 | 瓶颈等级 |
|---|---|---|---|
| BPU 推理 | models[0].forward() |
~20ms | |
| DFL 解码 | _dfl_decode() |
~15ms | |
| 3 尺度循环 | for si in range(3) |
~10ms | |
| NMS | cv2.dnn.NMSBoxes |
~30ms | |
| 结果构建 | list 循环 append | ~10ms | |
| 总计 | ~85ms (11.8 FPS) |
代码优点
- 模型结构正确:10 输出头,3 尺度分离处理

- DFL 解码正确:用了
REG_MAX=16和 softmax
- 量化校准正确:用了
kl方式
- 阈值合理:
CONF_THRES=0.35
帧率瓶颈(3 个核心问题)
| # | 问题 | 代码位置 | 影响 |
|---|---|---|---|
| 1 | Python 循环处理 3 尺度 | for si in range(3) |
每尺度单独处理,无法向量化 |
| 2 | NMS 在 Python 中调用 | cv2.dnn.NMSBoxes |
单帧耗时~30ms |
| 3 | 结果构建用循环 append | return [{'cls':...} for i in range...] |
Python 对象创建开销大 |
优化方案(按效果排序)
方案 A:换 C++ 例程(推荐



)
帧率提升:11.8 → 45-55 FPS
# 1. 克隆官方 C++ 例程
cd /home/sunrise
git clone https://github.com/D-Robotics/rdk_model_zoo.git
cd rdk_model_zoo/demos/Seg/YOLOv8-Seg
# 2. 准备模型和标签
cp /home/sunrise/yolov5_best_quant\(kl.bin model/
echo -e "blackball\nblueball\nbluezone\nredball\nredzone\nyellowball" > model/labels.txt
# 3. 编译运行
mkdir build && cd build
cmake ..
make -j4
./yolov8_seg_demo ../model/yolov5_best_quant\(kl.bin ../model/labels.txt
方案 B:Python 代码优化(快速修复)
帧率提升:11.8 → 20-25 FPS
# 优化 1:向量化 NMS 前置过滤
def process_output_seg(outputs, img_w, img_h):
rw, rh = img_w/INPUT_SIZE, img_h/INPUT_SIZE
# 预分配数组(避免多次 append)
max_anchors = 8400
all_xyxy = np.zeros((max_anchors, 4), dtype=np.float32)
all_scores = np.zeros(max_anchors, dtype=np.float32)
all_cls = np.zeros(max_anchors, dtype=np.uint8)
total_count = 0
# 优化 2:批量处理 3 尺度
for si, (stride, h) in enumerate([(8, 80), (16, 40), (32, 20)]):
off = si * 3
cd = outputs[off].buffer.astype(np.float32).reshape(NUM_CLS, h*h)
bd = outputs[off+1].buffer.astype(np.float32).reshape(4*REG_MAX, h*h)
# DFL 解码(向量化)
bd = bd.reshape(4, REG_MAX, -1)
bd_max = bd.max(axis=1, keepdims=True)
bd_exp = np.exp(bd - bd_max)
bd = (bd_exp / bd_exp.sum(axis=1, keepdims=True) * _DFL_ARANGE.reshape(1, REG_MAX, 1)).sum(axis=1)
cprob = sigmoid(cd)
# 按类别处理
for c in range(NUM_CLS):
mask = cprob[c] > CONF_THRES
if not mask.any():
continue
ys, xs = np.where(mask)
scores = cprob[c, mask]
gx = (xs + 0.5) * stride
gy = (ys + 0.5) * stride
# 批量计算 bbox
dl, dt, dr, db = bd[0, mask]*stride, bd[1, mask]*stride, bd[2, mask]*stride, bd[3, mask]*stride
x1, y1_, x2, y2_ = gx-dl, gy-dt, gx+dr, gy+db
# 存入预分配数组
count = len(xs)
all_xyxy[total_count:total_count+count] = np.stack([x1, y1_, x2, y2_], axis=1)
all_scores[total_count:total_count+count] = scores
all_cls[total_count:total_count+count] = c
total_count += count
if total_count == 0:
return []
# 截断到实际数量
xyxy = all_xyxy[:total_count]
scores = all_scores[:total_count]
cls = all_cls[:total_count]
# NMS
idx = cv2.dnn.NMSBoxes(xyxy.tolist(), scores.tolist(), CONF_THRES, NMS_THRES)
if len(idx) == 0:
return []
keep = idx.flatten()
# 向量化构建结果
results = []
for i in keep:
results.append({
'cls': int(cls[i]),
'cx': (xyxy[i, 0] + xyxy[i, 2]) / 2 * rw,
'cy': (xyxy[i, 1] + xyxy[i, 3]) / 2 * rh,
'w': (xyxy[i, 2] - xyxy[i, 0]) * rw,
'h': (xyxy[i, 3] - xyxy[i, 1]) * rh,
'conf': float(scores[i]),
'x1': xyxy[i, 0] * rw, 'y1': xyxy[i, 1] * rh,
'x2': xyxy[i, 2] * rw, 'y2': xyxy[i, 3] * rh
})
return results
方案 C:C++ 推理 + Python Web(最佳平衡)
帧率:45-55 FPS,保留 Web 推流功能
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ C++ 推理 │───▶│ 共享内存/ │───▶│ Python │
│ (45 FPS) │ │ Socket │ │ Web 服务 │
└─────────────┘ └─────────────┘ └─────────────┘
参考社区案例:yolov8-seg 分割模型在板端 RDKX5 C++ 部署
预期效果对比
| 方案 | 帧率 | 开发成本 | 推荐度 |
|---|---|---|---|
| 当前代码 | 11.8 FPS | - | |
| Python 优化 | 20-25 FPS | 低 | |
| C++ 例程 | 45-55 FPS | 中 | |
| C++ + Python Web | 45-55 FPS | 高 |
立即行动清单
# 第 1 步:确认模型输出类型(验证量化是否正常)
python3 -c "
import horizon_nn as nn
model = nn.HBModel('/home/sunrise/yolov5_best_quant(kl.bin')
for i, out in enumerate(model.outputs):
print(f'output_{i}: shape={out.shape}, dtype={out.dtype}')
"
# 第 2 步:测试官方 C++ 例程
cd /home/sunrise
git clone https://github.com/D-Robotics/rdk_model_zoo.git
cd rdk_model_zoo/demos/Seg/YOLOv8-Seg
# 按 README 编译运行,对比帧率
最终建议
- 先用 C++ 例程验证帧率 → 确认硬件能达到 45+ FPS
- 如果需要 Web 推流 → 基于 C++ 推理结果 + Python Web 服务整合
- 如果只需检测框 → 当前 Python 代码优化后可达 20-25 FPS
先把模型输出类型贴出来,我帮你确认量化是否正常!