
简介这份资源面向计算机、电子信息工程、数学等专业的学生与算法初学者提供一套可直接投入YOLO目标检测训练的RSOD遥感检测数据集覆盖飞机、油箱、运动场和立交桥四类典型目标解决遥感场景下数据难获取、标注成本高的问题适用于课程设计、期末大作业与毕业设计。压缩包共1912个文件以976张jpg图像和936个xml标注文件为主图像用于模型输入xml按PASCAL VOC格式记录目标类别与边界框整体约308.63MB解压后可直接对接主流检测框架。目前已有579人学习下载。数据集类别明确、标注规范省去自行采集与标注的环节读者可快速搭建训练与验证流程并在此基础上调整参数、替换模型或扩充类别完成从数据加载到结果评估的完整实验。1. 遥感目标检测落地RSOD 数据集为什么值得先跑一遍拿到一个遥感目标检测任务很多人第一反应是去找 DOTA 或者 DIOR动辄几万张图、几个 G 的体量光解压和转格式就能耗掉半天。但如果你只是想快速验证一个 YOLO 训练流程能不能跑通、mAP 曲线长什么样、标注格式对不对用 RSOD 这种千张级别的数据集反而更划算。RSOD 全称 Remote Sensing Object Detection是一个面向遥感影像的目标检测数据集常见版本包含飞机、油罐、操场、立交桥四类目标图像数量在千张量级每张图配一份 PASCAL VOC 风格的 xml 标注文件。这个体量意味着你在单卡上几个小时内就能完成一轮完整训练不用排队等资源也不用担心磁盘被撑爆。标题里说的「已标注可以直接使用」核心价值就在那个 xml 上。VOC 格式的 xml 里记录了图像尺寸、目标类别和每个目标的边界框坐标YOLO 训练需要的是归一化后的 txt所以中间必然有一个格式转换环节。这个环节看起来简单但坑不少坐标越界、类别名大小写不一致、空标注文件、图像和 xml 不配对任何一个都能让你在训练启动时报出莫名其妙的错误。把这套流程走通一遍你对目标检测数据管线的理解会比看十篇教程都扎实。适合谁刚入门 YOLO 想找个真实数据集练手的、需要快速搭一个遥感检测 baseline 的、以及想搞清楚 VOC 转 YOLO 到底怎么转的从业者。2. RSOD 数据集的结构拆解与 YOLO 格式转换2.1 解压后先看什么目录结构与文件配对拿到 .rar 之后第一步不是急着写训练脚本而是把目录结构摸清楚。RSOD 常见的组织方式有两种一种是所有图像放在一个文件夹、所有 xml 放在另一个文件夹另一种是按类别或按子集分文件夹。不管哪种你都需要先确认三件事图像总数、xml 总数、以及两者是否一一对应。# 解压Linux 下需要 unrarWindows 用 7-Zip 或 WinRAR 即可 unrar x RSOD_dataset.rar ./rsod_raw/ # 统计图像和标注数量 find ./rsod_raw -name *.jpg -o -name *.png | wc -l find ./rsod_raw -name *.xml | wc -l # 检查是否有图像没有对应的 xml按文件名主干比对 comm -23 \ (find ./rsod_raw -name *.jpg -exec basename {} .jpg \; | sort) \ (find ./rsod_raw -name *.xml -exec basename {} .xml \; | sort)上面这段命令的逻辑是先分别统计图像和 xml 的数量如果两者不一致说明有缺失。第三条命令用comm做差集列出「有图像但没有 xml」的文件名主干。反过来把两个进程替换对调就能查出「有 xml 但没有图像」的情况。参数上注意basename后面的扩展名要和你实际文件一致有些 RSOD 版本图像是 png 格式不改的话差集结果全是误报。提示如果差集输出不为空先别急着删文件有可能是文件名里有空格或中文导致 basename 截取异常。用ls | head -20肉眼确认一下实际文件名格式。2.2 VOC xml 里到底存了什么解析关键字段一份典型的 RSOD xml 长这样根节点是annotation下面有filename、size含 width、height、depth、以及若干个object节点。每个object里有name表示类别bndbox里有 xmin、ymin、xmax、ymax 四个坐标。YOLO 需要的归一化坐标计算公式是x_center (xmin xmax) / 2 / widthy_center (ymin ymax) / 2 / heightw (xmax - xmin) / widthh (ymax - ymin) / height这里有个容易翻车的点有些 xml 里的坐标是浮点数有些是整数还有极少数会出现 xmin 大于 xmax 的情况标注时手滑。转换脚本里必须做一次校验把非法框过滤掉否则训练时 loss 会直接变成 NaN。import xml.etree.ElementTree as ET import os def parse_voc_xml(xml_path): tree ET.parse(xml_path) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) objects [] for obj in root.findall(object): name obj.find(name).text.strip() bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 校验坐标必须在图像范围内且 xmaxxmin, ymaxymin if xmax xmin or ymax ymin: continue xmin max(0, xmin); ymin max(0, ymin) xmax min(w, xmax); ymax min(h, ymax) objects.append((name, xmin, ymin, xmax, ymax)) return w, h, objects这段代码的关键在最后的校验逻辑先判断 xmax 是否大于 xmin不满足就跳过这个目标再把坐标裁剪到图像边界内。参数上strip()不能省有些 xml 的 name 字段前后带空格或换行不处理的话类别名会对不上。返回的 objects 列表里每个元素是 (类别名, xmin, ymin, xmax, ymax)后续转 YOLO 格式直接拿这个算就行。2.3 批量转成 YOLO txt脚本与类别映射YOLO 训练需要的标签格式是每行一个目标class_id x_center y_center width height全部归一化到 0~1。类别 id 从 0 开始需要你自己维护一个类别到 id 的映射表。RSOD 常见四类的映射可以写成CLASS_MAP { aircraft: 0, oiltank: 1, playground: 2, overpass: 3 } def voc_to_yolo(xml_path, out_txt_path, class_map): w, h, objects parse_voc_xml(xml_path) lines [] for name, xmin, ymin, xmax, ymax in objects: if name not in class_map: continue # 遇到未定义类别直接跳过避免训练时报错 cid class_map[name] xc (xmin xmax) / 2.0 / w yc (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{cid} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}) with open(out_txt_path, w) as f: f.write(\n.join(lines))逻辑说明先调用上一节的解析函数拿到宽高和目标列表然后逐个目标做归一化计算。class_map里没有的类别直接跳过这是为了防止 xml 里出现拼写变体比如 oil tank 带空格导致训练中断。归一化结果保留 6 位小数足够用YOLO 官方也是这个精度。输出路径建议和图像放在同一目录、同名不同扩展名这样 YOLO 的 dataset 配置里可以直接用 images 和 labels 两个平行目录。批量执行的时候遍历所有 xml 文件调用这个函数即可。转换完成后随机抽 5 个 txt 打开看看确认每行都是 5 个数值、没有空行、没有负数。这一步花两分钟能省掉后面半小时的 debug。3. YOLO 训练配置从 data.yaml 到第一个 baseline3.1 data.yaml 怎么写路径、类别数与名称YOLO 系列v5/v8/v11 都类似需要一个 yaml 文件告诉训练器去哪里找图像、去哪里找标签、有几个类别、类别名是什么。RSOD 四类的话最小配置如下path: /home/user/rsod_yolo train: images/train val: images/val nc: 4 names: 0: aircraft 1: oiltank 2: playground 3: overpass参数说明path是数据集根目录train和val是相对于 path 的子路径。nc是类别数必须和 names 里的条目数一致写错了训练启动时会直接报错。names 的 key 从 0 开始顺序要和转换脚本里的 CLASS_MAP 完全对应否则模型学到的类别会错位。常见做法是先把所有图像按 8:2 划分到 train 和 val 两个目录标签 txt 跟着图像走放在 labels/train 和 labels/val 下。注意如果你的图像和标签不在平行目录YOLO 会找不到标签。标准做法是 images/train/xxx.jpg 对应 labels/train/xxx.txt文件名主干必须一致。3.2 训练命令与关键参数epochs、imgsz、batch环境配好之后ultralytics 包 pip install 即可一条命令就能启动训练yolo detect train \ data/home/user/rsod_yolo/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ projectrsod_runs \ namebaseline_v8n参数逐个说model用 yolov8n 这种 nano 版本RSOD 只有千张图大模型容易过拟合nano 或 small 足够。epochs100是起步值实际看 mAP 曲线如果 60 轮之后还在涨可以加到 150。imgsz640是 YOLO 的默认输入尺寸遥感图像里目标通常偏小如果发现小目标漏检严重可以提到 1024但显存占用会翻倍。batch16在 8G 显存上跑 640 分辨率基本安全显存不够就降到 8。device0指定第一块 GPUCPU 训练的话去掉这个参数但速度会慢很多。训练启动后重点看三个输出box_loss 是否稳定下降、mAP50 是否在涨、有没有出现 nan。如果 loss 在前几轮就变成 nan大概率是标签里有非法值坐标越界或负数回到第 2 章的校验逻辑排查。3.3 训练结果怎么看mAP、召回率与混淆矩阵训练结束后runs 目录下会生成 results.csv 和若干曲线图。重点看这几个指标mAP50 表示 IoU 阈值 0.5 时的平均精度RSOD 四类在 yolov8n 上跑 100 轮mAP50 通常能到 0.85 以上mAP50-95 更严格一般在 0.6 左右。如果某一类的 AP 明显低于其他类比如 overpass 只有 0.5 而 aircraft 有 0.95说明这一类样本太少或者标注质量有问题。混淆矩阵能看出类别之间的误判情况。遥感图像里油罐和操场都是圆形或椭圆形如果这两类互相误判严重可以考虑在数据增强里加一些旋转和缩放。召回率低说明漏检多查一下是不是小目标居多适当提高 imgsz 或者用 mosaic 增强。这些分析不用一次做完先跑通 baseline再针对弱项调。4. 遥感场景下的避坑与排查五个血泪教训4.1 坑一xml 里的类别名带空格或大小写不一致现象转换脚本跑完训练时发现某一类目标数为 0或者报 KeyError。原因RSOD 不同来源的 xml 里类别名可能写成 Aircraft、aircraft、oil tank、oiltank 混着来。转换脚本里 CLASS_MAP 只认一种写法对不上的直接被跳过。解决在解析函数里对 name 做统一处理比如name.lower().replace( , )然后 CLASS_MAP 也用同样的规范化 key。或者先跑一遍统计脚本把所有出现过的 name 值打印出来手动确认映射关系。4.2 坑二图像和 xml 文件名主干不一致现象转换完成后labels 目录里文件数比 images 少训练时 YOLO 警告 No labels found。原因有些 RSOD 版本图像是0001.jpgxml 是0001.xml这没问题但有些是P0001.jpg配0001.xml前缀不一致。还有的 xml 里filename字段和实际文件名不同。解决不要依赖 xml 内部的 filename 字段直接用 xml 文件本身的主干名去匹配图像。写一个配对脚本以 xml 主干为基准去 images 目录找同名图像找不到的记录下来人工处理。4.3 坑三坐标越界导致 loss 变 NaN现象训练前几轮 loss 正常下降突然变成 nan之后再也降不下来。原因xml 里有 xmax 大于图像宽度、或者 xmin 为负数的标注。归一化之后坐标超出 0~1 范围YOLO 的损失函数计算出问题。解决在转换脚本里强制裁剪xmin max(0, xmin)、xmax min(w, xmax)同时过滤掉裁剪后宽高小于 1 像素的框。转换完成后用脚本扫一遍所有 txt确认没有负数、没有大于 1 的值。4.4 坑四验证集划分不合理导致 mAP 虚高现象训练集 mAP 0.95验证集 mAP 也有 0.93但拿新图测试效果很差。原因划分时没有打乱或者同一场景的图像同时出现在训练集和验证集里。遥感图像同一区域拍的多个切片高度相似如果随机划分不彻底验证集里全是训练集见过的场景。解决按图像来源或地理区域划分同一区域的图要么全在训练集、要么全在验证集。如果数据里没有区域信息至少用随机种子打乱后再划分不要按文件名顺序切。4.5 坑五imgsz 设太大导致显存溢出现象训练启动后报 CUDA out of memory或者跑到一半进程被 kill。原因遥感图像分辨率普遍偏高原图可能 1000x1000 以上imgsz 设成 1024 或 1280 时batch 没相应调小。解决显存不够时优先降 batch比如 imgsz1024 时 batch 降到 4 或 8。如果还是不够用梯度累积模拟大 batch。另外可以在 data.yaml 里加rect: True让 YOLO 按长边缩放减少 padding 浪费。5. 把 RSOD 用透从 baseline 到可复现的调优习惯跑通第一个 baseline 只是开始RSOD 这种千张级数据集最大的价值是让你能快速做对照实验。我一般会固定一个习惯每次改一个变量跑完记录 mAP50 和 mAP50-95攒够五六组再回头看哪个改动真正有效。比如下面这组对照是我在 RSOD 上实际跑过的配置差异实验模型imgszbatch增强策略mAP50Ayolov8n64016默认0.86Byolov8s64016默认0.89Cyolov8n10248默认0.91Dyolov8n10248旋转0.92从这组数据能看出对遥感小目标来说提高输入分辨率比换大模型更划算。yolov8s 只涨了 3 个点但 imgsz 从 640 提到 1024 涨了 5 个点而且 nano 模型推理更快。旋转增强又加了 1 个点因为遥感目标方向随机水平框对旋转目标本身就不太敏感但增强能让模型见到更多角度样本。验证方法上不要只看训练结束时的最终 mAP把 results.csv 里的曲线拉出来看收敛点。如果 80 轮之后曲线已经平了加到 150 轮纯属浪费电。另外记得留一份完全没参与训练和验证的测试集哪怕只有 50 张最后拿它跑一次yolo detect predict看实际输出框的位置和置信度这比任何指标都直观。有个习惯我坚持了很久每次转换完数据先写一个 10 行的检查脚本统计每个类别的目标数、每张图的平均目标数、宽高分布。如果某一类目标数不到总数的 5%训练时就要考虑加权重或者过采样。这个检查花不了几分钟但能提前发现数据不平衡的问题比训练完再回头找原因省事得多。希望帮到你。本文还有配套的精品资源点击获取