简介基于YOLOv5的裂缝检测项目面向毕业设计、课程设计以及计算机视觉初学者解决道路、桥梁等基础设施表面裂缝的自动识别与定位问题。压缩包共51个文件以yaml配置、Python脚本、Shell辅助脚本为主另有Dockerfile、README文档和若干检测效果示例图整体大小约2.02MB。其中yaml文件用于定义模型结构和训练超参数py脚本覆盖数据加载、模型导出以及实时视频和静态图片检测sh脚本方便下载预训练权重与数据集Dockerfile则用于创建一致的容器化运行环境降低部署门槛。项目同时提供了训练好的权重和数据集目录可直接运行检测脚本观察裂缝识别效果也适合在此基础上开展迁移学习或继续调优。已有49人浏览学习可作为深度学习目标检测课程设计、毕业设计的完整参考也为后续扩展至桥梁隧道等场景提供基础。1. 裂缝检测看着像分类实际是目标检测问题处理过混凝土裂缝、路面裂缝的读者应该都有同感裂缝检测最麻烦的不是“有没有裂缝”而是“裂缝在哪、有多长、走向如何”。用纯 CNN 做二分类只能告诉你图片里有没有病害没法定位。YOLOv5 这类单阶段目标检测器一次把定位和分类都做了这也是它成为毕设和课设高频选题的原因。这份《基于YOLOv5的裂缝检测设计》压缩包我拆过之后确认它是完整可跑的工程包源码能直接训练数据集带好了标注还有已训好的权重可以直接做推理。适合两类人一类是拿它当毕业设计或课程设计底子需要快速跑通并出效果图另一类是想学 YOLOv5 训练自己数据集的从业者正好拿这套标注规范当模板。下面按实际落地顺序讲环境、数据、训练、踩坑、评估到部署。2. YOLOv5 环境配置与数据准备从 conda 到标注格式2.1 用 conda 锁住 Python 与 CUDA 版本YOLOv5 对环境的敏感程度远超普通项目最典型的翻车点是 Python 版本和 torch 版本不匹配导致 import 阶段报错。我一般用 conda 单独建环境不给系统 Python 添乱。这个包要求的核心依赖在 requirements.txt 里注意它锁的是 torch1.8对应的 CUDA 建议 11.x 起步。conda create -n yolov5_crack python3.8 -y conda activate yolov5_crack cd yolov5-master pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple这里指定 python3.8 不是保守是 YOLOv5 在 3.8 上经过最多验证3.10 以上版本跑旧版源码时torch 的 C 扩展编译容易出兼容毛病。requirements.txt 里包含 torch、torchvision、opencv-python、numpy 等用清华源能避开大部分网络超时。装完后先跑一句python detect.py --weights yolov5s.pt --source data/images/bus.jpg验证环境通不通能弹出检测框再进下一步。2.2 标注数据LabelImg 输出 YOLO 格式的 text 文件裂缝标注和通用目标标注有个关键的尺度差异裂缝是细长目标一个框里往往只占很小面积标歪一点 IoU 计算就崩。这个包里带的标注是用 LabelImg 做的保存格式是 YOLO 那种每行一个目标的 txt 文件格式为class_id cx cy w h坐标全部除以图片宽高归一化。我拆包时抽查过标注文件确认是这种格式可以直接喂给 YOLOv5 训练。labelImg images/ annotations/打开后注意两点PascalVOC 格式是 xmlYOLO 格式是 txt保存时在左侧选择 YOLO 格式裂缝这类细长目标标注时框要贴着裂缝的边界不要留大段空白否则训练出来的预测框会偏大mAP 看着还行但实际定位不准。标注完每个图片对应一个同名 txt 文件比如crack_001.jpg对应crack_001.txt。2.3 数据集划分与目录结构训练前要把数据拆成 train、val、test 三份。这个包自带了一个划分脚本逻辑是随机按 8:1:1 拆并保证图片和标签同步移动。如果自己重新标注数据可以用下面这段脚本做同样的事import os import random import shutil images os.listdir(images) random.shuffle(images) total len(images) train_n int(total * 0.8) val_n int(total * 0.1) for i, img in enumerate(images): name img.rsplit(., 1)[0] label name .txt src_img os.path.join(images, img) src_lab os.path.join(labels, label) if i train_n: dst train elif i train_n val_n: dst val else: dst test shutil.copy(src_img, f{dst}/images/{img}) shutil.copy(src_lab, f{dst}/labels/{label})这段脚本的逻辑是先把所有图片路径打乱再按比例落进三个文件夹。train_n和val_n是硬编码的 80% 和 10%如果你想改比例直接改这两个数就行。注意它是用 copy 而不是 move跑完检查一下原目录确认没丢文件再删。YOLOv5 训练时搜索的目录结构是train/images和train/labels成对存在图有了但标签没跟上训练时 log 会提示WARNING: no labels found这个错经常出在只拷了图片忘了拷标签。3. 训练自己的裂缝数据集超参数与训练命令详解3.1 编写数据集 YAML 文件YOLOv5 的数据集描述文件是 yaml训练前要把路径和类别写对。这个包里已经写好了crack.yaml我拆开看了一下核心内容是一个 dict 结构。如果你沿用官方源码重新建一个长这样train: ./datasets/crack/train/images val: ./datasets/crack/val/images test: ./datasets/crack/test/images nc: 1 names: [crack]train和val的值必须是绝对路径或相对路径否则训练时图找不到直接报错。nc是类别数单类裂缝就写 1如果还分横向裂缝、纵向裂缝、龟裂就按实际类别数改names里的顺序必须和标注文件里的 class_id 一一对应。这里最容易犯的错是标注时候 class_id 是从 0 开始yaml 里 names 列表的第一个元素就对应 class_id 0顺序反了模型会一直学错。3.2 超参数文件yolov5 的 hyp 到底在调什么YOLOv5 的超参数集中在data/hyps/hyp.scratch-low.yaml里这个包用的是低增强版本对裂缝这种细长目标更友好。几个关键参数拆开讲lr0是初始学习率默认 0.01训练裂缝数据集时如果类别单一、数据量少建议降到 0.005 防止震荡mosaic是马赛克增强它把四张图拼在一起训练对检测小目标有帮助但它会改变目标的长宽比裂缝因为太细长mosaic 增强后框容易变形所以这个包里设置的是 0.5只对一半的样本做。lr0: 0.005 # 初始学习率数据量小就调低 mosaic: 0.5 # mosaic 增强比例裂缝场景不建议拉满 fl_gamma: 0.0 # 类别不平衡的 focal loss 参数单类场景不用开这几个值是渗在源码里的改完直接保存。fl_gamma是给多类别不平衡用的裂缝检测通常是单类保持 0 就好开了反而可能压低正常样本的梯度。3.3 训练命令与参数选择训练入口是train.py这个包的命令参数基本是经典组合重点看--img、--batch、--epochs和--weights的搭配python train.py --img 640 --batch 16 --epochs 100 \ --data crack.yaml --weights yolov5s.pt \ --project runs/train --name crack_exp --exist-ok--img 640是输入分辨率裂缝目标细长且小用 640 是精度和速度的折中点升到 960 能提一点小目标召回但显存占用涨 60% 以上。--batch 16受显存限制8G 显存跑 640 分辨率最多 16跑不动就降到 8。--weights yolov5s.pt是加载 COCO 预训练权重做迁移学习对裂缝这类纹理特征清晰的目标用 s 版够了m 或 l 版提升不大却慢一倍。--exist-ok的意思是允许同名实验目录直接复用否则第二次跑同名字会报错让你改名。训练过程里留意命令行输出的 P、R、mAP 三个指标。裂缝单类目标的 mAP 通常能到 0.85 以上低于 0.7 说明数据或标注有问题不要急着加轮次先回头排查。日志里每个 epoch 末尾还有box_loss和cls_loss这两个值如果训练到后 20 轮还在明显下降说明没收敛继续加 epochs。3.4 锚框与后处理裂缝场景要不要改 anchorYOLOv5 会在训练开始前用 k-means 重新计算数据集的 anchor日志里会输出autoanchor的改进结果。裂缝这种长条目标默认 anchor 的长宽比是 1 到 4对极细长目标不一定最优。这个包的数据集规模不大autoanchor 在训练前会自动跑一遍。跑完看日志如果Best IoU比默认提高了 0.1 以上说明默认 anchor 确实不适合裂缝自动计算值得保留。如果在日志里看到Better than default anchors这样的话就是有效果了。后处理阶段 NMS 的iou_thres值在训练时不需要改推理时才有意义。裂缝框重叠率不高--iou-thres 0.45够用设太高会让重叠框全留下画面里一片红。4. 避坑与常见问题裂缝检测训练的五次踩坑记录4.1 现象训练时提示 no labels found但数据明明标好了原因YOLOv5 读取标签的路径是固定在数据集 yaml 里的标注文件放错了目录或者图片和标签的根目录层级不匹配。这个包里的数据集按官方要求放在datasets/crack/下labels 目录必须和 images 目录同级。解决检查 crack.yaml 里的路径是否指向train/images同时确认标签文件在train/labels。再验证一个 txt 文件打开看里面坐标是不是都在 0 到 1 之间如果有坐标大于 1说明标注工具选成了 VOC 格式的像素坐标要重新导出。4.2 现象训练能跑完但预测框把整个墙面框进去原因标注时框打得太松把裂缝周围大片背景包进去了模型学到的框正好比你标的框紧一点但视觉上还是大片区域。这属于标注质量导致的后处理结果问题。解决重新标数据框紧紧贴着裂缝边缘。这个包提供的标注文件质量比较稳如果自己扩展数据建议把小裂缝删掉而不是留着撑数量。单边小于 4 像素的裂缝YOLOv5 在 640 分辨率下的特征图只剩 20 个像素宽根本学不出有效特征。4.3 现象显存明明够batch 调到 32 就报 CUDA out of memory原因batch32时训练时会额外计算一部分验证集的前向传播加上 mosaic 增强需要多缓存几张图显存峰值比想象的更大。还有可能是开了--workers 8数据加载线程把内存暴涨间接拖累 CUDA 内存分配。解决batch 降到 16 甚至 8--workers设成 4 以内。如果还想提速度用--half半精度训练显存占用直接减半但 Ampere 架构之前的显卡不要开会有精度损失。4.4 现象训练中断后重启从头开始跑原因没有加--resume。YOLOv5 支持从断点继续训练但 resum 的前提是这个包里的 runs/train 目录没被清理。解决重新训练时加--resume runs/train/crack_exp/weights/last.pt模型会从上次的 epoch 继续同时把学习率恢复到对应位置。这个包里保留了 last.pt 和 best.pt 两个权重文件建议每跑完一个阶段就复制一份 best.pt 到别处防止误覆盖。4.5 现象mAP 高但实际推理漏检多原因训练指标用的是 IoU 阈值下的综合 mAP而实际推理默认conf_thres0.25这个值对裂缝来说偏保守细小的裂缝置信度本来就在 0.2 到 0.3 之间。解决推理时把--conf-thres降到 0.15 或 0.1召回率会明显提升代价是多几个误检框。如果误检不能接受再通过 NMS 的 iou 阈值从 0.45 提到 0.6把重叠框去掉。裂缝场景先保召回毕竟漏一条裂缝的代价比多框一个噪点高得多。5. 模型评估与结果处理读懂混淆矩阵和 PR 曲线5.1 用 val.py 输出评估指标训练完的模型好不好不能只看训练集 loss要用验证集跑指标。YOLOv5 的 val.py 会生成 confusion matrix、PR 曲线和 F1 曲线这些图保存在 runs/detect 或 runs/val 下。python val.py --weights runs/train/crack_exp/weights/best.pt \ --data crack.yaml --img 640 --iou-thres 0.45 \ --conf-thres 0.001 --task val--conf-thres 0.001是为了画 PR 曲线评估时必须把置信度阈值拉到最低才能看到模型在所有阈值下的表现。输出会有一个汇总表看mAP0.5和mAP0.5:0.95两个值。前者是 IoU 阈值 0.5 时的平均精度后者是 0.5 到 0.95 每隔 0.05 的平均值。裂缝检测场景mAP0.5到 0.9 以上是质量的mAP0.5:0.95通常低 10 到 20 个点这对长条形目标是正常的不用焦虑。5.2 用 PR 曲线的拐点反推置信度阈值PR 曲线的拐点位置直接决定推理时 conf_thres 怎么设。如果曲线在召回率 0.9 左右才开始掉精度说明大部分裂缝都能被高置信度检出推理时保持默认 0.25 就行如果曲线在前半段就平缓下滑说明模型输出普遍低置信度推理阈值按 4.5 里的做法调低。这个包的权重跑出来的 PR 曲线经验值是拐点在召回率 0.85 到 0.95 之间。我习惯在 val.py 的输出图里找这个拐点比如推导一次python detect.py --weights runs/train/crack_exp/weights/best.pt \ --source test_images --conf-thres 0.15 \ --iou-thres 0.45 --save-txt --save-conf--save-txt会保存每个框的坐标和类别--save-conf附带置信度这两项组合可以把推理结果做成 csv 再导入 Excel 做人工复核。遇到裂缝密集的图框太多看不清就按置信度排序只看每张图 top3 的框人工判断有没有漏检。6. 部署与轻量化把模型从训到用串成一条线裂缝检测最终要落到现场不能永远在训练环境里跑。这个包里的 best.pt 是 PyTorch 权重直接部署到生产环境还要做转换。常见做法是导出 ONNX 或 TensorRT看目标设备。如果要部署到 Jetson 或树莓派这类边缘设备推荐先导出 ONNX 再用 ONNX Runtime 推理。python export.py --weights runs/train/crack_exp/weights/best.pt \ --include onnx --opset 12 --simplify导出 ONNX 时注意--opset 12太高版本在老设备上不支持太低版本某些算子的表达方式会变。--simplify会跑一遍 onnx-simplifier能去掉一些冗余节点让推理速度提升 5% 到 10%。导出后先验证一下输出一致性加载 onnx 跑一张图对比原模型的框坐标偏差在 2 像素内就说明转换成功。部署脚本我习惯写成一个最小推理文件不依赖 YOLOv5 的 detect.py这样生产环境不需要装全套源码依赖import onnxruntime as ort import numpy as np import cv2 sess ort.InferenceSession(best.onnx) img cv2.imread(test.jpg) img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img cv2.resize(img, (640, 640)) / 255.0 img img.transpose(2, 0, 1)[None].astype(np.float32) outputs sess.run(None, {sess.get_inputs()[0].name: img}) boxes outputs[0][0] # 每一行: x1, y1, x2, y2, 置信度, 类别这段代码里最需要注意的是输入预处理必须和训练时保持一致包括 resize 方式、归一化分母、通道顺序。很多在边缘设备上部署翻车的人不是模型没导出对而是预处理写错了一个像素归一化。我踩过这个坑之后导出完 onnx 第一件事就是对比原模型和导出的输出差异超过 0.01 就回去检查预处理。如果是树莓派这类 CPU 设备ONNX Runtime 支持 ARM 架构跑 640 分辨率的单帧推理大约 2 到 3 秒勉强够用了。想更快就降分辨率到 320裂缝这种大目标在 320 下可接受但细小裂缝召回率会掉。实际部署时我会先跑一批现场图把置信度阈值调到 0.1 到 0.2 之间宁可多标几个噪点也不漏掉真实裂缝。这是我在一次现场测试中得出的教训——模型的 mAP 不能直接代表现场效果现场光照和墙面纹理的变化远比训练集复杂从那以后我每次换数据集都强制走一遍「导出 ONNX → 验证预处理一致性 → 现场图回放」的流程再把阈值定下来。希望这份拆解能帮你少走几步弯路。本文还有配套的精品资源点击获取