YOLOv5道路裂缝检测实战:从数据标注到边缘部署

发布时间:2026/9/15 12:40:05
YOLOv5道路裂缝检测实战:从数据标注到边缘部署 道路裂缝检测放在早几年绝对是个纯人工的活路面养护工人顶着大太阳拿尺子量、用眼睛看一条高速几十公里走下来效率低不说细小的龟裂和横向裂缝还特别容易漏掉。后来行业内开始尝试数字图像处理最典型的做法就是边缘检测加阈值分割,但裂缝形态太随机、背景又有大量噪声传统算法的泛化能力非常有限。直到Yolov5这类目标检测模型成熟之后裂缝检测才真正有了落地价值——至少我是从Yolov5开始把这个事情做成了一套可复用的流程。这篇文章会把整个项目从环境准备、数据标注、模型训练、调优到边缘设备部署的完整链路拆开来讲。内容兼容两类人一类是想做毕业设计或者课题研究的学生另一类是真正在道路检测相关行业做技术选型的工程师。我不打算只贴命令和代码重点把每一步为什么要这么做讲清楚因为裂缝检测和通用物体检测看起来都叫目标检测实际上从数据标注到后处理都有不少特殊讲究。1. 从人工巡检到智能识别为什么选了Yolov51.1 项目背景与技术选型道路裂缝检测本质上是一个目标检测问题但它和日常见到的行人检测、车辆检测差别很大。普通目标检测的对象通常具有明确轮廓和稳定特征比如人、车、红绿灯。裂缝恰恰相反它没有固定的宽高比例可能宽几毫米也可能延伸几十米表面还有细密的分支纹理。这种对象让检测既不能做得太粗放——否则会把路面接缝、水渍印子都框进来又不能太精细到像素级别——否则计算量过大实时性就保不住了。我最终选择Yolov5而不是Faster R-CNN或Mask R-CNN核心原因有三条第一Yolov5在保证检测精度的同时推理速度足够快单张GPU上处理一帧640x640的图像大约只需几毫秒到十几毫秒这在后续做实地巡检时非常重要。第二它把训练、验证、导出、部署的工具链全打通了从PyTorch训练完直接能导出ONNX或者TensorRT模型省去了大量工程适配工作。第三条最实际Yolov5在GitHub上社区活跃度极高遇到问题基本都能搜到解决办法这对一个人单干的项目来说是最省时间的选型。1.2 Yolov5版本选择与预训练权重Yolov5官方仓库提供了n、s、m、l、x五个规模的模型参数规模递增。我在道路裂缝检测这个场景里首推Yolov5s原因很直接裂缝数据集通常不会特别大几千张到几万张的量级是常见规模这种数据量下用Yolov5x反而容易过拟合训练时间翻倍但精度提升有限。Yolov5n速度最快但小目标检测能力偏弱裂缝恰恰就属于小目标所以I不推荐用n版本做教学或工程基底。关于预训练权重建议直接用COCO预训练权重作为初始权重。虽说不使用预训练权重从头训练也能收敛但COCO数据集上学习到的基础特征边缘、纹理、形状对迁移到裂缝识别是天然有利的收敛速度能明显加快最终精度通常也能高出两到三个点。权重文件在官方releases页面可以直接下载选择yolov5s.pt这个版本即可。如果网络下载受限从国内镜像源或者百度网盘资源拉取也可以注意校验下文件是否完整很多人踩过权重文件损坏导致训练直接报错的坑。1.3 为什么不用语义分割方案项目规划过程中我实际也评估过语义分割路线比如U-Net或者DeepLabV3。语义分割对裂缝这种细长形态的对象其实在理论上有天然优势——它能够给出每个像素是否属于裂缝的精细判断。但在实际项目中语义分割的落地难度要高很多训练数据的标注成本翻倍需要对裂缝做像素级标注而非简单的矩形框推理后的像素结果还需要后处理才能变成道路管理方想要的位置和长度信息。而检测结果直接输出目标框很容易换算成实际物理尺寸也更符合裂缝在哪个桩号、大概多长这种业务表达习惯。另外裂缝检测在工程上并不需要极致到像素级轮廓养护部门做决策的关键是裂缝的位置、长度、密度和分级矩形框加置信度已经足够支撑决策。这样的权衡下来我坚定地走了检测路线。2. 环境配置与数据集制作训练前最容易被卡住的环节2.1 环境配置实操与常见坑Yolov5在环境依赖方面还算友好但直接对着官网说明操作还是会踩一些版本坑。我这里给出一套我实测过多次、相对稳定的环境组合适用于绝大多数刚上手的读者组件推荐版本备注Python3.8 / 3.93.10以上部分依赖兼容性差PyTorch1.10 ~ 2.0CPU版和GPU版别装混CUDA11.3 或 11.8需与PyTorch版本匹配cuDNN对应CUDA版本一般随PyTorch安装torchvision与torch对应版本不匹配会运行报错硬件建议6GB显存以上4GB勉勉强强能跑n/s模型环境配置中最常见的坑是CUDA与PyTorch版本不匹配。很多人直接在官网pip install torch默认装上的往往是CPU版本训练时才发现用不了GPU。我建议到PyTorch官网的get-started页面按自己的CUDA版本选择对应命令安装后再在终端跑一段验证python -c import torch; print(torch.__version__, torch.cuda.is_available())如果输出中torch__version后面带有cu113之类的后缀且cuda.is_available()输出为True环境基本就没问题了。另一个常见问题是运行时提示缺少某些依赖包直接pip install -r requirements.txt就能解决但注意别随意升级核心库Yolov5很多依赖库的版本是互相锁定的。2.2 图像采集与标注数据采集是裂缝检测项目里最容易决定成败的环节。我见过太多人随意在网上下载一堆裂缝图片标注完训练出来的模型一测真实路况就崩。合理的采集方式要贴合使用场景如果你做的是车载巡检需要的是车载相机或手机固定机位在1米到2米高度拍摄的正面图像如果做手持设备巡检需要模拟人眼的拍摄角度如果做无人机巡检则是俯拍视角。不同视角下裂缝的形态和尺度差异巨大混着用会让模型混乱。标注工具我推荐LabelImg它有图形界面、操作简单、支持YOLO格式直接输出。标注时有几个纯靠实践才能体会到的原则裂缝框要完整能长则长别把一条连续裂缝拆成好几个框。否则模型会认为多条碎片是多个目标推理时输出大量重叠框。宽裂缝和窄裂缝要分开标注不要为了省事把所有宽度级别的裂缝都合成一类。实际业务场景经常需要对裂缝分级一开始分好类后面改起来成本最低。背景特别复杂的区域比如树影遮挡、大量水渍、路面补丁优先采集并标注为背景样本。裂缝检测模型误检根源往往在于背景不够丰富而非目标不够多。标注工作量的预估可以按比例算单张图像处理时间大约1到3分钟1000张图就是20到50小时的纯人工时间。我当时是几个同学分工做完的如果有条件用标注平台或半自动预标注流程能大幅减少时间但初期不建议过度追求全自动半自动预标注的错误框会对训练产生很坏影响。2.3 数据增强策略Yolov5内置了Mosaic、MixUp、HSV扰动、随机翻转、缩放等数据增强方法。对裂缝检测这种小目标密集的场景Mosaic增强尤其有效它把四张图拼成一张训练相当于变相增加了batch size小目标的检测能力会明显提升。不过用增强时要注意一个边界情况裂缝是细长物体过度的缩放和旋转会造成严重形态失真太激进的数据增强反而会让模型学到错误特征。我的经验是把hsv_h、hsv_s等颜色增强参数适当调低保留原始的灰度特征翻转增强在使用时也要注意道路图像的语义方向上下翻转会让模型混淆路面上裂缝和天空背景的边界。数据增强还有一招特别适合裂缝把原始图像切成多块训练。因为裂缝分布稀疏一张1024x1024的高清路面图里裂缝区域往往只占很小比例直接缩放到640x640会让裂缝变得过小。切块策略是先将大图切成若干640x640的重叠块再送入训练这样既保住了分辨率又变相扩充了数据规模。3. 模型训练与调优从能跑通到效果好3.1 训练参数与YAML配置Yolov5的数据配置通过一个YAML文件管理我习惯在项目下新建datasets/crack.yaml内容大致如下train: ./datasets/crack/images/train val: ./datasets/crack/images/val nc: 2 names: [transverse-crack, longitudinal-crack]类别数量nc按自己的裂缝分类设置这里我用的是横向裂缝和纵向裂缝两类的例子。如果只分一个裂缝类nc就写1。names的顺序必须和标注文件中的类别编号严格对应类别编号从0开始。很多人训练时发现类别对不上问题基本都出在这里。训练命令我用得最多的是这一条python train.py --img 1280 --batch 16 --epochs 200 --data crack.yaml --weights yolov5s.pt --cache参数--img 1280值得特别说明。默认的640分辨率对常规目标没问题但裂缝的宽度往往只占图像的几十像素甚至更少高分辨率输入能大幅提升小目标召回率。当然1280输入对显存要求也高8GB显存跑s模型batch_size只能开到8左右。如果你的硬件有限另一种方案是用640训练配合切图策略效果也能接近1280整图训练。训练过程中注意看终端输出和results.png中几个关键曲线Box Loss、Object Loss、Precision、Recall、mAP0.5。正常情况下随着epoch增加loss应该平滑下降mAP不断提高。如果loss震荡剧烈或者mAP始终上不去建议参考后面章节的排查方法。3.2 训练过程监控与评估指标做过检测项目的人都知道精度高不等于效果好。在裂缝检测里我主要关注三个指标的组合——Precision查准率、Recall查全率和mAP0.5。裂缝检测的业务场景里查全率比查准率更重要原因很直观漏掉一条裂缝意味着道路安全隐患可能被错过去而多框几个疑似区域还会有人工复核环节兜底。训练结束后在val集上会得到类似下表的性能统计模型输入尺寸PrecisionRecallmAP0.5速度(GPU)Yolov5s6400.8910.8640.902约2msYolov5s12800.9140.9020.936约7msYolov5m12800.9230.9150.945约13ms从1024或1280输入下mAP都显著高于640这就验证了高分辨率输入对裂缝检测的决定性作用。而m版本的精度增益相比s版本并不明显考虑到实时部署需求s版本是最优性价比选择。3.3 超参数调整与过拟合应对Yolov5的hyp.scratch.yaml中定义了学习率、动量、权重衰减等超参数。对裂缝检测我一直坚持的原则是默认参数够用但针对数据特点做小幅调整。很多同学一上来就改一堆参数反而把模型训崩了。真正有价值的调整有几个学习率。Yolov5默认的lr是0.01如果数据集比较小我建议起步先用默认观察训练前20个epoch的loss下降情况。如果loss发散或震荡剧烈把lr降到0.005左右再试。数据量几百张的级别过拟合几乎是必然最关键的手段不是调参而是数据增强加早停。Yolov5自带early stopping机制patience参数默认100个epoch也就是如果连续100个epoch没有提升就自动终止。这个机制在小数据集上非常实用。过拟合的明显特征是训练集loss持续下降但验证集loss上升或者mAP先升后降。除了数据增强我还会用两层手段减轻过拟合一是减小模型规模s版本如果还是过拟合就降到n版本二是减少可训练层数比如冻结Backbone的前几层让模型更多保留COCO预训练学到的基础纹理特征这个在源码里通过添加--freeze参数可以实现。4. 推理测试与边缘部署落地4.1 本地推理测试训练完成后best.pt就是验证集上表现最好的模型。先用官方detect.py跑一遍确认模型在真实场景下的表现python detect.py --source test_images/ --weights runs/train/exp/weights/best.pt --conf 0.5 --img 640 --save-txt--source参数可以接图片文件夹、视频路径甚至摄像头序号0Yolov5的detect.py对多种输入源做了统一封装省去写测试脚本的功夫。--save-txt会把检测结果保存成YOLO格式的文本文件如果你后续要做台账统计这个功能很实用。本地测试时一定要关注推理结果的置信度分布。裂缝检测的置信度普遍偏低正常裂缝的置信度在0.4到0.8之间是常态不像行人检测动不动就到0.9以上。部署时conf阈值建议设置在0.25到0.35之间货真价实的裂缝更容易被保留下来。如果设置太高漏检率会显著上升。4.2 模型转换与Jetson Nano部署模型部署阶段我更看好边缘计算设备而不是PC因为道路检测现场根本不可能放一台台式机。我用的方案是在Jetson Nano这类嵌入式设备上做边缘端推理整机功耗只有几瓦可以放到改装巡检车里用电池供电。Jetson Nano的具体部署流程分几步走第一步是把PyTorch模型转为TensorRT引擎。Yolov5官方提供了export.py脚本支持导出多种格式其中TensorRT格式就是为英伟达设备优化的python export.py --weights best.pt --include engine --device 0 --img-size 640在Jetson设备上执行时TensorRT会针对设备GPU做层融合和显存优化推理速度通常能比PyTorch的浮点模型快3倍以上。我之前在Jetson Nano上测试转成TensorRT后推理一帧640x640图像大约只需要60到80毫秒加上前后处理能稳定在12到15FPS基本满足低速巡检需求。第二步是写一个简化推理脚本。官方detect.py功能全面但依赖过多边缘部署时我更习惯精简出一个只包含核心推理逻辑的Python脚本加载TensorRT引擎后读入图像、预处理、推理、后处理、输出结果框。这样整体代码量小、依赖少、出错率低。4.3 速度和精度平衡分析边缘部署时一定会遇到速度与精度的取舍。Jetson Nano的算力有限如果导入TensorRT时使用FP16精度精度损失很小通常低于0.5%速度能提升一倍如果使用INT8量化速度继续提升但精度可能下降两到三个点而且标定过程相对复杂需要准备一组合适的标定图片。以我的实测数据为参考部署方案输入尺寸推理耗时mAP0.5适用场景GPU服务器FP321280约7ms0.936离线分析Jetson Nano FP16640约60ms约0.90实时巡检Jetson Nano INT8640约40ms约0.87追求速度场景我的建议是实地巡检用Jetson Nano跑FP16引擎即可精度损失在可接受范围内速度刚好匹配车辆低速行驶需求。如果需要更快的速度升级到Jetson Orin Nano效果更加明显。5. 常见问题与排查技巧实录5.1 训练结果不收敛怎么办这类问题在实际项目中出现的频率非常高我自己也踩过不少次。最典型的症状是loss一直不降或者训练完后mAP始终在0.2以下徘徊。遇到这种情况先别急着调参换模型按下面的顺序排查一遍往往就能定位问题。第一步检查数据是不是坏的。把训练集的图片和标注框可视化出来逐张看标注框是否对应真实的裂缝类别编号是否正确框有没有超出图像边界。我见过一个项目里数据集有一百多张图是纯背景标注文件全是空文件模型自然学不到任何东西。第二步是验证训练配置是否正确确认data yaml里类别名称和数量是否和标注文件一致。第三步才轮到参数问题降低学习率、加大batch size、增加预训练权重这几个手段按顺序试通常能把loss降下来。5.2 裂缝误检漏检排查清单训练完模型拿到现场一测最常见的抱怨集中在两方面不该框的东西乱框真正的裂缝反而没框出来。误检的来源通常是背景干扰树影、水渍、轮胎印、路面补丁都会被模型误认为裂缝。解决思路不是单纯调阈值而是把这些干扰样本系统地加入训练集。漏检的来源则更多样。如果漏检的是暗光条件下的裂缝考虑在数据增强里增加亮度扰动如果漏检的是特别细的裂缝考虑提高训练分辨率或采用切块策略如果漏检的是桥面接缝或道路伸缩缝这种规则纹理需要确认标注时是否把这些对象单独分成了新类别。我整理了一个排查速查表方便实际项目里对照查问题现象常见原因解决方向误检率高背景种类不足补充负样本细裂缝漏检输入分辨率不足提高--img参数远小目标漏检Mosaic增强破坏小目标调整增强参数或关闭部分增强结果框碎成多段标注时框碎了重新标注保持框完整同一条缝重叠框多NMS阈值过低调整NMS阈值或检测后合并5.3 数据层面容易踩的坑最后聊一个最容易被忽视但影响最大的环节数据管理。训练集、验证集、测试集要严格分离我习惯按8:1:1的比例随机划分且保证同一个路段、同一次采集的数据不跨集出现。很多人在路边拍摄的图片存在极强的连续相似性同一路段的几十张图非常像如果一部分进了训练集、另一部分进了验证集验证指标会虚高部署到新路段时精度断崖式下跌。另外裂缝检测这种小样本场景下数据的矛盾标注会对训练造成巨大干扰。如果一张图里同样的裂缝被标注成不同类别模型会迷失判断标准。我在项目中期设置了一个机制标注完成后随机抽10%的图像做二次审核让不同人独立复核标注结果发现不一致的部分重点修正。这个工作投入产出比极高强烈建议花时间做。写在最后做Yolov5道路裂缝检测这一年多我的最大体会是这类细分场景的检测项目真正的技术难点往往不在模型本身而在于怎么把通用模型适配到特定领域的真实场景中。裂缝检测看起来只是给Yolov5套了一层壳但光是把标注规范、数据增强策略、分辨率选择、部署形态这几个环节想明白就对工程能力有相当大的锻炼。如果你想在这个项目基础上继续延伸可以考虑两个方向一是从单帧检测扩展到视频连续帧的跟踪统计把同一段路上多次出现的裂缝合并计算真实长度二是结合道路桩号定位信息让检测结果自动生成带坐标位置的病害台账。这两个方向在道路养护行业里有着明确的实际需求和商业价值值得有心人深入探索。