资讯动态

RSOD-Dataset遥感图像数据集:小目标检测实战与避坑指南

发布时间:2026/10/13 8:36:27 来源:尧图企业网站定制
简介RSOD-Dataset遥感图像数据集面向遥感图像处理与计算机视觉方向的研究者、开发者及学生用于目标检测、图像分类与变化检测等任务的训练与验证。资源包共487个文件以189个jpg图像、149个xml标注文件和149个txt标签文件为主压缩包约309.44MB图像与标注一一对应便于直接接入YOLO、Faster R-CNN、Mask R-CNN等检测框架也可用于SVM、随机森林或CNN的分类实验。playground子文件夹提供样例图像、预处理脚本、标注文件及使用指南帮助快速完成数据探索与模型开发。目前已有3769人学习下载适合希望系统掌握遥感图像分析流程、积累标注数据与算法实践经验的读者参考使用。1. RSOD-Dataset遥感图像数据集为什么它成了小目标检测的“试金石”如果你最近在调遥感图像的目标检测模型大概率会撞上这样一个尴尬在通用数据集上mAP刷得挺好看一换到航拍视角就集体翻车——飞机变成几个像素的白点立交桥上的车小到连标注框都糊成一团。RSOD-Dataset遥感图像数据集就是在这种场景下被反复提起的。它不是一个“大而全”的遥感数据集而是一个聚焦四类典型目标、专门用来暴露小目标检测短板的实战型数据集。我最初接触它是因为一个做机场场面监视的模拟项目模型在COCO上能跑出不错的指标但面对跑道上的飞机和油罐召回率直接掉到六成以下。RSOD-Dataset的价值就在这里它逼着你正视遥感图像里目标尺度小、背景杂、方向任意这三个硬骨头。适合谁用做遥感目标检测的算法工程师、需要快速验证小目标改进策略的研究者以及想找一个“不太大但足够难”的数据集来做消融实验的开发者。它不解决所有问题但能让你在投入大规模数据标注之前先看清自己的模型到底卡在哪。2. RSOD-Dataset的四个类别与标注格式先搞清楚你手里拿的是什么2.1 四类目标为什么选飞机、油罐、立交桥、操场RSOD-Dataset遥感图像数据集包含四类目标飞机、油罐、立交桥、操场。这个类别组合不是随便凑的它覆盖了遥感检测里几种典型的难点。飞机和油罐属于小目标且排列密集飞机在停机坪上经常是几十个挤在一起油罐则是圆形目标且灰度相近容易漏检。立交桥是典型的大尺度、结构复杂目标标注框往往横跨大半个图像对回归分支的尺度适应能力要求高。操场则是背景干扰极强的类别塑胶跑道和周围植被、建筑的颜色对比度低模型容易把操场边缘和背景混淆。我一般会建议新手先用飞机和油罐这两类做基线因为目标相对独立标注质量也最稳定等基线跑通了再把立交桥和操场加进来观察模型在多尺度上的表现差异。2.2 标注格式PASCAL VOC XML的字段含义与读取RSOD-Dataset常见的标注格式是PASCAL VOC风格的XML文件每张图对应一个XML里面记录了图像尺寸、目标类别和边界框坐标。下面是一个读取单张标注并转成内部字典的Python片段我平时用这个来快速检查标注有没有越界或宽高为负的脏数据。import xml.etree.ElementTree as ET import os def parse_rsod_annotation(xml_path): 解析RSOD-Dataset的单张VOC格式XML标注。 返回: dict, 包含图像宽高和每个目标的类别与框坐标。 tree ET.parse(xml_path) root tree.getroot() # 图像尺寸用于后续归一化或越界检查 size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) objects [] for obj in root.findall(object): cls_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) # 常见脏数据坐标越界或宽高非正 if xmax xmin or ymax ymin: print(f[警告] 非法框: {xml_path}, 类别{cls_name}) continue if xmin 0 or ymin 0 or xmax img_w or ymax img_h: print(f[警告] 越界框: {xml_path}, 类别{cls_name}) # 这里可以选择裁剪到边界也可以直接丢弃 objects.append({ class: cls_name, bbox: [xmin, ymin, xmax, ymax] }) return {width: img_w, height: img_h, objects: objects} # 使用示例 ann parse_rsod_annotation(sample.xml) print(f图像尺寸: {ann[width]}x{ann[height]}, 目标数: {len(ann[objects])})这段代码的关键在于两个检查点一是宽高非正二是坐标越界。RSOD-Dataset里偶尔会出现标注框超出图像边界的样本直接拿去训练会让回归损失异常。我一般会在数据加载阶段就把这些样本过滤掉或者把框裁剪到图像范围内具体选哪种取决于你的任务对漏检和误检的容忍度。参数上img_w和img_h一定要从XML里读不要硬编码因为RSOD-Dataset的图像尺寸并不完全统一。2.3 类别不平衡的量化先算再调在动手改模型之前先统计一下四个类别的实例数。我见过太多人一上来就加Focal Loss结果发现油罐和飞机的比例其实没那么悬殊反而把立交桥的召回压下去了。下面这个脚本可以快速输出类别分布。import glob from collections import Counter def count_instances(ann_dir): 统计RSOD-Dataset目录下所有XML的类别实例数。 counter Counter() xml_files glob.glob(os.path.join(ann_dir, *.xml)) for xml_path in xml_files: ann parse_rsod_annotation(xml_path) for obj in ann[objects]: counter[obj[class]] 1 return counter dist count_instances(./annotations) for cls, cnt in dist.most_common(): print(f{cls}: {cnt})跑完这个统计你心里就有数了。如果某一类占比超过70%再考虑重采样或损失加权如果四类相对均衡优先检查小目标的绝对数量因为小目标本身才是遥感检测的主要矛盾。3. 从零跑通RSOD-Dataset数据划分、增强与训练配置3.1 训练集/验证集划分别用随机划分遥感图像有个特点同一区域拍摄的图像往往高度相似如果随机划分验证集里很可能出现和训练集几乎一样的背景导致验证指标虚高。我一般会按图像来源或拍摄区域做分组划分确保验证集的场景和训练集有足够的差异。RSOD-Dataset虽然没有官方的分组信息但可以通过图像文件名或尺寸分布做一个粗略的聚类把相似尺寸和相似目标密度的图像分到同一组。下面是一个按目标数量分层的划分脚本尽量让训练集和验证集的类别分布接近。import random import glob from collections import defaultdict def split_dataset(ann_dir, val_ratio0.2, seed42): 按目标数量分层划分训练集和验证集。 返回: train_files, val_files random.seed(seed) xml_files glob.glob(os.path.join(ann_dir, *.xml)) # 按目标总数分桶减少划分偏差 buckets defaultdict(list) for xml_path in xml_files: ann parse_rsod_annotation(xml_path) n_obj len(ann[objects]) bucket_key min(n_obj // 5, 10) # 每5个目标一个桶最多10桶 buckets[bucket_key].append(xml_path) train_files, val_files [], [] for key, files in buckets.items(): random.shuffle(files) n_val max(1, int(len(files) * val_ratio)) val_files.extend(files[:n_val]) train_files.extend(files[n_val:]) return train_files, val_files train, val split_dataset(./annotations) print(f训练集: {len(train)}, 验证集: {len(val)})分桶的依据是目标数量这样能保证验证集里既有目标稀疏的图也有目标密集的图。val_ratio一般设0.2如果数据量特别小可以降到0.1但不要低于0.1否则验证指标波动太大。3.2 针对小目标的增强Mosaic和Copy-Paste怎么选RSOD-Dataset里飞机和油罐的尺寸经常在32x32像素以下常规的随机翻转和裁剪对提升小目标召回帮助有限。我试过两种增强策略效果差异明显。Mosaic增强把四张图拼成一张能增加小目标在单张图中的出现次数但缺点是拼接边缘会产生不自然的截断立交桥这种大目标被切碎后反而干扰训练。Copy-Paste增强则是把小目标实例复制到其他图像的合理位置对飞机和油罐这类独立小目标很有效但需要额外的掩码或精确的框坐标实现成本高一些。我的建议是如果只做飞机和油罐优先上Copy-Paste如果四类一起训用Mosaic但把大目标的拼接概率调低。import cv2 import numpy as np def mosaic_augment(img_list, ann_list, output_size608): 简易Mosaic增强四图拼接。 img_list: 四张图像的numpy数组 ann_list: 对应的标注列表每个元素为[[cls, xmin, ymin, xmax, ymax], ...] h, w output_size // 2, output_size // 2 mosaic_img np.zeros((output_size, output_size, 3), dtypenp.uint8) mosaic_ann [] for i, (img, anns) in enumerate(zip(img_list, ann_list)): img_resized cv2.resize(img, (w, h)) # 计算拼接位置 if i 0: x_offset, y_offset 0, 0 elif i 1: x_offset, y_offset w, 0 elif i 2: x_offset, y_offset 0, h else: x_offset, y_offset w, h mosaic_img[y_offset:y_offseth, x_offset:x_offsetw] img_resized # 缩放标注框 scale_x w / img.shape[1] scale_y h / img.shape[0] for cls, xmin, ymin, xmax, ymax in anns: new_xmin xmin * scale_x x_offset new_ymin ymin * scale_y y_offset new_xmax xmax * scale_x x_offset new_ymax ymax * scale_y y_offset mosaic_ann.append([cls, new_xmin, new_ymin, new_xmax, new_ymax]) return mosaic_img, mosaic_ann这段代码里output_size一般设608或640和你的检测网络输入尺寸保持一致。注意拼接后要重新检查框是否越界尤其是右下角那张图的框很容易超出输出尺寸。我通常会在返回前加一个裁剪逻辑把超出边界的框裁到图像内。3.3 训练配置学习率、锚框和输入尺寸的联动RSOD-Dataset的图像分辨率差异较大直接缩放到固定尺寸会进一步缩小本就很小的目标。我一般会把输入尺寸设到608以上同时把锚框的尺度调小。以YOLO系列为例默认锚框是针对COCO的最小尺度也在32左右对RSOD-Dataset的飞机和油罐偏大。下面是一个锚框聚类的脚本用K-means在RSOD-Dataset的标注框上重新生成锚框。from sklearn.cluster import KMeans import numpy as np def cluster_anchors(ann_dir, n_clusters9): 对RSOD-Dataset的标注框做K-means聚类生成适配的锚框。 widths, heights [], [] xml_files glob.glob(os.path.join(ann_dir, *.xml)) for xml_path in xml_files: ann parse_rsod_annotation(xml_path) for obj in ann[objects]: xmin, ymin, xmax, ymax obj[bbox] widths.append(xmax - xmin) heights.append(ymax - ymin) data np.array(list(zip(widths, heights))) kmeans KMeans(n_clustersn_clusters, random_state42).fit(data) anchors kmeans.cluster_centers_ # 按面积排序方便分配到不同特征层 anchors anchors[np.argsort(anchors[:, 0] * anchors[:, 1])] return anchors anchors cluster_anchors(./annotations) for i, (w, h) in enumerate(anchors): print(fAnchor {i}: {w:.1f} x {h:.1f})聚类出的锚框如果最小的一两个只有十几像素说明小目标占比确实很高这时候输入尺寸至少要到640否则特征图上的感受野根本覆盖不到。学习率方面如果用了Mosaic或Copy-Paste初始学习率可以比常规配置低20%左右因为增强后的样本分布和原始分布有偏移太高的学习率容易让模型在早期震荡。4. 避坑与排查RSOD-Dataset训练中常见的五个翻车现场4.1 验证集mAP虚高测试集一塌糊涂现象训练时验证集mAP稳步上升换到实际航拍图或另一个区域的遥感图上召回率断崖式下跌。原因划分时没有按场景分组验证集和训练集的背景高度相似模型学到了背景捷径。解决用3.1节的分层划分或者手动把不同来源的图像分到不同集合。如果数据量允许留出一个完全独立的测试集不参与任何调参。4.2 小目标召回始终上不去加数据也没用现象飞机和油罐的召回率卡在0.5左右增加训练轮数或数据量都没有明显改善。原因输入尺寸太小小目标在特征图上只剩一两个像素网络根本提取不到有效特征。解决把输入尺寸从416提到640甚至768同时用3.3节的锚框聚类替换默认锚框。如果显存不够优先保证输入尺寸再考虑减小batch size。4.3 立交桥的框回归发散损失变成NaN现象训练几个epoch后立交桥类别的回归损失突然飙升最终变成NaN。原因立交桥的标注框尺度差异极大有的横跨整图有的只占一小块默认的回归损失对极端宽高比不鲁棒。解决检查标注里有没有宽高比超过10的框如果有用CIoU或EIoU损失替代IoU损失或者在数据加载时对超大框做下采样。另外梯度裁剪阈值设小一点比如1.0能防止早期发散。4.4 油罐和操场的类别混淆严重现象混淆矩阵显示油罐经常被预测成操场反之亦然。原因两者在灰度图上都是大面积均匀区域颜色和纹理特征接近。解决在数据增强里加入颜色抖动和灰度化强迫模型学习形状而不是颜色。如果用了预训练权重考虑在RSOD-Dataset上先冻结主干训练几个epoch再解冻微调让分类头先适应这两个类别的边界。4.5 训练速度慢到无法接受现象一个epoch要跑几十分钟GPU利用率只有30%左右。原因数据加载是瓶颈XML解析和增强都在CPU上串行执行。解决把标注预解析成JSON或numpy数组训练时直接读增强操作放到DataLoader的worker里并行如果用了Mosaic注意四张图的读取不要每次都从磁盘加载可以预先缓存到内存。我一般会把整个数据集预处理成TFRecord或LMDB训练速度能提升三到五倍。5. 进阶技巧用RSOD-Dataset做小目标检测的消融实验设计当你把基线跑通之后RSOD-Dataset最大的价值其实是做消融实验。它只有四类数据量不算大一次完整的训练在单卡上几个小时就能跑完非常适合快速验证某个改进点到底有没有用。我一般会按下面的表格来组织实验每行只改一个变量其他保持完全一致。实验编号输入尺寸锚框增强策略损失函数关注指标baseline416默认翻转裁剪CIoU四类mAPexp1640默认翻转裁剪CIoU小目标召回exp2640聚类翻转裁剪CIoU小目标召回exp3640聚类MosaicCIoU四类mAPexp4640聚类MosaicFocalCIoU类别平衡跑完这五组你就能清楚地看到每个改动带来的增益。我的血泪经验是输入尺寸和锚框的联动效果最明显但也是最容易被忽略的。很多人只调输入尺寸忘了锚框也要跟着变结果小目标召回提升有限反而大目标的定位精度下降了。另外Focal Loss在RSOD-Dataset上不一定总是正收益如果四类本身比较均衡它可能会让油罐这种易分类别的梯度被过度压制导致召回下降。建议先跑baseline和exp1、exp2确认小目标召回有提升后再考虑加Focal Loss。还有一个容易被忽视的点验证频率。RSOD-Dataset的验证集如果只有几十张图mAP的波动会很大建议每训练5个epoch验证一次并且保存最近三个最佳权重最后用投票或加权融合的方式选最终模型。我习惯在训练脚本里加一个早停机制如果连续10次验证mAP没有提升就停止避免过拟合。最后如果你打算把这个数据集用到实际项目里记得留出至少20%的数据做最终测试不要把所有数据都拿去训练和调参。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