简介:本资源是一套面向计算机视觉方向毕业设计与课程实践的轮胎缺陷检测完整实现方案,聚焦工业质检场景中的轮胎磨损识别与表面缺陷定位两大核心任务,适用于深度学习初学者及本科毕设学生快速上手项目开发。压缩包共34个文件,包含25个Python源码(涵盖数据预处理、Mask R-CNN模型训练与推理、摄像头实时检测、配置解析等模块)、4张示例图像(含mask与缺陷标注图)、2个JSON配置文件、2个说明文本及1份README文档,整体体积6.22MB,结构清晰、模块解耦,便于理解算法流程与复现实验。已有145人学习下载,提供从环境配置(requirements.txt)、训练脚本(train.py/test.py)到部署演示(cam.py)的全流程代码支持,并内置config.json与模型保存路径管理,显著降低调试门槛,适合用于毕设答辩、技术复现或工业质检入门实践。
1. 轮胎磨损+缺陷双任务检测:不是简单调个YOLO就完事,而是把工业现场“模糊划痕”“边缘毛刺”“橡胶老化色差”全塞进一个模型里跑通的毕业设计实战包
你手头正赶着毕业设计 deadline,导师说“得用深度学习做轮胎缺陷检测”,你搜了一圈发现全是单类检测(只检裂纹或只检鼓包)、数据集用的是合成图、训练脚本跑不通、推理结果连轮胎轮廓都框不准——别急,这个压缩包就是为这种场景生的。它不是教学Demo,而是一套在真实产线采集的217张轮胎图像(含磨损+鼓包+裂纹+缺胶四类)上实测收敛的完整 pipeline:从cam.py实时调用USB工业相机抓帧,到detectWear.py和detectDefect.py双分支并行推理,再到mask.png可视化叠加磨损热力图与缺陷掩膜。核心是改造过的 Mask R-CNN(非原版 mrcnn),支持 ROI Align 后接双头分类(wear severity: 0-3级 / defect type: 4类),所有 config.json 参数已按 NVIDIA GTX 1660Ti 显存(6GB)实测调优。适合本科毕设、高职实训、中小厂产线原型验证——不吹“SOTA”,但保证你 clone 下来改三行路径就能在自己笔记本上跑出带坐标+置信度+分割掩膜的检测结果。
2. 为什么选 Mask R-CNN 改造而非 YOLOv8 或 DETR:工业缺陷检测的三个硬约束倒逼架构选择
2.1 工业场景下“磨损程度量化”必须依赖像素级分割,YOLO 系列天然吃亏
轮胎磨损检测的核心诉求不是“有没有磨损”,而是“磨损到什么程度”。比如胎面沟槽深度低于1.6mm需强制更换,这要求模型输出不仅是 bounding box,更要精确到沟槽底部像素的连续掩膜(mask)。YOLOv8 的 segmentation head 虽支持 mask 输出,但其 mask 分辨率固定为 160×160,对轮胎侧壁细微龟裂(宽度常<5像素)分割精度不足;而本包中mrcnn/目录下的MaskRCNN类重写了build_mask_head(),将 mask 分辨率从默认 28×28 提升至 56×56,并在config.json中启用MASK_LOSS_WEIGHT: 2.5(原值1.0),强制模型聚焦 mask 边界细节。实测对比:同一张侧壁龟裂图,YOLOv8-seg 输出 mask 边缘锯齿明显(PSNR=21.3dB),本包 mask 输出边缘连续(PSNR=28.7dB)。
2.2 缺陷类型与磨损等级必须解耦建模,双头设计比单头多分类更鲁棒
原始 Mask R-CNN 的 class head 强制将“磨损等级0”和“裂纹类型A”视为同一语义空间,导致梯度冲突——磨损样本多时裂纹召回率暴跌。本包在trainer.py第127行插入DualHeadClassifier类:
class DualHeadClassifier(nn.Module): def __init__(self, in_channels, num_wear_levels=4, num_defect_types=4): super().__init__() self.wear_head = nn.Sequential( nn.Linear(in_channels, 256), nn.ReLU(), nn.Dropout(0.3), # 防止磨损过拟合 nn.Linear(256, num_wear_levels) ) self.defect_head = nn.Sequential( nn.Linear(in_channels, 512), # 缺陷特征更复杂,通道加倍 nn.ReLU(), nn.Dropout(0.5), # 缺陷样本少,dropout 加大 nn.Linear(512, num_defect_types) )关键参数在config.json中体现:WEAR_HEAD_DROPOUT: 0.3,DEFECT_HEAD_DROPOUT: 0.5。训练时两头 loss 加权求和:total_loss = wear_loss + 1.2 * defect_loss(权重1.2来自验证集 F1 平衡实验)。
2.3 小样本缺陷检测必须靠迁移学习+数据增强组合拳,不是光靠 augment.py
轮胎缺陷数据极度稀缺:217张图中,缺胶样本仅19张,鼓包仅23张。单纯用albumentations做旋转/裁剪会放大噪声。本包在utils/augment.py中实现三级增强策略:
- Level 1(基础):
RandomRotate90(p=0.5) + HorizontalFlip(p=0.5)—— 保胎面结构 - Level 2(缺陷特化):对缺陷区域(由
parse_config.py读取的defect_roi.json定义)单独应用ElasticTransform(alpha=120, sigma=12, p=0.7)模拟橡胶弹性形变 - Level 3(光照鲁棒):
RandomBrightnessContrast(brightness_limit=0.2, contrast_limit=0.2, p=0.8)+CLAHE(clip_limit=4.0, p=0.9)—— 抵消产线灯光不均
提示:
parse_config.py不是配置文件解析器,而是从config.json读取ROI_PATH后,加载defect_roi.json(含每张图缺陷区域坐标),供 Level 2 增强精准作用于 ROI。若你无 ROI 标注,需先用labelme标注并导出 JSON。
3. 从解压到推理:五步走通全流程,每步附命令、参数说明与失败信号
3.1 环境搭建:Python 3.8 + PyTorch 1.12.1 + CUDA 11.6(非最新版!)
本包所有.py文件经torch.cuda.is_available()和torch.version.cuda双校验,强制要求 CUDA 11.6。若你装了 CUDA 12.x,请先卸载:
# Ubuntu 示例(Windows 请用 NVIDIA 控制面板卸载) sudo apt-get remove --purge cuda-12-* sudo apt-get autoremove # 安装 CUDA 11.6(官方 runfile 方式) wget https://developer.download.nvidia.com/compute/cuda/11.6.2/local_installers/cuda_11.6.2_510.47.03_linux.run sudo sh cuda_11.6.2_510.47.03_linux.run --silent --override # 安装对应 cudnn(必须 8.4.0,非 8.5+) tar -xzvf cudnn-11.6-linux-x64-v8.4.0.27.tgz sudo cp cuda/include/cudnn*.h /usr/local/cuda/include sudo cp cuda/lib/libcudnn* /usr/local/cuda/lib64 sudo chmod a+r /usr/local/cuda/include/cudnn*.h /usr/local/cuda/lib64/libcudnn*然后创建虚拟环境:
python3.8 -m venv tire_env source tire_env/bin/activate pip install torch==1.12.1+cu116 torchvision==0.13.1+cu116 torchaudio==0.12.1 --extra-index-url https://download.pytorch.org/whl/cu116 pip install -r requirements.txt # 注意:requirements.txt 中 opencv-python==4.5.5.64(非 4.8+),因新版 cv2.dnn 接口变更失败信号:
import torch; print(torch.cuda.is_available())返回False→ 检查nvidia-smi是否可见 GPU;返回True但train.py报CUDA error: device-side assert triggered→ 通常是 cudnn 版本错,降级到 8.4.0。
3.2 数据准备:三类文件夹结构 +parse_config.py的真实作用
解压后目录结构必须严格为:
tire_project/ ├── dataset/ │ ├── train/ # 训练图(.jpg)+ 对应 mask(_mask.png) │ ├── val/ # 验证图 + mask │ └── test/ # 测试图(无 mask,用于 inference) ├── saved/ # 模型保存路径(自动创建) ├── config.json # 核心配置 └── ... # 其他源码parse_config.py的核心功能是:
- 读取
config.json中DATASET_ROOT路径 - 校验
dataset/train/下是否存在*.jpg和*_mask.png成对文件(缺一不可) - 生成
dataset/train/image_ids.txt(每行一个文件名,不含扩展名),供trainer.py加载
执行命令:
python parse_config.py --config_path config.json若报错
FileNotFoundError: xxx_mask.png not found,说明你的训练图命名不规范。本包要求:001.jpg对应001_mask.png,且 mask 中像素值:0=背景,1=磨损区域,2=裂纹,3=鼓包,4=缺胶。用utils/mask_generator.py可批量转换 labelme 导出的 JSON 到此格式。
3.3 模型训练:train.py的四个关键参数与显存监控技巧
运行训练前,务必修改config.json:
{ "BATCH_SIZE": 2, // GTX 1660Ti 最大安全值,设4会OOM "LEARNING_RATE": 0.001, // 初始 lr,warmup 后降至 0.0001 "NUM_EPOCHS": 120, // 小样本需足够 epoch,早停在 val_loss 连续5轮不降 "SAVE_INTERVAL": 10 // 每10轮保存一次 checkpoint }启动训练:
python train.py --config config.json --log_dir logs/train监控显存:
# 新终端,实时看显存占用(单位MB) watch -n 1 'nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits'关键现象:显存占用在
Epoch 0, Iter 0后稳定在 5200MB±200MB → 正常;若跳至 5900MB+ 并报CUDA out of memory→ 立即 Ctrl+C,将BATCH_SIZE改为 1,重启训练。
3.4 模型推理:test.py与cam.py的分工逻辑
test.py:离线推理,输入dataset/test/下图片,输出saved/predictions/中带 bbox+mask 的可视化图python test.py --config config.json --input_dir dataset/test/ --output_dir saved/predictions/cam.py:实时推理,调用 OpenCVcv2.VideoCapture(0)读取 USB 相机,每秒处理3帧(--fps 3),结果叠加在视频流上python cam.py --config config.json --camera_id 0 --fps 3
注意:
cam.py默认使用saved/model_final.pth,若你训练后保存了model_epoch_85.pth,需在cam.py第42行手动修改model_path = "saved/model_epoch_85.pth"。
3.5 结果解读:detectWear.py与detectDefect.py的输出字段含义
运行python detectWear.py --image_path dataset/test/001.jpg输出:
{ "image_id": "001", "wear_score": 2.7, // 磨损等级预测值(0-3浮点数,>2.5判为严重磨损) "wear_mask": "saved/masks/001_wear.png", // 磨损区域二值掩膜 "wear_heatmap": "saved/heatmaps/001_wear.jpg" // 热力图,越红磨损越深 }运行python detectDefect.py --image_path dataset/test/001.jpg输出:
{ "defects": [ { "type": "crack", // 类型:crack/groove/bulge/missing "bbox": [120, 85, 180, 130], // [x1,y1,x2,y2] 坐标 "confidence": 0.92, // 置信度 "mask": "saved/masks/001_crack_0.png" // 该缺陷的分割掩膜 } ] }提示:
wear_score是回归值,非整数类别;defects数组长度即缺陷个数,空数组表示“无缺陷”。
4. 避坑指南:五个血泪经验总结,每个都踩过真实翻车现场
4.1 现象:train.py报错RuntimeError: expected scalar type Float but found Half
原因:PyTorch 1.12.1 默认启用torch.cuda.amp(自动混合精度),但本包trainer.py中model.forward()未适配 half tensor,导致 loss 计算时类型不匹配。
解决:打开trainer.py,找到第312行with torch.cuda.amp.autocast():,将其整段注释掉(包括scaler.scale(loss).backward()等后续行),改用纯 float 训练。虽速度略慢,但稳定。
4.2 现象:cam.py打开摄像头黑屏,cv2.VideoCapture(0)返回False
原因:Ubuntu 系统下 USB 相机权限不足,或 OpenCV 未编译 FFmpeg 支持(导致无法解码 MJPEG 流)。
解决:
- 添加用户到 video 组:
sudo usermod -a -G video $USER,重启终端 - 检查相机是否被占用:
lsof /dev/video0,杀掉占用进程 - 若仍黑屏,在
cam.py第68行cap = cv2.VideoCapture(camera_id)后添加:cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')) # 强制 MJPEG cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
4.3 现象:test.py输出的 mask 全黑,或wear_score恒为 0.0
原因:config.json中MASK_THRESHOLD设为 0.5(默认),但轮胎磨损区域概率图(score map)峰值常在 0.3~0.4 区间,阈值过高导致 mask 全零。
解决:将config.json中"MASK_THRESHOLD": 0.5改为"MASK_THRESHOLD": 0.25,重新运行test.py。验证方法:用cv2.imread("saved/masks/001_wear.png", cv2.IMREAD_GRAYSCALE)查看像素值分布,正常应有大量 255 像素。
4.4 现象:detectDefect.py检出“裂纹”但 bbox 完全偏离轮胎区域
原因:config.json中ANCHOR_SCALES未适配轮胎尺寸。原值[32, 64, 128, 256, 512]适合 COCO 小物体,轮胎在 1280×720 图中占满画面,anchor 应放大。
解决:修改config.json:
"ANCHOR_SCALES": [128, 256, 512, 1024], "ANCHOR_RATIOS": [0.5, 1.0, 2.0] // 保持宽高比覆盖轮胎椭圆形态血泪经验:改完 anchor 后必须重新训练,不能直接用旧模型。
4.5 现象:saved/predictions/中图片 bbox 颜色混乱(如裂纹框成绿色,磨损框成红色)
原因:utils/visualize.py中COLOR_MAP字典顺序与config.json中CLASS_NAMES顺序不一致。本包约定:CLASS_NAMES = ["BG", "wear", "crack", "bulge", "missing", "groove"],但COLOR_MAP写成了{"wear": (255,0,0), "crack": (0,255,0), ...},而实际predict_class_id从1开始索引,wear对应 id=1 → 应取COLOR_MAP["wear"],但代码中误用COLOR_MAP[class_names[pred_id]]且class_names[1]="wear"正确,问题出在groove类别未在CLASS_NAMES中定义却出现在COLOR_MAP。
解决:打开utils/visualize.py,将COLOR_MAP严格按CLASS_NAMES顺序写为列表:
COLOR_MAP = [ (0, 0, 0), # BG (255, 0, 0), # wear → 红色 (0, 255, 0), # crack → 绿色 (0, 0, 255), # bulge → 蓝色 (255, 255, 0), # missing → 黄色 (255, 0, 255) # groove → 洋红 ]然后在draw_bbox函数中用COLOR_MAP[int(class_id)]取色,而非字典查找。
5. 进阶技巧:用detectWear.py的 wear_score 做产线分级预警,三步落地可执行方案
5.1 磨损等级映射表:把回归值转为可操作的工单指令
detectWear.py输出的wear_score是 0~3 的浮点数,但产线需要明确动作指令。本包在utils/wear_mapping.py中预置映射规则(可按你厂标修改):
| wear_score 区间 | 磨损等级 | 对应动作 | 响应时限 |
|---|---|---|---|
| [0.0, 1.2) | Level 0 | 正常使用 | 无 |
| [1.2, 1.8) | Level 1 | 记录台账,下次点检复核 | 72小时 |
| [1.8, 2.5) | Level 2 | 限速行驶,禁止重载 | 24小时 |
| [2.5, 3.0] | Level 3 | 立即停用,更换轮胎 | 立即 |
执行命令生成分级报告:
python detectWear.py --image_path dataset/test/001.jpg --output_json saved/reports/001_wear_report.json输出001_wear_report.json包含:
{ "image_id": "001", "wear_score": 2.73, "level": "Level 3", "action": "立即停用,更换轮胎", "deadline": "立即" }5.2 批量处理脚本:用batch_inference.py替代手动逐张运行
test.py一次只处理一个文件夹,产线需处理千张图。batch_inference.py提供并发控制:
python batch_inference.py \ --config config.json \ --input_dir dataset/batch_test/ \ --output_dir saved/batch_results/ \ --workers 4 \ # 启动4个进程 --batch_size 8 \ # 每进程批大小 --save_masks True \ # 保存 mask --save_heatmaps True # 保存热力图关键逻辑:batch_inference.py将dataset/batch_test/下所有.jpg按workers数分片,每片交由独立Process执行detectWear.py+detectDefect.py,结果汇总至saved/batch_results/summary.csv,含字段:image_id,wear_score,defect_count,defect_types,processing_time_ms。
5.3 置信度过滤:在detectDefect.py中加入动态阈值机制
固定CONFIDENCE_THRESHOLD=0.5会导致漏检(如微小鼓包)或误检(如光照噪点)。本包在detectDefect.py第89行实现自适应阈值:
def adaptive_conf_threshold(defect_type, base_thresh=0.5): """根据缺陷类型调整阈值:裂纹易检设低,鼓包难检设高""" thresholds = { "crack": base_thresh * 0.8, # 裂纹细长,降低阈值提召回 "bulge": base_thresh * 1.2, # 鼓包边界模糊,提高阈值保精度 "missing": base_thresh, # 缺胶区域大,用基准值 "groove": base_thresh * 0.9 # 沟槽磨损,中等阈值 } return thresholds.get(defect_type, base_thresh) # 在推理循环中调用: for pred in predictions: conf_thresh = adaptive_conf_threshold(pred["type"]) if pred["confidence"] > conf_thresh: valid_defects.append(pred)从那以后我每次部署到新产线,都强制走一遍
batch_inference.py跑 100 张图,统计各类型缺陷的confidence分布,再微调adaptive_conf_threshold中的系数——比如某产线鼓包常被误判为裂纹,就把"bulge"的系数从 1.2 提到 1.5。希望帮到你。
本文还有配套的精品资源,点击获取