ARTICLE DETAIL

资讯详情

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

Python+YOLOv5路面桥梁裂缝检测实战:数据标注、训练与避坑指南

Python+YOLOv5路面桥梁裂缝检测实战:数据标注、训练与避坑指南 简介基于PythonYOLOv5的桥梁与路面裂缝检测识别项目是一份可直接运行的毕业设计源码和模型包面向计算机相关专业学生、毕业设计及课程设计人群也适合零基础学习者用于项目实战练习。项目围绕基础设施裂缝检测这一现实任务提供了从数据配置、模型训练到图片/摄像头实时推理的完整流程结构清晰代码可运行并曾获导师认可、评审得分99分可直接作为毕设底稿或课程作业。资源包共85个文件以py源码、yaml配置、pyc编译文件为主体辅以sh环境脚本、Dockerfile和多种裂缝示例图片压缩包仅1.6MB轻量易下载便于快速部署。已有78人学习浏览适合正在完成毕设或想快速跑通目标检测项目的读者。借助该方案可复现裂缝检测全流程也能按需修改数据与参数用于后续算法改进或论文实验。1. 毕业设计选 PythonYolov5 做路面桥梁裂缝检测为什么这题看着简单却每年都有人翻车毕业设计要选 PythonYolov5 做路面桥梁裂缝检测几乎是计算机视觉方向最容易上手的目标检测题目。裂缝识别既有真实场景又能用边界框和置信度直观展示答辩时放一张裂缝被框出来的效果图比讲一堆数学公式更能让评委点头。但这个项目并不是把源代码和模型下载下来就能交差的Python 环境、数据标注、yolov5 超参数每一处都能让人卡上一周。适合的人群很明确想完整走一遍“采集数据 → 标注 → 训练 → 评估”流程的本科生或者刚入门目标检测、想拿裂缝当落地场景的开发者。下面按我实际跑通这个方向的顺序写照着做能省下不少反复摸索的时间。2. 裂缝检测前先看懂 Yolov5网络结构、模型选型与本地跑通 demo2.1 看懂 yolov5 网络结构图Backbone、Neck 与 Head 各管什么很多人一开始就跳过网络结构直接跑训练脚本结果模型变成黑匣子出了问题不知道去哪看。YOLOv5 的主体结构在任何一张 yolov5 网络结构图上都能看得很清楚它由三块拼起来Backbone 负责从原始图像里抽特征Neck 负责把不同尺度的特征融合Head 负责在最终特征图上输出预测框和类别概率。裂缝检测对这三块各有要求。Backbone 的深度决定了对细纹理的敏感度Neck 的多尺度融合决定了对长短不一裂缝的适配度Head 的锚框设计则决定了细小目标能不能被准确定位。YOLOv5 的 Backbone 使用了 CSPDarknet 结构把通道分成两部分一部分经过卷积计算另一部分直接跨层相连用这种设计减少重复梯度计算同时保留更多细节信息。路面桥梁裂缝在图像里往往是低对比度边缘背景里有沥青颗粒、桥墩阴影、伸缩缝这些都会干扰特征提取所以 Backbone 的浅层特征对裂缝边界尤其重要。Neck 部分是 FPN 加 PANet 的组合FPN 从高层往低层传语义信息PANet 再自底向上补充空间细节最后在 Head 端得到三个不同尺度的输出分别负责小、中、大目标。裂缝的长宽比差异极大一张图里可能同时存在几像素宽的细纹也有横向贯穿几十厘米的长缝这种跨度让单尺度输出完全失效。看网络结构图时要理解的是为什么需要三个输出头而不只是记住模块名字。很多毕业设计的失败不是模型不好而是压根不看结构就把源代码里的参数一顿乱改。改之前至少要在图上找到输入尺寸从哪里进入、三个预测层在哪些位置生成这样后面调训练参数时才知道改的是哪一个环节。2.2 路面桥梁裂缝该选哪个模型从 yolov5s 到 yolov5x 的取舍YOLOv5 常见有 n、s、m、l、x 五档模型。用在哪决定选哪档。如果手里的显卡只有 4G 到 6G 显存训练时间又只剩一两周老老实实选 yolov5s如果只做验证CPU 推理也能跑选 yolov5n 更轻松如果桥梁远景图片里的裂缝只有十几个像素显卡 10G 以上可以考虑 yolov5m 或 yolov5l但要接受训练时间翻倍的代价。我通常会先拿 yolov5s 和输入尺寸 640 跑一轮 baseline。这个组合在 6G 显存的笔记本上batch-size 设 16 勉强能跑速度也够。跑完看 mAP如果漏检多再换更大的模型或调高 imgsz。不要一开始就上 yolov5x那是典型的拿资源换虚荣心训练时间可能长到让毕设日期告急。imgsz 是另一个容易被忽略的入口参数640 适合车载摄像头拍的路面1280 适合无人机拍的桥面但显存占用会按面积增长小显存基本碰不了。所以模型档位和输入尺寸要一起规划。这里有一条血泪经验先做小模型跑通全流程再换大模型做对比这是最稳的节奏。很多失败案例都是第一天就在最大模型上调参结果连一次完整训练都没跑起来。2.3 先把环境跑通Python 安装、依赖安装与第一条 detect.py 命令无论拿到的是哪个版本的 YOLOv5 源代码第一步一定是先跑通推理 demo再碰训练。这一步能帮你确认 Python、PyTorch 和 CUDA 是否兼容也能让你提前感受模型输出长什么样。用虚拟环境管理项目依赖可以避免把系统 Python 环境搞乱。常见做法是先创建 conda 环境再按 requirements.txt 装依赖conda create -n yolov5 python3.8 -y conda activate yolov5 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install -r requirements.txt参数说明Python 版本不用追最新3.8 到 3.10 都可以torch 的安装源要根据 CUDA 版本选择如果只是 CPU 推理就装 CPU 版能省不少空间requirements.txt 在 YOLOv5 项目根目录下里面是 opencv-python、pandas、matplotlib 这类依赖。装完先别急着训练用一张裂缝图片跑推理python detect.py --weights yolov5s.pt --source 001.jpg --conf-thres 0.25 --save-txt这里关键参数有三个。--weights指定模型权重文件第一次运行会自动下载官方预训练权重--conf-thres是置信度阈值0.25 是偏低的值能看到更多候选框用来熟悉输出可以用来做正式统计则要调回 0.4 左右--save-txt会把每个框的类别、中心坐标、宽高和置信度写进 txt方便后面做裂缝数量统计。如果机器没有 NVIDIA 显卡detect.py 默认会用 GPU启动后会报错这时在命令末尾加--device cpuPyTorch 就会用 CPU 推理速度慢一点但流程能通。CPU 推理一张 640 的图大概要 1 到 3 秒是正常现象。权重下载如果网络连接不畅可以直接找已经下载过的同学拷贝一个 yolov5s.pt 放进项目根目录代码检测到文件已存在就不会再去下载。源代码管理这件事也很重要我习惯从第一天就把项目纳入版本管理每跑完一版训练就提交一次。runs/train/exp目录会按编号自增再把对应的训练命令和超参数写进备注文件否则过两周你根本分不清哪个权重是哪次实验产的。这一步属于典的后悔药机制毕设答辩前尤其关键。3. 把路面桥梁裂缝做成自己的数据集采集、标注与划分脚本3.1 裂缝数据集的两个来源与版权边界裂缝检测的训练数据有两个主要来源公开数据集和自采照片。公开裂缝数据集常见的有 CrackForest、Crack500、DeepCrack 这一类多来自城市道路和混凝土墙面标签形式有语义分割也有手工框。作为训练素材它们质量高、量大可以直接用来做预训练。但它们的场景和桥梁裂缝差异不小路面裂缝大多在平整沥青背景上桥梁裂缝常有混凝土纹理、模板接缝和锈迹直接把公开数据训练出来的模型拿去检测桥梁图片漏检率会明显上升。所以我常用的做法是公开数据做底料自采数据做精调。先拿公开数据集跑一轮让模型学会裂缝的基本纹理特征再在自己拍摄的几十张桥梁、道路照片上做二次训练。这样标注工作量能控制在两到三天内模型在答辩现场面对陌生人拍的图片时也不至于完全失效。还有一条要注意的是版权公开数据集的引用规则各不相同毕设论文要在数据集来源一节写清楚名称和出处这是评委容易追问的点。自采照片时要尽量覆盖白天、阴影、干燥、湿润、近距离、远距离这些条件。不要只拍大裂缝真实场景里的细小裂缝才是模型能否落地的关键。如果条件允许多拍一些带阴影、带水渍、带桥梁伸缩缝的图片这部分负样本在后面排查误检时非常有用。3.2 用 LabelImg 标注裂缝并导出 YOLO 格式 txt有了图片之后最花时间的就是标注。目标检测标注工具里LabelImg 因为轻量和稳定一直是首选。用 pip 直接安装pip install labelimg labelimg启动后在菜单里把标注格式从 PascalVOC 切换到 YOLO再打开图片文件夹。框选裂缝时用矩形框不要太贪心把大块背景包进去。裂缝是细长目标标注框应该贴着裂缝边缘宽度尽量覆盖裂缝实际占用的像素区域否则模型学到的是一个框里大部分是路面定位自然不准。类别名统一写 crack毕设阶段不要一上来分 road_crack 和 bridge_crack 两个类样本少的时候多分类会严重拉低精度。保存后每张图片会生成一个同名 txt 文件内容类似0 0.487307 0.318269 0.438462 0.159615这一行五个数字对应类别 id、中心 x、中心 y、宽、高前四个都是 0 到 1 的归一化坐标。值得强调的是YOLO 格式里没有像素坐标直接把像素值写进去会导致训练时所有边界都越界模型完全学不出来。标注完一定要抽查几行 txt看到大于 1 的数就回去改。这个细节可以说是裂缝标注里最容易发生的低级错误但绝大多数报错都会让你怀疑到模型代码头上实际是标签的问题。3.3 训练集/验证集/测试集划分一份不会串包的 Python 脚本标注完成后下一步是把图片按比例切成训练集、验证集和测试集。这一步看着简单实际操作里最常犯的错是图片和 txt 对不上。如果一张图没有对应标签文件训练时 yolov5 会报警告甚至跳过样本如果标签文件名不一致数据加载会漏样本。我习惯写一个脚本用文件名作为匹配键来划分import random, shutil from pathlib import Path random.seed(2024) # 固定种子保证每次划分结果可复现 dataset Path(dataset/raw) # 原始图片目录 out Path(dataset) split {train: 0.8, val: 0.1, test: 0.1} for img in dataset.glob(*.jpg): label dataset / (img.stem .txt) if not label.exists(): continue # 有图无标注的直接跳过别硬塞进训练集 mode random.choices(list(split), weightslist(split.values()))[0] (out / mode / images).mkdir(parentsTrue, exist_okTrue) (out / mode / labels).mkdir(parentsTrue, exist_okTrue) shutil.copy(img, out / mode / images / img.name) shutil.copy(label, out / mode / labels / label.name)这个脚本的逻辑很简单遍历原始图片强制要求同名 txt 存在缺失就跳过然后按比例用随机抽取的方式决定这张图进哪个集合。random.seed(2024)的作用是让每次运行结果一致这样论文里写的训练集和测试集划分答辩时还能复核。目录结构上YOLOv5 默认要求图片放 images同名标签放 labels所以脚本里在目标目录下又按 train、val、test 分层。最后检查三个目录下的文件数量大致 8:1:1 即可。这里还有一个很隐蔽的坑如果同一条裂缝被裁剪成多块这些图片会被随机划分到 train 和 val导致验证集和训练集高度相似mAP 虚高答辩时一换新图片就露馅。所以我后来会按来源批次分组划分同一批拍摄的图片要么全进训练要么全进验证避免数据串包。处理小数据集时这比简单随机划分重要得多。4. 用 YOLOv5 训练自己的裂缝数据集命令、超参数与迁移学习4.1 修改数据配置文件 data.yaml路径和类别的三处坑训练之前要先准备一个数据描述文件YOLOv5 约定俗成叫data.yaml。内容不多但三处细节容易出错train: dataset/train/images val: dataset/val/images test: dataset/test/images nc: 1 names: [crack]第一处是路径。建议用相对路径从项目根目录出发不要写带盘符的绝对路径换一台电脑就得改一遍。第二处是 train 和 val 的地址YOLOv5 会自动找同级 labels 目录也就是说配置里只需要写dataset/train/images它会自动对应dataset/train/labels所以千万不能把标签和图片放到同一个目录里。第三处是nc要和names数量一致如果标注时写了多个类别这里也要同步改类别数不一致会让训练报维度错误。如果启动训练时提示AssertionError: train: No labels found in ...第一反应不是去改 Python 代码而是检查dataset/train/labels是否存在、txt 文件名是否和图片一致。这个提示算是我见过最多的 YOLOv5 数据问题占了数据集报错的一半还多。4.2 train.py 训练命令拆解yolov5 超参数这么设才不玄学配置文件就绪后进入训练环节。核心命令如下python train.py \ --data data.yaml \ --weights yolov5s.pt \ --epochs 100 \ --batch-size 16 \ --imgsz 640 \ --workers 4 \ --device 0--weights yolov5s.pt是迁移学习的核心官方预训练权重在大规模公开数据上见过大量真实物体能提供一个不错的起点比随机初始化训练少花很多个 epoch 才能收敛。--batch-size是显存敏感参数6G 显存设 16 已经接近极限12G 可以设 32batch 太小会导致 BN 统计量不稳直观表现就是 loss 抖成心电图。--workers在 Windows 下别超过 2设 4 或 8 极容易出现 DataLoader 崩溃这不是代码问题是 Windows 多进程加载的经典冲突。--device 0指定 GPU 索引只有一张卡默认就是 0没有 GPU 就改成 cpu同时把 batch 降到 4 到 8。超参数不用全部在命令行传YOLOv5 把它放在data/hyps/目录下的 yaml 文件里不同版本文件名略有差异。训练时 train.py 会读入改这个文件就相当于改超参数。对裂缝检测这个任务我最常动的是下面三项超参数默认值我常用的值为什么lr00.010.005数据集小学习率低一点更稳mosaic1.00.5细长裂缝在马赛克拼图里容易被裁掉fliplr0.50.5左右翻转对裂缝也有效保持默认即可注意一次只改一个超参数做对比实验才有资格写进毕业设计的实验分析表。不要同时把 lr、mosaic、fliplr 全改了最后模型涨了一点根本不知道是哪个改动起了作用。这个做法在写论文时尤其重要单变量原则能让实验结果叙述干净很多。4.3 迁移学习与数据增强让细裂缝不漏检的进阶操作常规训练跑完如果漏检都集中在细裂缝建议先用冻结策略做两段式训练。常见做法是先冻结 Backbone 前十几层让模型在保留通用纹理特征的前提下只更新 Neck 和 Head 的参数python train.py --data data.yaml --weights yolov5s.pt --epochs 30 --freeze 10跑完 30 个 epoch 后再不加--freeze继续训练 70 个 epoch。这样做的原因是小数据集上直接微调所有层模型很容易把裂缝过拟合到背景纹理上先冻结主干让浅层特征保持稳定再解冻全网络去学习裂缝特有的边缘组合收敛过程会平稳很多。数据增强方面mosaic对裂缝检测是一把双刃剑。它能把四张图拼成一张提升训练效率但裂缝本来就是细长线条拼图时每张图被缩小一半裂缝可能直接缩到几个像素标注框也容易超出拼接边界。所以我通常把mosaic从默认 1.0 降到 0.5样本量小时这比牺牲精度换多样性划算。如果还是漏检再把--imgsz提到 1280 重跑一版。代价是训练时间几乎翻倍一般只作为冲刺手段。5. 裂缝检测避坑与排查训练不收敛、漏检错检、显存不足的翻车现场5.1 训练 loss 不降和 NAN先查标签再查学习率现象训练日志里 loss 曲线像心跳一样震荡几十个 epoch 过去精度还在原地踏步或者某一步突然输出 NAN模型权重随之报废。原因分两类。一是数据问题最常见的有标签文件为空、坐标越界、图片里根本没有裂缝但标签却写了目标二是超参数问题初始学习率太高或者 batch-size 太小BN 层统计量在批次间来回横跳。遇到 NAN 还有一个隐蔽原因PyTorch 和 numpy 版本不匹配老版本 YOLOv5 代码对新版 numpy 兼容性差推理时直接算崩。解决先写个小脚本统计整个数据集的标签文件确认没有越界和空标签然后把学习率调低 50%batch-size 尽量大过 8最后再看依赖版本把 numpy 固定在稳定版本。如果标签是手工编辑过的千万别靠肉眼检查用程序把所有 txt 的值打印一遍这一步成本最低收益最直接。5.2 细裂缝漏检、阴影误检从标注框和背景样本两方面治现象模型对粗裂缝框得很准但对细小裂缝完全没反应反过来对桥墩阴影、路面湿润反光框出大量假阳性一下框十几个看着像模像样实际全是误检。原因细裂缝在 640 输入下只占几个像素下采样后特征图保留不住细节阴影误检则说明训练集里缺少“没有裂缝但有阴影”的负样本模型只能从颜色深这一点硬猜。换句话说模型成了黑匣子判断依据是不是真裂缝只能通过数据和测试反推。解决第一把包含细裂缝的图片裁剪成 640 的小块再训练相当于变相提高 imgsz第二增加背景负样本把检测中误检的图片不添加任何标签直接放进训练集图片目录大部分 YOLOv5 默认配置会把它们当作没有目标的图片参与训练帮助模型学习“这张图里没有裂缝”的输出第三推理时把--conf-thres从 0.25 提到 0.4 到 0.5牺牲少量召回保住展示效果毕设答辩现场宁可漏检几个也好过满屏红框。5.3 显存不足、训练卡死与 Windows 进程崩溃现象训练开始不久就报CUDA out of memory或训练脚本启动后卡在 DataLoader日志一动不动还有一种是跑着跑着 worker 进程直接退出。原因显存不足主要是--batch-size和--imgsz组合超出显存上限卡住和进程退出在 Windows 上多数是--workers设置过高导致PyTorch 在 Windows 下的多进程数据加载本来就比 Linux 脆弱加上数据集路径里有中文还可能触发编码异常。解决遇到CUDA out of memory先把 batch-size 折半再不行就把 imgsz 降到 480或者加--cache ram把图片缓存到内存减少显存里解压图片的开销。遇到 DataLoader 卡死就把--workers设为 0强制单进程加载。项目路径里不要出现中文字符目录名和文件名统一用英文这个习惯能避开大量奇怪的编码问题。另外训练中断时不用从头再来。YOLOv5 会在runs/train/exp下保存last.pt重新训练时把--weights指向last.pt它会从断点继续。这是做毕设最需要的后悔药别等翻车了才想起来保存中间权重。5.4 样本太少和类别不均衡几十张图怎么救现象自采数据只有几十张图训练很快收敛验证集 mAP 很高但一到测试集就崩盘典型的过拟合。原因标注样本量不够模型把背景纹理也背下来了。加上裂缝目标细长目标框占整图比例低类别不均衡会让模型倾向预测背景导致漏检。解决先使用公开裂缝数据集做预训练再用自己的几十张图微调这是最有效的方法微调时使用数据增强包括旋转、平移、亮度扰动但注意不能对裂缝做随机裁剪否则会把目标切碎。如果公开数据集也找不到就至少保证每张图里都有裂缝目标训练集中不含目标占比太重然后把训练轮数降低并把学习率调低减少模型记忆背景的可能。6. 答辩前把模型收拾体面mAP 验证、PR 曲线与结果导出技巧6.1 用 val.py 算 mAP 并导出可视化结果训练完成后不要只在训练日志里看一个漂亮数字要跑一遍验证脚本拿到标准指标python val.py --data data.yaml --weights runs/train/exp/weights/best.pt它会在终端打印 Precision、Recall、mAP0.5、mAP0.5:0.95 四项指标同时在runs/val/exp里生成 PR 曲线、混淆矩阵和测试图的预测示例。答辩前我会把best.pt和last.pt各验一次两者差很多说明训练还没收敛就把 epochs 加到 150 再跑一版没必要舍不得时间。真正给答辩加分的是用测试集跑一批现场实拍图的检测结果。挑 6 到 8 张你之前没参与标注的图片放进 source 目录执行 detect.py把框出裂缝的结果图整理成一页 PPT。评委看到模型在自己没见过的图上还能准确定位比任何指标都有说服力。如果推理时裂缝框总是断成几截可以适当把置信度阈值降到 0.35推理完成后用形态学后处理把相邻框合并这是我做演示时常用的保留技巧。最后说一个个人习惯我当年做毕设时总喜欢在最后一周反复换权重和数据集结果答辩前夜发现最关键的权重文件忘了保存对应 epoch 版本只能灰头土脸用旧权重。从那以后每次训练都用统一格式记录日期、模型档位、imgsz、batch、epochs、mAP再和权重文件一起打包。这种习惯比任何调参技巧都管用。希望你不用走我这条弯路希望帮到你。本文还有配套的精品资源点击获取
返回列表