码科智能 | 加速实时视觉检测应用,在边缘设备部署上实现2.4倍的加速!

本文来源公众号“码科智能”,仅用于学术分享,侵权删,干货满满。

原文链接:加速实时视觉检测应用,在边缘设备部署上实现2.4倍的加速!

想象一个场景:高速公路上遇到200km/h超速车辆,这时30帧摄像头抓拍成“幻影”,AI违法事件监控功能直接失效。反之另一个场景:暴雨夜大货车侧翻,AI 监控毫秒内预警,救援响应大幅提速!

上述就是实现实时视觉应用的重要性,尤其是在算力低下或者边缘部署的情况下,模型运行效率更是评价系统的一个重要指标。

图片

YOLOv8 在高速公路摄像头上进行物体检测

在智能监控、工业检测等实时视觉应用中,端侧计算通过将处理保持在数据源附近,具备低延迟:本地处理避免网络传输延迟;低成本:节省带宽和云服务费用;隐私安全:敏感数据无需上传云端的优势。然而,边缘设备的计算能力往往成为瓶颈。

在本文中,将探索加速的三大关键技术,以YOLOv8为例实现在边缘设备上的极致加速:

  • 多线程异步处理:吞吐量提升11%,告别卡顿!

  • TensorRT极致优化:推理速度暴涨43%!

  • Deepstream全流程加速:最终实现48.2FPS,性能提升2.4倍!

一、视觉应用常见的推理Pipline

首先从一个基础的目标检测推理应用场景开始,推理流程通常包含如下几个部分:

GPU AI推理业务流程

  • 数据输入是摄像头获取的视频数据流,一般以H.264格式为主。

  • 然后通过FFmpeg软件,将连续的视频流进行拆帧和解码。

  • 下一阶段是对解码后的图像进行预处理,通常使用OpenCV对图像进行缩放,得到模型需要的图像规格。

  • 模型推理环节,用户可以选择的方式比较多,比较典型的是使用TensorRT进行推理应用开发。

  • 目标检测后处理需要进行NMS计算,进行图片画框等操作。

  • 数据输出阶段,用户根据需要实现一个结果呈现形式。

二、异步化你的处理流程

推理流程的各个步骤可以同时执行,多线程是实现这一目标的关键。在 Python 中,多线程通过上下文切换实现,当一个线程空闲时,处理器可以切换到其他线程,从而提高效率。对于包含 I/O 操作的推理管道,多线程尤为重要,因为它能让 CPU 在等待 I/O 操作完成时继续处理其他任务。

Roboflow 推理管道正是基于这一原理,将视频解码、推理和后处理分离到不同的线程中,实现并行处理。这种异步处理方式能有效提高处理速度,尤其是在处理批量帧时,CPU 可以在等待一批帧进行推理时继续处理其他任务。

多线程

三、OpenCV与Roboflow Inference加速效果对比

使用 OpenCV 中的 YOLOv8-nano 对象检测模型实现同步推理流程:

import cv2
from inference import get_model
import supervision as sv

model = get_model("yolov8n-640")

cap = cv2.VideoCapture('/path/to/video')
while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        print("Can't receive frame (stream end?). Exiting ...")
        break
    
    predictions = model.infer(frame)

    detections = sv.Detections.from_inference(predictions[0])
    annotated_image = sv.BoxAnnotator().annotate(scene=frame, detections=detections)
    annotated_image = sv.LabelAnnotator().annotate(scene=annotated_image, detections=detections)
在上述代码中,从视频流中读取一帧、调用检测模型以及渲染结果这三个步骤是按照顺序依次执行的。也就是说,只有在前一个步骤完成之后,下一个步骤才会开始。

接下来,我们将其与使用 Roboflow 推理实现的相同流程进行对比。

from inference importInferencePipeline
from inference.core.interfaces.camera.entitiesimportVideoFrame
import supervision as sv
import cv2

def on_prediction(
    predictions: dict,
    video_frameVideoFrame,
) -> None:
    
    detections = sv.Detections.from_inference(predictions)
    annotated_image = sv.BoxAnnotator().annotate(scene=frame, detections=detections)
    annotated_image = sv.LabelAnnotator().annotate(scene=annotated_image, detections=detections)
    
    cv2.imshow("output", annotated_image)
    cv2.waitKey(1)

# create an inference pipeline object
pipeline = InferencePipeline.init(
    model_id="yolov8n-640", 
    video_reference='/path/to/video'
)
# start the pipeline
pipeline.start()
# wait for the pipeline to finish
pipeline.join()

在 Nvidia Jetson AGX Xavier 设备上运行这两种程序后,我们得到了以下吞吐量的测量结果:

  • OpenCV(同步):20.1 FPS

  • Roboflow(异步):22.3 FPS

由此可见,多线程的应用带来了 11% 的性能提升,这已经是一个相当不错的成绩了。

四、选择正确的推理引擎再对比加速效果

通常情况下,机器学习(ML)模型是在 PyTorch 或 Tensorflow 等框架中进行训练的。这些框架主要目的是便于模型的训练。训练完成后,这些模型可以转换为以部署为中心的格式,从而利用加速后端实现更快的推理。推理引擎通常是针对特定芯片组进行优化的。常见的推理引擎包括:

  • TensorRT(适用于 Nvidia GPU)

  • OpenVINO(适用于英特尔 x86 CPU)

  • Tensorflow Lite / Lite Micro(适用于嵌入式设备)

  • ONNX(适用于多平台)

