帧率优化核心结论
你的代码架构不错,但后处理太重是主要瓶颈。根据社区案例 topic/34084,优化后处理可从 10 FPS 提升到 40+ FPS。
当前瓶颈分析
从你的代码看,耗时主要在:
| 环节 | 预估耗时 | 优化空间 |
|---|---|---|
cam.get_img() |
5-10ms | |
model.run() |
8-15ms | |
process_output_seg() |
30-50ms | |
| Web 编码/锁 | 5-10ms |
6 个关键优化方案
方案 1:降低输入分辨率(收益最大)
# 当前 640x640 → 改为 320x320 或 416x416
FRAME_W, FRAME_H = 320, 320 # 分辨率减半,帧率翻倍
INPUT_SIZE = 320 # 模型输入同步修改
PROTO_H = PROTO_W = INPUT_SIZE // 4 # 80 → 40
预期收益:帧率提升 40-60%
方案 2:简化 Mask 处理(关键)
你的 mask 处理太复杂,建议按需简化:
# 修改 process_output_seg 中的 mask 处理部分
# 只保留核心功能,去掉膨胀/收缩/轮廓近似
if cid in (OWN_ZONE, OPPONENT_ZONE) and batch_masks is not None:
zi = zone_idx.index(i) if i in zone_idx else -1
if zi >= 0:
# 简化:直接二值化,不做形态学操作
mask_full = batch_masks[zi]
det['mask'] = mask_full # 直接使用,不裁剪
去掉以下耗时操作:
cv2.findContours(每帧多次调用)
cv2.approxPolyDP(多边形近似)
np.roll膨胀/收缩操作
cv2.moments质心计算
预期收益:后处理耗时减少 50%
方案 3:优化锁机制(减少阻塞)
当前 web_lock 在主循环中,建议无锁设计:
# 使用原子替换代替锁
import threading
# 改为使用 threading.Event 或 queue
from queue import Queue
frame_queue = Queue(maxsize=2) # 双缓冲
# 主循环
frame_queue.put_nowait((nv12_raw, dets))
# Web 线程
nv12_raw, dets = frame_queue.get()
预期收益:减少 5-10ms 锁等待
方案 4:减少 NMS 计算量
# 当前对每个类别单独 NMS,可合并处理
# 或者提高 CONF_THRES 减少候选框
CONF_THRES = 0.35 # 从 0.25 提高到 0.35
NMS_THRES = 0.45 # 从 0.30 提高到 0.45
预期收益:后处理减少 20-30%
方案 5:使用 INT8 量化模型
确认你的模型是 INT8 量化:
# 检查模型文件
ls -lh /home/sunrise/yolov5_best_quant(kl.bin
# 如果是 FP16/FP32,重新量化为 INT8
# 参考:https://developer.d-robotics.cc/rdk_doc/
预期收益:推理速度提升 2-3 倍
方案 6:跳过非必要计算
# 添加跳帧机制,每 2 帧做一次完整后处理
frame_count = 0
SKIP_FRAME = 1 # 每 2 帧处理 1 次
while True:
nv12_raw = cam.get_img(2, FRAME_W, FRAME_H)
# 推理每帧都做
raw = model.run(...)
frame_count += 1
if frame_count % (SKIP_FRAME + 1) == 0:
dets = process_output_seg(raw, onames)
# 否则复用上一帧检测结果
预期收益:后处理耗时减半
快速优化版本(推荐先试)
# 关键修改点汇总
FRAME_W, FRAME_H = 320, 320 # 1. 降低分辨率
INPUT_SIZE = 320
CONF_THRES = 0.35 # 2. 提高阈值
# 3. 简化 process_output_seg 中的 mask 处理
# 去掉 cv2.findContours、cv2.approxPolyDP、np.roll 等操作
# 4. 使用双缓冲代替锁
from queue import Queue
frame_queue = Queue(maxsize=2)
预期帧率提升
| 优化项 | 当前预估 | 优化后预估 |
|---|---|---|
| 原始代码 | 15-20 FPS | - |
| 仅降低分辨率 | - | 25-30 FPS |
| + 简化 mask | - | 35-40 FPS |
| + 双缓冲 | - | 40-45 FPS |
| + INT8 模型 | - | 50-60 FPS |
建议执行顺序
- 先改分辨率 (320x320) → 立即见效
- 简化 mask 处理 → 去掉轮廓/膨胀操作
- 确认模型是 INT8 → 检查量化方式
- 最后优化锁机制 → 双缓冲设计
相关资源
需要我帮你改写优化后的完整代码吗? ![]()