ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

边缘AI目标检测实战:YOLO部署全流程与避坑指南

边缘AI目标检测实战:YOLO部署全流程与避坑指南 1. 边缘AI落地为什么总绕不开YOLO1.1 从一次产线改造说起去年帮朋友的一个小型注塑车间做质检改造需求说起来特别朴素在流水线末端装一个摄像头把有缺料、飞边、变形的产品挑出来替代原来两个工人轮班盯着看。预算给得很死硬件加开发一共不到两万块还要能离线跑车间网络时断时续不可能把视频流传到云端去推理。这个需求一摆出来方案空间其实就被压缩得很窄了。云端推理直接排除剩下的就是边缘设备本地跑模型。而边缘设备能选什么一块树莓派、一块Jetson Nano、一块RK3588的开发板或者干脆一台带核显的迷你主机。这些设备的算力从零点几TOPS到几TOPS不等内存普遍在2G到8G之间你要在上面跑一个能实时处理1080p视频流的目标检测模型可选的路其实不多。我当时试过几条路。一条是用传统图像处理阈值分割加轮廓提取针对缺料这种缺陷确实能work但飞边和变形这两种缺陷形态太随机传统方法调参调到崩溃也覆盖不全。另一条是用轻量分类网络把产品抠出来做二分类但问题是产品在画面里的位置不固定你得先定位再分类这就又回到了检测的范畴。绕来绕去最后还是回到了YOLO。这不是我一个人的经验。你去看任何一个边缘AI的落地案例只要是涉及“在画面里找东西并判断它是什么”这个任务十有八九最后选的都是YOLO系列。这不是因为YOLO是唯一的选择而是因为在边缘这个约束条件下YOLO在精度、速度、部署难度、生态成熟度这四个维度上达成了目前最难被替代的平衡。1.2 边缘设备的真实约束条件要理解为什么是YOLO得先把边缘设备的约束条件说清楚。很多人做算法选型的时候只看mAP觉得精度高的就是好模型这是典型的实验室思维。到了边缘侧约束条件完全变了。算力约束是最硬的一条。边缘设备的NPU或者GPU算力通常只有几TOPS到几十TOPS而且这个算力还要分给视频解码、预处理、后处理。一个在服务器上跑得好好的模型放到边缘设备上可能连一帧都跑不完。我实测过在一块算力约6TOPS的板子上跑YOLOv5s输入640x640FP16精度单帧推理大概在15到20毫秒加上前后处理整体能到30帧左右勉强够用。但如果换成YOLOv5l单帧推理直接飙到80毫秒以上实时性就没了。内存约束是第二条。边缘设备的内存普遍很小模型权重、中间特征图、输入输出缓冲区都要占内存。YOLOv5s的权重文件大概14MBYOLOv8n大概6MB这些数字看起来不大但中间激活值才是大头。输入分辨率越高中间特征图越大内存占用越夸张。我见过有人在2G内存的板子上跑640输入的模型跑着跑着就OOM了最后只能降到416输入。功耗约束是第三条尤其是电池供电的场景。功耗和算力基本是正相关的你要算力就得给电给了电就发热发热了就得散热散热又要占体积。这一连串的连锁反应最后都会反馈到模型选型上。YOLO的轻量版本在这个链条上表现相对好因为它的计算密度高单位算力能处理的像素多。部署约束是第四条也是最容易被忽视的一条。边缘设备的软件栈往往很封闭有的只支持特定格式的模型有的算子支持不全有的量化工具链很难用。你选一个学术上很漂亮的模型结果发现它在目标设备上根本部署不了或者部署了但精度掉得厉害那就白搭。YOLO系列在这方面占了很大便宜因为用的人多各家芯片厂商的部署工具链基本都优先支持YOLO你拿到的模型转换脚本、量化配置、推理demo都是现成的。1.3 YOLO在边缘侧的不可替代性把上面四条约束摆在一起你会发现YOLO几乎是唯一能同时满足的。它的单阶段检测架构决定了它不需要像两阶段检测那样先出候选框再分类一次前向传播就能出结果这对算力紧张的边缘设备至关重要。它的多尺度特征融合设计让它在小目标上也有不错的表现而边缘场景里小目标恰恰很常见比如远处的缺陷、小尺寸的零件。它的轻量版本在参数量和计算量上做了大量优化能在保持可用精度的前提下把模型压到几MB。更重要的是生态。你随便找一个边缘芯片厂商的文档里面一定有YOLO的部署示例。你随便找一个做边缘AI的工程师他大概率跑通过YOLO。这种生态惯性带来的效率提升是巨大的你不需要从零踩坑前人已经把坑填得差不多了。在边缘这种工程导向极强的场景里能快速跑通、稳定运行比理论上的最优解重要得多。2. YOLO到底是怎么工作的2.1 单阶段检测的核心逻辑YOLO的全称是You Only Look Once这个名字本身就点出了它的核心思想只看一次。传统的两阶段检测方法是先让网络生成一堆可能包含目标的候选区域然后对每个候选区域单独做分类和回归这个过程相当于看了两次甚至多次。YOLO把检测任务直接建模成一个回归问题输入一张图网络直接输出所有目标的位置和类别一次前向传播搞定。具体来说YOLO把输入图像划分成SxS的网格每个网格负责预测落在它中心区域的目标。每个网格会输出B个边界框每个边界框包含五个值中心点坐标x、y宽高w、h以及一个置信度。置信度反映的是这个框里有没有目标以及预测框和真实框的重合程度。同时每个网格还会输出C个类别的概率。最后通过非极大值抑制把重叠的框去掉剩下的就是最终检测结果。这个设计的好处是显而易见的。一次前向传播就能出所有结果速度极快。而且因为网络看到的是整张图它能利用全局上下文信息不像滑动窗口那样只能看到局部。但代价也有早期YOLO对小目标和密集目标的检测效果不好因为每个网格只能预测有限数量的目标网格划分又比较粗。后来的版本通过多尺度预测、锚框机制、特征金字塔等手段把这个短板补得差不多了。2.2 从v1到v8的演进脉络YOLO从2015年第一版出来到现在已经迭代了很多代。每一代都在解决前一代的痛点理解这个演进脉络对你选版本和调参很有帮助。YOLOv1是开山之作奠定了单阶段检测的基本框架但精度和召回都不太理想尤其是小目标。YOLOv2引入了锚框机制和批量归一化精度大幅提升还提出了Darknet-19骨干网络。YOLOv3是真正让YOLO火起来的一代引入了多尺度预测和残差结构骨干网络换成Darknet-53在精度和速度之间找到了很好的平衡到现在还有很多项目在用。YOLOv4和YOLOv5主要是工程上的优化把各种trick系统性地整合进来比如Mosaic数据增强、CIoU损失、自适应锚框等让训练更稳定、精度更高。YOLOv6和YOLOv7针对不同硬件做了优化有的偏向GPU有的偏向移动端。YOLOv8是Ultralytics推出的把检测、分割、姿态估计统一到一个框架里API设计得很简洁部署工具链也很完善。对于边缘部署来说我个人的经验是如果你追求极致的轻量YOLOv5n或者YOLOv8n是首选模型小、速度快、部署资料多。如果你对精度有更高要求且设备算力允许YOLOv5s或者YOLOv8s是更稳妥的选择。再往上边缘设备基本就吃不消了除非你有专门的加速硬件。2.3 损失函数里的门道YOLO的损失函数是很多人看论文时容易跳过、但实际调参时又绕不开的部分。它主要由三块组成边界框回归损失、置信度损失、分类损失。边界框回归损失负责让预测框逼近真实框。早期用的是均方误差直接回归x、y、w、h但这种方式对尺度敏感大框和小框的误差权重不一样。后来引入了IoU系列损失直接优化预测框和真实框的重合度。IoU本身有个问题当两个框不相交时梯度为零没法优化。GIoU通过引入最小闭包区域解决了这个问题。DIoU进一步考虑了中心点距离CIoU又加上了宽高比的一致性。现在YOLOv5和v8默认用的都是CIoU实测下来收敛更稳定位更准。置信度损失负责让网络学会判断框里有没有目标。这里有个细节YOLO把置信度定义为预测框和真实框的IoU乘以类别概率但实际训练时正样本的置信度目标值通常设为1负样本设为0然后用二元交叉熵来优化。这个设计是为了让网络在推理时输出的置信度能直接反映框的质量。分类损失负责判断目标类别用的是交叉熵或者二元交叉熵。YOLOv5之后普遍用二元交叉熵因为一个目标可能属于多个类别比如同时是“车”和“红色”多标签分类更灵活。调参的时候这三块损失的权重是需要关注的。默认配置下边界框损失的权重最高分类损失次之置信度损失最低。如果你的场景里定位精度比分类精度更重要可以适当调高边界框损失的权重。反过来如果类别混淆是主要问题就调高分类损失的权重。这个没有标准答案得根据你的数据和任务来试。3. 边缘设备上部署YOLO的完整流程3.1 环境准备与工具选型在边缘设备上部署YOLO第一步是把环境搭起来。这一步看起来简单实际上坑很多尤其是国产芯片的开发板文档质量参差不齐工具链版本混乱很容易卡住。先说通用方案。如果你用的是NVIDIA的Jetson系列那是最省心的因为NVIDIA的生态最完善。你需要装JetPack里面包含了CUDA、cuDNN、TensorRT这些都是YOLO部署的标配。装完之后用Ultralytics的YOLOv8或者YOLOv5的官方仓库直接导出TensorRT引擎然后在Jetson上跑推理就行。整个过程官方文档写得很清楚照着做基本不会出大问题。如果你用的是瑞芯微的RK3588或者RK3568那就要用RKNN工具链。流程是先把PyTorch模型导出成ONNX然后用RKNN-Toolkit2把ONNX转成RKNN模型最后在板子上用RKNN Runtime跑推理。这个流程里最容易出问题的是算子支持有些YOLO版本用的算子RKNN不支持你得改模型结构或者换版本。我的经验是YOLOv5的算子兼容性最好YOLOv8稍微麻烦一点但也能搞定。如果你用的是算能或者寒武纪的芯片流程类似都是ONNX转专有格式然后跑推理。这些厂商的文档通常没有NVIDIA那么细遇到问题得靠社区或者技术支持。我建议在选板子之前先去GitHub上搜一下有没有人在这块板子上成功部署过YOLO有现成的脚本和配置能省你很多时间。软件环境方面Python版本建议用3.8到3.10太新或太旧都可能遇到依赖问题。PyTorch版本要和你的CUDA版本匹配这个在PyTorch官网有对照表。ONNX和ONNX Runtime的版本也要注意不同版本对算子的支持不一样。我一般会用一个conda环境把版本锁死避免污染系统环境。3.2 模型训练与数据准备部署之前得先有模型。如果你用的是预训练模型直接推理那可以跳过这一步。但大多数实际项目都需要用自己的数据训练因为预训练模型的类别和你的场景对不上。数据准备是训练里最耗时的部分。你需要收集图片然后用标注工具把目标框出来。标注工具我推荐LabelImg轻量、好用、支持YOLO格式导出。标注的时候有几个细节要注意框要贴紧目标边缘不要留太多空白被遮挡的目标如果还能辨认也要标出来小目标不要漏标否则模型学不会检测小目标。标注完之后数据要按比例分成训练集、验证集、测试集通常是7:2:1或者8:1:1。数据增强是提升模型泛化能力的关键。YOLO默认开启了Mosaic增强把四张图拼成一张让模型在一张图里看到更多样的目标。还有随机缩放、随机裁剪、色彩抖动、翻转等。这些增强手段能显著提升模型在复杂场景下的表现。但要注意如果你的场景里目标方向是固定的比如产线上的产品永远是正着的那翻转增强反而会引入噪声应该关掉。训练参数方面学习率是最关键的。YOLO默认用余弦退火或者线性衰减初始学习率通常在0.01左右。批量大小根据你的显存来定显存小就调小批量同时按比例调小学习率。训练轮数看数据量几千张图通常跑100到300轮就够了。训练过程中要盯着损失曲线和验证集mAP如果损失不降或者mAP不涨可能是学习率太大或者数据有问题。3.3 模型转换与量化训练出来的PyTorch模型不能直接在边缘设备上跑需要转换成目标设备支持的格式。这个转换过程是部署里最容易掉精度的地方得特别小心。第一步通常是导出ONNX。YOLOv5和YOLOv8都提供了导出脚本一行命令就能搞定。导出的时候要注意输入尺寸和动态轴设置。如果你的输入尺寸是固定的就把动态轴关掉这样转换出来的模型更简洁推理也更快。如果输入尺寸会变那就得开动态轴但有些设备的工具链对动态轴支持不好可能会出问题。第二步是把ONNX转成目标格式。如果是TensorRT用trtexec或者Python API都行。转换的时候要选精度模式FP32最准但最慢FP16速度和精度平衡得比较好INT8最快但需要校准数据集精度损失也最大。边缘设备上我一般先用FP16如果速度不够再考虑INT8。INT8量化需要准备一批代表性图片做校准校准集要覆盖各种场景否则量化后的模型在某些场景下会崩。量化是掉精度的重灾区。我遇到过量化后mAP掉了十几个点的情况排查下来是校准集里缺少某类目标的样本导致那类目标的量化参数不准。解决办法是把校准集做得更全面或者对敏感层保持FP16精度。有些工具链支持混合精度量化就是大部分层用INT8少数关键层用FP16这样能在速度和精度之间找到更好的平衡。3.4 推理代码与性能调优模型转换好之后就要写推理代码了。推理代码的核心流程是读图或者读视频帧预处理缩放、归一化、通道转换推理后处理解码、NMS输出结果。预处理里最容易出错的是颜色通道。OpenCV读进来的是BGR而模型训练时用的是RGB如果不转换检测结果会莫名其妙地差。归一化也要和训练时保持一致通常是除以255。缩放的时候要注意保持宽高比多余的部分用灰边填充这样不会让目标变形。后处理主要是NMS。NMS的作用是去掉重叠的框只保留最好的那个。NMS的阈值需要调阈值太低会误删相邻目标阈值太高会留下重复框。我一般从0.45开始试根据实际效果微调。还有一个置信度阈值低于这个值的框直接丢掉。这个阈值也要调太低会引入大量误检太高会漏检。在产线质检这种场景里我通常把置信度阈值设得高一点宁可漏检不可误检因为误检会导致良品被误判为不良品损失更大。性能调优方面有几个方向可以试。一是降低输入分辨率从640降到416或者320速度能提升不少但小目标检测会变差。二是用多线程或者多进程把预处理和后处理放到CPU上并行推理放到NPU上这样能充分利用硬件资源。三是用批处理一次推理多帧但边缘设备上批处理会增加延迟实时场景要谨慎。四是模型剪枝把不重要的通道剪掉能减小模型体积和计算量但剪枝后需要微调否则精度会掉。4. 实际部署中踩过的坑与排查技巧4.1 精度掉点的常见原因模型在PC上跑得好好的一放到边缘设备上精度就掉这是最常见的问题。原因通常有几个。第一个是预处理不一致。PC上你可能用的是Python的PIL读图边缘设备上用OpenCV两者的缩放算法和颜色通道可能不一样。解决办法是统一预处理流程最好把预处理也放到模型里用ONNX的算子实现这样端到端一致。第二个是量化损失。INT8量化会引入误差尤其是对激活值分布不均匀的层。排查方法是逐层对比量化前后的输出找到误差最大的层对那层保持FP16。有些工具链提供了逐层敏感度分析能直接告诉你哪些层对量化敏感。第三个是算子替换。有些工具链会把某些算子替换成近似实现比如把Sigmoid换成HardSigmoid精度会有细微差别。如果差别太大就得找工具链的文档看能不能关掉这些替换。第四个是输入尺寸不匹配。训练时用的是640推理时用了416模型没重新训练的话精度会掉。解决办法是要么保持尺寸一致要么用416重新训练或者微调。4.2 速度不达标的优化思路速度不达标也是高频问题。你预期30帧实际只有10帧得一步步排查。先看瓶颈在哪。用工具链自带的profiler看推理耗时、预处理耗时、后处理耗时各占多少。如果推理占大头那就是模型太重或者硬件没跑满。如果预处理占大头那就是CPU太慢或者代码写得低效。如果后处理占大头那就是NMS太慢或者框太多。推理慢的话先确认硬件是不是真的在跑。有些板子默认用CPU推理你得手动切到NPU。切过去之后确认模型是不是真的跑在NPU上有些工具链会静默回退到CPU。确认没问题之后再考虑降分辨率、换更小的模型、用量化。预处理慢的话尽量用硬件加速。比如用GPU做缩放和颜色转换比CPU快很多。后处理慢的话可以限制检测框的数量或者用更快的NMS实现。有些工具链提供了NPU上的NMS比CPU快一个数量级。4.3 常见问题速查表问题现象可能原因排查方法解决思路精度大幅下降量化损失对比量化前后逐层输出敏感层保持FP16扩充校准集推理速度慢模型跑在CPU上查看推理日志或profiler切换到NPU确认算子支持检测框偏移预处理不一致对比PC和设备的预处理输出统一预处理流程端到端验证漏检严重置信度阈值过高降低阈值观察召回变化调低阈值或重新训练误检严重置信度阈值过低提高阈值观察精度变化调高阈值或增加负样本小目标检测差输入分辨率太低提高分辨率对比效果提高分辨率或用多尺度推理内存溢出中间特征图太大监控内存占用降低分辨率或换更小模型类别混淆分类损失权重低查看混淆矩阵调高分类损失权重增加数据4.4 几个独家避坑技巧第一个技巧是关于校准集的。做INT8量化的时候校准集不要只用训练集里的图要专门收集一批覆盖各种光照、角度、遮挡情况的图。我一般会从实际部署场景里录一段视频抽帧做校准集这样量化后的模型在实际场景里表现最稳。第二个技巧是关于模型导出的。导出ONNX的时候把opset版本设成11或者12兼容性最好。太新的opset有些工具链不支持太旧的又缺算子。导出之后用onnx-simplifier过一遍能去掉冗余算子简化计算图对后续转换和推理都有好处。第三个技巧是关于阈值调的。置信度阈值和NMS阈值不要拍脑袋定用验证集跑一遍画PR曲线找F1最高的那个点。实际部署时再根据业务需求微调比如质检场景偏向高精度就把阈值往高调。第四个技巧是关于版本锁定的。边缘部署最怕环境漂移今天跑得好好的明天换个版本就崩了。我习惯把整个环境用Docker打包包括Python版本、依赖库版本、模型文件、推理脚本全部锁死。这样换设备或者重装系统的时候直接拉镜像就行不用重新配环境。5. 边缘AI目标检测的选型思考5.1 什么场景适合YOLOYOLO不是万能的它有自己适合的场景。如果你的任务是通用目标检测目标类别是常见的几十类场景光照和角度变化不是特别极端那YOLO基本是首选。它的精度够用速度快部署方便生态成熟。如果你的任务是小目标检测比如航拍图里的车辆、遥感图里的建筑YOLO也能用但需要调输入分辨率、用多尺度推理、或者改网络结构。YOLOv8在这一点上比早期版本好很多但小目标依然是难点可能需要专门的数据增强和损失函数调整。如果你的任务是密集目标检测比如人群计数、零件计数YOLO的表现取决于目标的密集程度。太密集的话NMS会误删相邻目标这时候可能需要换基于点的检测方法或者改NMS策略。如果你的任务对精度要求极高比如医疗影像里的病灶检测YOLO可能不够得用更大的模型或者两阶段方法。但边缘设备上跑大模型不现实这种场景通常还是得把推理放到服务器上。5.2 替代方案的对比YOLO之外边缘侧还有几个可选的目标检测方案。SSD是另一个单阶段检测器比YOLO早一点出来结构更简单但在小目标上表现不如YOLO现在用的人越来越少了。如果你维护的是老项目可能会遇到SSD新项目不建议选。RetinaNet引入了Focal Loss解决了正负样本不平衡的问题精度不错但速度比YOLO慢边缘设备上跑起来吃力。EfficientDet是Google出的用EfficientNet做骨干精度和效率平衡得不错但部署生态没有YOLO成熟工具链支持差一些。Anchor-free的方法比如FCOS、CenterNet结构更简洁超参数更少但在边缘设备上的部署资料比较少遇到问题不好找答案。综合来看边缘侧选YOLO主要图的是生态和部署便利性。精度上它可能不是每一项都最优但综合成本最低。在工程场景里综合成本往往比单项指标更重要。5.3 后续扩展的方向YOLO部署好之后还有很多可以扩展的方向。一个是多模型串联。比如先用YOLO做目标检测把目标抠出来再用一个分类网络做细分类或者用一个分割网络做像素级分割。这种串联方案能在不显著增加计算量的前提下提升整体精度。另一个是模型集成。训练多个YOLO模型推理时取平均或者投票能提升精度和鲁棒性但计算量翻倍边缘设备上要谨慎。还有是持续学习。部署之后收集badcase定期用新数据微调模型让模型适应场景的变化。这个在产线场景里特别有用因为产品会更新缺陷形态会变化模型得跟着迭代。最后是端云协同。边缘设备做初步筛选把可疑的帧传到云端做精细分析这样既能保证实时性又能利用云端的算力。这个方案对网络有要求但很多工厂现在都有内网可行性越来越高。我个人在实际操作中的体会是边缘AI项目成功的关键不在于选了多先进的模型而在于把工程细节做扎实。预处理、量化、后处理、阈值调优每一个环节都可能成为瓶颈。YOLO之所以成为默认选择不是因为它完美而是因为它让工程师能把精力集中在这些工程细节上而不是在模型本身踩坑。
返回列表