YOLOv8实例分割在桥梁损伤检测中的全流程实践

发布时间:2026/10/18 5:50:34
YOLOv8实例分割在桥梁损伤检测中的全流程实践
搞过结构健康监测的朋友应该都有体会一个桥梁检测项目跑下来相机里少则几千张、多则几万张照片光是把裂缝、剥落、露筋这些损伤从照片里找出来就够检测人员标到怀疑人生。我最近刚做完一个桥梁损伤分割数据集项目代号YHT3261-5类数据规模是3261张图像覆盖钢筋外露、混凝土剥落、裂缝、钢筋锈蚀、结构变形五类损伤模型选用的是YOLOv8分割模型。这篇就把整个项目从数据构建、标注、训练到评估、排查的完整过程展开讲讲适合正在做结构病害识别、质检自动化或者刚接触实例分割又想落地到工程场景的人。1. 项目到底在干什么五类损伤为什么必须做分割1.1 五类损伤的形态差异桥梁表面损伤看着就是“破了、裂了、锈了”但它落到图像算法里完全是不同量级的问题。裂缝是最典型的线状目标宽度可能只有几个像素长度却横跨整张图。它不像箱子、人那种紧凑目标用检测框一框就能圈住框内绝大部分像素其实都是背景。钢筋外露和钢筋锈蚀这两类高度相关甚至经常同时出现在同一个区域。外露看的是混凝土保护层脱落露出钢筋的形态锈蚀则是钢筋表面的颜色和纹理变化两者的像素分布区域可以重叠但语义完全不同。混凝土剥落往往是片状、块状边界不规则但区域完整属于分割里最好学的那种目标真正难的是它和露筋经常粘连边界怎么切需要标注标准统一。结构变形这个类别最特殊它不是局部的表面损伤而是梁、板、墩柱整体的几何变化比如梁体挠曲、倾斜、侧移。在图像里往往表现为多块区域的组合变形单靠局部纹理区分很不靠谱需要标注人员结合构件形态和上下文判断。形态差异直接决定了算法选型。如果所有损伤都用矩形框去圈裂缝框里99%是背景露筋和锈蚀重叠时框会互相打架模型分类特征也容易被背景稀释。1.2 检测、分割、关键点方案怎么选这个项目一开始其实有人建议用目标检测因为标注快、模型训练也简单。但我评估后还是否了这个方案原因有几点一是裂缝的细长形态使检测框的IoU计算非常吃亏。一个高200像素、宽3像素的裂缝如果预测框的宽度偏了5个像素IoU可能就直接掉到一半以下。检测框天然不适合细长目标。二是五类损伤尤其是露筋和锈蚀区域重叠情况非常普遍。检测框无法表达“同一个位置既有外露又有锈蚀”这种像素级重叠关系只能靠分类阈值硬掰实际工程里效果很差。三是下游要做的量化分析比如计算裂缝宽度、剥落面积、锈蚀占比这些都需要像素级的边界。检测框最多给你一个粗略的外接矩形面积估算可能差好几倍。关键点检测也考虑过比如给裂缝标骨架线、给剥落标角点。但五类损伤形态差异太大关键点定义很难统一标注成本反而更高模型预测的稳定性也难保证。所以最终定了实例分割方案用YOLOv8-seg来做。实例分割能同时输出目标的检测框和逐像素掩码既保留了目标定位能力又能拿到精确的形状和面积和桥梁损伤量化评估的需求正好匹配。2. 数据集YHT3261的构建与坑从原始图像到YOLO标签2.1 数据采集清洗哪些图必须删YHT3261这个名字里3261就是最终入模的原始图像数量。但这个数字不是一次采集得到的而是从约5000多张原始照片里清洗出来的。清洗阶段我踩了几个坑。第一类是虚焦和运动模糊桥检车在移动状态下拍摄快门速度不够就容易糊。这类图模型怎么学都学不出有效特征必须删。我定的标准是在100%缩放下人眼都无法清晰辨认裂缝边缘的照片直接丢弃。第二类是光照极端的图。逆光拍摄导致阴影大面积覆盖混凝土表面或者强反光的潮湿桥底这些图如果强行保留模型会学到把阴影当作损伤的错误特征。清洗时我保留了部分中等阴影样本因为真实场景确实存在但完全过曝、死黑的图全部去掉。第三类是严重遮挡。比如后期架设的管道、线缆正好挡在损伤区域上人眼都看不全损伤边界标出来的掩码也不可靠。这类我选择删除而不是硬标因为标注噪声对分割模型的影响比检测更大。清洗完成后做了一次去重。桥梁检测照片很多是连续连拍相邻帧之间重叠度极高如果不去重同一块损伤会在训练集和验证集里同时出现评估指标会虚高。我用感知哈希做相似度过滤设定重合度阈值确保同一损伤目标只出现在一个数据子集里。2.2 标注流程细长裂缝怎么标才能让模型学明白标注环节是YHT3261项目里耗时最长的部分前后用了三个标注人员配合我一个人负责抽检和标准制定。标注工具用的是开源的多边形标注工具格式直接导出YOLO分割格式。这里必须先说清楚YOLO分割标签的定义。YOLOv8分割标签是归一化多边形坐标格式是class_id x1 y1 x2 y2 ... xn yn每个点是多边形顶点所有坐标除以图像宽高归一化到0到1之间。文件是txt格式和图像同名放在labels目录下。裂缝标注是最难统一的。裂缝宽度通常只有几个像素标注工具里需要放大到400%甚至800%才能看清。我定的规则是裂缝多边形沿裂缝走向逐段描边顶点间隔控制在15到30个像素太密会导致标签文件膨胀太疏又会让裂缝区域变成锯齿状影响训练时掩码的平滑度。裂缝是否要拆成多个实例我的判断标准是连通性和语义连续性。如果两条裂缝中间明显断开就分两个实例如果只是被阴影或污渍局部遮挡但走向和纹理连续就当一个实例。这个规则不统一会导致模型学到错误的实例分裂方式预测时同一道裂缝被切成好几段下游的裂缝长度统计就完全没法用。露筋和锈蚀同时出现时的标注顺序也要注意。思想是如果钢筋表面有混凝土残留优先标为外露如果钢筋表面颜色已经明显变化、有锈皮或锈斑则标为锈蚀。同一个像素不被重复标注两个类别避免训练时出现相同的特征对应两个不同掩码标签造成分类头振荡。2.3 数据增强和样本均衡不能一把梭YHT3261五类样本的原始分布很不均衡。裂缝最多因为桥梁表面裂缝最常见也最容易拍到结构变形最少因为变形不是每座桥都有而且拍摄角度限制大。表里的数值是掩码实例数量不是图像数量因为一张图可以同时包含多个损伤实例类别实例数量初始占比增强后目标占比裂缝241042%35%混凝土剥落89316%20%钢筋外露112020%18%钢筋锈蚀96417%18%结构变形5125%9%结构变形样本量太少只靠全图随机增强很难补够。我的处理方式是过采样加针对性增强对结构变形样本做水平和垂直翻转、小角度旋转、轻微缩放在YOLOv8默认增强基础上叠加将这部分样本重复采样到每轮迭代占比稳定。数据增强的参数不能一把梭。YOLOv8默认开启Mosaic、HSV扰动、随机平移缩放等但对桥梁损伤数据有两个参数必须改一是旋转角度。结构变形有大方向性梁体的水平倾斜如果被过度旋转增强模型会对角度的敏感性下降实际检测时反而容易把轻微变形漏掉。我设定degrees5只做小角度旋转。二是上下翻转。桥梁裂缝和剥落在上下翻转后语义不变但结构变形如果翻转梁体受拉面和受压面就反了实际场景里这个状态不会出现。我直接关闭上下翻转只保留水平翻转。Mosaic增强对裂缝这种细长目标帮助很大因为四张图拼接可以让模型在更复杂的背景下学习目标边界但Mosaic也会产生大量小目标需要在训练后期适当降低Mosaic概率让模型适应真实单图分布。实践中我在最后30个epoch把Mosaic关闭。3. YOLOv8分割模型选型与训练配置3.1 为什么是YOLOv8-seg而不是其他分割模型结构健康监测场景对模型有个很现实的要求计算资源有限推理设备往往就是桥检车上的工控机连独立显卡都不一定有。所以模型必须轻量、速度快同时精度不能差太多。我对比过几个路线。Mask R-CNN是两阶段实例分割的经典方案精度确实高但推理速度在公司内部测试的工控机上基本跑不到实时而且部署时依赖组件多导出到推理框架麻烦。DeepLab系列的语义分割虽然对裂缝这种线状目标效果不错但它输出的是像素级分类无法区分同一区域的多个实例这对露筋和锈蚀重叠的场景不够用。YOLOv8-seg属于单阶段实例分割在YOLOv8检测模型的基础上增加了分割头分支。它的特点是训练和部署工具链完整从标注格式到训练脚本到模型导出都一体化对工程落地极其友好。速度上最小规模的YOLOv8n-seg在普通显卡上单张推理可以到几毫秒就算我用的是中档规模的YOLOv8s-seg在边缘设备上也能保持实时。实际测试中YOLOv8s-seg对裂缝的掩码质量已经能满足我的量化需求。用ImageNet分类预训练权重做初始化再在YHT3261上微调比从零训练收敛快很多前30个epoch就能看到掩码mAP明显上升。对于工程团队来说YOLOv8-seg的训练成本、部署成本和模型迭代成本都是最低的。3.2 关键超参数一次实验试出来的经验值训练配置我用了下面的超参数组合这是在多次实验后定下来的适合YHT3261这个数据规模和损伤类型超参数取值说明模型规格yolov8s-seg精度速度均衡比n版稳图像尺寸640x640兼顾裂缝细节和显存占用批次大小16单卡可跑batch norm稳定初始学习率0.01用预训练权重时偏保守权重衰减0.0005防止过拟合小数据集训练轮数300配合早停策略早停耐心30轮mAP50-95连续无提升就停冻结层数10前期冻结backbone底层冻结backbone前10层这个操作很多人会忽略但对我来说很重要。桥梁损伤图像和ImageNet的自然图像差异很大底层卷积里的大部分浅层特征比如颜色、边缘在不同数据集间是可以共享的。冻结这些层可以防止小数据集上底层特征被污染同时减少显存占用。训练60个epoch后我再解冻全部层用小学习率微调30轮让高层特征也能进一步适应损伤数据。图像尺寸我试过从640提升到960裂缝的掩码质量确实有提升但训练时间和显存占用几乎翻倍。考虑到最终部署设备的分辨率限制640在工程上是最合理的平衡点。如果未来有更高算力的设备可以用更大的输入尺寸做二次微调没必要一开始就上高清。学习率策略用的是余弦退火。我观察过YOLOv8默认的调度在损伤数据上表现正常但训练后期如果学习率下降太快裂缝这种难样本的掩码细节会丢失。所以在300轮设置里前200轮用正常余弦退火最后100轮将学习率固定在初始值的0.01倍做精细打磨。这个操作让裂缝掩码的边界平滑度肉眼可见地提升。4. 完整训练实操从数据yaml到训练日志4.1 工程目录和标签格式动手训练之前先把数据集目录结构定好这个看似基础但非常重要。YOLOv8对数据集目录的要求并不严格但统一结构能减少后续切换模型、做交叉验证时的麻烦。我使用的标准目录如下YHT3261/ ├── images/ │ ├── train/ # 2608张 │ └── val/ # 653张 ├── labels/ │ ├── train/ │ └── val/ ├── data.yaml └── runs/其中train和val按8:2划分。前面提到的去重操作在划分之前完成划分时我用按桥梁编号分组的策略确保同一座桥的图像只出现在一个集合里避免数据泄漏导致评估虚高。data.yaml内容很简单注意路径要用绝对路径或相对于当前工作目录的相对路径嵌套目录太多时容易踩坑path: /home/user/YHT3261 train: images/train val: images/val names: 0: rebar_exposed 1: spalling 2: crack 3: rebar_corrosion 4: deformation类别ID的顺序要和标签txt文件里的class_id一一对应这个顺序一旦训练开始就不能改否则模型加载权重时会因为类别语义错位产生灾难性的结果。4.2 训练命令和迁移学习细节YOLOv8没有复杂的配置文件训练直接用命令行工具即可。我第一次训练用的命令是这样yolo train \ modelyolov8s-seg.pt \ dataYHT3261/data.yaml \ epochs300 \ imgsz640 \ batch16 \ lr00.01 \ freeze10 \ patience30 \ projectYHT3261 \ nameseg_v1model参数加载的是官方预训练权重yolov8s-seg.pt。这里有一个容易被忽略的点预训练权重中包含检测和分割头的参数但类别数不一定和我们匹配。YOLOv8会在加载时自动适配类别数它会保留backbone和颈部部分层的权重重新初始化和类别数不一致的输出头。所以如果你的类别数和官方不一致是完全正常的不要被控制台里的警告吓到。另一种做法是使用在COCO上预训练的模型然后在自己的数据上继续训练。对损伤数据来说COCO里的类别和损伤没有任何重叠但浅层特征依然有效迁移学习仍然比从零训练快得多。我发现关键点在于不要对预训练权重做精细挑选直接加载默认权重就行backbone的特征提取能力是通用的。如果想用更精细的迁移策略可以分两阶段训练。第一阶段冻结backbone只训练头部第二阶段解冻所有层微调。我在实验中发现这种方法对结构变形这种样本少的类别特别有效因为它避免了早期训练时头部梯度对backbone底层特征的破坏。4.3 训练过程怎么判断正常训练开始后我主要通过几个指标观察是否正常。首先是loss的下降趋势。YOLOv8-seg训练日志里会同时显示box_loss、cls_loss、dfl_loss和seg_loss四个分量。前三个是检测部分的损失seg_loss是分割掩码的损失。正常情况下四个分量的曲线都应该在初期快速下降然后趋于平缓。如果seg_loss先下降然后又反弹上去很可能是学习率太大或者Mosaic增强太强导致模型在小目标上进入振荡。其次是验证集mAP的走势。我习惯每10个epoch记录一次验证集的mAP50-95。第一个明显上涨通常出现在第20到40轮之间这说明迁移学习已经生效。到了150轮以后上涨速度会明显放缓这时不要急着停而是观察早停机制是否触发。我做实验的默认patience是30轮也就是说连续30轮验证指标没有提升就会自动停止。还有一个实操小技巧训练前先跑一次5个epoch的短测试不加载预训练权重用随机初始化跑通整个流程。这么做可以排除数据路径、标签格式、标注范围越界等基础问题。很多人一上来就训练300轮跑了一天发现是标签格式错误导致所有loss都不收敛白白浪费算力。训练完成后best.pt和last.pt会保存在项目目录下。best.pt是验证集指标最优的权重last.pt是最后一个epoch结束时的权重。大多数情况直接用best.pt但如果你打算继续训练更多epoch用last.pt做resume会更连贯。5. 评估指标与分类别结果解读5.1 别只盯着mAP50掩码质量才是关键模型训练完之后评估环节决定了这个模型能不能真正用于工程。YOLOv8在验证阶段会输出很多指标但如果只看总体的mAP很多问题会被掩盖掉。对分割模型来说mAP50和mAP50-95都是基于掩码的IoU计算的但两者的衡量标准差异很大。mAP50只要求预测掩码和真实掩码的IoU超过0.5就算正样本这对裂缝这种细长目标太宽松了一个预测掩码哪怕边界偏移了两个像素IoU可能也会超过0.5。mAP50-95则跨越多个IoU阈值更能反映掩码边界的精细度。我的经验是对桥梁损伤项目掩码IoU在0.5到0.75这个区间最值得关注。因为下游定量计算裂缝宽度、剥落面积时我们对边界精度的要求并不是像素级完美但也不能偏差太多。如果mAP50-95长期上不去说明掩码的边缘和真实损伤边界存在系统性偏差。此外还要注意YOLOv8日志中precision和recall是框粒度的指标和掩码质量不是一回事。它反映的是模型能不能找到损伤区域而mAP50(M)和mAP50-95(M)这种带(M)后缀的才是掩码指标。所以我会单独写一个评估脚本计算每个类别的掩码IoU分布、类别像素精度、边界F1-score用于分析掩码的真实质量。5.2 各类别表现差异与模型薄弱点下面是我在YHT3261验证集上实测得到的结果数值做了脱敏处理只保留相对趋势类别mask mAP50mask mAP50-95主要失败模式裂缝0.720.41裂缝断点、边界锯齿混凝土剥落0.830.58边缘外扩、小块漏检钢筋外露0.810.55与外露相邻的边界混淆钢筋锈蚀0.760.48锈蚀和阴影误分结构变形0.640.35小形变漏检、区域不完整裂缝这个类别mAP50不算太低但mAP50-95只有0.41明显低于剥落和露筋。原因是裂缝细长且语义复杂预测掩码经常比真实标签在两端短一截或者在某处断开导致高IoU阈值下得分很低。结构变形是五个类别里最弱的这既因为样本量少也因为它的特征本身就不是局部纹理能完全决定的。我在验证时发现模型对梁体明显倾斜的样本能检测出来但对轻微变形比如只有几个像素的位移它几乎全部漏检。这说明现阶段的模型更擅长发现“有形态突变”的变形对缓慢变化的几何畸变能力有限后续可能需要引入构件级先验比如借助直线检测做参考基准。还有一个值得注意的问题露筋和锈蚀的误分。数据显示两者之间的混淆误差占了总错误的相当一部分。我在剖析后发现当钢筋表面出现大面积锈迹但混凝土尚未完全脱落时模型倾向于把它预测成锈蚀而人工标注时这类区域通常标成外露。这属于标注标准不统一的问题不是模型缺陷。解决方法是增加标注规范中的实例描述同时在训练时对这两类样本做更精细的预清洗。6. 常见问题与排查速查表项目过程中遇到过不少问题多亏每一步都留了日志和中间产物排查起来才没有抓瞎。这里整理成速查表方便大家直接对照。现象原因解决方案训练loss不下降标签坐标越界或归一化错误写脚本检查所有txt标签中坐标是否在0到1区间验证mAP为0类别ID与names顺序不匹配检查data.yaml names顺序和txt首列ID裂缝掩码断成多段裂缝实例标注规则不统一统一“连续走向作为一个实例”的标注标准裂缝边界锯齿严重多边形顶点过密或过疏顶点间隔控制在15到30像素训练后用形态学闭运算后处理露筋和锈蚀互相误分标注标准未明确优先顺序定义“有残留混凝土优先外露表面锈变优先锈蚀”结构变形样本不收敛样本量太少且增强策略不当过采样加针对性小角度旋转增强关闭上下翻转模型在阴影处输出假损伤清洗数据时保留了过多阴影强干扰图增强阶段加入随机亮度和对比度扰动训练时提高验证阈值还有一个所有分割模型项目都会遇到的高频问题训练时一切正常验证指标也不差但一到现场实拍图像上效果明显变差。这个问题的核心是域差异。桥梁检测照片来自不同相机、不同光照、不同拍摄角度而训练数据基本集中在几个固定场景。我解决这个问题的办法是收集一批现场实拍图用已训练模型做半自动标注人只修正错误区域把这些图作为补充训练数据。这个闭环流程看起来简单但对工程落地效果提升极大。推理阶段的后处理也容易踩坑。YOLOv8-seg输出的原始掩码是分辨率与输入图像相同的概率图对裂缝这种细长目标直接用阈值0.5切割容易出现断点。我试过用0.3的置信度阈值配合一次形态学闭运算和一次连通域去除裂缝的连续性提升很明显。但阈值调低后小目标噪点也会变多所以需要根据实际场景做权衡。7. 部署落地与后续扩展模型训练只是第一步桥梁损伤分割要真正发挥作用还得经过模型导出和部署环节。YOLOv8-seg导出到ONNX的操作用官方命令即可yolo export modelbest.pt formatonnx imgsz640如果部署设备是NVIDIA系列可以考虑导出TensorRT版本推理速度比ONNX快不少。但对大多数项目来说ONNX配合通用的推理框架已经足够。部署时留两个接口很重要。一个是目标级接口输入图像数组输出每个目标的类别、置信度、检测框坐标和掩码多边形。另一个是像素级统计接口输出每个类别的像素总数和面积占比。我在桥检系统的落地里发现现场工程师最关心的不是模型的mAP而是“这面腹板上裂缝有多长、剥落面积占多少”。所以提前把面积计算和长度估算封装好会让整个系统在业务层面更有说服力。后续扩展方向上我计划做的是从单帧图像分割升级到视频序列的连续跟踪。桥梁检测车在行驶过程中连续采集图像相邻帧之间同一损伤会出现多次如果能利用时序信息做目标关联就能自动统计同一损伤的出现频次和面积变化这对病害演化分析意义很大。YOLOv8-seg目前是单帧模型需要额外接一个跟踪模块才能实现这是当前项目最有价值的延伸方向。另外YHT3261这套数据的标注流程已经沉淀成了一套标注规范后续采集的新数据只要按同样的标准标注就能持续扩充数据集。我个人认为对这类工程视觉项目来说数据标准比模型调参更重要一套可复制的数据构建方法比短期内刷高一个点的mAP更有长期价值。最后分享一个小经验做这类损伤分割任务不要一开始就把目标定在追求最顶尖的模型精度上。先跑通一个端到端的最小闭环从数据到模型到部署确认每个环节都可靠再回到模型精度上做优化。很多团队在标注阶段花了80%的时间结果发现标签标准和下游需求对不上返工成本极高。先想清楚“这些掩码到底要用来干什么”再开始标注和训练整个项目会顺利得多。