☰
跨江桥梁路面病害目标检测数据集:标注与训练避坑指南
2026/10/14 13:06:10 网站建设 项目流程

简介:面向跨江桥梁监测与道路资产管理场景的目标检测数据集,包含桥梁路面病害与道路资产标定图像及Labelme格式标注,可供计算机视觉研究者、算法工程师用于训练YOLO、Faster R-CNN、Mask R-CNN等模型。压缩包共1718个文件,含860个jpg原图与858个json标注文件,整体大小344.46MB;json文件保存目标类别与位置信息,可直接用于目标检测模型训练与评估。该数据集已有2458人学习下载,特别适合需要专门化桥梁场景数据进行模型调优的开发者。利用这些成对数据可自行划分训练集、验证集和测试集,通过交叉验证与超参数调优提升裂缝、破损、积水及桥墩、拉索、桥面等目标的识别精度,为桥梁预防性维护和道路资产管理提供自动化检测基础。

1. 目标检测遇上跨江桥梁:路面病害与道路资产标定数据集,先看清再动手

跨江桥梁的路面病害检测,真正卡住目标检测模型的地方,往往不是网络结构,而是标定数据的质量。做桥面巡检的人都知道,桥面病害不是普通路面裂缝的低级复刻——伸缩缝、修补块、桥面铺装层裂缝混在一起,单独把 YOLO 或 RT-DETR 拉上桥,跑出来的框总是多的多、漏的漏。这份资源,是一套以目标检测为任务核心的跨江桥梁路面病害与道路资产标定数据集,病害框、资产框和训练数据都按人工智能模型可直接消费的方式组织。它适合正在搭桥检信息化、做公路资产盘点,或者想用自有巡检视频快速起训检测模型的一线开发者。我拆完这套数据后的结论是:数据本身不难,难在标定规则和训练参数要不要跟着桥梁场景一起调。

2. 类别体系与标定格式:把病害和资产拆成模型能学会的标签

2.1 病害类别怎么定:裂缝、坑槽、修补块,不能只看框

跨江桥梁的桥面病害,和普通公路路面最大的区别在铺装层结构。桥面铺装层比路基路面薄,病害形态更碎,而且伸缩缝两侧经常出现复合型破损。标定病害类别时,我一般按「互相排斥、边界可判读」的原则组织,常见的六类如下:

编号类别标注边界说明
0横向裂缝与桥轴线近似垂直,按 2-3 米一段拆分标注,不画整条长框
1纵向裂缝沿行车方向延伸,同样分段,框的宽度不小于图宽的 2%
2龟裂网状细裂纹区域,按连通域画一个外接框,不逐条描线
3坑槽开放、不规则的凹陷,边界按破损边缘走
4修补区域规则矩形边界、颜色与周围差异明显,覆盖旧坑槽的属于修补
5拥包铺装层局部隆起,框包含整个隆起的可见范围

这条规则里,最难的是 3 和 4 的互斥。坑槽是开放凹陷,修补区域是有明显边界的补丁。我在实际拆数据时见过不少标注员把「修补过的旧坑槽」标成坑槽,模型训出来之后,凡是有一圈方形边界的区域都被当成缺陷框,误报率一下就上去了。标定规范里必须写死一句话:有规则边界、颜色分层明显的,一律归修补区域。

病害框还有一个细节:桥面裂缝经常是细长条,如果按目标检测的习惯「一个实例一个框」来处理,几十米长的纵缝在一个框里,框的长宽比会到几十比一。YOLO 这类 anchor-free 模型对极端长宽比对象回归很不稳定,预测框会沿着裂缝方向来回抖。所以病害标定的核心不是「画得准」,而是「拆得碎」。把长裂缝切成多段,每段一个框,训练时的回归目标才稳定。

2.2 道路资产类别怎么定:护栏、标牌、标线、伸缩缝的边界规则

资产检测的目标逻辑和病害完全不同。病害框是缺陷区域,资产框是完整对象,边界就是对象的物理边界。跨江桥梁上常见的资产,我建议按下面这套编号和规则标:

