资讯详情

X光行李违禁品检测实战:YOLOv5与YOLOv8的训练调优与部署全记录

📅 2026/10/21 22:51:04 | 华诺云谱 👁 阅读
X光行李违禁品检测实战:YOLOv5与YOLOv8的训练调优与部署全记录
前阵子整理一批X光行李安检图像数据准备做违禁物品检测方案自然选了目标检测领域最常用的YOLOv5和YOLOv8。说实话一开始我挺自信的——自然场景下的目标检测做过不少换成X光图无非是换个数据集罢了。真跑起来才发现X光行李违禁物品检测和常规目标检测完全是两种体验透视叠加、严重遮挡、伪彩通道含义特殊连数据增强策略都要推翻重来。这篇记录我从数据整理到v5/v8训练、再到后续部署优化的完整过程给准备入坑X光安检目标检测的朋友一个可复现的参考。我这次处理的这批数据编号是63对外的打标名就是“x光行李违禁物品数据集”里面附带作者已经跑好的YOLOv5/YOLOv8模型权重。也就是说数据集本身还自带baseline这其实是个很好的起跑线省去了很多从零试错的成本。不过我还是坚持了自己重训一版因为自带模型的类别定义、训练细节和部署口径未必适合我这边实际的业务约束。1. 拿到这批X光数据后先别急着开训X光图像到底特殊在哪1.1 透视叠加不是“部分遮挡”而是“彼此贯穿”自然图像里一辆车挡住一个人那个人的可见面积可能只有10%甚至更小但语义上是独立的边缘明确、轮廓可见。X光行李图像完全不是这个逻辑一个行李箱内所有物品的密度信息会同时投影到同一张二维图像上书本、笔记本电脑、金属框架、保温瓶、雨伞全部叠在一起不同材质在密度维度上互相穿透。这就导致同一个像素位置可能同时属于三四个目标的轮廓而模型要做的不是识别“谁在前谁在后”而是从叠加后的密度分布里把每个目标的轮廓从语义上剥出来。我第一次拿YOLOv5默认参数直接跑mAP看着还行但细看预测框发现大量漏检都发生在高密度堆叠区域——多个物体挤在一起时模型倾向于只报置信度最高的那个其余直接消失。后来我想明白一件事常规目标检测的anchor或query设计本质上假设目标是一个“独立的整体”而X光场景里这个假设经常不成立。训练时必须刻意让模型见过足够多“被半遮挡但边界仍能辨析”的正样本它才可能学会抠边缘而不是认整体。1.2 颜色通道不是普通RGB伪彩是一种材质编码很多人第一次拿到X光图像会困惑为什么图片上物品是橙色、蓝色、绿色混杂的这其实是安检设备根据等效原子序数和密度做的材质映射——有机物通常显示橙色无机物显示蓝色混合物显示绿色。也就是说颜色本身携带了“材质类别”信息而不是自然图像里那种光照反射结果。这带来一个非常重要的训练约束绝对不能像处理自然图像那样做随机HSV抖动、色调偏移、颜色反转这类增强。我早期版本图省事直接套用了默认的增强pipeline结果模型在验证集上掉点明显尤其是金属物与有机物叠在一起的目标边界预测变得一团糟。原因很好理解你把橙色物品的颜色往蓝色方向抖一下材质语义就彻底错了模型等于在学一套错误映射。后续我把hsv增强全部关掉只保留几何类增强训练稳定性立刻上来了。这个点我在后面的避坑章节还会展开讲但它值得在最开头就强调X光图像的每个通道都有物理含义增强之前先想想会不会破坏物理语义。1.3 这批数据的构成与标注质量观察我快速统计了一下这批数据的基本盘大约2万多张图像标注实例数量接近4万覆盖常见违禁物品类别。原始数据包含两种形态一种是标准的伪彩图三通道另一种是灰度图三通道复制。后者在训练时价值略低因为灰度图丢失了材质映射信息但作为泛化补充仍然有用。标注质量方面我观察到两处需要处理的地方。第一部分类别存在同物异名的问题比如“刀”和“折叠刀”被分在两个类里实际语义一致第二大量重叠目标的标注框只圈了可见部分完整轮廓并没有标注出来。对于第一个问题我的处理方式是合并同类项把语义接近的类别归并成一个大类对于第二个问题我没有强行手动补标全部轮廓而是把它当成一种隐式的“可见部分检测”任务来训练推理时接受完整框和部分框同时出现再用后处理合并。2. YOLOv5还是YOLOv8放在X光场景里怎么选2.1 两者核心差异对这个场景的影响YOLOv5和YOLOv8的差异网上分析很多我只挑对X光检测影响最大的三点说。第一检测头设计。YOLOv5是anchor-based需要预设anchor尺寸YOLOv8改成anchor-free用中心距离加宽高比的方式直接回归目标框。在X光场景里物体形状极度多样刀的细长框、充电宝的方正框、液体瓶的矮胖框混在一起anchor-free的解耦头对形状变化的容忍度明显更高尤其对细长物体召回更好。第二主干网络结构。YOLOv8使用C2f模块替代v5的C3模块梯度流更丰富理论上对细小目标的特征表达能力更强。我用同样数据量分别跑了v5s和v8sv8s在小物体打火机、小刀尖端上的召回率要高3到5个百分点代价是显存占用和推理延迟略增。第三训练策略。YOLOv8内置的loss设计DFL加CIoU对边框回归更精细训练过程中loss下降更平滑。但对小规模数据集v5的收敛速度更友好不容易一上来就过拟合。v5s参数量大约7Mv8s大约11M参数更多但数据不充裕时优势会被过拟合抵消一部分。两个模型在X光场景的适用性我放在一张表里总结。对比项YOLOv5YOLOv8对X光场景的实际影响检测头anchor-basedanchor-free解耦头v8对细长/异形物体召回更好主干模块C3C2fv8小目标特征表达略优模型体量轻量v5s约7M偏重v8s约11M小数据量时v5更稳部署生态资料极多导出方便新特性全看团队熟悉程度自带增强传统增强更丰富的训练策略但颜色增强必须关闭2.2 我最终采用的组合方案我的结论是不要二选一而是让它们各司其职。我用YOLOv8s作为主检测模型因为它在重叠和异形目标上的表现更符合安检场景的需求同时保留YOLOv5s作为快速迭代实验的baseline因为v5训练速度更快适合做数据清洗和类别合并验证。最终部署时我用的是v8s蒸馏自v8l的轻量版本——大模型负责学更多细节小模型负责实际推理这是后面章节会详述的优化路线。如果手头硬件紧张只跑CPU或老GPU那v5s依然是合理选择它的生态成熟度和稳定性毋庸置疑。关键是训练策略必须按X光图像的特性重调模型本身不是瓶颈。3. 数据准备与预处理把图像调教到模型“看得懂”的状态3.1 目录结构与Label格式必须统一所有训练框架对数据的组织方式都大同小异我这边最终统一成YOLO格式的标准目录结构。如果是VOC格式的XML标注或者COCO风格的JSON标注需要先转成txt格式。转换时要注意类别映射关系最容易出错的是类别索引对不上训练出来的模型预测结果驴唇不对马嘴。我通常把转换脚本写成可重复执行的工具而不是手工转换因为后续很可能要反复调整类别合并策略。目录结构固定为datasets/ ├── xray_sec/ │ ├── images/ │ │ ├── train/ │ │ ├── val/ │ │ └── test/ │ ├── labels/ │ │ ├── train/ │ │ └── val/ │ └── xray_sec.yamlXML转txt的脚本核心逻辑很简单无非是解析bounding box坐标并归一化。写的时候注意两点一是坐标要归一化到0到1之间二是宽高必须是非负数过滤掉宽度或高度为零的坏标注。import xml.etree.ElementTree as ET import os def voc_to_yolo(xml_path, out_dir, class_map): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) lines [] for obj in root.findall(object): cls_name obj.find(name).text if cls_name not in class_map: continue cls_id class_map[cls_name] box obj.find(bndbox) x1 float(box.find(xmin).text) y1 float(box.find(ymin).text) x2 float(box.find(xmax).text) y2 float(box.find(ymax).text) cx (x1 x2) / 2.0 / img_w cy (y1 y2) / 2.0 / img_h w (x2 - x1) / img_w h (y2 - y1) / img_h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) if lines: out_txt os.path.join(out_dir, os.path.splitext(os.path.basename(xml_path))[0] .txt) with open(out_txt, w) as f: f.write(\n.join(lines))3.2 针对X光图像做的几项预处理和增强完成格式统一后接下来是训练前的一轮图像预处理。我做了三件事每一件都有明确目的。第一是CLAHE对比度增强。X光原始图经常有动态范围很大、局部对比度不足的问题传送带匀速运动还会带来轻微模糊。限制对比度自适应直方图均衡能在不明显放大噪声的前提下提升局部边缘可见度这对小目标检测很有帮助。注意参数不要设太激进clipLimit我一般取2.0tileGridSize取8x8过强会让材质颜色失真。第二是上采样策略。X光原图分辨率普遍较高而训练框架默认会把图像缩放到640x640。直接缩放会把许多小物体缩成一个点。我的做法是优先在1280x1280的分辨率下训练如果显存不足至少也要用960并用马赛克增强模拟多尺度的上下文。第三是选择性使用复制粘贴增强。X光场景里物体本来就是叠加的把一个目标的小图随机粘贴到另一张正常图上其实非常接近真实分布。但对类别少的样本要严格控制粘贴次数防止模型学到“同类物体总是成对出现”的错觉。增强配置上几何类随机水平翻转、随机缩放、轻微旋转颜色类全部保持原样。训练框架里如果有HSV增强参数直接置零。3.3 类别不均衡的处理思路这批数据的类别分布并不均匀打火机、刀类样本多压力罐、液体容器样本少。直观影响就是样本多的类别AP高样本少的类别AP低。处理办法我按优先级排序类别重采样按有效样本数的倒数加权采样让每个batch里稀有类别出现的比例不低于某个阈值。复制粘贴增强把稀有类别的小图复制粘贴到普通行李图像上生成新的复合样本。损失加权如果框架支持给稀有类别更高的分类loss权重。三种方法我叠加使用后压力罐类别的AP从原来的62%提升到79%代价是打火机类别跌了1.5个点总体看划算。关键是要在验证集上持续观察每个类别的AP曲线不要只看整体mAP。4. 训练过程实录关键参数、评价指标和效果数据4.1 训练命令与关键超参数解读我用YOLOv8官方代码库训练数据配置文件如下path: /data/xray_sec train: images/train val: images/val nc: 6 names: 0: knife 1: scissors 2: lighter 3: pressure_can 4: liquid_bottle 5: power_bank训练命令如下几个关键参数我逐一解释yolo detect train \ modelyolov8s.pt \ dataxray_sec.yaml \ epochs300 \ imgsz1280 \ batch16 \ optimizerSGD \ lr00.01 \ lrf0.01 \ weight_decay5e-4 \ hsv_h0.0 hsv_s0.0 hsv_v0.0 \ mosaic1.0 \ close_mosaic50imgsz1280是最重要的调整因为原图本身分辨率高640会让小目标信息大量丢失。mosaic1.0表示前250个epoch全程开启马赛克但在最后50个epoch我设置了close_mosaic让模型适应没有马赛克的真实分布。这在X光场景尤其关键马赛克增强会把四个图的物体叠在一起实际上进一步加剧了X光本来就很严重的“多物叠加”现象训练早期能用但后期必须关闭。weight_decay取5e-4对2万张左右的数据集来说正则强度适中。优化器我偏好SGD而不是Adam类因为SGD配合warmup和cosine学习率在检测任务上更容易收敛到低泛化误差的平坦区间。4.2 训练过程的观察点loss曲线和类别AP训练过程中我不会只看总loss而是每10个epoch记录一次各分类的AP和召回率。总loss平滑下降说明模型在整体学但隐藏的问题是某些小类别可能从头到尾都没被充分学习。一个值得注意的曲线特征是train loss持续下降、val loss在120个epoch后开始走平或上升这是过拟合的信号。X光数据集里的伪彩模式相对固定模型很容易记住训练图里的特定材质纹理而不是学到通用轮廓。遇到这种情况我通常先停掉mosaic再看loss变化如果仍然过拟合就降低模型规模或加dropout。4.3 效果数据mAP、召回率和误检的权衡最终一版的效果数据如下表类别AP差异能直观反映数据集不平衡的影响。类别样本数AP0.5AP0.5:0.95刀类68000.910.75剪刀52000.930.79打火机81000.880.66压力罐15000.790.54液体容器26000.860.63充电宝39000.820.61整体mAP50约0.87mAP50-95约0.66。单看mAP在安检场景里其实不够更要关注误检率。推理时把conf_threshold从0.25降到0.1召回率提升约3%但误报数量翻了近一倍。安检场景对召回的要求极高漏检的后果远比误报严重所以我倾向于保持较低置信度阈值再用二次校验环节过滤误报。这个双阈值策略在部署章节详细说。5. 最容易翻车的五个细节踩坑记录与规避策略5.1 NMS和重叠目标的“框融合”X光场景中两把折叠刀叠在一起或者充电宝与金属框架叠合模型会输出两个高度重叠的预测框。默认NMS会把IoU超过阈值的两个框直接合并成一个导致一个违禁物被漏计。我第一次跑出来的“漏检”大量就是这样造成的而不是模型本身没检测到。规避策略是调高NMS的IoU阈值。我用0.7替代默认值显著降低了对重叠目标的合并概率。同时针对刀类这种细长目标我会额外做一次基于方向的后处理两个细长框重合度用普通IoU不敏感改用旋转框IoU作为补充判断。5.2 伪彩图千万别乱做颜色增强前面说过X光伪彩是材质编码颜色增强必须关掉。这个坑我再细说一下具体症状某次实验我保留了一部分随机色相增强模型训练了200个epochmAP整体没掉多少但可视化预测时发现大量刀类目标把柄的方向判断错误边缘框住了旁边的不锈钢水杯。原因是水杯和刀柄在抖动后的颜色空间里被拉近了模型学到了错误的材质关联。这个教训提醒我在X光数据上做任何预处理都要先问一句“这个操作会不会改变材质语义”。5.3 小目标在降采样过程中消失打火机、小刀、液体瓶盖这类目标在640分辨率下往往只有10到30像素。经过模型的多次降采样后特征图上的有效响应非常弱即便模型理论上有能力检测小目标实际效果也大打折扣。除了提高输入分辨率另一个有效方案是切patch推理把原图切成若干重叠块分别推理再融合结果。离线场景可以这样做实时场景就得靠TensorRT和更大分辨率输入的部署优化来兜底。5.4 样本不平衡导致的“单类塌陷”训练初版模型时压力罐类别只有1500个样本打火机有8100个结果压力罐类别AP一直上不去而且在很多非压力罐目标上产生了大量误报。这是典型的类别不平衡导致的“多数类淹没少数类”。处理方案在3.3节已经给出了这里只说教训一定不能在训练前忽略类别分布统计。我后来在数据准备阶段就直接按类别做样本量直方图一旦发现某类样本数不足先从数据端补齐再考虑调模型。5.5 只有正样本没有负样本误报必然爆表这批数据有个容易忽略的问题几乎每张图都包含至少一个违禁物品标注缺少大量“纯正常行李”图像。模型在训练时没见过足够多没有目标的正例推理时就容易把行李箱里的普通金属物、复杂纹理误判成违禁物。应对方法是额外收集一批正常行李X光图像加入训练集不给标注让模型学会“无目标”的模式。如果一时收集不到大量负样本也可以在验证集构造包含正常行李的混合场景持续监控误报率。6. 从训练到上机模型部署、后处理和后续优化方向6.1 导出ONNX并用TensorRT提速训练完成只是第一步现实安检场景对推理延迟有硬性要求。我先把YOLOv8s从PyTorch导出成ONNX再转成TensorRT FP16引擎。设备上实测下来1280x1280输入在主流GPU上能达到40到60毫秒一帧如果是1080p原图裁剪成多patch再拼回结果整体耗时约120毫秒能满足慢速过包场景。导出过程有几个细节要注意。一是动态维度要打开因为实际图像的宽高比例不完全固定二是FP16精度下某些细小目标的置信度会轻微下降需要对比验证集指标确认损失是否可接受。对精度要求更高的场景可以保留FP32但延迟会翻倍。yolo export modelbest.pt formatonnx dynamicTrue imgsz1280 trtexec --onnxbest.onnx \ --saveEnginebest_fp16.engine \ --fp16 \ --minShapesimages:1x3x1280x1280 \ --optShapesimages:4x3x1280x1280 \ --maxShapesimages:8x3x1280x12806.2 双阈值策略和人机复核闭环安检场景对漏检零容忍而任何模型都有不可避免的误报和漏检所以实际部署不能单靠一个置信度阈值一杆子打死。我采用的方案是双阈值预测置信度大于0.7的目标直接进入危险品告警队列置信度在0.3到0.7之间的目标进入人工复核队列由安检员看一眼确认低于0.3的忽略。这个策略把模型的“不确定区间”明确暴露给人机交互流程既保留了高置信度目标的快速处置能力又给了低置信度目标第二次被看见的机会。实测下来将人工复核覆盖的目标范围收敛后整体漏检率比单阈值下降了一个数量级。这套方案的核心不是模型而是流程设计让模型做初筛让人的判断力兜底。6.3 后续可以继续做的方向蒸馏与小目标专门分支最后提一个我验证过有效、而且值得继续深挖的方向知识蒸馏。我用YOLOv8l作为教师模型YOLOv8s作为学生模型用教师输出的软标签加上真实标签一起训练学生。结果学生模型在压力罐这种小样本类别上的AP比单独训练提升了4.2个百分点推理速度却保持和学生模型原始版本一致。小目标方向上我还在尝试给模型加一个专门的浅层检测分支不参与最终全图的预测只在特征金字塔的低层单独输出一些小尺度候选框再统一送入后续判断。这个方向相对复杂但考虑到X光场景中打火机、刀具尖端这类小物件的检测价值值得持续投入。就我个人的实操体会来看做X光安检目标检测最大的难点其实不在于模型选型或调参而在于能否丢掉自然图像检测的思维惯性。给模型喂数据、调参数都只是时间问题真正拉开差距的是你对X光图像物理语义的理解深度。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