从ONNX到RK3588:YOLOv5-DeepSort多目标跟踪模型部署实战

边缘计算设备上的多目标跟踪技术正在重塑智能监控、自动驾驶和工业检测等领域。RK3588作为瑞芯微旗舰级AIoT芯片,凭借6TOPS算力和丰富接口成为端侧部署的理想选择。本文将完整呈现YOLOv5-DeepSort模型在RK3588平台的部署全流程,特别针对ONNX转RKNN过程中的典型陷阱提供解决方案。

1. 模型部署前的技术准备

多目标跟踪(MOT)技术融合了目标检测与特征匹配双重能力,YOLOv5-DeepSort作为当前主流方案,其部署到边缘设备需要理解完整的算法流水线。DeepSort在YOLOv5检测结果基础上,通过卡尔曼滤波预测目标运动轨迹,并利用深度特征进行跨帧目标关联,最终实现ID持续跟踪。

核心组件依赖关系

graph TD
    A[YOLOv5检测模型] --> B[目标检测框输出]
    B --> C[DeepSort特征提取器]
    C --> D[卡尔曼滤波预测]
    D --> E[匈牙利算法匹配]
    E --> F[稳定跟踪轨迹输出]

开发环境配置建议:

  • Ubuntu 20.04 LTS系统
  • Python 3.8-3.10环境
  • RKNN-Toolkit2 1.6.0及以上
  • ONNXruntime 1.13.1
  • OpenCV 4.5.5

注意:RKNN工具链对Python版本敏感,3.11+版本可能存在兼容性问题

2. ONNX模型转换关键步骤

原始PyTorch模型需先转换为ONNX中间格式,这是通向RKNN的必要桥梁。YOLOv5的导出需要特别注意动态轴设置:

import torch
model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)

# 关键导出参数
input_names = ['images']
output_names = ['output0']
dynamic_axes = {
    'images': {0: 'batch'}, 
    'output0': {0: 'batch'}
}

torch.onnx.export(
    model,
    torch.randn(1, 3, 640, 640),
    "yolov5s.onnx",
    opset_version=13,
    input_names=input_names,
    output_names=output_names,
    dynamic_axes=dynamic_axes
)

常见转换问题解决方案:

错误类型 表现特征 解决方法
算子不支持 ONNX导出时报错Unknown node 升级torch/onnx版本或自定义算子
形状不匹配 推理时维度错误 检查dynamic_axes设置
精度下降 mAP指标显著降低 验证时保持FP32一致性

对于DeepSort的特征提取器,需特殊处理其ReID网络:

python export_onnx.py \
    --weights ckpt.t7 \
    --output deepsort.onnx \
    --opset 12 \
    --simplify

3. RKNN转换的深度优化

RKNN转换是部署成功的关键环节,需要平衡精度与性能。以下对比不同量化策略的影响:

量化方式 推理速度(ms) mAP@0.5 显存占用(MB)
FP32 152 0.873 342
FP16 68 0.869 198
INT8 42 0.851 156

推荐转换配置:

from rknn.api import RKNN

rknn = RKNN()
rknn.config(
    mean_values=[[0, 0, 0]],
    std_values=[[255, 255, 255]],
    quantized_dtype='asymmetric_quantized-u8',
    quantized_algorithm='normal',
    optimization_level=3
)

ret = rknn.load_onnx(model='yolov5s.onnx')
ret = rknn.build(do_quantization=True, dataset='./dataset.txt')
ret = rknn.export_rknn('yolov5s.rknn')

动态batch处理技巧

  1. 在模型最后添加Reshape节点
  2. 使用 rknn.build() 时指定 batch_size=1
  3. 运行时通过 inputs 参数控制实际batch

实测发现RK3588对动态shape的支持有限,建议固定输入尺寸

4. 开发板部署实战

部署到RK3588开发板后,需要通过视频流测试完整流程。性能优化策略包括:

多核NPU分配方案

// 在C代码中设置核心掩码
rknn_set_core_mask(ctx, RKNN_NPU_CORE_0_1_2);

视频处理流水线优化

def inference_pipeline():
    # 初始化
    cap = cv2.VideoCapture(0)
    rknn = RKNNLite()
    rknn.load_rknn('model.rknn')
    rknn.init_runtime()
    
    # 处理循环
    while True:
        ret, frame = cap.read()
        img = preprocess(frame)
        outputs = rknn.inference(inputs=[img])
        boxes = postprocess(outputs)
        draw_results(frame, boxes)
        
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    
    # 释放资源
    cap.release()
    rknn.release()

内存管理注意事项:

  • 每10帧主动调用 gc.collect()
  • 限制同时处理的视频流数量
  • 使用 rknn.release() 及时释放模型

5. 典型问题排查指南

问题1:模型转换后精度异常

  • 检查预处理是否与训练时一致
  • 验证量化校准数据集代表性
  • 尝试关闭量化对比FP32结果

问题2:NPU利用率低下

# 监控NPU使用情况
cat /sys/kernel/debug/rknpu/load

优化方向:

  • 增加batch_size提高并行度
  • 使用双缓冲提升流水线效率
  • 调整CPU频率配合NPU节奏

问题3:跟踪ID频繁跳变

  • 调高DeepSort的匹配阈值
  • 增加卡尔曼滤波的过程噪声
  • 优化特征提取器的量化方式

实际测试数据显示,在1080p分辨率下,RK3588可实现YOLOv5s+DeepSort的25FPS稳定处理,满足大多数实时场景需求。相比纯CPU方案有8-10倍的加速比,而功耗保持在5W以内。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