滑坡检测数据集实战:823张YOLO+VOC双格式微调指南
发布时间:2026/10/11 13:06:02 锦皓数字建站

简介本资源为面向计算机视觉与地质灾害识别方向的目标检测数据集聚焦山体滑坡单类别识别任务适合从事遥感影像分析、灾害监测预警及深度学习模型训练的研究者与开发者使用。压缩包共约2000个文件整体63.01MB包含823张jpg图片、823个xml标注文件与825个txt标签文件分别对应图像数据、VOC格式标注与YOLO格式标签可同时满足两种主流检测框架的读取需求。数据集仅设landslide一个类别共标注950个矩形框图像分辨率清晰未做数据增强标注准确合理。目前已有484人学习下载可为滑坡目标检测模型的训练、验证与对比实验提供直接可用的数据基础帮助读者省去自行采集与标注的成本快速搭建实验流程并评估算法效果。1. 滑坡检测数据集怎么选823 张 YOLOVOC 双格式的实战价值做地质灾害监测的兄弟多半遇到过这个场景项目催着要一个滑坡识别 demo模型结构选好了、训练脚本也跑通了结果卡在数据上——公开的遥感数据集要么是建筑物变化检测要么是道路提取真正标注好的滑坡样本少得可怜。这份 823 张的滑坡目标检测数据集恰好补的就是这个缺口。它同时提供 YOLO 和 VOC 两套标注格式意味着你拿到手不用先写转换脚本YOLOv5/v8/v11 系列直接吃 txtFaster R-CNN、SSD 这类走 VOC 路线的框架直接读 xml。823 张听起来不算大但对滑坡这种正负样本极不均衡、标注成本又高的场景来说够你把一个预训练模型微调到能用的程度。适合谁做遥感目标检测的算法同学、搞地质灾害预警的工程团队以及想拿真实场景练手 YOLO 微调流程的入门者。下面我按「数据长什么样 → 怎么接进训练 → 坑在哪」的顺序拆一遍。2. 拆开压缩包YOLO 与 VOC 两套标注到底怎么对应2.1 目录结构与标注格式的映射关系拿到压缩包先别急着解压到训练目录我一般会先在一个临时路径展开把结构看清楚。这类双格式数据集常见的组织方式有两种一种是 images/ 和 labels/ 平铺YOLO 的 txt 和 VOC 的 xml 分开放另一种是按 train/val 分好子集每个子集里再分 images 和 labels。不管哪种核心是搞清「一张图对应哪几个标注文件」。YOLO 格式的标注是每张图一个同名 .txt每行一个目标格式为class_id x_center y_center width height后四个值都是归一化到 0~1 的相对坐标。VOC 格式则是每张图一个同名 .xml里面用bndbox记录xmin ymin xmax ymax的绝对像素坐标类别名写在name里。这两套描述的是同一批标注框只是坐标系和存储方式不同所以理论上可以互相转换但转换过程有精度损失的风险这也是为什么这份数据直接给两套格式更省心。先跑一段脚本把结构摸清楚别靠肉眼数文件import os from pathlib import Path root Path(./landslide_dataset) # 改成你解压后的实际路径 for sub in sorted(root.rglob(*)): if sub.is_dir(): files list(sub.glob(*)) exts {} for f in files: exts[f.suffix] exts.get(f.suffix, 0) 1 if exts: print(f{sub.relative_to(root)}: {exts})这段脚本递归遍历目录按扩展名统计每层文件夹里的文件数量。跑完你就能一眼看出 images 和 labels 是否一一对应、txt 和 xml 数量是否一致。如果某个子目录里 jpg 有 823 个而 txt 只有 800 个那说明有 23 张图漏标或者标注文件命名对不上这种问题不提前发现训练时要么报错要么静默跳过属于典型的血泪经验。2.2 类别定义与标签映射滑坡检测通常只有一个类别但有些数据集会把「滑坡」细分成「浅层滑坡」「深层滑坡」「滑坡堆积体」等。这份数据具体几个类得看 YOLO 的classes.txt或者 VOC xml 里出现过的name值。我一般会统计一遍所有出现过的类别名确认没有拼写不一致的情况——比如有的标landslide有的标LandslideYOLO 训练时会被当成两个类直接翻车。import xml.etree.ElementTree as ET from collections import Counter xml_dir Path(./landslide_dataset/VOC/Annotations) names Counter() for xml_file in xml_dir.glob(*.xml): tree ET.parse(xml_file) for obj in tree.findall(object): names[obj.find(name).text.strip()] 1 print(类别分布:, dict(names))这段代码遍历所有 VOC 标注统计每个类别名出现的次数。如果输出里出现两个高度相似但大小写或空格不同的名字就得统一。YOLO 那边同理检查classes.txt的行数和顺序确保class_id和类别名的对应关系没错位——错位是新手最容易踩的坑模型训出来框的位置对但类别全乱。2.3 图像尺寸与标注框合法性检查滑坡遥感图的尺寸往往不统一有的 512×512有的 1024×1024甚至更大。YOLO 训练时会统一 resize 到网络输入尺寸比如 640但 VOC 的绝对坐标在 resize 后需要同步缩放如果你自己写转换脚本这一步漏了就会导致框偏移。另外要检查有没有越界框xmin 0、xmax width、width 0这类脏数据训练时可能不报错但会拉低 mAP。from PIL import Image img_dir Path(./landslide_dataset/images) bad_boxes [] for img_file in img_dir.glob(*.jpg): w, h Image.open(img_file).size label_file Path(./landslide_dataset/labels) / (img_file.stem .txt) if not label_file.exists(): continue for line in label_file.read_text().strip().split(\n): parts line.split() if len(parts) ! 5: bad_boxes.append((img_file.name, 格式错误, line)) continue cls, xc, yc, bw, bh map(float, parts) if not (0 xc 1 and 0 yc 1 and 0 bw 1 and 0 bh 1): bad_boxes.append((img_file.name, 越界, line)) print(f异常标注 {len(bad_boxes)} 条) for b in bad_boxes[:10]: print(b)这段检查 YOLO 标注的归一化坐标是否在合法范围内。正常情况应该输出 0 条异常如果有就得回到原始标注去修。注意bw和bh不能为 0也不能大于 1否则框要么退化成一条线要么超出图像边界。这一步做完数据质量心里就有底了。3. 接进 YOLOv8 训练配置文件与微调参数怎么设3.1 生成 data.yaml 与数据集划分YOLO 系列训练靠一个data.yaml描述数据路径和类别。这份数据如果已经分好 train/val直接填路径如果没分得自己按 8:2 或 7:3 切。滑坡样本少我一般用 8:2验证集留够 160 张左右才能让 mAP 有统计意义。划分时注意同一区域拍的图别同时进训练和验证否则验证集精度虚高上线就露馅。import random import shutil random.seed(42) img_dir Path(./landslide_dataset/images) train_img Path(./dataset/images/train) val_img Path(./dataset/images/val) train_lbl Path(./dataset/labels/train) val_lbl Path(./dataset/labels/val) for d in [train_img, val_img, train_lbl, val_lbl]: d.mkdir(parentsTrue, exist_okTrue) imgs sorted(img_dir.glob(*.jpg)) random.shuffle(imgs) split int(len(imgs) * 0.8) for i, img in enumerate(imgs): dst_img (train_img if i split else val_img) / img.name dst_lbl (train_lbl if i split else val_lbl) / (img.stem .txt) shutil.copy(img, dst_img) src_lbl Path(./landslide_dataset/labels) / (img.stem .txt) if src_lbl.exists(): shutil.copy(src_lbl, dst_lbl)这段按固定随机种子划分数据集保证可复现。seed(42)是习惯换成别的也行但别不设种子否则每次跑结果不一样调参时根本分不清是改动生效还是随机波动。复制而不是移动保留原始数据改错了还能重来。对应的data.yamlpath: ./dataset train: images/train val: images/val nc: 1 names: [landslide]nc是类别数滑坡单类就写 1。names的顺序必须和 YOLO 标注里class_id的数值对应0 对应landslide。如果数据里有多个类按 id 顺序列全。3.2 微调参数从预训练权重出发的关键设置823 张图从头训基本没戏必须用 COCO 预训练权重微调。YOLOv8 的命令行方式最省事yolo detect train \ data./data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.001 \ lrf0.01 \ patience20 \ project./runs \ namelandslide_v8n逐项说下为什么这么设。modelyolov8n.pt选 nano 版是因为数据量小大模型容易过拟合nano 参数量少、训练快先跑通再考虑换 s 或 m。epochs100配合patience20意思是 20 轮验证指标不涨就早停避免无效训练。lr00.001是初始学习率微调场景比从头训的 0.01 小一个量级防止把预训练学到的特征冲掉。lrf0.01是最终学习率相对初始值的比例余弦退火到 1e-5 左右收尾。batch16在 8G 显存上跑 640 分辨率基本稳显存不够就降到 8 并同步把lr0调小。训练启动后重点盯三个指标box_loss是否稳定下降、mAP50是否在涨、val/box_loss和train/box_loss的差距。如果训练 loss 降但验证 loss 抬头就是过拟合要么加数据增强要么减 epoch。滑坡目标通常尺度差异大建议在配置里开mosaic1.0和scale0.5增强对小目标的鲁棒性。3.3 用 VOC 格式走 Faster R-CNN 的接法如果团队用的是 PyTorch 的 torchvision 检测框架VOC 格式更顺手。核心是继承Dataset类把 xml 解析成target字典import torch from torchvision.models.detection import fasterrcnn_resnet50_fpn from torchvision.transforms import functional as F from PIL import Image import xml.etree.ElementTree as ET class LandslideVOC(torch.utils.data.Dataset): def __init__(self, root, transformsNone): self.root Path(root) self.imgs sorted((self.root / JPEGImages).glob(*.jpg)) self.transforms transforms def __getitem__(self, idx): img Image.open(self.imgs[idx]).convert(RGB) xml self.root / Annotations / (self.imgs[idx].stem .xml) tree ET.parse(xml) boxes, labels [], [] for obj in tree.findall(object): b obj.find(bndbox) boxes.append([ float(b.find(xmin).text), float(b.find(ymin).text), float(b.find(xmax).text), float(b.find(ymax).text) ]) labels.append(1) # 滑坡单类背景为 0 target { boxes: torch.tensor(boxes, dtypetorch.float32), labels: torch.tensor(labels, dtypetorch.int64) } if self.transforms: img self.transforms(img) return F.to_tensor(img), target def __len__(self): return len(self.imgs)关键点是labels从 1 开始0 留给背景这是 torchvision 检测模型的约定。boxes用绝对坐标模型内部会自己处理。VOC 的 xml 里如果有difficult标记为 1 的目标建议跳过不加入训练这类通常是遮挡严重或难以辨认的样本硬训反而干扰。4. 避坑与排查滑坡数据集训练中最容易翻车的五件事4.1 现象训练 loss 正常但 mAP 一直是 0原因多半是类别 id 错位。YOLO 的class_id从 0 开始如果你的data.yaml里names写了[landslide]但标注文件里写的是 1模型学到的就是「id 1 是滑坡」而验证时按 id 0 去匹配自然全错。解决跑一遍统计脚本确认标注里出现的所有class_id值和names的索引对齐。4.2 现象验证集 mAP 很高实际推理框全偏这是数据划分泄漏的典型症状。同一座山的连续帧被分到了训练和验证两边模型记住了背景纹理而不是滑坡特征。解决划分前按图像来源或地理位置分组同组只进一边。如果数据没有来源信息至少用感知哈希去重把高度相似的图归到同一侧。4.3 现象训练到一半报 CUDA out of memory滑坡遥感图分辨率高640 输入下 batch16 可能撑爆显存。解决先把batch降到 8同时把lr0按比例降到 0.0005或者开ampTrue混合精度显存能省三成左右。别硬扛着不改OOM 中断后恢复训练很麻烦。4.4 现象小滑坡目标漏检严重823 张里如果小目标占比高640 输入下小滑坡可能只剩几个像素。解决把imgsz提到 1024但 batch 要同步降或者在data.yaml同级开overlap_mask和mosaic增强。另一个思路是切片推理把大图切成 512 小块分别检测再合并工程上常用。4.5 现象VOC 转 YOLO 后框位置整体偏移原因是转换时用了图像原始尺寸归一化但训练时 resize 到了 640两者不一致。解决转换脚本里归一化用的宽高必须是图像实际宽高而不是网络输入尺寸。YOLO 训练时会自己按输入尺寸缩放标注你只需要保证 txt 里的坐标是相对原图的。5. 进阶技巧用 823 张撬动更好效果的三个实操手段数据量摆在这想再往上提点精度得在训练策略上做文章。第一个手段是两阶段微调先用 640 分辨率训 50 轮让模型适应滑坡特征再切到 1024 分辨率训 30 轮学习率降到 1e-4。高分辨率阶段能显著改善小目标召回代价是显存和时间但滑坡检测里小目标漏检往往比误检更致命。第二个手段是难例挖掘。第一轮训完用模型在验证集上推理把漏检和误检的图挑出来人工复核标注后加入训练集再训一轮。823 张里通常有几十张是「硬骨头」补进去后 mAP 能涨几个点。这个流程我一般写成脚本自动跑from ultralytics import YOLO model YOLO(./runs/landslide_v8n/weights/best.pt) results model.predict(source./dataset/images/val, save_txtTrue, conf0.25) # 对比预测结果和真实标注挑出漏检图 import numpy as np hard_cases [] for r in results: pred_boxes r.boxes.xyxy.cpu().numpy() if r.boxes else np.array([]) gt_path Path(./dataset/labels/val) / (Path(r.path).stem .txt) gt_count len(gt_path.read_text().strip().split(\n)) if gt_path.exists() else 0 if len(pred_boxes) gt_count: hard_cases.append(r.path) print(f疑似漏检 {len(hard_cases)} 张)这段用训练好的权重在验证集上推理统计预测框数量少于真实框数量的图这些就是漏检候选。conf0.25是置信度阈值调低能召回更多但误检也涨按场景权衡。挑出来的图人工看一遍确认是标注问题还是模型能力问题再决定是否补进训练集。第三个手段是模型集成。YOLOv8n 和 YOLOv8s 各训一个推理时用 WBF加权框融合合并结果对小目标和不规则滑坡边界的稳定性比单模型好。代价是推理速度翻倍如果部署在边缘设备上要算好帧率预算。我一般会在验证集上对比单模型和集成的 mAP涨不到 2 个点就不值得上集成工程上简单可靠比那点精度重要。从那以后我每次拿到新数据集都强制先跑一遍结构统计和标注合法性检查再动手写训练配置。这一步花十分钟能省掉后面几小时的排查。希望帮到你。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。