【HZHY-AI300G智能盒试用连载体验】使用YOLOv8进行车辆流量监测

目录

YOLOv8的RKNN模型

程序的部署

流量统计


本文首发于电子发烧友论坛:【新提醒】【HZHY-AI300G智能盒试用连载体验】+ 智能工业互联网网关 - 北京合众恒跃科技有限公司 - 电子技术论坛 - 广受欢迎的专业电子论坛! (elecfans.com)

环境准备好之后,接下来利用RK3588的NPU进行道路视频中的车辆识别,根据识别到的车辆的数量估计道路的流量情况,实现智慧交通中的流量监控功能。

YOLOv8的RKNN模型

我们使用YOLOv8框架进行目标的检测。YOLOv8(You Only Look Once version 8)是一个深度学习框架,用于实现实时对象检测。YOLOv8 继承了前代模型的优点,并在此基础上进行了多项改进,包括更复杂的网络架构、更优化的训练流程和更强大的特征提取能力。

厂商在其Github仓库中提供了大量已经优化和测试验证过的模型,其中就包括YOLOv8:

https://github.com/airockchip/rknn_model_zoo/blob/main/examples/yolov8/README.md

厂商提供的模型是一个优化后的模型,与官方原始模型不同。以yolov8n.onnx为例来展示它们之间的差异。

1、它们输出信息的对比如下。左边是官方原始模型的输出,右边是优化后的模型输出。如图所示,原始模型的输出被分为三个部分。例如,在输出集合([1,64,80,80],[1,80,80,80],[1,1,80,80])中,[1,64,80,80]是边界框的坐标,[1,80,80,80]是对应于80个类别的边界框置信度,而[1,1,80,80]是80个类别置信度的总和。

请注意,这里的解释是基于常见目标检测模型(如YOLO系列)的输出格式,具体细节(如维度含义)可能因模型版本或实现而异。但一般来说,上述解释提供了关于YOLO类模型输出结构的通用理解。

2、以输出集合([1,64,80,80],[1,80,80,80],[1,1,80,80])为例,瑞芯微在模型中移除了两个卷积节点之后的子图,保留了这两个卷积的输出([1,64,80,80],[1,80,80,80]),并增加了一个reducesum+clip分支来计算80个类别置信度的总和([1,1,80,80])。

这里的“reducesum”操作通常用于对某个维度上的元素进行求和,而“clip”操作用于限制求和结果的取值范围,以避免数值溢出或保持数值在特定范围内。

 

这里提供的YOLOv8模型的训练方法和官方的完全相同,只是在导出的时候做了一些修改,有关导出 RKNPU 适配模型说明请见:https://github.com/airockchip/ultralytics_yolov8/blob/main/RKOPT_README.zh-CN.md

程序的部署

YOLOv8程序在RK3588上的部署,我们参考了风筝2100的博文RK3588 npu python运行 YOLOv8 和 YOLOv8-seg 的教程_rk3588支持yolov9版 android-CSDN博客,在此表示感谢。

和RKNN_model_zoo 中的examples 提供的YOLOv8 的相关 demo对比,该程序有两点改进:

1)借助rknn-multi-threaded(https://github.com/leafqycc/rknn-multi-threaded)使用多线程推理提高NPU的占用率,参考:多线程异步提高RK3588的NPU占用率,进而提高yolov5s帧率_rk3588 多线程_rknn多线程-CSDN博客

2)优化了Python 后处理部分去除PyTorch 依赖,将后处理耗时从几百毫秒降低到了几十毫秒。

在 main.py 文件中,可以修改模型、线程数,还可以修改成实时推理摄像头。

# 推理视频文件

cap = cv2.VideoCapture('./720p60hz.mp4')


# 推理实时摄像头
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH,640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT,480)

 程序启动后会显示RNKK的相关信息:

python3 main.py

I RKNN: [19:25:32.433] RKNN Runtime Information, librknnrt version: 2.0.0b0 (35a6907d79@2024-03-24T10:31:14)

I RKNN: [19:25:32.433] RKNN Driver Information, version: 0.9.3

I RKNN: [19:25:32.434] RKNN Model Information, version: 6, toolkit version: 1.6.0+81f21f4d(compiler version: 1.6.0 (585b3edcf@2023-12-11T07:42:56)), target: RKNPU v2, target platform: rk3588, framework name: ONNX, framework layout: NCHW, model inference type: static_shape

./rknnModel/yolov8s.rknn         done

I RKNN: [19:25:32.644] RKNN Runtime Information, librknnrt version: 2.0.0b0 (35a6907d79@2024-03-24T10:31:14)

I RKNN: [19:25:32.644] RKNN Driver Information, version: 0.9.3

I RKNN: [19:25:32.644] RKNN Model Information, version: 6, toolkit version: 1.6.0+81f21f4d(compiler version: 1.6.0 (585b3edcf@2023-12-11T07:42:56)), target: RKNPU v2, target platform: rk3588, framework name: ONNX, framework layout: NCHW, model inference type: static_shape

./rknnModel/yolov8s.rknn         done

I RKNN: [19:25:32.770] RKNN Runtime Information, librknnrt version: 2.0.0b0 (35a6907d79@2024-03-24T10:31:14)

I RKNN: [19:25:32.770] RKNN Driver Information, version: 0.9.3

I RKNN: [19:25:32.771] RKNN Model Information, version: 6, toolkit version: 1.6.0+81f21f4d(compiler version: 1.6.0 (585b3edcf@2023-12-11T07:42:56)), target: RKNPU v2, target platform: rk3588, framework name: ONNX, framework layout: NCHW, model inference type: static_shape

./rknnModel/yolov8s.rknn         done

流量统计

我们在每帧推理结束后,统计其中"car"、"motorbike "、 "bus"和"truck"对象的数量,作为流量统计的依据。

def myFunc(rknn_lite, IMG):
    IMG2 = cv2.cvtColor(IMG, cv2.COLOR_BGR2RGB)

    # 等比例缩放
    IMG2, ratio, padding = letterbox(IMG2)

    # 强制放缩
    # IMG2 = cv2.resize(IMG, (IMG_SIZE, IMG_SIZE))

    IMG2 = np.expand_dims(IMG2, 0)
    outputs = rknn_lite.inference(inputs=[IMG2],data_format=['nhwc'])
    #print("oups1",len(outputs))
    #print("oups2",outputs[0].shape)

    boxes, classes, scores = yolov8_post_process(outputs)
    global car_num
    global truck_num
    global motorbike_num
    global bus_num

    car_num = 0
    truck_num = 0
    motorbike_num = 0
    bus_num = 0

    if classes is not None:
            for box, score, cl in zip(boxes, scores, classes):
               if CLASSES[cl] == 'car':
                  car_num = car_num + 1
               elif CLASSES[cl] == 'motorbike':
                  motorbike_num = motorbike_num + 1
               elif CLASSES[cl] == 'bus':
                  bus_num = bus_num + 1
               elif CLASSES[cl] == 'truck':
                  truck_num = truck_num + 1

    if boxes is not None:
        draw(IMG, boxes, scores, classes, ratio, padding)
    return IMG

 我的程序已经可以在开发板上实时运行,并显示车辆检测结果。

  • 22
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神一样的老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值