航拍滑坡数据集4315张:VOC转YOLO及YOLOv8训练避坑全指南
发布时间:2026/9/26 15:15:07来源:尧图网络
简介航拍滑坡目标检测数据集面向计算机视觉研究者与深度学习开发者主要用于滑坡灾害遥感影像识别、目标检测及模型训练。数据集包含4315张512×512高分辨率航拍影像标注类别为landslide共11315个矩形框覆盖全部4315张图像适合滑坡体定位与轮廓范围估计等任务。资源包共2000个文件以Pascal VOC格式的XML标注文件为主1999个另附1个TXT说明文件压缩包大小约200.98MB可解压后按需划分数据集。目前已有34人浏览学习。数据由labelImg工具人工标注已做增强处理适应航拍视角下形态不规则、背景复杂的特点未提供现成训练/验证/测试划分需自行处理同时兼容VOC与YOLO两种标注格式便于直接接入YOLOv5、Faster R-CNN等常见框架省去格式转换时间。1. 航拍滑坡数据集4315张VOCYOLO格式.zip先拆格式再谈训练拿到一个名为“航拍滑坡数据集4315张VOCYOLO格式.zip”的压缩包最容易浪费时间的环节不是训练而是解压之后不知道拿哪套格式下手。压缩包里同时给了 VOC 和 YOLO 两套标注不少人以为随便选一个就能训结果要么被 XML 的目录结构搞晕要么转格式时把坐标弄错训练日志反复报标签为空。这个数据集的真正价值是帮你跳过从零标注滑坡边界的最苦阶段直接用无人机影像训练滑坡检测模型难点在于航拍图里山体阴影、露岩、道路填方都会伪装成滑坡模型训练起来远不如常规照片稳定。它适合已经用过 YOLO、手头有 GPU 或云资源的从业者纯新手建议先把标注结构读透再跑训练否则大概率在格式转换和类别不平衡上反复翻车。2. 打开 zip 后的第一课VOC 目录和 XML 标注怎么读2.1 VOC 的 JPEGImages、Annotations、ImageSets 各管什么4315 张图的数据集解压后如果作者按 VOC 格式归档目录结构通常是固定的三层landslide_voc/ ├── JPEGImages/ ├── Annotations/ └── ImageSets/ └── Main/ ├── train.txt ├── val.txt └── test.txtJPEGImages 放原图Annotations 放同名 XML 标注ImageSets/Main 里的 txt 按行给出不带扩展名的文件基名。train.txt 列出训练集样本val.txt 列出验证集样本test.txt 是测试集。这套划分文件是 VOC 训练流程的老传统训练脚本不自己去文件夹里扫描所有图片而是读 txt 决定哪些图进训练、哪些进验证。所以做数据清洗时优先改的是 ImageSets/Main 下的 txt而不是来回移动图片目录否则训练结果和验证结果对不上后期排查起来很痛苦。拿到 zip 先做两个核对一是数 train.txt 的行数看是否和 JPEGImages 里的实际文件数对得上二是确认划分后的训练集里有没有“名单里有图、但没有对应 xml”的脏样本。这一步值得花十分钟因为不少第二手转发的数据集改过目录txt 文件名和实际图片名带不带空格、后缀是 jpg 还是 jpeg都可能被搞乱。我用 Python 做了一遍全量核对import os voc_root dataset/landslide_voc train_txt os.path.join(voc_root, ImageSets/Main/train.txt) with open(train_txt) as f: lines [x.strip() for x in f if x.strip()] for line in lines: jpg os.path.join(voc_root, JPEGImages, line .jpg) xml os.path.join(voc_root, Annotations, line .xml) if not os.path.exists(jpg): print(缺图:, line) if not os.path.exists(xml): print(缺标注:, line) print(train 样本数:, len(lines))逻辑很简单txt 每行是文件基名不带扩展名把它拼上 JPEGImages 和 Annotations 两个路径分别判断是否存在。如果任意一边缺失就打印出来后续训练前先补齐。参数说明如果数据集里图片是 .jpeg 或 .JPG 后缀要同步改这里的后缀更稳妥的做法是先列目录看实际后缀再写死否则会误报一片缺图。对于 4315 张的数据集这段脚本秒级跑完省下后面反复试错的时间。2.2 读一张 XMLbndbox 的四个整数坐标代表什么随便抽一张 Annotations 下的 XML内容大致是这个结构annotation filenameIMG_1024.jpg/filename size width1920/width height1080/height depth3/depth /size object namelandslide/name bndbox xmin320/xmin ymin410/ymin xmax1560/xmax ymax1015/ymax /bndbox /object /annotationsize 里的 width 和 height 不是摆设YOLO 转换时要用它们做归一化分母不能自己猜图像尺寸。object 里 name 是类别名一般滑坡数据集只有 landslide 一个类bndbox 四个值是像素坐标xmin/ymin 是框左上角xmax/ymax 是右下角。航拍滑坡图经常出现一张图里有多个 object可能是一个滑坡体被分成多个矩形框标注也可能是图里确实有多个独立滑塌区。这种情况转成 YOLO 后一个 txt 里会有多行训练时它们算同一个类别损失按每个框独立计算。读取 XML 时有一个隐含约定问题标注工具生成的 xmax/ymax 有些是闭区间像素索引有些是“像素索引1”。大多数开源数据集用的是前者直接拿来做差没问题但如果某个标注工具的导出逻辑不同xmax 可能比图像宽度大 1或者 xmax 减去 xmin 之后是 0。这种脏数据在 YOLO 里会变成宽高为 0 的非法框轻则被跳过重则导致损失计算报错。我处理 VOC 转 YOLO 的历史经验是转换脚本里必须做宽高大于 0 的过滤再顺手把坐标夹到图像尺寸内这一步不做后面训练日志里全是莫名其妙的警告。2.3 从 VOC 转 YOLO坐标归一化与目录重组脚本如果标题里的 zip 内部已经给了 YOLO 格式的 txt那这步可跳过如果只有 VOC就得自己转换。目标是把每张图的 XML 变成一个同名 txt每行格式是class_id x_center y_center width heightclass_id 是类别编号后四个值全部除以图像宽高归一化到 0~1x_center/y_center 也是相对整图的比例坐标。这也是 YOLO 和 VOC 最大的区别VOC 存的是左上角、右下角像素坐标YOLO 存的是中心点和宽高的相对比例脱离图片尺寸后依然可以直接喂给模型。import xml.etree.ElementTree as ET import os def voc_to_yolo(xml_path, save_dir, img_w, img_h, class_map): tree ET.parse(xml_path) root tree.getroot() name os.path.splitext(os.path.basename(xml_path))[0] lines [] for obj in root.findall(object): cls_name obj.find(name).text.strip() if cls_name not in class_map: print(f未知类别 {cls_name}, 跳过) continue b obj.find(bndbox) xmin float(b.find(xmin).text) ymin float(b.find(ymin).text) xmax float(b.find(xmax).text) ymax float(b.find(ymax).text) w xmax - xmin h ymax - ymin if w 0 or h 0: print(f{name} 存在非法框: {xmin},{ymin},{xmax},{ymax}) continue x_c (xmin xmax) / 2.0 / img_w y_c (ymin ymax) / 2.0 / img_h nw w / img_w nh h / img_h lines.append(f{class_map[cls_name]} {x_c:.6f} {y_c:.6f} {nw:.6f} {nh:.6f}) with open(os.path.join(save_dir, name .txt), w, encodingutf-8) as f: f.write(\n.join(lines) \n)逻辑说明先解析 XML逐个 object 读取坐标宽高用 xmax 减 xmin 计算先过滤掉非正数再归一化中心点取 xmin 和 xmax 的均值再除以整图宽高得到 0~1 的相对坐标。参数说明class_map 是 {类别名: 类别 id} 的字典单类数据集就是 {landslide: 0}img_w/img_h 建议从 XML 的 size 节点读不要自己硬编码否则图片一换尺寸坐标就全偏。对 4315 张图这个脚本跑几十秒就完。转完之后还需要把图片和 txt 按 YOLO 的习惯目录重组YOLOv8 训练时默认在 images 同级的 labels 目录里找标注mkdir -p dataset/yolo/images/{train,val,test} \ dataset/yolo/labels/{train,val,test}然后按 VOC 的 ImageSets/Main 划分把对应的 jpg 拷贝进 images 子目录、txt 拷贝进 labels 子目录。如果嫌拷贝占空间也可以用软链接但复制一份更省心训练时 IO 也更快。到这里格式层面的准备工作就算完工可以进第 3 章搭环境了。3. 搭 YOLOv8 环境并训练 4315 张滑坡数据一次跑通的最小配置3.1 Anaconda 环境配置要求Python、PyTorch 与 ultralytics不少人在 YOLO 环境搭建这一步踩过坑YOLOv8 用的是 ultralytics 这个包不是以前的 yolov5 仓库装完老版本后训练命令对不上。我的做法是用 Anaconda 单独建一个虚拟环境避免把系统 Python 弄乱。YOLOv8 Anaconda 环境配置要求并不高按下面的顺序一次能过conda create -n yolo python3.10 -y conda activate yolo conda install pytorch torchvision pytorch-cuda12.1 -c pytorch -c nvidia pip install ultralyticsPython 3.10 配 torch 2.x 跑 YOLOv8 最省事。Python 3.11、3.12 也能跑但 3.10 在 opencv、labelme 这类和标注处理相关的第三方库上兼容性最好。PyTorch 版本跟着 CUDA 走服务器 CUDA 是 12.x 就装 pytorch-cuda12.1老显卡驱动只支持 CUDA 11.8 的把命令里的 12.1 换成 11.8 即可。CPU 环境也能训练但 4315 张 1920x1080 的航拍图用 CPU 训练一轮是小时起步强烈不推荐。装完先验证一下环境python -c from ultralytics import YOLO; m YOLO(yolov8s.pt); print(m.model.__class__.__name__)如果打印出 DetectionModel说明环境就绪。这条命令还会触发 YOLOv8 预训练模型下载默认拉取 yolov8s.pt 到缓存目录。预训练模型下载是 YOLO 训练的默认行为如果下载卡住就手动从官方 release 把 yolov8s.pt 放进去再在训练命令里指定本地路径。这里没有太多玄学环境起不来九成是 torch 和 CUDA 版本不匹配重装前先看一眼 nvidia-smi 输出的驱动版本选对应的 torch 安装命令。3.2 写 data.yaml路径、类别与验证集YOLOv8 训练必须先写一个数据描述文件 data.yaml告诉模型数据在哪、编号从几开始。对滑坡单类数据集最小可跑版本长这样# landslide.yaml path: /home/user/dataset/yolo train: images/train val: images/val test: images/test names: 0: landslide四个关键点path 是根目录train/val/test 指向 images 下的子目录这是相对 path 的写法YOLOv8 会自动在 images 同级的 labels 目录里找对应 txt不用单独写标签根路径。如果 labels 和 images 放反了训练日志里会出现大量 warning说在标签路径下没找到文件。names 必须从 0 开始单类也写成字典形式这个写法在新版本里最不容易出错。写完 yaml 后检查一张图的标签是否被正确配对我常用的免训练验证命令是yolo detect train modelyolov8s.pt datadataset/landslide.yaml epochs1跑一个 epoch 起不了模型但足以暴露路径错误日志会提示 train 数据集加载了多少张图、多少张带标注。如果出现 “0 labels” 之类的输出基本是 labels 目录路径不对或者 txt 文件名和 jpg 基名不一致。这个检查比直接跑完整训练省时间得多。3.3 训练参数怎么定epochs、imgsz、batch、预训练权重第一次训练把命令控制在最简yolo detect train \ modelyolov8s.pt \ datadataset/landslide.yaml \ epochs150 \ imgsz640 \ batch16 \ patience30 \ projectruns \ namelandslide_v8s参数说明epochs 对 4315 张图而言 150 轮通常够配合早停 patience30 能在验证指标不再上升时自动停下。imgsz 我建议先用 640把 1920 宽的航拍图缩放训练显存压力和速度都均衡等模型基本收敛后再用 imgsz1280 微调几十轮滑坡边界往往能更细致。batch 大小取决于显存16G 显存跑 yolov8s 在 imgsz640 下 batch16 比较稳V100 或 A100 可以提到 32但航拍图像分布差异大batch 太小会导致 BN 统计量抖动后面会专门讲。modelyolov8s.pt 默认加载 COCO 预训练权重虽然滑坡和 COCO 类别差异大但底层纹理特征迁移仍然有用建议保留不要从零训练。跑起来以后不要只盯着 loss 曲线。重点看 val 指标和验证集上的 P/R 曲线。如果训练集里很多图根本没有滑坡目标这些空图占了大半 batch模型会被带偏成“把所有图都预测成背景”。这种结构性问题不是改超参数能解决的得回到数据层面处理正是下一章的避坑重点。4. 航拍滑坡数据训练避坑记4 个最常翻车的位置4.1 现象loss 曲线震荡、mAP 卡在 0.3 上不去用 YOLOv8 默认参数训练滑坡数据常见现象是前 20 轮 loss 掉下来之后验证 mAP 在 0.3 附近反复跳怎么训都不涨。原因有两层一是航拍滑坡在整图里占比往往很小正样本像素极少默认 cls0.5 的分类损失权重对滑坡这类“小目标加少样本”的监督不足二是 YOLO 的损失函数由框损失、置信度损失和分类损失三块组成在极端类别不均衡时分类损失需要单独加大权重。我的解决方法是把 cls 提到 1.5 到 2.0同时关掉 label smoothingyolo detect train modelyolov8s.pt datadataset/landslide.yaml \ epochs200 imgsz640 batch16 cls2.0 label_smoothing0 \ projectruns namelandslide_v8s_cls2参数含义cls 是分类损失权重权重加大后梯度会更偏向“把滑坡类别认对”代价是误检可能增加但滑坡场景先保住召回更重要。label_smoothing 会把正例信号模糊化单类小目标下先关掉。如果调了仍然无效就回去统计一下训练标注里真正有目标的图有多少张写个脚本扫描所有 labels txt非空行数量如果连总量一半都不到说明空图太多了要在 batch sampler 里多采样含目标的图或者把空图挪到验证集。这是滑坡数据集常见的结构问题不是超参数能兜底的。4.2 现象train 的 BN 统计量崩掉几轮后准确率归零航拍数据的经典翻车现场训练到二三十轮loss 突然变成 nan或者验证指标整体归零日志报出一串和半精度、数据类型有关的错误。真正常见的原因有两个一是无人机影像在不同季节、不同光照下差异太大同一个 batch 里阴影区域和强光区域像素分布完全不同BatchNorm 统计量被带偏这就是常说的 YOLO 训练中 BN 崩溃二是默认学习率 0.01 对这种分布不稳定的数据集偏大BN 层的 gamma、beta 更新步长过猛。我的处理习惯是第一次训练先降学习率并拉长 warmup如果还在崩用 freeze 让主干网络先不更新yolo detect train modelyolov8s.pt datadataset/landslide.yaml \ epochs150 imgsz640 batch16 lr00.005 freeze10 \ projectruns namelandslide_v8s_freezelr0 是初始学习率YOLOv8 默认 0.01航拍数据我一般先用 0.005 起手freeze10 表示冻结前 10 层网络这些层主要是底层边缘纹理特征对滑坡检测够用冻结后 BN 统计只算后半段稳定性明显改善。还有一个隐蔽来源如果 imgsz 设置过大某些推理预处理会把坐标溢出边界导致验证阶段出现半精度数据错。遇到崩溃先回到 imgsz640 跑一轮确认能收敛再加大分辨率。4.3 现象zip 解压到一半报 CRC 错误或解压出来一串乱码标题写的是 zip 压缩包而 4315 张图加对应标注文件会让包体积很大解压环节出问题很常见。Windows 自带 zip 工具对大文件、中文文件名、长路径的处理一直不算稳常见现象是解压到一半报“无法完成操作”或者解压出来文件名乱成一团。第一步是换工具7-Zip 或 Bandizip 能报出具体是哪个文件 CRC 失败判断是压缩时损坏还是归档不完整第二步处理乱码这多半是压缩包用了 GBK 编码而当前系统按 UTF-8 解Linux 下可以用 unzip 的编码参数重解一次unzip -O GBK landslide.zip -d landslide_voc这里还有一个常见技术词叫“zip 伪加密”文件本身没加密但压缩包头部的 general purpose bit flag 被置位解压工具弹出要求输入密码。识别方法是用 7-Zip 打开后能预览文件名但一解压就要密码。如果是从技术社区下载的资源先确认来源是否可靠不排除有人故意给 zip 伪加密包引流正规数据集出现伪加密的概率很低真遇到就回到原始出处找正确版本不建议花时间去改文件头绕过密码。数据解出来之后建议做一次全量文件数核对。VOC 格式应该有 4315 张 jpg 对应 4315 个 xmlYOLO 格式应该 images 和 labels 成对。数量对不上的时候基本可以确定包存在损坏或目录被裁剪这时候再怎么调训练参数都白搭。4.4 现象训练一开始就报图像损坏或标签配对失败这是格式转换阶段埋下的坑常见于自己把 VOC 转 YOLO 后直接训练。报错通常长这样“All images are corrupt”或者“train: 0 labels found in xxx”。原因依次排查三处一是 txt 写到了和 images 完全不同的根目录YOLO 要求 labels 和 images 同名同路径images 和 labels 是固定配合关系二是图片文件名里有空格或者前后缀不一致VOC 的 filename 写的是 IMG_1024但实际文件名可能是 IMG 1024训练脚本按 txt 找图自然找不到三是转换时坐标出现越界值比如 xmax 比图像宽度还大归一化后宽超过 1模型加载时索性丢弃该框。我的习惯是转换完立刻做全量校验检查每个 txt 的六个值是否都在合理区间import os label_root dataset/yolo/labels for split in [train, val, test]: split_dir os.path.join(label_root, split) for fn in os.listdir(split_dir): if not fn.endswith(.txt): continue with open(os.path.join(split_dir, fn)) as f: for line in f: parts line.split() if len(parts) ! 5: print(f{fn} 列数不对: {line.strip()}) continue cid, xc, yc, w, h parts vals [float(xc), float(yc), float(w), float(h)] if any(v 0 or v 1 for v in vals): print(f{fn} 坐标越界: {line.strip()})检查逻辑很简单YOLO 标签的五个字段里class_id 是整数其余四个都必须在 0 到 1 之间超过 1 或者小于 0 的行就是脏标签。打印出具体文件路径后回到对应 XML 检查原坐标多半是 bndbox 里写了下标越界的值。处理完再跑训练日志里关于标签的报错基本就会消失。5. 验证不只看 mAP混淆矩阵与置信度门限应该这样调5.1 混淆矩阵里漏检 vs 误检怎么读以及总和不为 1 的问题训练结束后runs/landslide_v8s/ 目录下会生成 confusion_matrix.png这是判断检测器能不能用的第一张图。矩阵里行是真值、列是预测对单类数据核心看左上角区域真值 landslide 被正确预测成 landslide 的占比越高越好真值 landslide 被预测成 background 的格子代表漏检真值 background 被预测成 landslide 代表误检。航拍滑坡场景里漏检比误检更危险。漏掉一个滑坡意味着安全风险误检还能靠人工复核过滤。所以读矩阵的姿势应该是优先看漏检那一格如果真值 landslide 这一行里落在 background 的占比超过 20%说明模型把不少滑坡当成了背景得回头调召回如果 background 被预测成 landslide 的比例高说明模型对裸土、阴影过于敏感再考虑提置信度门限或者加负样本。不少人第一次用 YOLOv8 会问混淆矩阵每一行和每一列加起来为什么不是 1这是正常的。矩阵有两种统计口径按真值行归一化每一行之和为 1表示每个真值类别被分到各类的比例按预测列归一化每一列之和为 1表示每个预测类别里各真值来源的占比。默认绘图有时还会把背景单独抽出来导致看起来行和不是 1。所以关键不是纠结“总和不唯一”而是搞清楚你现在看的是哪种归一化。两个口径一起看才完整mAP 代表整体水平行归一化代表漏检分布列归一化代表误检来源三者结合才能定位模型的问题。用现成的验证接口可以一次拿到全部指标from ultralytics import YOLO model YOLO(runs/landslide_v8s/weights/best.pt) metrics model.val(datadataset/landslide.yaml, conf0.25, iou0.5) print(mAP0.5:, metrics.box.map50) print(mAP0.5:0.95:, metrics.box.map) print(precision:, metrics.box.mp) print(recall:, metrics.box.mr)conf0.25 是验证时用的置信度门限调高它会提升 precision、降低 recalliou0.5 是框匹配的 IoU 标准滑坡这种边界模糊的目标用 0.5 比 0.75 更贴近工程实际。注意验证指标的 conf 和推理时的 conf 不是一回事验证指标只是算 mAP 的阈值起点部署推理时还需要单独按场景调。5.2 调置信度门限精度优先还是召回优先模型训练完推理时第一个要调的就是置信度门限。conf0.7 会少很多框但漏检也变多conf0.1 会满屏是框噪声巨大。YOLO 检测里调整置信度门限是最直接的工程手段因为不需要动模型就有两种工作模式# 高置信度模式做自动出图、成果提交误检要少 yolo predict modelruns/landslide_v8s/weights/best.pt \ sourcetest_images conf0.55 imgsz1280 save_txtTrue # 低置信度模式做风险排查、人工复核漏检要少 yolo predict modelruns/landslide_v8s/weights/best.pt \ sourceall_survey_images conf0.15 imgsz1280 save_txtTrue两条命令只差 conf 一个值。地质灾害监测我建议先用低置信度把可疑目标全部筛出来再进人工或规则过滤因为滑坡的视觉特征和裸土、积水区高度相似低置信度框虽然多但配合后处理能保住召回。做自动报告才用高置信度因为没人愿意在成果图上标一堆假滑坡。门限具体定多少不能拍脑袋。把验证集按 0.05 到 0.7 间隔扫一遍画出 precision-recall 曲线取曲线的屈曲点附近作为候选门限。YOLOv8 训练日志的 runs 目录里已经保存了 P/R 曲线图val 结束后在 curve 文件夹里能看到。别人给一个固定 conf 值不如直接看自己数据的曲线靠谱毕竟不同地区的地表纹理差异很大同一套模型换到另一个山区最优门限可能差出 0.2 都不止。6. 部署前最后一步模型压缩与检测热力图检查6.1 导出 ONNX 与 TensorRT 量化训练收敛后4315 张图的数据量撑起一个能用的滑坡检测模型但无人机侧载板和边缘盒子的算力往往有限还要过压缩这一关。最常见的路线是先导出 ONNX再做 TensorRT 的 FP16 或 INT8 量化yolo export modelruns/landslide_v8s/weights/best.pt formatonnx dynamicTrue imgsz640 trtexec --onnxbest.onnx --saveEnginebest_fp16.engine --fp16trtexec 是 TensorRT 自带的命令行工具FP16 量化对滑坡检测的精度影响很小INT8 能再压一半显存但边界框会模糊一些适合 Jetson 这类设备推 1080p 视频流。导出 ONNX 时 dynamicTrue 保留动态宽高方便部署时切分辨率如果确定只用固定 imgsz去掉 dynamic 反而能省一点显存。6.2 用热力图验证模型看到的是滑坡而不是阴影压缩之前建议先做一次可信度验证方法是用 ultralytics 的 explain 接口生成类激活热力图from ultralytics import YOLO model YOLO(runs/landslide_v8s/weights/best.pt) out model.explain() out(test_images/IMG_2048.jpg)out 是模型自带的解释函数传入一张测试图会在图上叠加模型关注的高亮区域。如果热力图集中在坡体滑面说明模型学到了滑坡形貌如果高亮区域全在树荫边界、道路边缘说明模型学的是纹理差。这类模型换一个地区之后 mAP 会明显掉这时候回去调数据比硬调超参数更值。我自己的教训是每跑完一轮把 best.pt、data.yaml、训练参数都记录成一条实验日志否则两周后对着 runs 目录里十几个 name根本分不清哪次用了 cls2.0、哪次改了冻结层。一个 zip 数据集从解压到可部署最花时间的从来不是训练而是把格式、参数、验证口径都理顺。按本文顺序走一遍新手大概两天能出第一版结果老手把这些坑提前规避一天内能从裸数据到 mAP 报告。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网