编号类别标注边界说明
6桥梁护栏包含立柱和横栏的连续段,不跨伸缩缝断口
7标牌只标牌面本身,不包含立柱
8标线按实线段标,虚线按段标,不横跨整幅桥面
9照明设施灯杆与灯头作为整体标,多个灯杆并排时逐个标
10泄水设施泄水孔、集水井盖,按井盖外沿标
11伸缩缝跨整幅的金属/橡胶边界带,与裂缝严格区分

伸缩缝是跨江桥梁场景里最容易被误检成裂缝的资产。视觉上它是一条横贯桥面的规则缝隙,和横向裂缝非常像。标定规则里要写清楚:与桥轴线近似垂直、有连续金属或橡胶边界、跨整幅断开的,标为伸缩缝;形状不规则、沿铺装层发散的,才算裂缝。我在自己的项目里吃过这个亏,第一次训练没做这个区分,验证集 mAP 有 0.82,结果实际巡检视频里伸缩缝位置全是误报框,每一帧报警。后来把伸缩缝单独拉出来当资产类,重新标了一批难例,误报才压下来。

标线这一类还有个容易踩的坑:有人把整条标线包括箭头一起框成一个巨大矩形,模型学到的是「一长条白色区域」。建议把箭头单独设子类,或者干脆只标实线段,让模型学的是「标线语义段」而不是「白色大块」。这套数据里我建议的写法是:虚线按每条短线段标,箭头不并入标线类。

2.3 标注格式与文件组织:YOLO txt 与 COCO json 的对应关系

目标检测训练生态里,YOLO 格式还是最省事的:每个图片对应一个同名 txt,每行是「类别编号 cx cy w h」,坐标用图片宽高归一化到 0-1。这套数据既然面向训练,最常见的组织方式是先建好 images 和 labels 的 train/val 两个目录,再配一个 data.yaml。

path: /data/bridge_dataset train: images/train val: images/val test: images/test names: 0: horizontal_crack 1: vertical_crack 2: alligator_crack 3: pothole 4: patch 5: bump 6: guardrail 7: sign 8: road_marking 9: lighting 10: drainage 11: expansion_joint

这个 yaml 里有几个地方容易错。path 必须写绝对路径或者相对 data.yaml 所在目录的完整相对路径,只写train: images/train而 path 配错,训练时会报数据集不存在的错。names 的索引顺序必须和标签 txt 里的第一个整数严格一致,YOLO 不看类名字符串,只看编号。如果资源里同时给了 VOC 或 COCO 格式,建议先统一转成 YOLO txt,再用 json 做可视化检查。

import os import xml.etree.ElementTree as ET # 类别编号顺序必须与 data.yaml 的 names 一致 label_map = { "horizontal_crack": 0, "vertical_crack": 1, "alligator_crack": 2, "pothole": 3, "patch": 4, "bump": 5, "guardrail": 6, "sign": 7, "road_marking": 8, "lighting": 9, "drainage": 10, "expansion_joint": 11, } def voc_to_yolo(xml_path, out_path): tree = ET.parse(xml_path) root = tree.getroot() size = root.find("size") img_w = float(size.find("width").text) img_h = float(size.find("height").text) lines = [] for obj in root.findall("object"): diff = obj.find("difficult") if diff is not None and diff.text == "1": continue # difficult 样本通常不参与训练,直接跳过 name = obj.find("name").text.strip() if name not in label_map: continue # 不在类别表的对象不写入标签,避免编号越界 box = obj.find("bndbox") xmin = float(box.find("xmin").text) ymin = float(box.find("ymin").text) xmax = float(box.find("xmax").text) ymax = float(box.find("ymax").text) cx = ((xmin + xmax) / 2) / img_w cy = ((ymin + ymax) / 2) / img_h bw = (xmax - xmin) / img_w bh = (ymax - ymin) / img_h lines.append(f"{label_map[name]} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}") with open(out_path, "w", encoding="utf-8") as f: f.write("\n".join(lines))

上面这段脚本的关键点有两个。一是归一化,cx、cy、bw、bh 全部除以图片真实宽高,YOLO 训练时不会二次换算,写错成像素坐标的话,loss 会直接跳到 NaN 或者框全贴到左上角。二是 difficult 标签跳过,VOC 里 marked as difficult 的实例边界往往不清晰,硬拉进训练集会变成噪声标签。跑完转换后,我习惯抽查 20 张图,把标签画回原图看框是否贴边,这一步能挡掉 80% 的格式错误。

