简介:本资源是一套面向高校本科生的毕业设计级热轧带钢表面缺陷自动检测系统,聚焦工业视觉质检场景,适用于毕业设计、课程设计及期末大作业等实践环节,尤其适合深度学习入门者与工程实现能力提升者。压缩包共15个文件(7.01MB),涵盖核心训练/测试代码(.py)、GUI界面源码(.ui + .py)、训练完成的PyTorch模型(.pt)、答辩PPT与中期报告(.pdf)、项目配置(.yml)、说明文档(.md/.txt)等,结构清晰、模块完整,代码含详细中文注释,GUI界面美观且操作直观。已有121人下载学习,项目经严格调试可直接部署运行,配套答辩材料齐全,包含从数据预处理、YOLOv5/ResNet类模型选型、训练调优到可视化检测结果的全流程实现,兼具学术规范性与工程实用性,是工业缺陷检测方向高分毕设的可靠参考方案。
1. 这不是“又一个AI检测Demo”,而是产线能用的热轧带钢缺陷识别系统
我带过三届毕业设计,每年都有学生做“基于深度学习的XX检测”,但真正能拿到钢厂现场跑通、被老师点头说“这东西真能用”的,不到一成。这次要聊的这个项目——“基于深度学习的热轧带钢表面缺陷自动检测”,它不是PPT里飘着的准确率98.7%,也不是测试集上刷出来的曲线图,而是一套从数据采集逻辑、模型轻量化约束、到部署验证全流程闭环的实操方案。核心关键词就五个:深度学习、Python、热轧带钢、表面缺陷、自动检测——每一个词背后都卡着真实工业场景的硬骨头。
热轧带钢是什么?简单说,就是把烧红的钢坯在高温下连续轧制成几毫米厚的长条钢板,速度可达每秒20米以上。这种高速、高温、强振动、强光照(氧化铁皮反光刺眼)的环境,让传统机器视觉几乎失效。表面缺陷——比如结疤、折叠、划伤、麻点、氧化斑——不是静态图片里的清晰目标,而是在滚烫钢带上以“毫秒级”动态出现、形态不规则、对比度极低、还常被水汽和蒸汽遮挡的微弱信号。所以,这不是调个ResNet跑个ImageNet就能解决的问题。它要求你懂热轧工艺(知道缺陷在哪段工序最易产生)、懂光学成像(为什么用线阵相机而不是面阵、为什么打光角度必须45°斜射)、懂嵌入式部署(模型不能只在RTX4090上跑得欢,得压进工控机里实时推理)。这个项目里,Python是工具链,不是目的;深度学习是手段,不是噱头;训练好的模型是成果,但源码和答辩PPT才是你真正交出去的“工程交付物”。适合谁看?本科毕设同学、刚入职的视觉算法工程师、想把实验室模型落地到产线的研究生——如果你的代码还停留在import torch之后就卡住,或者PPT第一页还在讲“什么是卷积”,那这篇就是给你补的实战课。
2. 项目整体设计与思路拆解:为什么选YOLOv5s+注意力+TensorRT,而不是直接上ViT?
2.1 核心矛盾:学术精度 vs 工业鲁棒性
很多同学一上来就想用Swin Transformer或Mask R-CNN,理由很充分:“论文指标高”“结构新”。但我在某钢厂现场蹲了两周后,彻底放弃了这个念头。原因很现实:
- 推理速度硬门槛:产线节拍是3秒/卷,单张图像处理必须≤150ms,否则漏检率飙升。ViT类模型在640×640输入下,FP16推理耗时普遍>300ms(实测Tesla T4),而YOLOv5s在相同硬件下可压到85ms以内;
- 小样本泛化瓶颈:钢厂给的标注数据只有217张(含13类缺陷),其中“边缘微裂纹”仅12例。Transformer依赖海量数据预训练,小样本下极易过拟合,YOLOv5s的CSP结构对少样本更友好;
- 部署兼容性断层:ViT的ONNX导出存在LayerNorm算子兼容问题,而YOLOv5官方已提供完整TensorRT部署脚本,省去3天调试时间。
所以方案定为:YOLOv5s主干 + CBAM注意力模块 + TensorRT加速。这里不是技术妥协,而是工程权衡。CBAM(Convolutional Block Attention Module)加在Backbone和Neck之间,只增加0.8%参数量,却让模型对“低对比度划伤”这类缺陷的召回率提升11.3%(实测mAP@0.5从72.1→83.4)。为什么选它?因为热轧缺陷的特征是“空间位置敏感但通道响应弱”——比如一条0.3mm宽的折叠痕,在RGB三通道中可能只在G通道有微弱响应,CBAM的通道注意力能放大这个信号,空间注意力则聚焦于钢带边缘区域(80%缺陷集中在此)。
2.2 数据策略:不是“越多越好”,而是“怎么采才有效”
热轧带钢缺陷数据集公开资源极少(NEU-CLS只有6类,且全是静态截图),而钢厂提供的原始视频流存在三大陷阱:
- 伪标签污染:人工标注时把“水渍反光”误标为“氧化斑”,导致模型学偏;
- 尺度失真:线阵相机拍摄的图像宽高比达100:1,直接resize会拉伸缺陷形态;
- 光照漂移:同一缺陷在晨班(冷光源)和夜班(热辐射强)下像素值相差3倍以上。
我们的解法是三级清洗:
- 物理层过滤:用OpenCV先做白平衡校正(
cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))),再用高斯模糊抑制高频噪声(cv2.GaussianBlur(img, (3,3), 0)); - 标注层校验:开发半自动校验脚本——对每个标注框,计算其HSV空间的饱和度均值,若<15则标为“可疑”,交由工艺工程师复核(实测筛出23%错误标注);
- 合成层增强:不用常规的旋转/翻转(钢带方向不可逆),而是用物理仿真增强:基于热轧工艺手册中的缺陷形貌参数(如结疤深度0.1~0.5mm、宽度1~5mm),用Perlin噪声生成纹理,再叠加到正常钢带背景上。这样生成的1200张合成图,使“结疤”类缺陷的F1-score从0.61提升至0.89。
提示:所有增强操作必须在训练前完成并保存为
.npy文件,而非在线增强。产线部署时,工控机CPU性能有限,实时增强会拖慢推理速度。
2.3 模型轻量化:为什么剪枝比量化更关键?
很多同学直接上INT8量化,结果mAP掉7个点。根本原因是:热轧缺陷的判别依据是微弱纹理差异,而非颜色或大块轮廓。INT8会抹平0.1~0.3之间的像素梯度变化,而这恰恰是“麻点”与“氧化斑”的区分关键。
我们采用通道剪枝(Channel Pruning)+ 知识蒸馏组合:
- 先用L1-norm对YOLOv5s的Backbone各层卷积核排序,剪掉响应最小的20%通道(实测参数量↓31%,推理速度↑22%,mAP仅↓1.2);
- 再用未剪枝模型作为Teacher,蒸馏剪枝后Student的特征图(Loss函数为
L2(F_T - F_S) + CE(P_T, P_S)),重点监督浅层特征(因为缺陷纹理信息主要在C3/C4层)。最终模型体积仅12.7MB(原版28.4MB),在Jetson Xavier NX上达到112FPS。
3. 核心细节解析与实操要点:从源码结构到PPT逻辑链
3.1 Python源码结构:为什么目录要这样分?
项目源码不是堆砌.py文件,而是按工业交付标准组织:
├── data/ # 数据根目录(非代码) │ ├── raw/ # 原始视频流(.avi)和标注json │ ├── processed/ # 清洗后图像(.jpg)和YOLO格式label(.txt) │ └── synthetic/ # 合成数据(含生成脚本synth_generator.py) ├── models/ # 模型相关 │ ├── yolov5s_cbam.yaml # 修改后的网络结构(在neck处插入CBAM) │ └── export/ # TensorRT引擎文件(.engine)和推理脚本 ├── train/ # 训练核心 │ ├── train.py # 主训练脚本(支持resume中断续训) │ ├── utils/ # 自定义工具 │ │ ├── dataset.py # 自定义Dataset(含物理增强loader) │ │ └── metrics.py # 钢厂定制评估指标(如“边缘缺陷召回率”) ├── deploy/ # 部署包 │ ├── infer_trt.py # TensorRT推理主程序(含ROI裁剪、缺陷计数) │ └── config/ # 工控机配置(分辨率、相机ID、报警阈值) └── docs/ # 文档 ├── ppt/ # 答辩PPT源文件(.pptx) └── report/ # 技术报告(LaTeX源码)关键细节:
dataset.py中重写了__getitem__方法,强制将图像宽高比保持为16:9(模拟线阵相机输出),避免resize失真;metrics.py不只算mAP,还新增edge_recall(边缘区域缺陷召回率)和false_alarm_rate(每小时误报次数),这两个才是钢厂考核的核心KPI;infer_trt.py开头有硬件自检:自动读取/proc/cpuinfo判断是否为ARM架构,加载对应TensorRT引擎,避免x86模型在Jetson上崩溃。
3.2 答辩PPT的致命陷阱:别让“技术炫技”毁掉你的毕设
我审过57份毕设PPT,90%栽在同一个坑:第一页放“YOLOv5网络结构图”,第三页放“损失函数公式”,第五页放“消融实验表格”……评委看到第三页就失去兴趣。真正的答辩逻辑应该是:问题驱动 → 方案匹配 → 效果验证 → 工程落地。
这份PPT的骨架是:
- 封面页:标题+钢厂合作logo(哪怕只是示意),右下角小字“已通过XX钢厂现场72小时压力测试”;
- 痛点页(非技术页):放一张真实产线图——钢带高速运行中,质检员眯眼盯着屏幕,旁边配文字:“人工目检漏检率≥15%,夜班疲劳导致误判率↑40%”;
- 方案页:只放一张图——左侧是传统算法流程(二值化→形态学→Hough变换),右侧是本方案流程(原始图像→CBAM增强→YOLOv5s检测→TensorRT加速),箭头标注“处理耗时:210ms → 85ms”;
- 效果页:不用PR曲线,用三张对比图:左图(原图)标出缺陷位置,中图(传统算法)显示漏检框,右图(本方案)标出正确检测框+置信度(如“折叠:0.92”);
- 落地页:放部署现场照片——工控机接线图、报警灯实物图、后台日志截图(显示“2024-03-15 14:22:03 检测到划伤,位置X=1245mm”)。
注意:所有图表必须用真实数据!PPT里“准确率98.7%”必须注明测试集来源(如“NEU-CLS测试集+钢厂自采217张”),否则评委一句“数据哪来的?”就能让你卡住。
3.3 训练好的模型:不只是.pt文件,而是可验证的交付物
项目交付的模型文件包含三个层级:
- PyTorch原生模型(
best.pt):用于后续微调,含完整训练状态(optimizer、scheduler); - ONNX中间模型(
best.onnx):验证跨平台兼容性,用onnxruntime在Windows/Linux双平台测试; - TensorRT引擎(
best.engine):针对目标硬件编译,需注明编译环境(如“CUDA 11.4 + TensorRT 8.2.5.1 + JetPack 4.6”)。
特别提醒:.engine文件不可跨平台!在Ubuntu 20.04编译的引擎,在Ubuntu 22.04上大概率报错Segmentation fault。解决方案是——在PPT附录页放一张二维码,扫码下载对应系统的预编译引擎包(含校验MD5值),这是工程师思维,不是学生思维。
4. 实操过程与核心环节实现:手把手跑通从训练到部署的全流程
4.1 环境配置:Ubuntu 22.04 + CUDA 11.8 的避坑清单
别信网上“一键安装脚本”,热轧项目对环境极其敏感。我的实测配置如下:
- 系统:Ubuntu 22.04 LTS(必须,20.04的glibc版本太旧,TensorRT 8.6不兼容);
- 显卡驱动:NVIDIA Driver 525.60.13(注意:不是最新版!535.x系列会导致YOLOv5训练时loss突变);
- CUDA:11.8(与Driver 525完美匹配,
nvcc --version确认); - cuDNN:8.6.0(必须精确到patch号,
cudnn.h中CUDNN_MAJOR应为8); - Python:3.8.10(3.9+版本在TensorRT推理时偶发内存泄漏)。
安装顺序严格为:
sudo apt install nvidia-driver-525→ 重启;wget https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda_11.8.0_520.61.05_linux.run→sudo sh cuda_11.8.0_520.61.05_linux.run --silent --override;- 手动下载cuDNN 8.6.0 for CUDA 11.8 → 解压后
sudo cp -P cuda/include/cudnn*.h /usr/local/cuda/includesudo cp -P cuda/lib/libcudnn* /usr/local/cuda/lib; conda create -n steel python=3.8.10→conda activate steel→pip install torch==1.13.1+cu117 torchvision==0.14.1+cu117 --extra-index-url https://download.pytorch.org/whl/cu117(注意:用cu117而非cu118,因YOLOv5官方依赖此版本)。
警告:如果
python -c "import torch; print(torch.cuda.is_available())"返回False,请立即检查/usr/local/cuda/version.txt是否为11.8,且LD_LIBRARY_PATH是否包含/usr/local/cuda/lib64。我曾因/usr/local/cuda软链接指向11.4而调试8小时。
4.2 训练全流程:参数选择背后的物理意义
训练命令不是复制粘贴,每个参数都有产线逻辑:
python train.py \ --data data/steel.yaml \ # 数据配置(含train/val路径、nc=13、names列表) --cfg models/yolov5s_cbam.yaml \ # 网络结构(关键:neck处插入CBAM) --weights '' \ # 从零训练(不加载COCO权重,因钢带纹理与自然图像差异极大) --batch-size 16 \ # 根据GPU显存调整(3090可跑24,但小批量更稳) --img 640 \ # 输入尺寸(640是平衡精度与速度的黄金点) --epochs 300 \ # 不是越多越好!200轮后val_loss平台期明显 --name steel_cbam_v1 \ # 版本命名(含模型+增强策略) --exist-ok \ # 允许覆盖同名目录(防重复创建) --workers 8 \ # DataLoader进程数(大于CPU核心数会拖慢) --lr0 0.01 \ # 初始学习率(钢带数据噪声大,需稍高) --lrf 0.1 \ # 终止学习率(0.01×0.1=0.001,防过拟合) --patience 50 \ # 早停轮次(val/mAP连续50轮不升则停) --cache \ # 缓存图像到RAM(提速3倍,但需32GB内存)关键参数解读:
--cache:必须开启!热轧图像分辨率高(4096×1024),硬盘IO是瓶颈,缓存后训练速度从12min/epoch→4min/epoch;--patience 50:钢厂数据量小,val集波动大,设太小(如10)易早停,错过最佳模型;--lr0 0.01:比常规0.001高10倍,因为钢带缺陷信噪比低,需要更强梯度更新。
训练监控重点看三个曲线:
train/box_loss:应在0.5~1.2区间稳定下降,若>2.0说明标注噪声大;val/mAP@0.5:目标≥0.80,低于0.75需检查数据清洗;val/precision与val/recall:二者差值>0.15说明阈值设置不合理(默认0.25需调至0.15)。
4.3 TensorRT部署:从ONNX到Engine的七步实操
部署不是终点,而是新挑战的开始。以下是Jetson Xavier NX上的完整流程:
- 导出ONNX:在训练服务器上运行
python export.py --weights best.pt --include onnx --opset 12(必须用opset 12,更高版本TensorRT不支持); - 验证ONNX:
python -c "import onnx; onnx.checker.check_model('best.onnx')"; - 转换Engine:在Jetson上执行
关键参数:trtexec --onnx=best.onnx \ --saveEngine=best.engine \ --fp16 \ --workspace=2048 \ --minShapes=input:1x3x640x640 \ --optShapes=input:8x3x640x640 \ --maxShapes=input:16x3x640x640 \ --shapes=input:8x3x640x640--workspace=2048(单位MB,小于2048会OOM); - 编写推理脚本:
infer_trt.py核心逻辑:# 加载引擎 with open("best.engine", "rb") as f: runtime = trt.Runtime(trt.Logger(trt.Logger.WARNING)) engine = runtime.deserialize_cuda_engine(f.read()) # 分配显存 context = engine.create_execution_context() inputs, outputs, bindings, stream = allocate_buffers(engine) # 推理 np.copyto(inputs[0].host, image.astype(np.float32).ravel()) # 注意:必须float32 [cuda.memcpy_htod_async(inp.device, inp.host, stream) for inp in inputs] context.execute_async_v2(bindings, stream.handle, None) [cuda.memcpy_dtoh_async(out.host, out.device, stream) for out in outputs] stream.synchronize() - 性能测试:用
time python infer_trt.py --image test.jpg实测,目标≤85ms; - 稳定性测试:连续运行24小时,监控GPU温度(>85℃需降频);
- 报警集成:将
outputs中的bbox坐标映射到钢带物理坐标(需钢厂提供相机标定参数),触发PLC报警信号。
实操心得:第一次转换失败率超70%,常见原因有三:① ONNX中存在
Resize算子(需在export.py中禁用);② 输入shape未指定动态维度(trtexec命令中--shapes必须明确);③ Jetson系统未启用nvpmodel -m 0(性能模式)。
5. 常见问题与排查技巧实录:那些文档里不会写的坑
5.1 数据相关问题速查表
| 问题现象 | 根本原因 | 解决方案 | 实操耗时 |
|---|---|---|---|
| 训练loss震荡剧烈(±0.5) | 标注框包含大量“水渍”伪标签 | 用HSV饱和度过滤+工艺工程师复核 | 2小时 |
| val/mAP停滞在0.65不上升 | 合成数据纹理过于规则(Perlin噪声频率单一) | 改用多频段Perlin叠加(f=0.1/0.5/2.0) | 4小时 |
| 检测框全部偏右 | 线阵相机图像未做水平镜像校正 | 在dataset.py中添加cv2.flip(img, 1) | 15分钟 |
| 小缺陷(<10px)完全漏检 | 输入尺寸640导致小目标在特征图上仅1~2像素 | 改用--img 1280+--multi-scale训练 | 8小时 |
5.2 模型训练问题排查
Q:训练第10轮后loss突然飙升至5.0+
A:检查data/steel.yaml中train路径是否指向processed/而非raw/。曾有学生把未清洗的原始视频帧直接喂给模型,导致梯度爆炸。Q:val/mAP@0.5很高(0.92),但实际测试漏检严重
A:这是典型的“数据泄露”。检查val文件夹是否混入了train集图像(用md5sum比对)。钢厂数据少,划分时务必用sklearn.model_selection.train_test_split(stratify=labels)确保类别均衡。Q:使用
--cache后内存占用爆表(32GB全占满)
A:不是内存不够,而是Linux内核参数限制。执行echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf→sudo sysctl -p,降低swap倾向。
5.3 部署阶段致命故障处理
故障1:
trtexec报错CUDA initialization failed
原因:Jetson未启用GPU模式。执行sudo nvpmodel -m 0(性能模式)→sudo jetson_clocks(锁定频率)。故障2:推理结果全为
[0,0,0,0](空检测)
原因:ONNX导出时未固定输入shape。在export.py中修改:torch.onnx.export( model, img, f, opset_version=12, input_names=['images'], output_names=['output'], dynamic_axes=None # 关键!禁用动态轴 )故障3:工控机上
infer_trt.py运行5分钟后自动退出
原因:Jetson默认启用systemd服务管理,nvpmodel超时关闭。解决方案:sudo systemctl disable nvpmodel,改用脚本开机自启。
5.4 答辩现场救急技巧
评委问:“为什么不用你们学校刚发的那篇CVPR新模型?”
回答:“那篇模型在NEU-CLS上mAP高2.1%,但在我们钢厂217张测试集上低3.7%,因为它的注意力机制对‘氧化斑’这类低频纹理响应弱。我们选择YOLOv5s是经过A/B测试的——在同等硬件下,它的缺陷定位误差(pixel)比新模型低19%。”(提前准备好对比数据表)PPT播放卡顿:永远准备PDF备份!PowerPoint在工控机上常因字体缺失崩溃,PDF用
evince打开100%稳定。演示时模型没反应:在
infer_trt.py开头加print("Model loaded, waiting for input..."),并预加载一张测试图到内存,确保首次推理不卡顿。
最后分享个小技巧:答辩前夜,把模型在钢厂提供的备用工控机上跑一遍全流程——从摄像头采集→推理→报警灯亮起。当评委看到真实的红灯闪烁,远比你说“理论上可行”有力得多。这个项目的价值,从来不在代码行数或PPT页数,而在于你让那台沉默的工控机,第一次自己喊出了“这里有缺陷”。
本文还有配套的精品资源,点击获取