回到前面的例子,Roboflow Inference 默认使用 ONNX 运行时引擎。为了充分发挥 Jetson 设备上 Nvidia GPU 的性能,我们可以通过设置相应的环境变量来启用 TensorRT。这样会从 YOLOv8 权重文件编译出 TensorRT 模型引擎。再次运行上述两种推理流程后,我们得到了以下结果:

  • OpenCV(同步):26.7 FPS

  • Roboflow(异步):31.9 FPS

TensorRT 引擎为这两条管道都带来了显著的性能提升。有趣的是,两条管道之间的吞吐量差距从 11% 扩大到了 19%,这表明异步管道从加速引擎中获得了更多的好处。

五、加速其余流程

在加速了推理步骤之后,我们还可以继续提升其余管道组件的性能。为此,我们使用了 Nvidia 的 Deepstream SDK。该 SDK 将推理管道拆分为一组基于 GStreamer 媒体框架构建的硬件优化插件。

我们使用以下 Deepstream 插件构建了相同的推理管道:

  • UriDecodeBin:自动解码一系列视频源,包括已保存的文件、USB 摄像头和 RTSP 流

  • Nvstreammux:批处理帧并实例化 NvDsBatchMeta 以保存推理结果和帧元数据

  • Nvinfer:TensorRT 推理引擎

  • Nvvideoconvert:将帧转换为可显示的格式

  • Nvosd:屏幕显示容器

  • Sink:在桌面上显示或保存到文件

  • 队列:实现管道元素之间的异步

这相当于使用 Deepstream Python 绑定的以下 Python 应用程序。

import gi
gi.require_version('Gst''1.0')
from gi.repositoryimportGLibGst
import sys
# append the dir containing helper functions from deepstream-python-apps
sys.path.append('/opt/nvidia/deepstream/deepstream-6.3/sources/deepstream_python_apps/apps')
from common.bus_callimport bus_call
import pyds

# DeepStream configuration for the application
# InitializeGST
Gst.init(None)

# Create the pipeline
pipeline = Gst.Pipeline()

# Create the video source
uri_name = 'file:///path/to/video'
source_bin=create_source_bin(0, uri_name)
pipeline.add(source_bin)

# Streammux
streammux = Gst.ElementFactory.make('nvstreammux''streammux')
pipeline.add(streammux)

# Set streammux properties
streammux.set_property('batch-size'1)
streammux.set_property('width'852)
streammux.set_property('height'480)

sinkpad= streammux.get_request_pad("sink_0")
srcpad=source_bin.get_static_pad("src")
srcpad.link(sinkpad) 

# Create the primary inference element (GIE)
primary_gie = Gst.ElementFactory.make('nvinfer''primary-gie')
primary_gie.set_property('config-file-path''/path/to/yolov8/config/file')

# Createnvvidconv (video converter)
nvvidconv = Gst.ElementFactory.make('nvvideoconvert''nvvidconv')

# Create the OSD (On-ScreenDisplay)
osd = Gst.ElementFactory.make('nvdsosd''osd')

# Create the sink (display output)
sink = Gst.ElementFactory.make('nv3dsink''sink')
sink.set_property('sync'0)

# Add elements to pipeline
pipeline.add(primary_gie)
pipeline.add(nvvidconv)
pipeline.add(osd)
pipeline.add(sink)

# Create queue elements for asynchronous pipeline
queue1=Gst.ElementFactory.make("queue","queue1")
queue2=Gst.ElementFactory.make("queue","queue2")
queue3=Gst.ElementFactory.make("queue","queue3")
pipeline.add(queue1)
pipeline.add(queue2)
pipeline.add(queue3)

# Link elements
streammux.link(queue1)
queue1.link(primary_gie)
primary_gie.link(queue2)
queue2.link(nvvidconv)
nvvidconv.link(queue3)
queue3.link(osd)
osd.link(sink)

# Initialize loop
loop = GLib.MainLoop()
bus = pipeline.get_bus()
bus.add_signal_watch()
bus.connect ("message", bus_call, loop)

# Start playing the pipeline
pipeline.set_state(Gst.State.PLAYING)

# Start the main loop
try:  
    loop.run()
except Exceptionase:
    print("Error during pipeline execution:", e)
    pass

pipeline.set_state(Gst.State.NULL)

运行该应用程序后,我们获得以下吞吐量测量值:

  • Deepstream— 异步:48.2 FPS

与前两种实现方式相比,性能又有了显著的提升。

总的来说,本教程展示了如何使用 Roboflow Inference Pipeline 和 Deepstream SDK 构建异步和加速推理管道,从而使吞吐量提高了 2 倍以上。

对于那些性能受到严重限制的设备,还可以通过其他技术进一步降低推理延迟,例如帧批处理、模型量化和修剪以及使用更简单的模型。希望本指南能够对你开发实时视觉应用程序有所帮助。

THE END !

文章结束,感谢阅读。您的点赞,收藏,评论是我继续更新的动力。大家有推荐的公众号可以评论区留言,共同学习,一起进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值