拓冰建站拓冰建站
首页 / 资讯中心 / 正文

航拍路面病害检测:VOC+YOLO双格式数据集与YOLOv8训练实战

简介航拍路面病害检测数据集提供3302张道路图像配套Pascal VOC与YOLO两种标注格式适合用于目标检测、裂缝定位等视觉任务面向计算机视觉初学者与道路设施巡检算法开发者。压缩包共2000个文件以1999个XML标注文件为主体另含1个TXT使用说明整体大小约166MB每张图像均配套VOC格式XML与YOLO格式TXT可免去手动格式转换直接接入主流检测框架训练。数据集标注了7类路面病害涵盖龟裂、纵向裂缝、斜裂缝、坑洞与修补区域等典型缺陷图像来自航拍视角贴近真实巡检场景。目前已有1197人学习下载适合需要标准格式训练数据、开展裂缝检测算法验证与毕业设计的读者使用。1. 航拍路面病害检测与道路裂缝数据集为什么两条标注链路都得保留航拍路面病害检测这几年在道路巡检里越来越常见无人机带个相机扫完一段国道回来就是几千张带坐标的影像。真正耗时间的不是飞而是标注——裂缝细长、坑槽形状不规则画框的工时常年压着项目进度。所以当你拿到一份 3302 张、7 类别的航拍路面病害 VOCYOLO 双格式数据集时等于把最贵的标注环节省掉了一半。这份数据最大的价值不在张数而在“VOCYOLO”双格式这个设计VOC 方便人工检查和二次修正YOLO 格式可以直接喂给检测框架训练。适合做道路养护信息化、桥梁检测、无人机巡检的工程师也适合刚准备跑通第一个目标检测项目的算法同学——你不需要懂标注工具导出细节把目录结构搞清楚就能开工。2. 看懂 VOC 与 YOLO 双格式目录结构、标注文件与转换逻辑拿到压缩包之后第一件事不是解压就跑训练而是先弄清里面两种标注格式各自的目录组织和坐标表达方式。这一章把 VOC 和 YOLO 的差异讲透并给出一个可复用的转换脚本方便你把它转成自己习惯的格式。2.1 VOC 格式的组成JPEGImages、Annotations 与 ImageSets 三层目录VOC 格式源自 PASCAL VOC 竞赛后来成为目标检测数据集的标准交换格式。常见目录组织如下dataset_root/ ├── JPEGImages/ # 原始图像jpg或png ├── Annotations/ # 每个图像对应的XML标注 ├── ImageSets/ │ └── Main/ # train.txt / val.txt / test.txtAnnotations里的每个 XML 文件与 JPEGImages 下的图片一一对应一个典型的 XML 标注文件包含这些关键节点annotation filenameIMG_0001.jpg/filename size width5472/width height3648/height depth3/depth /size object namecrack/name bndbox xmin1200/xmin ymin850/ymin xmax1420/xmax ymax910/ymax /bndbox /object /annotationXML 里记录的是绝对像素坐标size节点里的宽高是转换时必须依赖的信息。ImageSets/Main/下的 txt 文件则按行列出图片文件名不带扩展名用来划分训练集和验证集。VOC 格式好排查——任何坐标异常都可以直接打开 XML 看原始数值但它有两个问题文件冗余一张图配一个 XML且不直接适合当前主流检测器的输入需求。这也是为什么 YOLO 格式能成为训练侧的主流。2.2 YOLO 格式的 .txt 标注归一化坐标与类别索引YOLO 系列对标注的要求非常统一每张图片对应一个同名 .txt 文件每一行标注一个目标格式如下class_id x_center y_center width height所有数值都是归一化的。以 2.1 里那组坐标为例假设图片宽 5472、高 3648框的左上角 (1200, 850)、右下角 (1420, 910)中心点像素坐标就是 (1310, 880)框宽 220、高 60。归一化公式x_center 1310 / 5472 0.2394 y_center 880 / 3648 0.2412 width 220 / 5472 0.0402 height 60 / 3648 0.0164最终在 txt 里写入0 0.2394 0.2412 0.0402 0.0164其中 0 是crack类别在类别列表里的索引。注意 YOLO 的坐标是中心点加宽高不是左上角加右下角——这是从 VOC 转 YOLO 时最容易出错的点。下表把两套格式的差异做了一个直接对比对比项VOCYOLO标注文件后缀.xml.txt坐标体系绝对像素坐标归一化浮点数坐标表达左上角 (xmin, ymin) 与右下角 (xmax, ymax)中心点 (x_center, y_center) 与宽高 (w, h)类别表达字符串名称整数索引训练集划分ImageSets/Main 下的 txt由目录结构隐式划分是否依赖图片尺寸本身不依赖但读取时需配合 size 节点必须用图片宽高做归一化类别索引不是随便排的。如果后续准备在 YOLOv8 或者 MMDetection 上训练那个索引顺序在整个训练和推理阶段必须全局一致。航拍路面病害数据集的 7 个类别通常按裂缝类型和病害程度划分不同版本的数据集类别定义会有差异动手前先核对一遍类别清单。2.3 用 Python 脚本把 VOC 转成 YOLO并校验样本数虽然很多标注工具自带导出功能但在命令行环境下用脚本转换永远是最后一道保险。下面是通用的 VOC 转 YOLO 脚本核心逻辑是对每个 XML 做解析、归一化、写出对应 txtimport xml.etree.ElementTree as ET from pathlib import Path # 类别顺序必须固定之后训练配置里的 names 要与此处保持一致 CLASSES [crack, longitudinal_crack, transverse_crack, pothole, patch, alligator, repair] def voc_to_yolo(xml_file: Path, output_dir: Path, classes: list) - int: tree ET.parse(xml_file) root tree.getroot() # VOC XML 里带了真实图片宽高优先用它缺失时由外部传入 size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) lines [] for obj in root.findall(object): name obj.find(name).text.strip() if name not in classes: continue # 跳过不在类别清单里的目标 cls_id classes.index(name) bbox obj.find(bndbox) x1 float(bbox.find(xmin).text) y1 float(bbox.find(ymin).text) x2 float(bbox.find(xmax).text) y2 float(bbox.find(ymax).text) # 防呆裁掉越界坐标防止训练时出现负数宽高 x1 max(0, min(x1, img_w)) x2 max(0, min(x2, img_w)) y1 max(0, min(y1, img_h)) y2 max(0, min(y2, img_h)) if x2 x1 or y2 y1: continue cx (x1 x2) / 2 / img_w cy (y1 y2) / 2 / img_h w (x2 - x1) / img_w h (y2 - y1) / img_h # 归一化后的值理论上在 0~1 之间超过要警惕标注异常 if cx 1 or cy 1 or w 1 or h 1: raise ValueError(f{xml_file.name} 中存在非法归一化坐标) lines.append(f{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) if not lines: return 0 output_dir.mkdir(parentsTrue, exist_okTrue) txt_path output_dir / f{xml_file.stem}.txt txt_path.write_text(\n.join(lines) \n, encodingutf-8) return len(lines) input_dir Path(Annotations) output_dir Path(labels) total_objects 0 for xml_path in input_dir.glob(*.xml): count voc_to_yolo(xml_path, output_dir, CLASSES) total_objects count if count 0: print(f警告: {xml_path.name} 没有有效目标) print(f处理完成共转换 {total_objects} 个目标框)脚本里的几个点值得注意CLASSES列表顺序直接决定 txt 里的类别索引训练配置里的names必须与其逐位对应max/min裁剪逻辑是为了处理标注工具偶尔产生的越界框如果裁剪后宽高仍不为正则丢弃最后一步数值越界检查能在数据集层面帮你抓出异常标注避免训练时 loss 异常炸掉。转换完成后建议立即对照检查——随机挑几张原图把 txt 里的归一化坐标还原成像素坐标画框目视确认框是否贴合裂缝目标。这一步成本很低但能省掉后面排错的大量时间。3. 用 YOLOv8 在本地跑通裂缝检测训练环境、配置与最小命令格式转好了接下来的标准动作是跑 YOLOv8 训练。这章按当前社区最主流的 YOLOv8 流程来涵盖环境准备、数据集目录整理、data.yaml 写法以及启动命令完整走一遍训练前的最后 100 米。3.1 数据集目录组织与 YOLO 环境配置YOLOv8 对数据集目录并不苛求固定结构只要 data.yaml 里写对路径即可。但按社区惯例把图片和标签分开放是最不容易出错的datasets/RoadCrack/ ├── images/ │ ├── train/ # 训练图片 │ └── val/ # 验证图片 ├── labels/ │ ├── train/ # 与 images/train 同名的 .txt │ └── val/ # 与 images/val 同名的 .txt划分比例一般取 82 或 91。3302 张图不算多91 的话验证集约 330 张对裂缝这种长尾分布的数据更合理。划分时可以用sklearn.model_selection.train_test_split也可以直接用 shell 脚本按文件名前缀分组——关键是保证同一张图的 jpg 和 txt 进同一个集合不要出现图片在 train、标签在 val 的错位。环境配置上PyTorch 2.x CUDA 的组合是当前最省心的路径。conda 创建独立环境注意版本对齐问题conda create -n roadcrack python3.10 -y conda activate roadcrack pip install ultralytics torch torchvision --index-url https://download.pytorch.org/whl/cu121装完后先验证 GPU 是否被正确调用。torch.cuda.is_available()返回 True 还不够最好看一眼实际显卡型号和显存——这决定了后面 batch size 和 imgsz 能开多大。显存低于 8GB 的卡直接放弃 imgsz1280 的念头老实从 640 起步。如果你是 Mac 用户mps设备也能跑但航拍大图场景下 CPU/GPU 的吞吐差距会非常明显能做迁移学习的还是优先 CUDA。3.2 data.yaml 写给航拍小目标imgsz 和类别顺序是关键data.yaml 是整个训练配置里最不该想当然的文件。路径写错、类别顺序与转换脚本不一致都会在训练早期以诡异的 loss 曲线形态暴露出来。下面是一个基准配置# datasets/RoadCrack/data.yaml path: /absolute/path/to/datasets/RoadCrack train: images/train val: images/val nc: 7 names: 0: crack 1: longitudinal_crack 2: transverse_crack 3: pothole 4: patch 5: alligator 6: repairpath建议写绝对路径避免相对路径在不同工作目录下引发 FileNotFoundError。names的索引顺序必须严格等于第 2 章转换脚本里的CLASSES顺序否则类别错位会静默地发生在训练数据里——模型不会报错只会学到一个错误的映射。这点在多人协作时尤其危险不同人跑过不同版本的格式转换脚本后类别顺序很容易出现漂移。航拍路面病害的特殊性在于裂缝是典型的小目标在原图上可能只占几十个像素宽、几百个像素长。imgsz 直接决定这些小目标在输入分辨率下还剩多少像素。经验上航拍道路场景 imgsz1280 比 640 有明显提升显存足够就优先 1280不够则用 960 折中但不要低于 640。数据集的 7 个类别里如果crack和longitudinal_crack这类细长目标占多数imgsz 带来的收益会比一般数据集更显著。3.3 启动训练完整命令行与关键参数语义ultralytics 包安装完毕后训练入口统一收敛到yolo detect train命令。一个可直接执行的最小命令如下yolo detect train \ datadatasets/RoadCrack/data.yaml \ modelyolov8s.pt \ epochs100 \ imgsz1280 \ batch8 \ device0 \ workers4 \ patience20 \ projectoutputs/roadcrack \ nameexp_s_1280逐项说明modelyolov8s.pt表示加载 YOLOv8s 的预训练权重COCO 上训过的特征提取器对裂缝边缘纹理的迁移效果通常好于从零训练epochs100是总轮数配合patience20实现早停——验证集 mAP 连续 20 轮不提升就自动结束防止过拟合batch8在 1280 分辨率下约占 16GB 显存如果你的卡是 12GB 建议降到 4workers4是数据加载线程数Windows 上过高的 workers 容易触发 DataLoader 报错4 到 8 是安全区间。训练开始后不需要干等盯两个信号即可。第一是前 20 轮的train/box_loss是否平滑下降如果 loss 曲线在前几轮剧烈震荡且伴随 NaN优先怀疑类别索引错位或标签文件里有空行。第二是验证集metrics/mAP50(B)是否在 30 轮左右进入上升通道。如果 mAP50 始终低于 0.3后面第 4 章的优化手段会帮你找到瓶颈。训练日志会同步输出预测样例图到outputs/roadcrack/exp_s_1280/建议每 20 轮打开看一眼。注意观察裂缝的检出框是否连续——裂缝检测里最常见的失败模式是“一段断成好几截”即模型把一整条裂缝识别成多段mAP 看着还行实际工程上没法用。这种情况在训练阶段就要看出来不要拖到部署后才返工。4. 针对道路裂缝的二阶段优化类别不均衡、损失函数与增强策略第一轮 baseline 跑完后通常要面对两个现实问题类别不均衡和长条目标的漏检。3302 张航拍图里横向裂缝和纵向裂缝的样本量可能相差数倍而repair修补带这种类别往往样本较少直接导致 mAP 被稀有的类别拖低。这一章给出三个行之有效的迭代方向。4.1 先用混淆矩阵定位漏检类别从结果反推数据缺口YOLOv8 训练结束后验证集上会输出confusion_matrix.png。别急着看整体 mAP先看对角线之外的高频错误落在哪里。常见模式有两种一是crack被频繁预测成transverse_crack——说明这两个类别在视觉上高度相似标注边界本身存在模糊地带二是某个少数类别比如alligator龟裂几乎不出现在预测结果里——典型的样本不足或标注不一致。处理方式分两步。先看类别分布# 统计每个类别的目标框数量 cat datasets/RoadCrack/labels/train/*.txt | awk {print $1} | sort | uniq -c | sort -rnfrom collections import Counter from pathlib import Path counter Counter() label_root Path(datasets/RoadCrack/labels/train) for txt in label_root.glob(*.txt): for line in txt.read_text().strip().splitlines(): cls_id int(line.split()[0]) counter[cls_id] 1 total sum(counter.values()) for cls_id, cnt in sorted(counter.items()): print(f类别 {cls_id}: {cnt} 个框, 占比 {cnt / total:.1%})多数情况下会发现头部类别占 50% 以上尾部几个类别加起来不到 10%。这时再回看混淆矩阵确认是不是尾部类别贡献了主要漏检。如果是优先做的不是加数据而是检查尾部类别的标注质量——航拍图的标注错误率其实不低常见问题是遮挡处漏标、裂缝断点处误标为两条。4.2 类别权重配置与 YOLO 损失函数层面的调整思路YOLOv8 默认的损失函数是分类损失BCE 回归损失CIoU 分布焦点损失DFL的组合。它没有内置的类别权重参数但有两个间接手段可以影响少数类的训练强度。第一个是过采样少数类样本把alligator、repair这类占比极低的图片在训练目录里重复几次再启动训练。第二个是从数据增强角度增加少数类出现的频率比如针对包含尾部类别的图片提高 mosaic 参与度。如果不想改数据可以换modelyolov8s-seg.pt用分割头来训练——裂缝这种细长目标的掩码标注比矩形框更贴合真实形状但前提是你的标注里有 polygon 信息。VOC 格式的 XML 中bndbox只存矩形框所以这个方案对当前数据集不一定适用。一个更直接的调整是修改损失函数权重Ultralytics 在loss.py里通过hyp[cls]和hyp[box]控制各项损失的缩放。在ultralytics/cfg/default.yaml里可以覆盖# 假设你想加大分类损失的权重 cls: 0.8 # 默认 0.5提高后模型对类别判别的惩罚更强 box: 7.5 # 默认 7.5回归损失权重不变动手前先想清楚加大cls会压制误分类但同时会让模型对难样本的预测更保守如果问题本质是标注噪声调大 cls 只会让模型在噪声边界上过拟合。所以权重调整应该在数据检查之后做而不是之前。4.3 关闭 Mosaic 的时机航拍大图与小目标的增强博弈YOLOv8 默认在训练最后 10 个 epoch 会自动关闭 Mosaic 增强目的是让模型在接近真实分布的输入上精调。但航拍裂缝场景里Mosaic 从第 0 轮起就可能帮倒忙四张图拼在一起后原本就细的裂缝被缩放到原来的 1/4目标有效像素进一步减少梯度信号变弱。常见做法是在训练结束后用关闭 Mosaic 的方式再续跑少量 epoch即两阶段训练。第一步正常训练 100 轮第二步加载 best.pt用关闭增强倍率的方式再训 20~30 轮作为精调。命令行可以这样组合yolo detect train \ datadatasets/RoadCrack/data.yaml \ modeloutputs/roadcrack/exp_s_1280/weights/best.pt \ epochs30 \ imgsz1280 \ batch8 \ mosaic0.0 \ close_mosaic0 \ nameexp_s_1280_refinemosaic0.0在主配置里直接关闭拼接增强close_mosaic0用于禁用训练管线中“最后 N 轮自动关闭”的逻辑否则它可能在训练中途重新打开。这一步通常能带来 2~3 个点的 mAP50 提升并且会让裂缝框的连续性明显变好。如果你的验证结果显示裂缝三段断框多试这个方案大多数情况下比换更大的模型更有效。下表总结了三种增强策略在裂缝场景下的适用性判断方便你在第二版实验里快速做选择策略适用场景不适用场景开启 Mosaic默认常规目标检测、整体类别均衡细长小目标占比高的航拍裂缝数据集关闭 Mosaic 精调模型已有一定收敛追求框连续性训练前 30 轮内旋转/翻转增强裂缝方向分布多样横向、纵向、斜向定向裂缝检测如只检横向裂缝5. 裂缝检测模型的下游应用大图切片推理与数据集完整性核验模型训练收敛只是中点航拍实战中的难点是把模型用在大尺寸正射影像或拼接图上。这章的三个技巧分别对应推理效率、数据资产管理和结果输出。5.1 大图切片推理把 5472×3648 的航拍图切成可推理的窗口常见的航拍原图分辨率动辄数千万像素直接缩放后输入模型会让裂缝变成一两个像素的线再强的模型也救不回来。主流解法是滑窗推理——把大图按固定步长切成若干个 1280×1280 的 patch分别推理后再合并结果。切图时让相邻 patch 保留 20% 的重叠率避免裂缝恰好横跨切缝被截断import cv2 import numpy as np from ultralytics import YOLO model YOLO(outputs/roadcrack/exp_s_1280_refine/weights/best.pt) img cv2.imread(drone_shot_001.jpg) H, W img.shape[:2] patch_size 1280 overlap 256 step patch_size - overlap detections [] for y in range(0, H, step): for x in range(0, W, step): x2 min(x patch_size, W) y2 min(y patch_size, H) patch img[y:y2, x:x2] results model(patch, imgsz1280, conf0.25, verboseFalse) for box in results[0].boxes.data.cpu().numpy(): px1, py1, px2, py2, conf, cls_id box # 把 patch 坐标还原到原图坐标 detections.append((x px1, y py1, x px2, y py2, float(conf), int(cls_id))) print(f共检测到 {len(detections)} 个目标)这里最关键的是坐标还原patch 的像素坐标加上该 patch 在整张图中的偏移量才是目标在全图上的真实位置。重叠区域里的同一个目标可能被检测两次后处理时用非极大值抑制NMS按 IoU 合并即可conf0.25的阈值可以根据现场误报率多试几档航拍场景 0.25 到 0.35 之间通常是误报与漏检的甜点区。5.2 用 7z 校验命令确认数据集完整避免训练到一半报错.7z 压缩包在传输和解压时偶发损坏而训练时的报错不一定直指某个文件损坏。解压前先做完整性校验7z t 航拍路面病害检测道路裂缝检测数据集VOCYOLO格式3302张7类别.7z7z t会逐个文件计算校验和。全部通过后再用7z x解压。解压后做两层核对一是文件数量JPEGImages 下应有 3302 张图片Annotations 下应有 3302 个 XML二是图片与 XML 的 basename 一一对应用以下命令找出来ls -1 JPEGImages | sed s/\.[^.]*$// | sort /tmp/imgs.txt ls -1 Annotations | sed s/\.[^.]*$// | sort /tmp/xmls.txt comm -3 /tmp/imgs.txt /tmp/xmls.txtcomm -3输出只在其中一个文件中出现的行任何输出都说明有文件缺失或命名不一致。这类问题越早发现成本越低训练跑到第 20 轮才发现 label 对不上图是最坏的剧本。5.3 结果输出的工程化裂缝框坐标反算到 WGS84 经纬度航拍病害检测的最终交付物往往是一张带地理坐标的病害分布表。正射影像如果带 GeoInfo可以通过 TIFF 的世界文件.tfw或内嵌地理标签完成像素坐标到地理坐标的转换。一般做法是读取图片的世界文件拿到六个仿射变换参数A, D, B, E, C, F其中x_geo A * x_pixel B * y_pixel Cy_geo D * x_pixel E * y_pixel F。把 5.1 里反算出的原图像素坐标再代入这个公式就能得到每个病害框的经纬度或投影坐标。输出成一个 CSV交给养护部门直接用 GIS 软件加载longitude,latitude,class,confidence,width_m,height_m 116.3912,39.9071,pothole,0.92,0.45,0.38如果数据来源没有精确的 POS 信息至少把像素坐标和航高记录到结果文件里后续做面积估算时航高和相机焦距是换算地面尺寸的必要输入。数据集本身给到 3302 张图价值在于把模型这半边跑通而真正能形成闭环的是把检测结果落到地理坐标上——那才是道路养护系统里会被真实调用的数据。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门