简介:基于深度学习的机场安检危险品自动识别系统Python源码,是一套面向课程设计、期末大作业与毕业设计的完整项目,适用于计算机视觉、大数据、人工智能等专业学生及从业者。代码以计算机视觉与深度学习技术为核心,针对安检场景中危险品识别问题,提供从数据样本、模型训练到界面交互的工程化实现。资源共179个文件,压缩包大小为9.73MB,主要包含37个py源码文件、53个pyc编译文件、63张jpg样本图片,以及6个png、4个xml配置、2个ui界面、sh脚本、pyd扩展、c源文件与gif演示动画等类型;其中jpg样本可用于模型训练与验证,xml配置与ui文件支持界面和参数调整,bat与sh脚本便于在不同系统下快速启动,iml、lib等文件则支撑项目编译与依赖管理,目录结构清晰,便于按功能模块查阅。已有345人学习下载。这套源码包不仅包含可直接运行的检测系统源码,还带有编译依赖与样例图片,可帮助学习者快速搭建实验环境,理解Faster R-CNN等模型在危险品识别中的应用流程;代码经过功能验证,稳定可靠,适合在现有基础上进行二次开发,也可直接用于项目展示与答辩准备。
1. 机场安检危险品识别,为什么值得用深度学习重做一遍
机场安检的X光图像判读,本质上是目标检测任务:在灰度或伪彩的行李扫描图里,找到刀具、枪支、易燃液体、打火机这些危险品。传统方案靠人工盯屏幕,疲劳之后漏检率直线上升;早期计算机视觉靠颜色阈值、形状模板做匹配,遇到叠放物品就失效。基于深度学习的检测模型,尤其是CNN系列,能把“危险品长什么样”直接学进网络权重里。这套Python源码的核心工作就是:用目标检测模型替代人眼,在安检X光图像中自动画出危险品的位置和类别。
这个方向适合两类人:一是要做毕业设计或项目实训的学生,需要一套能跑通、能讲清楚原理的完整代码;二是安检设备厂商或机场信息化部门的工程师,想评估深度学习方案在真实场景下的精度和落地成本。全文从模型选型、数据标注、训练调参到部署推理逐步展开,中间穿插几个真实踩过的坑,希望能让你少走弯路。
2. 选YOLOv8还是自定义CNN:安检场景的模型选型逻辑
2.1 CNN做分类和YOLO做检测的本质差别
很多初学者看到“基于深度学习”就立刻想到搭建一个卷积神经网络,把图片缩成224×224,用Softmax输出“是刀/不是刀”。这是分类思路,只能回答“图片里有没有危险品”,答不了“危险品在哪”。安检场景里,行李图像里危险品往往只占画面的一小块,旁边还叠着充电宝、金属保温杯、雨伞。你需要的是检测输出,也就是每个目标的边界框坐标加上类别置信度。
YOLO系列把检测问题转化为回归问题:一次前向传播同时输出目标的类别概率和边框位置。它的核心思想是把图像划分成网格,每个网格负责预测中心点落在自己区域内的目标。相比Faster R-CNN这种两阶段检测器,YOLO牺牲了一部分定位精度换来了推理速度,而安检场景正好吃这套——运行在边缘设备上,不能为一次推理等上几百毫秒。源码里既然写的是“自动识别系统”,必然要落检测,直接选用YOLO系比从零搭CNN更贴合标题意图。
2.2 选型对比:YOLOv7/YOLOv8/RT-DETR在小目标上的取舍
我建议首选YOLOv8。理由有三条:第一,Ultralytics提供的Python包做得非常完整,训练、验证、导出一条命令搞定,对新手友好;第二,YOLOv8在COCO上的精度与YOLOv7持平,但训练速度和推理速度更快;第三,社区活跃,遇到报错搜一下就有答案。RT-DETR精度更高但依赖Transformer结构,显存占用大,安检设备通常只配6到8GB显存的工控机,跑起来吃力。
在安检这个具体任务里有一个关键点:打火机、刀片这类小目标很多。YOLOv8默认从80×80的Feature Map检测小目标,配合PANet结构融合高层语义和低层纹理信息,基本够用。如果实测中小目标漏检严重,可以改用YOLOv8-seg做实例分割,或者把输入分辨率从640提到1280,代价是推理速度下降一半左右。RT-DETR适合追求极致精度的离线分析场景,实时性要求高的在线检测慎用。
2.3 环境搭建:Python版本、PyTorch安装与CUDA验证
源码基于Python运行,环境配不好后面全是坑。我建议用Python 3.9或3.10,PyTorch 2.x,CUDA对应版本装12.1及以上。以下是一个可用的环境搭建流程,我用conda操作:
conda create -n security python=3.10 -y conda activate security # 安装PyTorch,指定CUDA 12.1,如果机器没N卡就把cu121改成cpu pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121 # 安装YOLOv8依赖包 pip install ultralytics opencv-python labelimg这段命令先创建一个干净的conda环境,避免把系统Python搞乱。PyTorch是深度学习框架,YOLOv8的推理和训练都建立在它之上;opencv-python负责图像读写和预处理;labelimg是数据标注工具,后面转换格式时会用到。
装完后跑一条验证命令:
import torch print(torch.__version__) print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else "CPU mode")如果torch.cuda.is_available()返回True,说明GPU可用,训练速度至少是CPU的10倍。返回False就检查驱动和CUDA版本是否匹配,最常见的翻车是PyTorch装成了CPU版,或者NVIDIA驱动版本太老。纯CPU也能跑通整条流程,只是训练一个epoch要等很久,建议先拿小数据集验证代码,再上GPU正式训练。
3. 数据准备:安检X光图像数据集标注与预处理
3.1 公开数据集与自采数据的取舍
模型精度上限由数据决定,深度学习圈内叫“Garbage in, garbage out”。安检领域能直接用的公开数据集有SIXray和OPIXray,都来自真实安检X光设备,包含刀具、枪支、打火机等类别。SIXray有超过一百万张图片,但类别不平衡严重,枪支样本占比极低;OPIXray专门针对刀具,细分为直刀、折叠刀、剪刀等。
如果做课设或预研,用公开数据集就够了;如果做工程落地,必须以现场设备实测数据为主。安检X光机和网上照片的成像差异很大,密度、色彩映射、视角都不同,模型在新设备上掉点很正常。常见做法是先用公开数据预训练,再用现场数据微调。标注工作最好让安检员参与,他们对危险品的视觉形态最熟悉,工程师容易把“像刀的金属片”标成“刀”,引入噪声。
3.2 labelimg标注流程与格式转换:VOC转YOLO脚本
标注工具用labelimg,安装后启动并设置自动保存:
labelimg images classes.txt按W键画框,按A/D翻页,标注结果会存成Pascal VOC格式的XML文件,里面记录图片路径、目标类别和边框坐标。YOLO训练需要的是TXT文件,每行class x_center y_center width height,坐标全部归一化到0到1之间。转换脚本如下:
import xml.etree.ElementTree as ET import os def voc_to_yolo(xml_path, out_dir, class_list): 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'): name = obj.find('name').text if name not in class_list: continue cls_id = class_list.index(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) # 换算成YOLO格式:中心点坐标和宽高,全部归一化 cx = (x1 + x2) / 2 / img_w cy = (y1 + y2) / 2 / 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: base = os.path.basename(xml_path).replace('.xml', '.txt') with open(os.path.join(out_dir, base), 'w') as f: f.write('\n'.join(lines)) # 使用示例 classes = ['gun', 'knife', 'lighter', 'bottle'] # 按你的标注顺序排列 for xml in os.listdir('annotations'): if xml.endswith('.xml'): voc_to_yolo(os.path.join('annotations', xml), 'labels', classes)转换脚本的逻辑是:读取XML里记录的原始图片宽高和每个目标的左上角、右下角坐标,先算出框的中心点坐标和宽高,再除以图片宽高做归一化。这里有个容易出错的地方——XML里如果记录的是width和height字符串,必须转成float再参与运算,否则会做字符串拼接,生成的坐标全是错的。另一个坑是类别索引必须和训练配置里的names顺序严格一致,索引错位会导致模型把刀识别成枪。
3.3 数据增强:安检场景下哪些增强有效
训练时YOLOv8默认开启Mosaic增强,把四张图拼接成一张,能显著提升模型对遮挡和小目标的鲁棒性。但安检X光图像有自己的特点:背景是统一的深色,物品密度高,边缘锐利。我踩过的坑是,把随机色度抖动开太强反而掉点——X光图像的色彩来自材质密度映射,随意改变色相会破坏物理语义,模型学到的“颜色—材质”关联就被打乱了。
建议在augment.yaml或训练参数里这样配置:关闭HSV的H通道增强,保留S和V的微调;开启随机平移和缩放,模拟行李物品随机摆放;翻转增强要谨慎,闸机方向固定的设备不要开水平翻转,因为刀具的刃口方向在不同通道有物理含义。旋转增强控制在±10度以内,大幅旋转会让长条形危险品变成对角线方向,干扰卷积核的学习。
4. 训练与调参:从零跑通最小训练命令
4.1 数据组织与配置文件
训练前先把数据集按固定目录结构整理好,YOLOv8要求图片和标签分开存放,并用一个YAML配置文件描述路径和类别名。目录结构如下:
dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── security.yamlsecurity.yaml内容:
path: /home/user/dataset train: images/train val: images/val names: 0: gun 1: knife 2: lighter 3: bottle配置文件的逻辑很直白:path是数据集的根路径,train和val是相对于根路径的图片目录,names的字典顺序必须和标注脚本里的class_list一致。这里要强调一个关键点:标签TXT文件的文件名必须和图片文件名完全相同,后缀从.jpg换成.txt。比如img_001.jpg对应img_001.txt,放错目录或命名不一致,训练时该图片的所有标注都会被忽略,mAP却不会报错,只能在日志里看到这条图片样本量为0。
4.2 训练启动:参数含义与调整方向
用Ultralytics跑训练只需一条命令:
yolo detect train \ data=security.yaml \ model=yolov8n.pt \ epochs=100 \ batch=16 \ imgsz=640 \ device=0model=yolov8n.pt表示加载YOLOv8n的预训练权重,n是nano版本,参数量最小,适合安检工控机;如果显存够大换成yolov8s.pt或yolov8m.pt精度更高。epochs是训练轮数,100轮是起步值,看到验证集mAP连续20轮不涨就可以提前停了。batch受显存限制,8GB显存跑640分辨率建议batch设为8到16,过大直接OOM报错。imgsz=640是输入分辨率,想提升小目标检测效果可以调到1280,但训练时间翻倍。
训练过程中日志会打印每个epoch的box_loss、cls_loss和mAP50-95。box_loss下降说明边框回归在收敛,mAP50-95是综合精度指标,安检场景建议同时关注mAP50,它只要求预测框与真实框的IoU超过0.5就算对,更贴合“检出危险品”这一需求。注意看验证集指标,训练集指标掉进过拟合的陷阱。
4.3 训练完成后的验证与指标解读
训练结束后在runs/detect/train目录下会生成权重文件best.pt和last.pt。用best.pt跑验证集:
yolo detect val \ model=runs/detect/train/weights/best.pt \ data=security.yaml验证结果会输出每个类别的精确率、召回率和各类别mAP。安检场景里最该盯的是召回率(Recall),漏检一次危险品的后果远比误报严重。如果召回率偏低,优先检查标注是否漏标、数据增强是否过激,不要一上来就调置信度阈值——阈值只影响推理阶段,训练收敛质量才是根本。
5. 避坑指南:安检危险品识别的5个翻车现场
5.1 小刀漏检率高,Recall上不去
现象:训练好模型后,测试集里折叠刀和剃须刀片漏检严重,而日常物品的检测精度正常。
原因:小目标在YOLOv8的深层Feature Map上只占几个像素,经过5次下采样后信息几乎消失。另外X光图像中刀片和背景的对比度低,和金属保温杯叠放时更是难分彼此。
解决:把输入分辨率从640提到1280,用更大尺寸的特征图容纳小目标。数据增强里把Mosaic加强,让模型多见到叠放场景。如果还不行,换成YOLOv8-seg做分割,分割分支对边缘信息的敏感度高于检测框回归。这几个手段叠加后,我的经验是刀片召回率能从72%提到90%左右。
5.2 误报率高,金属餐具被当成刀具
现象:叉子、钥匙、不锈钢餐刀频繁被模型标为危险品,安检员没法接受这种误报率。
原因:训练数据里金属餐具的负样本太少,模型没见过相似的背景和目标形态,只能靠纹理特征猜测。这不是模型结构问题,是数据分布问题。
解决:把误报的图片收集起来,归入一个negative类重新标注训练,让模型学到“金属但无害”这类样本。调低置信度阈值只会让误报更多。还有一个思路是增加类别间相似度惩罚,但实操复杂度高,不如直接补数据来得快。
5.3 训练Loss下降但mAP卡死不涨
现象:loss曲线持续下降,看起来在收敛,但验证集mAP永远在0.5以下波动,怎么调参都没用。
原因:90%的情况是标签文件出了问题。比如XML里坐标值范围是像素值,但没除以图片宽高就写进TXT;或者标注框有零宽度、零高度,训练时这部分样本的梯度直接把模型带偏。
解决:写个脚本读取TXT标签,检查每行坐标是否都在0到1之间、宽高是否大于0,再随机挑几张图画出标注框可视化。这个步骤虽然枯燥,但能省出整整一个周末的调参时间。另外检查类别ID是否超出names数量,索引越界不会报错,但损失计算会乱掉。
5.4 推理速度不达标,达不到实时
现象:模型精度不错,但单张图推理耗时200ms,机场通道要求每件行李处理时间在100ms以内。
原因:代码里直接用model.predict()逐张推理,每个batch只处理一张图,GPU完全没吃满,而且没有做任何格式优化。
解决:把推理改成批量模式,用batch=16填满显存。更彻底的做法是导出ONNX格式并用TensorRT跑,后面第6章会详细讲。先看NVIDIA官方文档确认工控机的GPU型号支持哪些算子,老架构的Maxwell显卡跑TensorRT会很痛苦。
5.5 换一台设备就掉点
现象:训练用的X光机和新部署的设备型号不同,新设备采集的图片放进去测试,mAP掉了20个百分点。
原因:不同厂家的安检机能量不同,X光图像的灰度映射和色彩空间有差异,模型的底层卷积核学的是训练设备的成像特征,换设备后分布偏移。
解决:传输通道数据做图像归一化时,去掉厂商自定义的色彩映射。现场部署后在设备端采集至少2000张图做二次微调,先用预训练模型生成伪标签,再由安检员修正,能大幅减少标注成本。一定要在项目计划里留出这个适配环节。
6. 部署阶段技巧:TTA推理与NMS参数,调到什么程度能上线
6.1 测试时增强:精度不够时的最后一张牌
TTA(Test-Time Augmentation)就是把同一张图做水平翻转、缩放后再多次推理,把结果做加权融合。YOLOv8里开启方法:
from ultralytics import YOLO model = YOLO('best.pt') results = model.predict( source='test_img.jpg', imgsz=640, augment=True, # 开启TTA conf=0.25, # 置信度阈值,调低提高召回 iou=0.45 # NMS的IoU阈值 )参数说明:augment=True让模型对原始图和翻转图各跑一次前向,合并预测结果后再做非极大值抑制,漏检率能降5到8个百分点。代价是推理时间翻倍,所以TTA只用在二次判读或重点行李复查上,不能用于每件行李的实时初检。conf=0.25是我在安检场景的常用值,比通用检测的0.5低,因为漏检一个危险品的后果远大于多标几个框,宁可让安检员多看一眼。iou控制NMS阶段两个框合并的阈值,0.45是均衡值。
6.2 NMS参数对叠放物品检测的影响
安检X光图里物品叠放是常态,同一物体被预测框多次框住的情况频繁。NMS阈值调高到0.6以上,相邻框更容易被合并,能减少重复检测;但叠放的刀和叉距离很近,阈值过高会把两个真实目标合并成一个框。我的习惯是iou设置在0.4到0.5之间,配合max_det=20限制每张图最多输出的目标数,避免某个区域框爆炸。
上线前一定要用探针图集测试,专门收集那些叠放严重的实际行李图,逐张对比模型的输出框和人眼判断。把每个类别的置信度阈值分开设置,比如枪支阈值可以低到0.15,因为漏掉枪支的后果不可接受,而打火机阈值可以保持0.4,减少干扰。
6.3 导出ONNX并验证端到端部署
训练好的PyTorch模型不能直接给C++设备端用,导出为ONNX是常见做法:
model.export(format='onnx', imgsz=640, opset=12)导出后先用onnxruntime验证一次精度,确保导出过程没破坏权重:
import onnxruntime as ort import numpy as np from PIL import Image sess = ort.InferenceSession('best.onnx') input_name = sess.get_inputs()[0].name img = np.array(Image.open('test.jpg').resize((640, 640)), dtype=np.float32) / 255.0 img = img.transpose(2, 0, 1)[None] # HWC转CHW并加batch维度 outputs = sess.run(None, {input_name: img})这段代码用ONNX Runtime加载导出后的模型,手动做了一遍和PyTorch推理等价的前处理。注意h*w转c*h*w的维度顺序,不转的话模型输出的坐标全是乱的。ONNX Runtime在CPU上的推理速度一般能比PyTorch快30%到50%,如果要上GPU就继续转TensorRT,用FP16量化后速度还能再翻一倍,精度损失在1个百分点以内,安检场景可以接受。
我自己做过的项目里,最深的体会是不要一上来就追求涨点,先把数据管线跑通,用可视化工具画出预测框看实际效果,胜过盯着mAP数字纠结。换设备、调阈值、补样本这些脏活累活,才是这个方向真正的门槛。希望这篇文章能帮你在安检危险品识别这条路上少踩几个坑。
本文还有配套的精品资源,点击获取