
简介本资源是面向嵌入式AI开发者与边缘计算工程师的RK3588平台YOLOv8多线程推理实战Demo聚焦于高性能视频流实时检测场景解决ARMNPU异构平台下模型部署、多线程数据流水与低延迟推理等核心问题。压缩包共41个文件9个头文件、9个C源码、6个RKNN量化模型、3个ONNX中间模型、6个说明文本及2份Markdown文档涵盖摄像头/视频文件双路输入适配、Yolov8n模型推理主流程、ROS2集成参考及性能调优关键配置整体大小95.38MB。已有918人下载学习适合具备C基础与RKNN开发经验的进阶用户快速上手国产AI芯片部署。读者可直接复用多线程Pipeline架构、获取已验证的RK3588Yolov8n全链路代码含CMake构建、模型加载、预处理与后处理、参考xlsx对比文档理解v8/v10差异并通过附带MP4演示视频直观评估100FPS级实时推理效果。RK3588上跑Yolo多线程推理从视频文件到摄像头实时识别我把帧率压到了100fps最近在RK3588平台上做目标检测落地把之前的Yolo推理demo重新整理了一遍。这个项目一开始的定位很明确跑通一条完整的推理链路——从视频文件和摄像头读取画面经过模型推理最终输出检测结果。当时手里正好有一块RK3588开发板就想着把Yolov8n模型部署上去实测下来最高推理帧率能到100帧/秒。今天把这套多线程推理demo的完整思路、代码框架和调优过程整理出来给正准备在RK3588上做视觉方案的朋友一个参考。这个demo适合谁看如果你手上有RK3588开发板想把Yolo系列模型跑起来或者正在纠结怎么设计多线程推理框架这篇文章应该能帮你少走不少弯路。我尽量把关键代码和踩坑细节都说透不是那种只能看不能跑的代码而是真正能跑到100fps的完整方案。1. 项目背景与整体设计思路1.1 这块板子到底能干什么RK3588是瑞芯微推出的一款ARM架构SoC8核心设计4个A76大核加4个A55小核内置的NPU算力标称6 TOPS。这个算力在端侧设备里算是相当能打的了。但说实话光看算力数字没有意义关键是这个算力能被高效利用起来。我当时拿到板子之后的第一个想法就是能不能把Yolo这种稍微重一点的检测模型跑起来并且在多路视频流或者高清视频场景下保持实时性。很多人容易忽略的一点是RK3588不只有NPU它的编解码能力也很强。板载的VPU支持4K 60fps的H.265/H.264硬件编解码。这意味着视频流处理的瓶颈根本不在CPU上解码交给硬件就能搞定。CPU可以腾出来做调度和预处理NPU专注做推理整个系统并行运转这才是能达到高帧率的核心逻辑。我这次demo的目标场景其实覆盖了两类一类是读取本地视频文件做离线分析另一类是直接接摄像头做实时识别。这两类应用在安防、工业质检、智慧交通里非常典型。demo做的时候就把两种输入源统一进去了切换起来很方便。1.2 demo要解决的核心问题这个demo叫“多线程推理”但多线程不是目的要解决的实际问题主要是三个第一视频源阻塞问题。如果单线程里又读帧又做推理摄像头的帧率波动或者解码偶尔卡顿会直接把推理线程拖住。第二NPU利用率问题。推理请求是断续的如果每次推理之间都要等数据准备NPU的空闲时间会非常长。第三整体时延问题。即使单帧推理很快但如果采集、预处理、推理、后处理全部串行端到端的延迟仍然会很大。用多线程把各个环节拆开让采集线程、解码线程、推理线程、显示线程各干各的活中间用队列衔接就能让整个流水线持续运转。就好比工厂流水线每个工位只负责自己那一道工序上一道工序做完往传送带上一放下一道工序立刻接着做整条线就不会停下来等。这就是多线程推理的核心价值。2. 硬件平台与工具链选型解析2.1 为什么选RK3588而不是其他平台在端侧做视觉推理市面上常见的方案有几种NVIDIA Jetson系列、瑞芯微RK系列、地平线征程系列还有各种带NPU的手机SoC。我做这个demo选择RK3588理由其实很务实。首先是算力够用。6 TOPS的NPU算力跑Yolov8n这种轻量模型绰绰有余。我实测单次推理时间大约在10毫秒左右。其次是接口丰富。RK3588有MIPI-CSI接口可以直接接摄像头也有PCIe、USB3.0等接口扩展性很强。再加上HDMI输入输出配合VPU硬解能力非常适合做视频处理类的设备。最关键的一点是RKNN工具链的成熟度。瑞芯微提供的rknn-toolkit2支持从ONNX、PyTorch、TensorFlow等格式转换成RKNN格式模型整个转换流程比较顺踩坑点也比较少。相比某些平台的NPU只能用自研框架、模型兼容性差的情况RK3588的部署体验在国产平台里算第一梯队。这里要提醒一句RK3588平台还支持通过UEFI方式启动可以引导标准的Linux发行版对习惯用Ubuntu的开发环境的人来说非常友好。我这个demo就是在Ubuntu RKNN SDK环境下跑的。2.2 模型选型为什么是Yolov8nYolo系列已经发展了很多个版本从Yolov5到Yolov8再到最新的一些改进版本。demo选Yolov8n不是拍脑袋决定的核心考虑是推理速度与精度的平衡点。Yolov8n里的“n”代表nano是Yolov8系列里最小的版本。它的参数量大约只有3.2M计算量在8.7 GFLOPs左右。这个规模在RK3588的NPU上跑起来毫无压力单帧推理延迟可以控制在10ms以内。如果是用Yolov8s或者更大的版本算力开销会成倍增加在6 TOPS的平台上很难做到100fps。实用性角度来看Yolov8n的精度在常见检测场景里完全够用尤其是配合输入分辨率控制可以在速度和精度之间灵活调节。我在demo里把输入分辨率设成640x640这是Yolo系列的默认输入尺寸。如果你想追求更高帧率还可以把分辨率调到320x320帧率能再提升不少但精度会有一定损失。另外说明一点yolo模型在端侧的部署不只是目标检测一个方向很多人做车牌识别、实例分割、目标跟踪也会用Yolo系列做前置检测器。这个demo用的目标检测是基础版本你完全可以把检测头换成其他任务的模型框架思路是不会变的。2.3 工具链ONNX到RKNN的转换路径要在RK3588的NPU上跑Yolo模型第一步是把训练好的模型转换成RKNN格式。这个过程大概是这样的训练好的PyTorch模型先导出成ONNX格式然后用rknn-toolkit2把ONNX转成RKNN格式。转换的时候有几个关键参数要特别注意mean_values和std_values要跟训练时候的预处理保持一致不然推理结果会偏得离谱量化方式选择int8可以显著提升推理速度但会对精度有一定影响。我用的转换脚本核心部分大概是这样的from rknn.api import RKNN rknn RKNN(verboseTrue) # 配置模型输入注意RK3588的NPU对输入格式有要求 rknn.config( mean_values[[0, 0, 0]], std_values[[255, 255, 255]], target_platformrk3588 ) # 加载ONNX模型 ret rknn.load_onnx(modelyolov8n.onnx) if ret ! 0: print(模型加载失败) exit(-1) # 构建RKNN模型do_quantizationTrue表示int8量化 ret rknn.build(do_quantizationTrue, datasetdataset.txt) if ret ! 0: print(模型构建失败) exit(-1) # 导出RKNN模型 ret rknn.export_rknn(yolov8n.rknn) if ret ! 0: print(模型导出失败) exit(-1)这里有个细节dataset.txt里要放若干张代表性图片的路径量化的时候会拿这些图做统计计算激活值的分布范围。图片选得越有代表性量化后的精度损失就越小。我当时选了几百张包含各种检测目标的图片这样量化后的模型在不同场景下表现都比较稳定。如果你用的是yolov8其他版本比如带旋转框的OBB模型或者实例分割模型转换流程会稍微复杂一点需要处理额外的输出头但基础步骤是一样的。3. 多线程流水线整体架构设计3.1 四段式流水线到底怎么划分整个demo的核心架构可以概括成一句话把视频处理拆成四个独立的环节用多线程并行执行。这四个环节包括视频采集、解码与预处理、模型推理、结果绘制与输出。视频采集线程负责从视频文件或者摄像头读取原始数据。如果是视频文件就是按帧率读取读出压缩后的视频帧如果是摄像头则是通过V4L2接口获取传感器采集到的原始图像数据。解码与预处理线程拿到原始数据后如果是编码后的视频帧就通过RK3588的硬解码器MPP解码成YUV图像再转换成RGB、缩放到模型输入尺寸。预处理还包括归一化操作把像素值从0到255映射到0到1之间。推理线程是这个流水线的核心它持有RKNN上下文负责接收预处理好的图像数据送入NPU执行推理然后对输出做后处理——解码出检测框坐标、类别和置信度再用NMS去除重复框。绘制与输出线程负责把检测结果画到原始图像上然后用显示窗口显示或者编码压缩后输出成新的视频文件。这四个线程之间用队列传递数据。每两个相邻线程之间有一个缓冲区队列生产者线程把处理好的数据放到队列尾部消费者线程从队列头部取数据继续处理。如果某个环节比较慢队列会起到缓冲作用不会直接把上游线程卡死。3.2 线程间同步无锁队列还是加锁队列多线程编程最核心的问题就是数据共享与同步。这个demo里四个线程之间需要传递图像数据如果处理不好会出现数据竞争或者死锁问题。我最初用的是std::mutex加std::condition_variable的方式来实现线程间同步。生产者往队列里放数据的时候加锁通知消费者可以取数据了消费者取数据的时候加锁如果队列为空就等待通知。这套逻辑是最经典的生产者消费者模型优点是实现简单、逻辑清晰、不容易出错缺点是有锁竞争的开销。在实测过程中我发现在高帧率场景下锁竞争的开销其实很小。因为图像数据比较大拷贝和预处理的时间远大于锁操作的时间。真正影响性能的是数据拷贝——如果每帧图像在队列传递过程中都要拷贝一次CPU带宽和内存占用会很高。所以我在设计上做了两个优化一是队列里传的是图像数据的指针或者引用而不是图像本身二是用环形缓冲区替代无界队列固定分配内存避免频繁地new和delete。具体实现上我用了一个简单的有界队列类内部是一个固定大小的vector配合读写指针来实现出入队操作用mutex和condition_variable来保证线程安全。这种方式预处理线程和推理线程之间传递图像实测下来非常稳定也不会因为队列无限增长导致内存爆炸。3.3 为什么不采用同步调用可能有人会问既然推理只要10毫秒单线程同步跑也能达到100fps为什么要费劲搞多线程这个问题的答案在于端到端延迟和吞吐量的区别。单线程同步执行的流程是读一帧图像、解码、预处理、推理、绘制、显示然后再读下一帧。假设每一步耗时分别是5ms、3ms、10ms、2ms、2ms那么单线程情况下每帧总耗时是22ms实际帧率只有45fps左右。即使推理本身很快但整个流程串行下来帧率被最慢环节之外的叠加耗时严重拉低。多线程流水线的效果是每个线程只负责自己那一段各线程之间并行执行。第1帧在处理的时候第2帧已经在预处理的路上第3帧可能已经在解码了。这样整体吞吐量取决于最慢的那个环节也就是推理线程。只要推理线程能跑到10ms一帧整个系统就能接近100fps的吞吐量前提是其他环节的速度跟得上。这就是流水线设计的意义——用并行换吞吐量。当然如果你追求的是单帧延迟最低那多线程不一定是最优解因为队列会增加一些等待时间。但在视频流连续处理的场景下大家更关心的是每秒能处理多少帧多线程流水线是绝对的主流方案。4. 核心模块实现拆解4.1 视频采集与输入源统一采集模块要解决这两个输入源的统一问题。我设计了一个VideoSource抽象类提供open()、read()、close()接口然后分别实现FileVideoSource和CameraVideoSource两个子类分别处理视频文件和摄像头。文件视频源比较简单底层用FFmpeg或者OpenCV的VideoCapture就能搞定。摄像头源码稍微复杂一点在Linux系统上需要通过V4L2接口操作设备节点比如/dev/video0。V4L2的初始化流程包括查询设备能力、设置像素格式、设置分辨率、申请缓冲区、启动采集等步骤。我之前在这个项目里遇到过一个问题就是插上USB摄像头后设备节点可能不是固定的/dev/video0重新插拔之后可能变成/dev/video1。这会导致程序打不开摄像头。后来我用了一个更稳健的方式遍历/dev/video*设备节点用VIDIOC_QUERYCAP查询设备能力找到哪个节点是摄像头并且支持我们需要的能力再打开。这样系统里插多个摄像头也不会弄混。RK3588还有一个特色的摄像头接入方式——MIPI-CSI接口。MIPI-CSI摄像头直接挂在SoC上通过ISP处理后输出图像带宽大、延迟低、画质好适合对画质有严格要求的工业场景。代码层面跟USB摄像头类似也是通过V4L2操作但走的是内部ISP通路配置会复杂一些。4.2 解码与格式转换硬解还是软解视频文件和摄像头采集到的数据格式是不一样的。摄像头通过V4L2采集到的通常是原始格式比如YUV422或者MJPEG。视频文件里的帧是编码后的H.264/H.265数据要先解码才能得到图像。RK3588最值钱的地方之一是它有强大的硬件解码器VPU。用硬件解码器处理视频文件CPU占用率极低解码速度飞快可以轻松处理4K视频。如果不用硬件解码而是用FFmpeg的软件解码器4K视频会把CPU占满解码都来不及更别提做推理了。RK3588的硬件解码在Linux下通过MPPMedia Process Platform库来调用。瑞芯微提供了完整的MPP接口支持H.264、H.265、VP9、AV1等多种格式解码输出YUV数据。我demo里处理视频文件时走的就是MPP硬解然后再用RGARaster Graphic Acceleration2D图形加速单元做格式转换和缩放操作。RGA是RK3588上另一个容易被人忽略的加速器。它能做格式转换、旋转、缩放、裁剪等操作完全由硬件完成不占用CPU。我在预处理阶段用RGA把MPP解码出来的YUV图像转成RGB格式同时缩放到640x640分辨率整个过程耗时几乎可以忽略不计。这样CPU就可以专注于图像队列的管理和线程调度整个流水线里CPU几乎不参与图像像素级的运算所有重活都交给了VPU、RGA和NPU。这就是能达到100fps的关键底层支撑。4.3 推理线程的实现与输出解析推理线程拿到预处理好的图像数据后调用RKNN接口执行推理。RKNN的推理接口很简单核心是一个rknn_run()调用但里面有个容易踩坑的地方——输入数据的格式。RK3588的NPU对输入数据的排布方式有要求默认是NHWC格式即通道在最后。但是很多训练框架导出的模型是NCHW格式即通道在第二个维度。RKNN在转换模型的时候会自动处理这个差异但你在调用推理接口时必须按照模型转换时要求的格式来填充输入缓冲。我demo里用的是rknn_input结构体pass_through字段设为0表示数据需要经过内部预处理同时设置正确的fmt为RKNN_TENSOR_NHWC。推理输出的解析也是很多新手容易搞不明白的地方。Yolov8的输出跟Yolov5不太一样它是一个张量形状是[1, 84, 8400]其中84表示4个框坐标加80个类别概率8400是不同尺度下的候选框数量总和。后处理的时候第一步是遍历所有候选框找出置信度大于阈值的框第二步是把取出的框坐标映射回原始图像尺寸第三步是对这些框做NMS去重。Yolov8的输出是解耦的不需要像Yolov5那样先做objectness乘以class probability的计算解析起来反而更简单。后处理这部分我建议用多线程做优化——如果你的CPU核心多可以把8400个候选框按类别分组并行处理能显著降低后处理耗时。我的demo里后处理在A76大核上跑单帧大约需要2ms够用。4.4 帧率统计与结果可视化帧率统计是评估推理性能最直观的指标。我实现了一个简单的滑动平均帧率计算器维护一个时间戳队列每秒统计一次当前队列里有多少帧被处理完然后清零重新计数。这样显示的fps值比较平滑不会因为个别帧的抖动导致读数剧烈波动。在显示环节我用OpenCV的imshow窗口显示检测结果同时在图像左上角叠加fps信息。如果你是要部署到嵌入式设备上的正式方案显示模块通常会被替换成RTSP推流或者封装成API接口但demo阶段用OpenCV显示是最方便的方便肉眼验证检测效果。显示线程还有一个作用就是配合按键交互实现退出逻辑。我在循环里监听键盘事件按下q键就退出整个程序。所有线程通过一个全局的atomicbool标志来控制退出析构阶段按顺序通知各个线程停止然后join回收线程资源。整个线程框架的代码结构大致如下class InferencePipeline { public: void start() { running_ true; capture_thread_ std::thread(InferencePipeline::captureLoop, this); preprocess_thread_ std::thread(InferencePipeline::preprocessLoop, this); infer_thread_ std::thread(InferencePipeline::inferLoop, this); display_thread_ std::thread(InferencePipeline::displayLoop, this); } void stop() { running_ false; // 唤醒所有等待中的线程 queue_capture_.wakeup(); queue_preprocess_.wakeup(); queue_infer_.wakeup(); // 回收线程 capture_thread_.join(); preprocess_thread_.join(); infer_thread_.join(); display_thread_.join(); } private: std::atomicbool running_{false}; BoundedQueuecv::Mat queue_capture_; // 原始帧队列 BoundedQueuecv::Mat queue_preprocess_; // 预处理后队列 BoundedQueueInferResult queue_infer_; // 推理结果队列 };5. 性能调优与实测数据5.1 100fps是怎么跑出来的标题里写了“最高推理帧率可达100帧/秒”这不是空口白话。我实测的场景是用RK3588读取视频文件做推理视频源是1080p、H.264编码。300帧的视频文件从开始读取到全部推理完成总共耗时约3秒换算下来帧率确实在100fps左右。这个高帧率其实是多个因素共同作用的结果。模型小是基础前提。Yolov8n本身计算量小NPU推理时间大约8到12毫秒。硬解与硬件加速是倍增器。视频解码走MPP硬解格式转换和缩放走RGACPU几乎没有参与图像处理省下的CPU资源全部用于线程调度和后处理。最关键的是流水线并行。四个环节并行工作端到端吞吐量接近最慢环节的速率。推理环节约10毫秒其他环节只要控制在10毫秒内整体帧率就能拉到100fps。我在demo中对三个队列都设置了深度限制避免某一路输入速度过快导致内存膨胀。这里还要提一个容易被忽视的参数——输入分辨率。我用的是640x640输入如果你换成320x320NPU推理时间可以降到5毫秒左右帧率还能再翻倍但精度会下降。实际部署中要根据业务需求权衡。如果检测目标比较小建议保持640或者更高分辨率如果只是检测人、车这种大目标320就够。5.2 线程绑定与CPU调度RK3588有4个A76大核和4个A55小核。A76性能强、功耗高A55省电但性能弱。线程调度如果不做干预操作系统可能会把重负载线程调度到小核上导致性能下降。我在demo里用了线程亲和性绑定把推理线程和后处理线程绑定到A76大核上把采集线程和解码线程放到A55小核上。具体代码使用pthread的pthread_setaffinity_np接口。先调用sysconf(_SC_NPROCESSORS_ONLN)获取CPU核心数然后指定要绑定的核心编号。RK3588的CPU编号一般是0-3为A554-7为A76。把最消耗CPU的两个线程绑到4号和5号核心上其他线程绑到0到3号核心上。这个优化做之前帧率大约70到80fps做之后稳定在100fps左右。因为A76的整数计算能力是A55的好几倍后处理的NMS循环和解析逻辑跑在大核上确实快很多。如果你也遇到帧率上不去的情况检查一下线程都被调度到哪个核上了这可能就是一个隐藏的瓶颈。5.3 内存复用申请一次内存循环使用图像处理demo里一个常见的问题是频繁的内存分配和释放。每帧图像都是几百KB甚至几MB的数据如果每帧都重新分配内存内存分配器的开销会很大还会产生内存碎片。我的优化方案是在流水线启动之前预先分配好几块足够大的图像缓冲区放到一个空闲队列里。采集线程从空闲队列取一块内存把图像数据填充进去然后把这块内存放到下一级队列。下游线程处理完后再把这块内存归还到空闲队列。整个循环过程中不产生任何新的内存分配彻底消除了内存分配开销。这个模式在图像处理领域非常常见核心思想就是内存池复用。尤其在高帧率场景下这个优化带来的收益非常明显。如果你的demo跑一段时间后内存占用持续增长那大概率是某处内存泄漏或者队列里堆积了太多帧排查思路可以从队列长度和内存分配两个方向入手。RK3588平台还有零拷贝的可能性比如NPU输入直接引用RGA输出缓冲区避免在CPU和NPU之间搬运数据。我在demo里没有做这套但如果你追求极致性能可以研究一下RKNN和RGA的dma_buf共享机制理论上可以把每帧的拷贝开销降为零。6. 常见问题与实操排坑6.1 摄像头只能打开一次第二次打开就报错这个问题我遇到过也看到很多人在论坛上问。现象是第一次打开摄像头读取图像正常程序退出后再次运行打开摄像头失败。根本原因在于摄像头设备没有正确释放。V4L2设备在打开时需要申请缓冲区退出时必须释放缓冲区并关闭设备。如果程序异常退出或者没有走完整的释放流程内核里的设备状态就没被清理干净。解决办法有两个层面。程序层面确保退出时调用VIDIOC_STREAMOFF停止采集munmap取消内存映射close关闭设备文件。系统层面如果摄像头设备状态卡死了可以重新插拔USB摄像头或者做一些系统层的复位操作恢复设备状态。在RK3588平台上有些MIPI-CSI摄像头还涉及到ISP管线的状态复位可能还需要重启ISP相关服务。6.2 检测画面颜色不对要么偏绿要么偏紫推理出来的检测框位置是对的但显示画面颜色发绿发紫。这是典型的图像格式理解不一致问题。从摄像头采集到的原始数据大多数是YUV格式比如YUV422或NV12NPU模型训练时用的是RGB图像。如果YUV转RGB的时候颜色通道对应关系搞错了或者YUV的排列方式理解错了就会出现颜色错乱。排查方法是分步验证先用系统自带的工具比如v4l2-ctl采集一张原始图像保存下来确认摄像头输出的颜色本身就是对的然后再检查转换代码中YUV到RGB的转换矩阵是否正确。在RK3588上用RGA做转换时要确认输入的src_format和输出的dst_format都配置对了。比如NV12转RGB要指定正确的宽高对齐参数否则转换出来的图像可能会出现边缘错位或者颜色不对。6.3 帧率上不去总在四五十帧徘徊代码逻辑看起来没问题但帧率就是上不去。这种情况通常不是某一个环节慢而是整个流水线的瓶颈没有找对。我建议做一个简单的耗时统计在每个线程的关键步骤前后打时间戳看哪个环节耗时最长。常见瓶颈有几个解码太慢如果用的是软件解码而不是MPP硬解CPU会被解码占满预处理慢OpenCV的resize和cvtColor在CPU上跑比较耗时应该改用RGA线程调度不合理重负载线程被调度到小核上队列设计不合理队列长度太短导致生产者频繁阻塞。我之前遇到的一个隐蔽问题是OpenCV的HighGUI显示拖慢帧率。在嵌入式平台上OpenCV的窗口显示是用GTK实现的渲染效率不高。如果显示线程跟主逻辑混在一起整个流水线都会被拖慢。解决方法是把显示操作放到独立线程并且允许显示线程丢弃来不及显示的帧只保证显示最新一帧。这样即使显示端跟不上也不会影响推理链路的速度。6.4 内存持续增长跑着跑着系统就卡了内存泄漏在C多线程程序里很容易出现尤其是涉及图像数据传递的时候。最常见的原因是队列中的图像没有正确释放或者智能指针的循环引用导致对象永远无法析构。推荐用内存池的方式彻底规避这个问题。前面讲到过所有图像缓冲区在启动时就分配好通过空闲队列循环利用。这样从源头上杜绝了动态内存分配自然也不会出现泄漏。另外建议在调试阶段给程序加上-fsanitizeaddress编译选项ASan会直接报告内存泄漏的具体位置排查起来效率高很多。还有一个小技巧用/proc/{pid}/status里的VmRSS字段监控进程内存变化如果内存稳定说明没有泄漏如果不断增长就需要排查了。7. 后续扩展建议这个demo的框架本身是通用的。我后来尝试过把模型替换成Yolov5s来做车牌识别场景的预研只需要改一下模型转换脚本和后处理解析部分整个多线程流水线不用动。这说明架构设计的前瞻性很重要——先把数据流的框架搭好后续换模型、加功能都只是“插入”而不是“重写”。如果你想在这个demo基础上做更复杂的事情有几个方向可以考虑。第一是多路视频流处理一个推理线程可能跟不上多路输入的需求可以在流水线框架上增加多路并行处理的能力。第二是动态模型切换通过模型选择器在运行过程中切换不同的检测模型适配不同的检测需求。第三是接入跟踪算法在检测结果的基础上加DeepSORT等跟踪算法实现目标的持续跟踪和计数。我自己在实际操作中的体会是跑通一个demo并不难难的是把每一处的细节都搞清楚。为什么用多线程为什么用RGA做预处理为什么量化用int8这些问题想明白了你才算真正掌握了一套可以在生产环境中复用的推理框架。希望这篇实践分享能帮你省下一些在坑里摸索的时间。本文还有配套的精品资源点击获取