十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

高分辨率工业检测实战:YOLOv5调优、TensorRT加速与边缘部署

高分辨率工业检测实战:YOLOv5调优、TensorRT加速与边缘部署 接手这个项目的时候甲方给的需求并不复杂在一条产线上用海康工业相机对产品表面做实时检测检出微小缺陷并分类。但真正把相机架起来、把YOLOv5跑起来之后才发现高分辨率输入带来的问题远比想象中多——显存占用暴涨、推理帧率跳水、小目标漏检严重甚至相机偶尔丢帧、触发信号不稳定都把整个流程带崩过。这篇文章把整个实践过程从头到尾拆开讲包括工业相机怎么接、触发信号怎么排查、YOLOv5在高分辨率输入下怎么改怎么调、数据集标注怎么快速搞定、TensorRT加速后能跑到什么程度以及在Jetson Nano这类边缘设备上部署的实测结果。内容是我踩坑踩出来的能帮想入这个坑的人少走不少弯路。1. 高分辨率检测为什么是个硬骨头从漏检追溯到根本矛盾先说结论大多数跑在YOLOv5上的项目训练和推理都用了640x640或1280x1280的输入这在高分辨率工业检测场景下会直接翻车。我一开始用的是一张4096x3000的样图直接resize到640x640送进模型检测结果惨不忍睹——几个毫米级划痕全漏了只有一个较大缺陷被框了出来。原因不复杂就是目标尺寸和输入缩放之间的矛盾。一个只有30x20像素的微小缺陷在4096宽的图像里占比不到1%直接缩放到640宽时缺陷区域被压成了大概5x3像素这个大小已经远低于YOLOv5特征层能够有效感知的极限。要知道YOLOv5下采样32倍后的最小特征图只有20x20640输入5x3像素的目标在特征图上可能连一个完整anchor都分不到。这种情况下第一个直觉是“把模型输入调大”比如直接上1280甚至1536。这确实有效果但随之而来的代价非常现实。我这里列一下实测的显存和速度数据用的是一张RTX 3080 10G的卡模型是YOLOv5s输入分辨率推理耗时(ms)显存占用(GB)缺陷召回率640x6406.81.252%1280x128021.54.178%1920x192047.28.786%原始4032x3024爆显存10G无法运行从这个表格能看到输入分辨率从640涨到1920召回率确实在涨但显存占用和推理延时的增长更吓人。如果产线实时性要求是每秒处理10帧以上1920输入配合YOLOv5s在3080上勉强才够换到普通配置就完全跑不动了。所以高分辨率检测的核心矛盾从来不是“模型能不能检测”而是“在分辨率、速度、显存之间怎么找到工程上可接受的平衡点”。这个平衡点取决于你手上的硬件、产线节拍、以及缺陷的物理尺寸。这里还要纠正一个常见误区很多人以为工业相机的分辨率越高越好甚至为了“看得清”直接上2500万像素或更高。但在检测算法侧高分辨率图像如果喂不进模型本质上就是一堆用不上的像素。搞工业检测项目算法工程师必须和硬件选型绑定思考——分辨率的关键不是“拍得清不清楚”而是“目标在模型输入尺寸下能占多少个像素”。一个我实际沿用的经验值缺陷最短边在模型输入图上至少要占到8个像素以上否则漏检概率会急剧上升。反过来算如果你需要在4096宽的图中检测5mm的缺陷模型输入1280时缺陷约占1.6像素这远远不够。所以要么提高输入分辨率要么物理上缩短视场宽度让同样像素数覆盖更小的物理范围。2. 海康工业相机的接入与触发同步从MVS驱动到“未收到触发信号”的完整排查2.1 相机选型和连接的基本配置海康工业相机按照接口主要分GigE网口和USB 3.0两种。项目里我用的是MV-CA系列GigE相机型号具体不说了感光芯片是Sony的分辨率500万像素帧率理论上能做到17fps2448x2048。但这是理论值实际跑起来还要受网卡带宽、曝光时间、传输协议等多重限制。连接采图用的软件是海康官方提供的MVSMachine Vision Software这个工具集成了相机搜索、参数配置、实时预览、SDK调用示例等功能。装好之后第一步是配置IP地址——GigE相机和电脑之间需要能ping通一般把电脑网卡IP设为和相机同一网段比如192.168.1.x子网掩码255.255.255.0。这里有一个非常容易踩的坑Windows系统的防火墙默认会拦截GigE相机的广播包导致MVS搜索不到设备。不是每次都会拦但搜不到设备时第一反应应该是检查防火墙而不是反复重装驱动。我当时在这个问题上折腾了两个小时最后把防火墙对私有网络的拦截关掉设备立刻出现了。2.2 触发模式下“未收到触发信号”的根因定位项目实际运行时用的是硬件触发而不是连续采图这样可以保证每一帧图像都在固定光照条件下拍摄避免运动模糊和亮度波动。海康相机默认是连续模式需要到MVS里把触发模式从Off切到On并选择触发源为Line0或Line2。但切到硬件触发之后麻烦就来了。软件提示“未收到触发信号”图像预览黑屏。当时第一反应是plc那边没有发出信号用万用表量了之后确认信号是有的于是开始逐步排查相机侧的配置。排查链路大致如下检查触发源配置是否正确。海康相机触发源可以是Line0、Line2、软件触发等不同相机型号支持的光耦隔离输入引脚不同我用的型号Line0和Line2是输入Line1是输出配置错了自然会没信号。检查触发沿类型。相机常见的有上升沿触发和下降沿触发两种PLC那侧如果输出的是高电平脉冲相机要配上升沿有效如果配置成下降沿就会一直收不到有效信号。检查曝光时间与帧率上限的约束。当时我把曝光时间设到9500us,接近该型号上限触发信号间隔又很短相机处于“忙”状态时会跳过触发。这个问题如果不看相机日志根本发现不了MVS的SDK可以读取错误码排除了硬件问题后我调了SDK日志才发现有帧丢失的记录。接线干扰问题。工业现场的电机、变频器会对信号线产生电磁干扰信号线必须用双绞屏蔽线并且屏蔽层单端接地。最终定位到的问题是Line2引脚因为接线端子氧化导致接触电阻过大信号幅值被拉低触发源电平阈值判断不到高电平。换了一条线缆后问题彻底消失。排查这个问题的最大教训是不要一看到“未收到触发信号”就认定是PLC的问题相机侧的触发源配置、触发沿、曝光时间、硬件接线每一个环节都可能是根因。2.3 多相机同时采集时的同步后续项目又加了第二台相机两台相机需要同时抓拍同一运动物体这时候触发同步就变得有点讲究了。工业上常用的做法是用一台PLC或信号发生器同时输出两路触发信号给两台相机。但电信号在传输过程中会有微小的延迟差高速运动下两台相机的抓拍位置差异可能达到毫米级。如果精度要求高可以用海康的同步触发盒或者由一台相机输出同步信号给另一台。软件层面MVS SDK也提供了多相机同步采集的API核心是调用MV_CC_SetCommandValue设置同步触发模式然后统一等待回调。我的建议是能靠硬件同步就不要依赖软件同步因为Windows不是实时操作系统网络传输抖动会导致帧时刻不稳定这在精密测量里是完全不能接受的。3. YOLOv5在高分辨率输入下的显存与推理优化从切图到TensorRT的完整路线3.1 为什么不建议直接裸跑大分辨率前面已经说过直接把4000x3000的图像送进YOLOv5会爆显存。就算显存够推理耗时也无法接受。有一种做法是把模型本身的stride调大或减少层数来换取速度但牺牲的是小目标检测能力在工业缺陷检测场景下得不偿失。更合理的做法是切图推理也就是把高分辨率图像切分成多个有重叠的patch分别送进模型检测最后把检测框映射回原图坐标做融合。3.2 切图策略和重叠率的工程考量切图看似简单里面细节不少。直接用滑窗切割最简单比如4096x3000切成1280x1280步长也设为1280一共得到12张图。但这样漏检风险很大如果一个缺陷正好被切在两张图的交界边缘模型很可能因为上下文信息不完整而漏检。最直接的解法是设置overlap也就是让相邻切块之间有一定重叠。我在项目里用的重叠率大约是15%1280的滑窗配192像素的重叠保证缺陷至少完整出现在某一张切图里。但不能为了不漏检就把重叠率无脑调高重叠率越高同样一张大图被切成的patch数量就越多推理总耗时越长。从算法角度出发还有一个更聪明的做法——根据检测需求动态调整切图策略。比如先用低分辨率快速检测一遍在目标密集区域做二次高分辨率切图这样可以把单帧处理时间明显降下来但工程复杂度会上一个台阶。当时项目时间比较紧我没有用这种动态策略而是用固定切图加TensorRT加速的方式把整体帧率拉了起来。切图后的坐标映射也是个容易出错的点。模型输出的边界框坐标是针对patch自身的需要加上patch在原图中的左上角偏移量才能在原图上画框。如果做了overlap同一个目标可能在多张切图中被重复检测这时要做NMS合并。我的做法是把所有检测框先还原到原图坐标然后用一个较低置信度阈值过滤掉单张图里的弱检测再做全局NMS置信度阈值设为0.35IoU阈值0.45复测效果比较稳定。切图还有一个好处是可以配合GPU并行。如果把一张大图切成12个patch在批处理维度上一次性送进模型GPU利用率会高很多总推理时间反而比一张张串行快不少。3.3 高分辨率场景下的模型结构选择模型结构选择上我对比过YOLOv5s、YOLOv5m、YOLOv5l以及YOLOv5的P6模型。P6模型是YOLOv5针对大分辨率输入专门设计的变体在原来的P3/P4/P5三个输出层基础上增加了一个P6层下采样倍数从32倍降到64倍更适合检测1280x1280甚至更大尺寸输入中的中小目标。我最后用的就是YOLOv5s-P6输入1280x1280单张patch推理速度在3080上大约32ms和小目标的召回率平衡下来比较理想。如果切图patch较小比如640或768就不建议用P6模型了因为P6层在小编码器上体现不出优势白白增加计算量。模型选型要跟着patch尺寸走这算是我自己实践下来的一条经验。3.4 TensorRT加速int8量化的实用经验YOLOv5的PyTorch权重在GPU上直接推理速度其实并没有榨干GPU的能力。把模型转成TensorRT引擎之后速度可以提升2~3倍。TensorRT的转换流程不复杂官方仓库提供了gen_wts.py脚本先把PyTorch权重转成wts文件再用TensorRT版本的YOLOv5工程把wts转成engine。这里我要分享三个最实用的经验第一个是动态batch和动态shape。工业检测场景下输入尺寸固定其实更好优化TensorRT构建引擎时用固定shape能获得更好的kernel选择和显存分配。我当时固定了1x3x1280x1280这样每个patch串行推理虽然单张慢一点但内存占用低、逻辑简单。如果单帧多patch并行用固定batch8性能表现更好但显存占用会明显上涨8张1280x1280输入在10G显存上已经比较紧张。第二个是INT8量化的标定集选择。TensorRT的INT8量化需要标定数据calibration dataset很多人随便拿几十张图跑一遍就完事。我的经验是标定集必须覆盖所有缺陷类型和背景分布特别是要包含带缺陷的图否则量化后模型会对缺陷这种“稀疏模式”产生明显的精度损失。我当时用了项目里的500张标注图做标定量化前后在测试集上map只掉了约0.8%完全可接受。第三个是不要盲信FP16和INT8的速度对比。在很多GPU上FP16和INT8的推理速度差距没有传说中那么大尤其在显存带宽吃紧的卡上。我实测在3080上用YOLOv5s-P6推理1280x1280FP16引擎大约33msINT8引擎大约16msINT8快了一倍但如果精度衰减超过2%我宁愿用FP16。量化本身是一个精度和速度的trade-off不是非用INT8不可。4. 数据集标注与训练落地半自动标注、超参数调整和一套让我少踩坑的流程4.1 用界面工具搞定YOLOv5数据集的自动标注之前项目里用LabelImg纯手工一张张框缺陷两三千张图让人画到怀疑人生。这次学聪明了先用手头已有的检测模型做预标注再用专门的标注工具做人工复核修正。我用的工具是X-AnyLabeling这个工具可以直接挂载YOLOv5模型权重把一批待标注的图跑一遍自动生成框然后人工在界面上修正错框和漏框。一个几百张图的数据集纯手工标注要两天半自动标注加修正半天就差不多搞定了。具体流程是这样的先把已经标注好的少量图片200张左右训练出一个初版模型哪怕精度不高也没关系反正只是用来预标注。把待标注的大批量图片放进一个文件夹用训练好的权重自动推理生成一个带标签的json或txt标注文件。用X-AnyLabeling打开这些图片和自动标注结果人工过一遍调整错框、删除误检、补上漏检。保存为YOLO格式的txt标注文件直接就能放进训练流程。这套流程对工业检测特别友好因为产线场景相对固定背景变化不大初版模型的预标注准确率通常能有70%以上人工复核压力不大。4.2 训练策略中的几个关键配置训练超参数的调整在YOLOv5里其实很直观主要通过data/*.yaml和hyp.scratch-low.yaml配置文件来控制。我重点调过的几个参数imgsz训练时的输入尺寸我设为1280和推理时保持一致。这一点很重要训练和推理的输入尺寸最好一致否则模型要适配不同的尺度分布影响检测精度。batch size在3080上YOLOv5s-P6用1280输入时batch设到8已经是显存极限了。batch太小训练不稳定batch太大容易吃显存。我的建议是能多大就多大但不要牺牲稳定性一般8~16比较健康。epochs训练了300轮。其实YOLOv5会在训练后期自动早停我当时设了patience50如果50轮内map没有提升就自动停止实际模型在第180轮左右就收敛了。mosaicYOLOv5默认使用马赛克增强这个增强策略在工业小目标检测里尤为重要它会把四张图拼接起来随机缩放相当于变相增加了小目标在图像中的占比对小目标召回率提升非常大。我在最后一少部分epoch开始关闭mosaic约总epoch的20%让模型在接近真实分布的数据上微调避免mosaic增强带来的分布偏差。训练时的迁移学习也很关键。用COCO预训练权重做初始化比从零开始训练收敛快得多而且最终精度普遍更高。不用自定义数据集太小就担心训练不上恰恰因为数据集小预训练权重的价值更大。4.3 数据不平衡和背景干扰的处理工业场景的一个共性是缺陷样本和正常样本数量严重失衡。一个产品表面可能只有1%的概率存在缺陷如果训练集里全是真实场景下的缺陷样本模型很容易对“正常”区域产生误检。我的处理方法是正常样本加背景负样本混合训练在数据集里保持20%~30%的负样本比例这些负样本不需要标注模型会学会将它们预测为background。这点在工业检测里很关键纯缺陷样本训练出来的模型即使map很高上了产线也会被误检率打爆。还有一个容易被忽略的细节是光照一致性。工业相机的安装角度、光源亮度、频闪方式稍有变化图像分布就变了模型可能瞬间失效。所以采集训练数据时尽量覆盖光源亮度的上下浮动范围让模型见过足够的亮度变化这对产线鲁棒性帮助很大。5. 从PC到边缘部署Jetson Nano上的移植与性能实测5.1 Jetson Nano上的环境配置关键点Jetson Nano不是x86架构而是ARM架构PyTorch不能直接用pip装必须用英伟达官方提供的JetPack里的预编译版本。JetPack自带CUDA、cuDNN、TensorRT版本之间是有绑定关系的装环境时最忌讳混装。我当时用的是JetPack 4.6.1自带CUDA 10.2、TensorRT 8.2。YOLOv5仓库有一个requirements.txt但里面的torch版本是x86的需要到英伟达官方论坛下ARM版torch的whl文件来装。一个很实用的经验先在PC上把所有代码调通再到Jetson Nano上部署。在ARM板上调试代码的效率大约是PC的十分之一内存和CPU性能都差很多除非必要不要在板上跑训练或大量调试逻辑。5.2 边缘设备上的实测数据Jetson Nano的GPU算力大约是0.5 TFLOPS FP16和桌面级显卡完全不是一个量级。把前面优化的YOLOv5s-P6跑到Nano上1280x1280输入TensorRT FP16引擎推理耗时大约420ms大概2.4帧每秒。这里不是它不快是这个设备的算力上限摆在那里。但实际项目里我发现把输入降到640x640用Nano跑单帧推理大约105ms接近10帧每秒的实时性代价是小缺陷召回率会有所下降。如果像素-物理尺寸换算之后640输入已经满足检测精度需求那Nano完全可用如果非要1280输入建议直接上Xavier NX或Orin Nano算力翻了好几倍。5.3 边缘部署时的省显存技巧Jetson Nano的显存和内存是共享的4GB型号跑起大模型很容易OOM。我当时用了两个技巧把显存压了下来第一个是开启TensorRT的显存池复用避免每次推理都重新分配显存长期运行过程中能减少非常多内存碎片和峰值占用。第二个是把图像的预处理放到CPU上用cv2异步完成。GPU负责推理CPU负责缩放、归一化等预处理双流水线并行能让帧率再上一个台阶。如果图像分辨率很高、预处理部分耗时明显占比高可以尝试用OpenCV的UMat把部分图像处理放到GPU上做但是否值得取决于具体瓶颈在哪里。6. 实测效果复盘数据、问题与可复用的调优建议把整个流程跑通后我对最后的效果做了一次完整复盘。在这个部分直接上实测数据和踩坑后的建议方便后来者直接参考。6.1 最终效果数据最终方案是YOLOv5s-P6TensorRT FP16引擎输入1280x1280在RTX 3080上单patch推理33ms单帧4096x3000图像切12个patch并行batch12总耗时约110ms折合9帧每秒。在Jetson Nano上单patch推理420ms但通过切图并行并不能提升帧率上限Nano的内存带宽限制很严重只能串行跑所以单帧大图需要5秒左右在产线节拍要求不高时可以接受。精度方面测试集缺陷召回率约91.6%误检率约每帧0.7个。和最初640输入时52%的召回率相比整套优化下来提升非常明显。6.2 后来者可直接参考的调优清单根据整个项目踩过的坑我整理了一份可以直接套用的清单不要盲目希望低分辨率模型处理高分辨率图像小目标检测需要给模型足够的输入尺寸。切图必须有overlap15%到20%是一个合理的起点。训练和推理的输入尺寸尽量保持一致。如果是工业小目标场景优先看YOLOv5s-P6这一档模型性价比很高。TensorRT的INT8量化要做但标定集必须覆盖真实分布做完量化一定要在测试集上验证精度损失。工业检测数据集一定要加入负样本否则产线误检率会失控。相机触发信号异常时按“触发源配置-触发沿-曝光时间和帧率约束-硬件接线”的顺序排查不要一上来就怀疑PLC。Jetson Nano上跑大模型要提前算好算力预算别指望它能跑出和3080一样的效果。6.3 关于实时性的一个延伸思考实时检测的定义在工业场景里不是固定的。有些产线节拍是每秒30帧有些只需要每秒2帧甚至更低。做方案设计时先问清楚产线的节拍要求和缺陷大小再反推计算输入分辨率、模型结构和推理后端这样才能做出来真正可落地的方案。我自己之前一直想在算法上一步到位结果反而把简单问题复杂化了。另外如果后续想进一步提升小目标的检测准确率除了换更大模型、更高分辨率之外可以尝试在YOLOv5的检测头之前增加基于注意力机制的模块例如在Backbone的深层特征上添加SE或CBAM模块让模型更关注缺陷区域的特征响应。对工业小目标检测来说这是一个有效但常被忽略的优化方向。这次项目整体下来最大的感悟是高分辨率实时检测不难难的是在高分辨率、实时性、显存容量、检测精度四个变量之间找到平衡。很多教程只告诉你YOLOv5怎么训练怎么部署却忽略了工业相机接入、触发信号同步、数据分布适配这些“脏活累活”。这些细节才是决定项目能否真正落地的东西。
返回列表