ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

RSOD数据集详解与YOLOv8遥感目标检测训练实战

RSOD数据集详解与YOLOv8遥感目标检测训练实战 简介遥感目标检测是计算机视觉的重要方向其核心挑战在于高空视角下目标尺寸小、排列密集。RSOD作为经典遥感目标检测数据集以轻量级、格式规范著称非常适合快速验证检测算法。基于VOC格式的标注可便捷转换为YOLO格式结合YOLOv8框架能快速完成训练与评估。从数据集结构解析到格式转换再到YOLOv8训练参数调优系统梳理了遥感目标检测的完整技术链路并针对小目标检测与类别不平衡问题给出SAHI切片推理等实用方案为目标检测入门及工程实践提供了可复用的参考。 做目标检测这些年跑过的数据集不少COCO、VOC、Open Images、DOTA都折腾过但如果有人问我“想快速验证一个检测器在遥感图像上的效果拿什么数据集最合适”我大概率会推荐RSOD。这话可能有点武断但我见过太多人被大型数据集预处理劝退而RSOD在整个流程上实在太友好了。它足够小下载、解压、转格式、跑训练一个下午就能走完全流程它的目标类别又都是遥感场景里的高频地物——飞机、操场、立交桥、船舶问题足够真实不是那种只适合表演的玩具数据集。这篇文章我会从RSOD数据集的背景、结构讲起再到下载、格式转换、YOLOv8训练、推理评估最后聊聊我实际操作中遇到的坑和应对思路。适合刚入门目标检测、想用遥感数据练手的朋友也适合已经在用YOLO、想了解小目标检测和遥感数据特性的人。很多人第一次接触RSOD是在论文的对比实验里但论文通常只写一句“we evaluate on RSOD dataset”很少讲清楚数据内部长什么样所以这篇文章换个角度以RSOD为样本把遥感目标检测的数据准备和训练细节一次说透。1. RSOD是什么遥感目标检测里绕不开的经典benchmark1.1 为什么遥感检测需要专属数据集遥感目标检测和普通目标检测最大的区别在于视角和尺度。普通数据集里一张图可能就一两个目标目标在画面中占很大面积遥感图像则是高空俯拍地面目标在画幅里通常很小而且排列密集。比如一个机场的遥感影像里可能有几十架飞机每一架只占几十个像素。用自然场景训练的模型迁移过来经常会漏检小目标因为模型学到的特征尺度完全不匹配。所以遥感领域必须单独准备数据集来驱动模型迭代RSOD、DOTA这些数据集就是干这个的。很多人以为目标检测的算法是通用的换个场景无非是换个数据重新训练。这句话对了一半。算法框架确实通用但数据分布决定了模型的强项和弱项。RSOD这种遥感数据第一个要教会模型的就是“从高空往下看目标可以很小、很密、角度很随意”。你拿COCO预训练模型直接往遥感图上砸效果往往惨不忍睹只有在这个场景下重新训练模型才开始真正适应遥感图像的纹理、背景和目标尺寸。1.2 RSOD的四个类别与大致规模RSOD全称是Remote Sensing Object Detection Dataset一套面向遥感图像目标检测的开源数据集。根据网上公开资料显示它由国内高校团队整理发布图像主要采集自Google Earth等遥感影像覆盖机场、港口、城区、立交桥、运动场等典型场景。类别一共四类aircraft飞机、playground操场、overpass立交桥、ship船舶。光看这四类“操场”和“立交桥”似乎不太像遥感领域的高频目标但恰恰是这两类目标尺度大、结构复杂和飞机、船舶的小尺度目标形成对照训练出来的模型能同时兼顾大小目标这比单纯全是小目标的数据集更有锻炼价值。从公开资料看各类目标实例数量大致如下类别实例数量约典型场景aircraft 飞机4000机场停机坪、跑道密集群目标playground 操场150左右学校、体育场目标大数量少overpass 立交桥170左右城市道路交叉口形状复杂ship 船舶4000港口海面分布不均匀合计大概有上千张遥感图像、接近一万个标注框。不同渠道下载的版本统计数据可能略有差异具体以你实际解压出来的压缩包为准。总之这是一个非常典型的小规模数据集单张图像几百KB到几MB一张普通显卡几分钟就能跑完一个epoch。训练成本低这是它作为demo和基准测试数据集的最大优势。1.3 RSOD和DOTA、DIOR、NWPU VHR-10的差异可能有人会问既然有DOTA这种大而全的遥感数据集为什么还要用RSODDOTA确实更大、类别更多、带旋转框但带来的问题是下载慢、预处理复杂、对显存要求高。对刚开始做遥感目标检测的人来说一下子上DOTA很容易被数据预处理淹没。NWPU VHR-10和DIOR也是经典遥感数据集类别更多但相对RSOD来说标注格式和文件组织方式没有这么“轻量”。RSOD的定位更像一块敲门砖数据量小、标注规范、格式是大家最熟悉的VOC格式几乎不用花太多时间在数据整理上。你可以在它上面快速跑通一个检测流程、验证算法方向的可行性然后再切换到DOTA、DIOR这种大规模数据集做正式实验。我自己有个习惯新模型先用RSOD检测一通如果模型连RSOD都做不好那拿到DOTA上大概率也不会好到哪去。2. 数据集细节那些官方文档不会细讲的坑2.1 图像尺寸不统一输入resize要谨慎RSOD原始图像尺寸很不统一有的只有几百像素有的到几千像素。用YOLO训练时网络会固定输入尺寸比如640x640。直接把这批图resize到640很多小目标信息会被压缩掉。举个例子一张2000x1500的机场图里飞机宽度可能只有40个像素缩放5倍后变成8个像素模型能看到的特征就非常模糊。所以训练之前建议先做一次数据分析统计训练集图像的分辨率分布、目标宽高比、目标占全图的比例。如果发现目标普遍小于32x32就要考虑提高输入分辨率或者在推理时用SAHI这种切片推理方案。RSOD最大的价值之一就是让你在训练早期就意识到这个问题的存在而不是等到业务数据上出了大问题才回头补课。2.2 类别不平衡操场和立交桥很容易被“无视”飞机和船舶各有4000多实例操场和立交桥只有150、170左右这个悬殊程度在目标检测数据集里算是比较极端的。模型训练的时候损失函数会被实例数量多的类别主导操场、立交桥的AP往往低得可怜。这不是模型有问题而是数据分布决定的。处理办法通常有几个方向图像级重采样在数据加载时提高含操场、立交桥图像的采样权重让每个epoch里少样本类被看到更多次复制粘贴增强把少样本类目标从原图裁剪出来随机粘贴到其他图像上并同步生成标注这个策略在遥感检测里效果不错类别平衡损失给少样本类更高的loss权重。这些都属于锦上添花。我的建议是先不调任何技巧直接训练一个baseline看看各类别AP到底差多少再来决定要不要处理。别一上来就上复杂方案否则你根本不知道哪个环节真正起了作用。2.3 标签质量训练前一定要做一次体检RSOD整体标注质量算是不错的但公开数据集传到手里谁也不能保证中间没被改过。我接过一次网上下载的RSOD解压后发现有几张图片和XML文件名对不上还有个别XML里类名大小写混用“Ship”和“ship”甚至有一些标注框坐标超出图像尺寸。这种问题不提前排查训练过程就会出现莫名其妙的报错loss曲线也会乱跳。我建议先写一个校验脚本检查下面几项图片文件与XML文件是否一一对应XML里类别名是否都在预期列表内bndbox坐标是否在图片尺寸范围内是否出现宽度或高度为0的无效框。这里给出一个简单的Python校验脚本可以直接根据自己的目录结构改import os import xml.etree.ElementTree as ET from PIL import Image annot_path annotations img_path images expected_classes {aircraft, playground, overpass, ship} for xml_file in os.listdir(annot_path): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(annot_path, xml_file)) root tree.getroot() filename root.findtext(filename) img_file os.path.join(img_path, filename) if not os.path.exists(img_file): print(f[MISSING IMAGE] {filename}) continue with Image.open(img_file) as img: w, h img.size for obj in root.iter(object): name obj.findtext(name) if name not in expected_classes: print(f[BAD CLASS] {xml_file}: {name}) box obj.find(bndbox) xmin int(box.findtext(xmin)) ymin int(box.findtext(ymin)) xmax int(box.findtext(xmax)) ymax int(box.findtext(ymax)) if xmin 0 or ymin 0 or xmax w or ymax h: print(f[BAD BOX] {xml_file}: {name} ({xmin},{ymin},{xmax},{ymax})) print(check done)这段代码虽然简单但能把最典型的三个问题筛查出来。推荐训练前跑一遍几秒钟的成本能省掉后面排查问题的一天时间。2.4 目标密集且多尺度这正好是遥感检测核心难点RSOD里飞机密集场景特别典型停机坪上十几架甚至几十架飞机挨着停有的还有角度倾斜船舶场景里港口区域船挨着船边界容易重合。这些特点让小目标检测、NMS阈值选择、标注框匹配都比自然图像麻烦不少。换个角度想这也是RSOD适合练手的原因——它在某种程度上反复提醒你遥感检测不是“缩小的自然图像检测”它有自己的独立问题域。模型在这个数据集上学到的不只是四个类别还有密集排列下的区分能力。3. 下载与格式转换从VOC到YOLO3.1 下载渠道和注意事项RSOD数据集在网络上公开渠道不少。GitHub上有不少仓库做过镜像Kaggle也能找到打包好的版本国内一些平台也有直接分享的下载链接搜“RSOD Dataset Download”就能看到。由于链接变化比较快这里不写死某个具体地址只提醒两点优先选择包含原始图像和XML标注的完整版本下载后先核对文件结构确认图像和标注都齐全。如果在Kaggle下载你通常会看到别人整理好的CSV格式标注虽然方便但字段名可能各不相同我建议还是以VOC XML为准自己写脚本转格式最稳。别嫌麻烦格式转换这步自己亲手做一遍后面遇到任何标注问题你都能更快定位。3.2 目录结构怎么组织下载下来的原始包经常是按类别拆开的比如“aircraft”文件夹里既有图也有XML“ship”文件夹里也是。直接这样训练也可以但建议把四类合并到同一套目录下后面管理起来更省心RSOD/ ├── images/ │ ├── 001.jpg │ ├── 002.jpg │ └── ... ├── annotations/ │ ├── 001.xml │ ├── 002.xml │ └── ...如果你的压缩包是每个类别一个子目录可以用一个简单的脚本把所有jpg和xml复制到同一个目录重名时加上类别前缀避免覆盖。处理完之后记得再跑一遍前面的校验脚本确认文件一一对应。3.3 VOC转YOLO格式的完整脚本YOLO训练要求每个图像对应一个txt标注文件每行基本格式是class cx cy w h其中cx、cy是归一化后的中心点坐标w、h是归一化后的宽高。RSOD的XML是标准VOC格式转换逻辑很直接import os import xml.etree.ElementTree as ET class_names [aircraft, playground, overpass, ship] class2idx {name: i for i, name in enumerate(class_names)} annot_dir annotations label_dir labels os.makedirs(label_dir, exist_okTrue) for xml_file in os.listdir(annot_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(annot_dir, xml_file)) root tree.getroot() img_w int(root.findtext(size/width)) img_h int(root.findtext(size/height)) lines [] for obj in root.iter(object): name obj.findtext(name) if name not in class2idx: print(fskip unknown class: {name}) continue cls_id class2idx[name] box obj.find(bndbox) xmin float(box.findtext(xmin)) ymin float(box.findtext(ymin)) xmax float(box.findtext(xmax)) ymax float(box.findtext(ymax)) cx (xmin xmax) / 2 / img_w cy (ymin ymax) / 2 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) txt_file os.path.join(label_dir, xml_file.replace(.xml, .txt)) with open(txt_file, w) as f: f.write(\n.join(lines))这里有三个细节要注意。第一类名统一用小写映射表里也一律小写避免“Ship”和“ship”这种大小写问题。第二有些XML里没有size字段或字段缺失那就用PIL读取图片宽高来兜底。第三cx、cy、w、h理论上应该在0到1之间个别越界框可以通过clip强制夹紧但最好还是人工看一眼因为越界往往意味着原始标注有问题。3.4 训练集/验证集划分的逻辑分割建议按8:1:1划分为train/val/test但不要单纯按文件名排序切。RSOD里飞机、船舶的图片多操场、立交桥的图片少简单切分很可能让验证集里压根没有操场和立交桥。更合理的做法是按图片是否包含少样本类来分层抽样保证验证集和训练集的类别分布大致一致。实际操作中可以把全部图片路径按“是否包含操场或立交桥”分成两个子集合两个子集合各自按比例切分再合并成最终的train/val。这样虽然不能保证完全均衡但至少不会出现少样本类完全没进验证集的极端情况。分层切分代码不复杂用sklearn的train_test_split再带上stratify参数就能做。4. YOLOv8训练RSOD数据集的完整流程命令、参数与评估4.1 安装与数据准备推荐Python 3.9以上用conda建一个干净环境避免和系统Python环境互相污染conda create -n rsod python3.10 conda activate rsod pip install ultralytics pip install sahiYOLOv8用Ultralytics库统一管理训练、验证、推理都方便。接下来把图片放到images/train、images/val把txt标注放到对应labels/train、labels/val注意目录结构和名字不能错。Ultralytics默认会自动去找与图片同名的label文件如果找不到训练时会报“unable to find label”之类的错经验就是目录名千万别自己发明。建议目录结构RSOD/ ├── data.yaml ├── images/ │ ├── train/ │ │ ├── 001.jpg │ │ └── ... │ └── val/ │ ├── 002.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── 001.txt │ │ └── ... │ └── val/ │ ├── 002.txt │ └── ...4.2 data.yaml配置Ultralytics训练时需要一份数据集配置文件内容很简单path: /你的绝对路径/RSOD train: images/train val: images/val names: 0: aircraft 1: playground 2: overpass 3: ship注意path最好写绝对路径。新手最容易在这里翻车写了相对路径后训练时提示图片路径找不到实际上就是运行目录和data.yaml里的路径对不上。naval还有一个坑val列表里不要写测试集测试集留到最终评估时单独指定或用脚本计算。4.3 训练参数怎么选一条基线训练命令yolo detect train dataRSOD/data.yaml modelyolov8s.pt epochs100 imgsz640 batch16 device0几个参数的考虑modelyolov8s.pt用COCO预训练的YOLOv8s作为初始权重。虽然COCO类别和RSOD完全不同但预训练权重提供的是底层通用特征迁移效果远好于从零训练。RSOD这种小数据集从零训练很容易过拟合。imgsz640比较均衡的输入尺寸。跑通后再试1280小目标AP一般会明显提升但显存占用和训练时间也会明显增加。我在RSOD上实测过1280输入下飞机类AP提升明显尤其对小目标。batch16根据显存调整普通6GB显存跑YOLOv8s没问题显存小就降到8或4。epochs100小数据集上100轮足够再长容易过拟合训练完可以看曲线决定是否早停。4.4 看评估指标而不是只看mAP训练结束后执行yolo detect val modelruns/detect/train/weights/best.pt dataRSOD/data.yaml会输出mAP50、mAP50-95以及每个类别的AP。这时候重点看类别AP表格。如果aircraft、ship的AP很高但playground、overpass的AP很低那就是类别不平衡问题暴露了。mAP50被数量多的类拉高代表不了真实水平。我实际跑下来的体验是YOLOv8s在imgsz640下RSOD的mAP50通常能到0.75到0.85不同版本标签数据会有浮动但playground和overpass的AP可能只有0.3到0.5。想提升这两类就要针对性做数据增强或者重采样。别看到mAP50有0.8就觉得万事大吉分开看才知道模型短板在哪。4.5 推理可视化训练完可以做一次推理看看效果yolo detect predict modelruns/detect/train/weights/best.pt sourcetest_images/ saveTrue可视化结果默认保存到runs/detect/predict。如果发现大量漏检先尝试把置信度阈值调低默认0.25在密集小目标场景下可能偏保守如果调阈值还是不行就需要考虑更大输入尺寸或者切片推理了。另外推理时可以加一句show_labelsTrue看类别标签是否有明显错乱一些类别定义问题在可视化时一眼就能看出来。5. 遥感检测踩坑实录小目标、类别不平衡与数据校验5.1 小目标为什么那么难RSOD里飞机和船舶很多都是小目标。YOLOv8输出特征图分三层P3/P4/P5小目标主要靠P3这种高分辨率特征图来检测但即使P3层stride为8原图上一个8x8区域在特征图上也只占1个像素。对于只有十几个像素的小飞机特征基本是模糊的。增大输入尺寸是最直接的缓解手段另一个思路是SAHI切片推理把大图切块分别检测再合并结果。5.2 SAHI切片推理的实际效果SAHISlicing Aided Hyper Inference在做超清遥感图像推理时非常有用。用法不复杂Ultralytics模型可以被SAHI直接加载from sahi import AutoDetectionModel from sahi.predict import get_sliced_prediction detection_model AutoDetectionModel.from_pretrained( model_typeultralytics, model_pathruns/detect/train/weights/best.pt, confidence_threshold0.25, image_size640, ) result get_sliced_prediction( imagetest_images/airport.jpg, detection_modeldetection_model, slice_height512, slice_width512, overlap_height_ratio0.2, overlap_width_ratio0.2, ) result.export_visuals(export_diroutput/)我实测下来的感受是在目标密集区域切片推理的召回率比整图推理高不少代价是推理时间增加。简单任务整图推理就够了但面对几千像素的大图、或者小目标密集成群的场景SAHI的提升相当明显。切片重叠率建议设在0.2左右太低会导致切缝处目标被斩断太高浪费算力。5.3 类别不平衡的正确打开方式前面一直提到操场和立交桥AP低那你到底该怎么处理如果目的是做本文还有配套的精品资源点击获取
返回列表