YOLOv5路面桥梁裂缝检测:从源码到部署的完整实战指南
简介这是一份基于Python与YOLOv5实现的路面桥梁裂缝检测识别项目面向计算机相关专业正在完成毕业设计、课程设计或期末大作业的学生也适合需要YOLOv5实战练习的学习者。项目提供完整可运行的源代码与预训练模型评审得分99分能够直接用于路面裂缝、桥梁表面缺陷等目标的检测识别任务。资源包共85个文件压缩包约1.6MB主要包含Python源码如模型定义、检测脚本、工具模块、23个YAML配置文件涉及模型结构、训练超参与数据集设置、Shell脚本用于自动下载权重、以及示例图片等便于对照模型效果与理解配置流程。目前已累计80人学习说明具备一定的参考价值。通过这份资料读者可以获得YOLOv5目标检测的完整落地思路从数据集配置、模型构建、训练调参到图片/摄像头检测均有涵盖目录结构清晰有助于高效复现与二次开发。1. 路面桥梁裂缝检测为什么我推荐直接用这份 YOLOv5 源码做过施工质检或者道路巡检相关项目的朋友应该深有体会裂缝检测这种任务看着简单真做起来全是坑。传统图像处理用 Canny 边缘检测或者形态学滤波晴天还好一到阴天、有阴影、路面有油渍误检率能高到没法看。而基于 Python 的 YOLOv5 目标检测方案本质上是把裂缝当作一种目标框出来而不是靠灰度阈值硬切泛化能力完全不在一个量级。这份毕业设计资源我拆过之后可以负责任地说它不只是拿来交作业的代码完整、模型权重齐全从训练到推理的闭环全都有。它解决的不只是有没有裂缝的二分类问题而是把每条裂缝的位置、大小、走向都能框出来对后续的裂缝宽度测量、严重程度分级都有直接帮助。适合三类人正在做毕设的计算机相关专业学生、想练手 YOLOv5 工程落地的新手、以及有道路或桥梁检测需求但不想从零写网络的从业者。2. 项目结构先摸清这套代码里到底藏了哪些东西2.1 从目录反推设计思路把压缩包解压之后我习惯先不看 README直接看目录结构。这份资源走的是典型的 YOLOv5 官方仓库风格但做了裁剪和定制目录结构大致是├── detect_photo.py # 单张图片检测脚本日常测试最常用 ├── detect_camera.py # 摄像头实时检测脚本接 USB 摄像头即可 ├── data/ │ ├── coco128.yaml # COCO 数据集配置 │ ├── coco.yaml # 完整 COCO 配置 │ └── voc.yaml # VOC 格式数据集配置 ├── models/ │ ├── yolov5s.yaml # 小模型结构 │ ├── yolov5m.yaml # 中等模型结构 │ ├── yolov5l.yaml # 大模型结构 │ ├── yolov5x.yaml # 超大模型结构 │ ├── common.py # 网络通用模块 │ ├── yolo.py # YOLOv5 核心检测逻辑 │ └── export.py # 模型导出脚本可转 ONNX/TorchScript ├── weights/ # 训练好的模型权重配合 download_weights.sh 使用 ├── runs/ # 训练和检测的输出目录 ├── scripts/ │ └── hubconf.py # 模型加载辅助脚本 ├── utils/ │ ├── datasets.py # 数据集加载与增强逻辑 │ ├── loss.py # 损失函数 │ ├── metrics.py # 评估指标 │ ├── general.py # 通用工具函数 │ └── autoanchor.py # 自动计算 anchor 的脚本 └── requirements.txt # 依赖清单这套结构本身就是一个标准的 YOLOv5 分层逻辑models负责网络定义utils负责训练和推理的辅助功能data管数据集配置detect_*.py是不同场景下的入口脚本。runs目录用来存放每次训练和检测的日志、权重和结果图片这个设计对迭代实验特别友好——我自己的项目里也沿用这个习惯每次跑完模型输出都自动按时间戳归档不会互相覆盖。2.2 detect_photo.py 和 detect_camera.py 的分工逻辑这两个入口脚本是拆包的钥匙一个是静态推理一个是动态推理它们的定位差异很重要。detect_photo.py是最常用的入口核心逻辑是这样的import torch import cv2 import os # 加载训练好的模型权重 model torch.hub.load(., custom, pathweights/best.pt, sourcelocal) def detect_image(img_path, conf_thres0.25, iou_thres0.45): # 读取图片并转为 RGBYOLOv5 训练时用的是 RGB 输入 img cv2.imread(img_path) img_rgb cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 模型推理返回检测结果 results model(img_rgb, size640) # 解析结果坐标、置信度、类别 boxes results.xyxy[0].cpu().numpy() # x1, y1, x2, y2, conf, cls for box in boxes: x1, y1, x2, y2, conf, cls box if conf conf_thres: # 在图上画矩形框和置信度 cv2.rectangle(img, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2) label fcrack {conf:.2f} cv2.putText(img, label, (int(x1), int(y1) - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) # 保存结果到 runs/detect 目录 os.makedirs(runs/detect, exist_okTrue) save_path os.path.join(runs/detect, os.path.basename(img_path)) cv2.imwrite(save_path, img) print(f检测完成结果保存至 {save_path}) if __name__ __main__: detect_image(test.jpg, conf_thres0.3, iou_thres0.5)这里重点说明几个参数。conf_thres是置信度阈值低于这个值的检测框会被过滤掉裂缝检测场景我一般建议设 0.25 ~ 0.3因为这个数据集的背景复杂度高阈值设太高容易漏检细裂缝iou_thres是 NMS 的 IoU 阈值控制重叠框的合并力度裂缝这种细长目标偶尔会出现多个框套同一个物体的情况0.45 是个比较稳的取值。size640是输入分辨率YOLOv5 默认训练尺寸就是 640改大能提升小裂缝的检出率但显存占用和推理时间也会线性上涨。import cv2 import torch def detect_camera(source0, conf_thres0.25): # 加载同一套模型权重 model torch.hub.load(., custom, pathweights/best.pt, sourcelocal) # 打开摄像头0 表示默认摄像头 cap cv2.VideoCapture(source) while True: ret, frame cap.read() if not ret: break # 推理当前帧 results model(frame, size640) # 渲染检测结果到画面 rendered results.render()[0] # 显示实时画面 cv2.imshow(Crack Detection, rendered) # 按 q 退出 if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()这个摄像头推理脚本的思路是边读帧边检测用cv2.VideoCapture循环读帧每一帧传入模型推理然后results.render()把检测框直接画到图上。需要注意的一个点是render()返回的是带标注的新图像不会修改原始帧所以内存管理上比较干净。在实景测试时如果摄像头画面卡顿优先检查是不是推理速度跟不上帧率而不是摄像头的问题。3. 模型与数据配置YOLOv5 的几个关键选择3.1 用哪个 backbones/m/l/x 的选型逻辑这套代码里models目录下有四个网络结构文件对应 YOLOv5 的四个规模版本。它们的区别主要体现在深度和宽度两个维度模型参数量推理速度(V100)精度(mAP)适用场景YOLOv5s7.2M2.4ms37.4低显存、边缘设备YOLOv5m21.2M3.2ms45.4中等算力平衡方案YOLOv5l46.5M4.6ms49.0服务器推理追求精度YOLOv5x86.7M6.9ms50.7离线高精度场景对裂缝检测来说我的真实经验是如果用的是 GTX 1060 或者 1650 这种 4G 显存的卡YOLOv5s 是唯一的现实选择——YOLOv5m 虽然精度更高但 batch size 稍微调大一点就直接 OOM如果显存 8G 以上YOLOv5m 是精度和训练时间的最优解。另外还要看训练数据量数据量不足 500 张时上大模型几乎是必过拟合的小模型反而泛化更好。3.2 数据集 YAML 配置和 anchor 调优data/目录下的 YAML 文件是训练时告诉模型去哪里找数据、数据是什么结构的入口。我拆包后看到有coco128.yaml、coco.yaml和voc.yaml说明这套代码支持 COCO 和 VOC 两种格式的数据集标注。如果自己标注数据一般推荐转成 YOLO 格式因为 YOLOv5 原生读 YOLO 格式最方便。# data/coco128.yaml 简化后的配置示例 train: ./data/coco128/images/train/ # 训练集图片路径 val: ./data/coco128/images/val/ # 验证集图片路径 nc: 1 # 类别数量这里是 1裂缝就一类 names: [crack] # 类别名称列表nc和names是必须和你的数据对应的两个字段——我们做裂缝检测如果只分裂缝一类就把nc写成 1names列表里只写crack如果想区分横向裂缝和纵向裂缝就得改成nc: 2和[transverse, longitudinal]。train和val路径既可以是绝对路径也可以是相对于项目根目录的相对路径建议用相对路径换机器跑的时候不会因为路径问题翻车。anchor 的设置是另一个新手容易忽略的点。YOLOv5 的utils/autoanchor.py会在每次训练开始前自动计算当前数据集的最优 anchor 尺寸。但如果数据集的标注框分布很极端——比如裂缝框特别长、特别窄——默认的自动计算可能不够准。这时候可以手动跑一次python utils/autoanchor.py --data data/voc.yaml --img 640这个脚本会重新聚类出与当前数据集最匹配的 anchor 尺寸并把建议值写进模型配置文件。我一般会在训练大模型前跑一次然后把结果手动更新到models/yolov5s.yaml的anchors字段里。注意autoanchor 给出的值是基于当前数据集标注框的统计特征换数据集必须重新跑直接沿用官方预训练模型的 anchor 不一定是最优的实测对裂缝这类细长目标影响最多能差 2~3 个点的 mAP。4. 复现训练从零开始跑通自己的裂缝检测模型4.1 环境搭建的完整路径先说环境这套代码对 Python 版本有硬性要求——YOLOv5 官方要求 Python 3.8 以上实际测试 3.8 和 3.9 最稳3.10 会踩到一些依赖兼容的坑。完整流程如下# 1. 创建独立虚拟环境避免污染系统 Python conda create -n yolov5 python3.9 -y conda activate yolov5 # 2. 安装 PyTorchCPU 版和 GPU 版选一个 # GPU 版需要先安装 CUDA 驱动和 cuDNN pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 3. 安装项目依赖 cd 项目根目录 pip install -r requirements.txt关于 PyTorch 版本的选用一个血泪经验YOLOv5 的源码对 torch 版本有兼容范围太新的版本有时会报torch.utils.tensorboard或者torchvision.ops.nms的 API 变更错误。项目配套里如果指定了版本就严格按指定的装没指定的话torch 1.13 或 2.0 这代版本兼容性最好不要一上来就装 2.3 以上的版本。验证环境是否装好跑一段最小推理测试import torch # 检测 GPU 是否可用 print(torch.cuda.is_available()) # 输出 True 说明 GPU 可用 # 打印 CUDA 版本和 GPU 名称 if torch.cuda.is_available(): print(torch.cuda.get_device_name(0)) print(torch.version.cuda)torch.cuda.is_available()返回False的话后面训练直接变成龟速模式——一个 300 张图的裂缝数据集在 CPU 上可能要跑 4 个小时GPU 上 20 分钟搞定。没有 GPU 环境的话建议上 Colab 或者租云 GPU 实例别硬扛。4.2 预训练权重下载与模型加载路径这套代码自带download_weights.sh作用是把 YOLOv5 官方在 COCO 上预训练好的权重拉下来。这个脚本很关键——不是因为它能省训练时间而是因为加载 COCO 预训练权重做迁移学习是在小数据集上拿到高精度的重要前提。# 给脚本添加执行权限 chmod x download_weights.sh # 执行下载 YOLOv5s 预训练权重 ./download_weights.sh # 或者直接命令行下载指定模型 python -c import torch; torch.hub.load(ultralytics/yolov5, yolov5s)上面的脚本会先把 COCO 预训练权重下到本地然后把权重文件放到weights/目录。用迁移学习的原因很朴素YOLOv5 的 backbone 在 COCO 上见过 80 类物体的纹理、边缘、形状特征裂缝虽然不在 COCO 类别里但边缘纹理的底层特征是可迁移的。从上千万张图里学过的特征提取器再拿来学裂缝只需要微调后面几层就行——这能在数据量很小的情况下有效防止过拟合。训练脚本的标准调用方式如下python train.py --data data/voc.yaml --weights weights/yolov5s.pt --batch-size 16 --epochs 100 --img 640关键参数说明--weights预训练权重路径不传就用随机初始化同样的 epoch 数最终 mAP 可能会差 10 个点以上。--batch-size由显存容量决定3060 显卡 12G 显存可以上到 321660 这种 6G 卡就乖乖用 16。--epochs裂缝检测数据集通常 100~150 个 epoch 足够超过之后 loss 就不再下降了纯浪费时间。--img 640和训练数据的输入尺寸一致如果数据集里的裂缝很小可以改成 960但对显存压力更大。训练过程中要盯日志里三个关键指标box_loss框坐标回归损失持续下降是正常的、cls_loss分类损失趋近于 0 说明分类已经学会、mAP0.5泛化性能最直观的指标。训练结束后runs/train/目录下会生成weights/best.pt和weights/last.pt前者是验证集上表现最好的权重后者是最后一个 epoch 的权重——部署推理时一定用best.pt不要用last.pt。4.3 用自己训练的权重做推理验证训练完成后把 back 最好权重替换掉推理脚本里原来加载的路径python detect_photo.py --weights runs/train/exp/weights/best.pt --source 测试图片.jpg跑完之后去runs/detect/里翻结果需要重点检查两类错误一是该检测的裂缝没检出来漏检二是把阴影、路面接缝、水渍误判成裂缝误检。如果发现漏检多优先考虑降低conf_thres如果误检多就升高conf_thres。这是一个典型的精度-召回率权衡问题没有绝对的正确参数要在自己的验证集上反复试。5. 避坑指南训练和推理中的四个典型翻车现场5.1 现象训练刚开始就报CUDA out of memory这是出镜率最高的问题。一上来直接跑默认的--batch-size 32 --img 640结果连第一个 epoch 都撑不住就崩了。原因很简单batch size 超出显存容量YOLOv5 在 forward 阶段要同时保存整个 batch 的中间特征图。解决方法是逐步缩小配置直到能跑起来# 先试 batch-size 8 python train.py --data data/voc.yaml --weights weights/yolov5s.pt --batch-size 8 --img 640 # 还不行就同时降分辨率和 batch size python train.py --data data/voc.yaml --weights weights/yolov5s.pt --batch-size 4 --img 480另外一个容易被忽视的技巧是启用梯度累积--batch-size 8 --accumulate 4相当于每 16 张图才更新一次梯度效果约等于 batch size 16但显存占用只是 8 的水平。5.2 现象训练 loss 不下降一直徘徊在某个值附近先排除一个低级错误确认 label 文件没有全空或者类别编号越界。YOLO 格式的标签文件是纯文本每个标注框一行class_id x_center y_center width height坐标是相对于图片宽高的归一化值。如果某张图的 label 文件是空的模型在这张图上就没有学习信号。另一个常见原因是学习率设置不当。YOLOv5 默认从0.01起步配合 cosine 学习率调度。如果发现 loss 在 5 个 epoch 内纹丝不动可以尝试调低--lr0到0.001这种问题在自定义数据集上出现频率真的不低。5.3 现象训练集精度很高验证集精度非常差这是典型的过拟合信号。裂缝数据集往往存在一个通病训练图片很多来自同一个桥梁或同一段路面背景纹理高度重复模型很容易记住背景而不是学会裂缝。应对手段有两条路数据增强是首选YOLOv5 默认开启 mosaic、flip、hsv 增强对数据量少的情况帮助很大# data/hyps/hyp.scratch.yaml 中提高增强强度 hsv_h: 0.02 # 色调增强 hsv_s: 0.7 # 饱和度增强 hsv_v: 0.5 # 亮度增强 flipud: 0.0 # 上下翻转概率路面裂缝场景建议不开 fliplr: 0.5 # 左右翻转概率 mosaic: 1.0 # mosaic 增强其中hsv_v: 0.5值得重点注意——室外采集的路面裂缝图片光照变化很大把亮度增强开到 0.5 相当于在训练时模拟不同光照条件对提升泛化能力很有帮助。flipud在路面场景不建议开因为路面裂缝存在方向性上下翻转会让模型学到错误的方向特征。如果数据增强后验证集精度仍然上不去就要考虑换更强的正则化把--dropout加上或者干脆换更小的模型从 m 换到 s。5.4 现象摄像头推理时卡顿明显画面像幻灯片当detect_camera.py的推理时间大于帧间隔时视频流就会明显卡顿。首先要搞清楚瓶颈在哪是模型推理慢还是图像预处理占了时间。用简单的计时工具就能定位import time # 在 detect_camera.py 中加计时 start time.time() results model(frame, size640) end time.time() print(f单帧推理耗时: {end - start:.3f}s)如果单帧耗时超过 0.3 秒即帧率低于 3FPS必须先做模型压缩优先考虑--img 320降低输入分辨率。如果降到 320 后帧率仍然不达标可以考虑转 ONNX 后用 ONNXRuntime 推理速度提升在 20%~40% 左右python models/export.py --weights weights/best.pt --include onnx --img 6406. 进阶用法模型裁剪、TensorRT 加速与按需改造6.1 把检测置信度热力输出变成裂缝严重程度分级很多人做完裂缝检测就停了但实际工程里有没有裂缝只是第一步还需要判断这条裂缝严不严重。这个需求不用重训网络直接在推理阶段做后处理逻辑就能实现def severity_grade(results, max_len_pixel640, min_conf0.3): 按检测框尺寸和置信度给裂缝定级 boxes results.xyxy[0].cpu().numpy() grades [] for box in boxes: x1, y1, x2, y2, conf, cls box if conf min_conf: continue # 计算裂缝长度对角线长度近似 length ((x2 - x1) ** 2 (y2 - y1) ** 2) ** 0.5 # 归一化到图片尺寸比例 length_ratio length / max_len_pixel if length_ratio 0.1: grades.append(轻度) elif length_ratio 0.25: grades.append(中度) else: grades.append(重度) return grades这个函数的思路是以检测框的对角线长度近似裂缝长度然后按比例分三档。实际使用中可以根据场景调整阈值——对桥梁这种重要结构阈值要更敏感对普通路面可以放宽一些。除了长度还可以把框的宽度裂缝宽度加入判断裂缝宽度越大通常说明路面结构损伤越严重。这些判断逻辑不必改网络结构在输出端加一层规则即可。6.2 TensorRT 加速把推理速度提到 3 倍以上如果部署设备是 Jetson Nano、TX2 这种边缘设备光换 ONNX Runtime 还不够。实测过同样一个 YOLOv5s 模型在 1080Ti 上用 TensorRT FP16 推理单帧耗时能从 8ms 降到 3ms 以内。转换流程如下# 第一步先导出 ONNX python models/export.py --weights weights/best.pt --include onnx --img 640 # 第二步用 trtexec 把 ONNX 转成 TensorRT 引擎 /usr/src/tensorrt/bin/trtexec --onnxweights/best.onnx --saveEngineweights/best.engine --fp16TensorRT 引擎文件是硬件相关的在 A 机器上生成的.engine拿到 B 机器上不一定能跑这是新手最容易忽略的坑。每次换设备部署都要在新设备上重新走一遍转换流程不能直接拷贝。转完后推理代码也要换推理方式完全不同用 TensorRT Python API 加载引擎import tensorrt as trt import numpy as np # 加载 TensorRT 引擎 def load_engine(engine_path): runtime trt.Runtime(trt.Logger(trt.Logger.WARNING)) with open(engine_path, rb) as f: engine runtime.deserialize_cuda_engine(f.read()) return engine # 推理前需要把输入输出都转成固定 dtype 的数组 # 输入 [1, 3, 640, 640] float32输出 [1, 25200, 6]TensorRT 的优化底层逻辑是四点层融合把 ConvBNReLU 合并成一个算子、精度校准FP16 下用 KL 散度找最佳量化范围、显存复用减少显存分配次数、kernel auto-tuning为每个算子选最优 CUDA 实现。对深度学习部署而言特别是对算力有限的边缘设备这个优化效果非常直观。6.3 数据增强策略的深度调优回到训练侧再补一个技巧裂缝检测的特殊性在于裂缝是细线状目标常规的随机裁剪很容易把裂缝切到图片边缘甚至切没。YOLOv5 的 mosaic 增强在处理细长目标时不是最优解我一般会在训练参数里调低 mosaic 概率同时配合额外的旋转增强# hyp.finetune.yaml 中的针对性调整 mosaic: 0.3 # 降低 mosaic 概率减少细长目标被切碎的概率 degrees: 15.0 # 随机旋转 ±15 度模拟不同拍摄角度 translate: 0.1 # 平移增强 scale: 0.4 # 缩放增强旋转角度degrees: 15.0对桥梁裂缝这类方向性目标很关键——桥梁上的裂缝往往垂直于受力方向但如果拍摄角度偏了模型需要旋转不变性。注意旋转不能无限加大超过 45 度会让细长目标变形得不像真实裂缝。这类超参数调整没有绝对标准建议每次改完跑一个完整训练对比 mAP用数据说话别凭感觉。我从那以后每次训练前都会强制走一遍数据可视化验证抽查增强后的图片有没有把裂缝切碎或者变形过头——一张一张看训练集的增强样本大概花十分钟但能省下一次四小时的无效训练这笔账怎么算都划算。希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联
返回资讯列表 →