提示:如果这套资源里同时出现 COCO json 和 YOLO txt,别只看 json。以 txt 为准,json 可能是按 COCO 类名排的,和你的 data.yaml 对不上。先跑校验脚本人眼查一遍再开训。

3. 从数据到模型:训练准备、数据增强与迁移策略

3.1 数据检查与切分:一个校验脚本把坏标注挡在训练前

拿到带标注的数据集,第一件事不是看目录,是跑校验。桥面巡检数据里最常见的坏标签有三类:坐标越界、类别编号越界、空标注文件。如果数据是从多个采集批次合并的,还会出现图片尺寸不一致的问题。我一般会先写一个全量扫描脚本:

import os from PIL import Image img_root = "images/train" label_root = "labels/train" errors = [] for img_name in os.listdir(img_root): stem = os.path.splitext(img_name)[0] img_path = os.path.join(img_root, img_name) label_path = os.path.join(label_root, stem + ".txt") if not os.path.exists(label_path): errors.append(f"{img_name}: missing label") continue with Image.open(img_path) as im: img_w, img_h = im.size with open(label_path, "r", encoding="utf-8") as f: for line in f: parts = line.strip().split() if len(parts) != 5: errors.append(f"{stem}: bad line -> {line.strip()}") continue cls_id, cx, cy, bw, bh = parts cls_id = int(cls_id) cx, cy, bw, bh = map(float, (cx, cy, bw, bh)) if cls_id < 0 or cls_id > 11: errors.append(f"{stem}: class id {cls_id} out of range") if not (0 <= cx <= 1 and 0 <= cy <= 1 and 0 < bw <= 1 and 0 < bh <= 1): errors.append(f"{stem}: box {line.strip()} out of range") for err in errors[:50]: print(err) print(f"total errors: {len(errors)}")

这里注意两个参数:类别编号上限要根据 data.yaml 的实际类数改,我上面按 0-11 共 12 类写的;图片宽高从 PIL 直接读,不要假设所有图都是统一分辨率,跨江桥梁的巡检视频抽帧经常混入不同相机型号的图,分辨率不一致会导致归一化标签在 A 图正常、在 B 图上错位。校验脚本跑完,errors 超过总数 1% 就要回头修标注,硬着头皮训练只是在错误数据上浪费时间。

数据切分也在这一步做,但我不会随机切。跨江桥梁的病害数据往往是视频连续抽帧,同一段桥面在相邻几秒内的画面高度相似,随机切分会让训练集和验证集出现「同一个裂缝的两种角度」,验证集 mAP 虚高,一到新桥段就露馅。常见做法是按桥名或采集批次做分组切分。

import os from sklearn.model_selection import GroupKFold # samples 每项是 (图片路径, 分组标签) samples = [] for bridge in ["bridge_a", "bridge_b", "bridge_c"]: for img in os.listdir(f"images/{bridge}"): samples.append((img, bridge)) X = [s[0] for s in samples] groups = [s[1] for s in samples] gkf = GroupKFold(n_splits=5) for train_idx, val_idx in gkf.split(X, groups=groups): train_files = [X[i] for i in train_idx] val_files = [X[i] for i in val_idx] # 这里把 train_files / val_files 写入对应的 txt 清单

GroupKFold 的逻辑是保证同一个 bridge 分组不会同时出现在训练集和验证集,n_splits 设 5 是为了后续可以做 5 折交叉验证;如果你的采集批次数量不足 5,就把 n_splits 改成批次数的约数,否则划分会报错。这个脚本跑完,训练集和验证集的 lits 文件要分别存好,YOLO 的 data.yaml 里也可以直接用 txt 清单路径替代目录路径。

3.2 类别不均衡怎么处理:从样本统计到重采样

桥面病害数据里,横向裂缝和龟裂的数量可能差五倍以上;资产里标牌多、泄水设施少。直接拿原始分布训练,少数类 AP 会明显落后。我在训练前会先统计每个类别的实例数和出现图片数,然后决定用哪种策略。

先跑一段统计脚本,看每个类别的实例总数和占图片比例:

from collections import Counter cls_counter = Counter() img_counter = Counter() for label_file in os.listdir("labels/train"): with open(os.path.join("labels/train", label_file), "r") as f: cls_ids = set() for line in f: cls_id = int(line.split()[0]) cls_counter[cls_id] += 1 cls_ids.add(cls_id) for cls_id in cls_ids: img_counter[cls_id] += 1 for cls_id in range(12): print(f"class {cls_id}: instances={cls_counter[cls_id]}, images={img_counter[cls_id]}")

这里有两个统计口径:实例总数和图片数。YOLO 的类权重一般按图片级频率算,因为每张图里所有目标都参与 loss,如果一个类只在 5 张图里出现 100 个实例,它在训练里遇到的机会还是远少于另一个在 200 张图里各出现 1 个实例的类。所以判断样本够不够,先看 img_counter 而不是 cls_counter。

处理不均衡,我习惯的组合是:图片级重采样 + copy-paste 增强。图片级重采样就是给少数类的图片提高采样概率,实现上可以在训练脚本里按 cls 分布算一个 sample weight;copy-paste 则是把少数类目标从它所在的图上抠出来,贴到其他图上,相当于免费的样本扩充。这一步对桥面病害特别有效,因为桥面背景高度重复,粘贴过去的裂缝、坑槽不会违和。如果资源里配了 YOLO 的增强配置,建议优先开 copy_paste,其次是 mosaic 和 mixup。

3.3 迁移训练:用预训练权重而不是从零训

桥面病害的纹理特征和自然图像差异很大,但底层的边缘、纹理、明暗特征是可以迁移的。我一般会用 COCO 预训练权重起步,不推荐从零训练。起点模型选 YOLOv8m 或者同级的 RT-DETR,s 太小,小裂缝细节学不动;l 太大,单卡训练周期太长。命令大致这样:

yolo detect train \ model=yolov8m.pt \ data=bridge.yaml \ epochs=100 \ imgsz=1280 \ batch=8 \ lr0=0.01 \ mosaic=1.0 \ close_mosaic=10 \ cache=True

每个参数在这个场景里都有讲究。imgsz=1280 是跨江桥梁病害场景我最坚持的一项,桥面裂缝在 1080p 巡检视频里宽度只有几个像素,用 640 训练,细节直接被下采样吞掉;显存不够时把 batch 降到 4 也不要动 imgsz。mosaic=1.0 前 90 个 epoch 开着,最后 10 个 epoch 用 close_mosaic=10 关掉,因为 mosaic 拼图会让小目标被缩得更小,后期要让模型在接近真实分布的尺度上收敛。batch 要看显存,8G 卡跑 1280 分辨率时 batch=4 更稳,16G 以上再开 batch=8。cache=True 是把图片预加载到内存,数据集几百张图时提速明显,但机器内存小于 16G 时建议关掉,改成 cache=False 只缓存标签。

跑完 100 个 epoch 先别急着下结论。我会再做一轮替换实验:把 yolov8m.pt 换成 yolov8l.pt 继续训 50 个 epoch,对比 mAP 增幅有没有超过 0.5。桥面数据量通常不大,模型容量的边际收益很快到顶,与其换大模型,不如回头补难例数据。

4. 避坑:跨江桥梁场景下最容易翻车的五个标注与训练问题

4.1 标定与数据准备阶段:三个高频翻车点

坑一:病害框「一框到底」,验证集 mAP 虚高但实拍全崩。

现象:一条几十米长的纵缝标成一个大框,训练后 loss 很低,预测输出却是一串忽大忽小、沿裂缝方向来回跳的框。

原因:回归头对极端长宽比对象天然不稳定,尤其是细长框的中心点稍微偏一点,IoU 就会大幅波动,模型没法学到稳定的定位信号。

解决:按 2-3 米一段拆框,同时设一个下限——小框短边不要小于图片宽度的 2% 到 3%。这个下限能避免裁出大量只有 1-2 像素宽、人眼都难判别的「伪裂缝」。我处理这套数据时,第一轮训练前只修了这一项,裂缝类 AP 从 0.58 提到 0.73。

坑二:标线类把箭头和虚线混在一个框里,模型学到的是「白色大块」。

现象:标线的 AP 看着有 0.8,但新视频里桥面阴影、反光白块全部被识别成标线,误报数量远超预期。

原因:类别定义有歧义,标注员有的把整条虚线横跨画框,有的只标单段,模型从混乱标注中学到的是「白色 + 条状」这个粗糙特征。

解决:重新定义「标线」的标注边界——虚线按段标,实线按连续段标,箭头单独设一个类别,统一规范后再校验一轮。如果资源里已经标乱了,比起手工一框框改,我建议直接删掉标线类重标,改动量看着大,实际比反复训练试错省时间。

坑三:训练集和验证集来自同一个桥的连拍帧,「数据串集」导致评估失真。

现象:5 折交叉验证 mAP 都过 0.8,部署到另一座桥的巡检视频上,mAP 直接掉到 0.4 以下。

原因:随机切分只是简单打乱,同一个裂缝的不同角度帧被拆进了训练和验证两堆里,模型其实「见过」验证集的内容。

解决:切分前按桥名或采集批次分组,用 2.1 节里 GroupKFold 的方式保证同一批次不分家。这是一个入场就要做的决定,训练完再发现,只能重训。

4.2 训练与推理阶段:两个隐藏较深的坑

坑四:mosaic 增强让细裂缝「碎框」更严重。

现象:开了 mosaic 之后,验证集上小目标类 AP 不升反降,检查训练日志发现 loss 收敛变慢。

原因:mosaic 把四张图缩小拼成一张 1280 的图,每条细裂缝被缩小到 2px 以内,特征在骨干网络下采样后彻底消失,相当于强制模型学习噪声。

解决:把 close_mosaic 从默认的 10 加大到 15-20,或者把 mosaic 概率从 1.0 降到 0.5,另外给细裂缝类多配 copy-paste 增强,用「大图上的原尺度目标」训练定位能力。我现在的习惯是:小目标占比高的数据,mosaic 概率不会超过 0.7。

坑五:推理时把伸缩缝当裂缝,把修补区域当坑槽,误报集中在易混类别。

现象:模型在测试集上的总体 mAP 正常,画图看检测结果时,误报框几乎全落在伸缩缝和修补区域这类「结构上像病害的正常资产」上。

原因:训练时没有做易混类的互斥处理,模型学到的是「深色条状区域 = 裂缝」「有边界区域 = 坑槽」,而不是「是否发生在铺装层开裂」这个判别信号。

解决:先在标注规范里把互斥边界写死,用于纠错重标;然后做一轮难例回填——把推理阶段误报的图片收集起来,按类目挑出最典型的 50-100 张,加上正确标签放回训练集,再微调 20-30 个 epoch。这一招在桥面检测里几乎每次都能把误报压下去 30% 以上。

5. 验证与进阶:mAP 之外,用每类别 AP 和误检图卡住模型质量

5.1 按类别拆 AP 报告,不只看总 mAP

桥面数据集的类别分布在训练前后完全不一样,只看总体 mAP 会掩盖少数类的失败。训练完我会强制出一份 per-class 报告:

yolo detect val model=runs/segment/train/weights/best.pt data=bridge.yaml

拿到结果后,按类别对着这张表看:横向裂缝、坑槽这类病害主类的 AP 必须排在前列,伸缩缝、护栏这类资产类掉一点可以接受,但如果护栏 AP 比裂缝还高,说明模型把精力花错地方了。文件头部的 Class 列和 mAP50-95 列逐行比对,优先处理那些 AP50 高但 AP50-95 低的类别,这个差异大说明框的位置不稳定,多半是标注框边界松垮,回去重修这批标签。

5.2 误检聚类与难例回填,把模型逼到会区分「像」与「是」

每类别 AP 报告正常,不等于现场能用。我会把验证集里所有置信度大于 0.25 的预测框导出,按真实标签归成三类:正确命中、漏检、误检。误检框聚类后放大看,人眼很容易发现规律——伸缩缝的金属盖板边缘、桥面阴影交界处、修补块的方形边界是三大误报源。这三类误检直接回填进训练集,不需要改网络结构。难例回填的规模控制在 50-200 张之间,数量太少没效果,太多会破坏原有分布。

从那以后,我每次接手一套桥面标定数据,都强制自己走一遍完整流程:先查类别互斥和伸缩缝区分,再按桥分组切分,然后看每类别 AP 和误检聚类图,最后才敢说这个模型能上桥。这套数据和训练配置拿去,顺序别跳,坑都在前面几步。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询