简介面向遥感场景下的目标图像语义分割任务这份数据集包含约5,000张遥感影像及对应的像素级标注覆盖水体、交通运输、建筑、耕地、草地等8个常见地物类别遥感影像地物尺度差异明显、边界复杂此类数据有助于模型学习更稳健的语义特征。数据已完整划分为训练集和验证集训练集约1,800张验证集约800张每个子集均按images原图目录与masks标签目录组织下载解压后即可直接用于分割模型的训练与效果评估省去自行整理数据的步骤。资源内还附带一个可视化Python脚本可随机抽取一张样本将原始图像、真实标签以及标签叠加在原图上的效果并排展示并保存方便快速核查标注质量和模型预测效果。整份资料共2,000个文件包含1,818个PNG、180个JPG、类别说明TXT及可视化脚本压缩包约30.81MB目前已有76人学习下载适合需要现成基准数据来入门遥感语义分割的研究者或开发者使用也可用于对比不同分割网络的表现。1. 遥感场景下的目标图像语义分割数据集先看懂它的规模和边界遥感场景下的目标图像语义分割数据集最容易被低估的坑是你以为有图和标签就能直接训练实际还得处理尺寸、类别分布和波段问题。做自然资源监测时我拿过几套通用语义分割数据集去跑屋顶提取和植被分类结果在航拍图上表现不错的权重一换到卫星影像上就全面翻车。后来我意识到问题不在模型而在数据遥感影像的覆盖范围大、目标尺度小、类别占比悬殊这套约5,000张数据和标签的数据集价值在于把高分辨率遥感图与人工像素标签对齐了省去从原始影像里抠图、标注的几个月时间。适合给遥感图像目标检测、语义分割算法做预训练或迁移学习的读者——你知道自己要什么也知道标签长什么样剩下的是怎么把它用起来。2. 把数据集拆开看目录结构、文件格式与标签映射拿到任何数据集第一件事不是急着训练而是先搞清它内部怎么组织。遥感场景下的目标图像语义分割数据集和自动驾驶数据集有两种常见的打包习惯一种是像Cityscapes那样按图像与标签分目录另一种是像COCO那样用JSON记录多边形标注。这套数据集既然强调“数据和标签”多半是前者——图像一张、同名的标签图一张标签保存为8位PNG单通道图因为每个像素点都存放类别ID不宜用有损压缩的JPG来存。2.1 图像、标签与类别映射先列文件树和类别清单拿到压缩包后先解压再列文件树不要凭感觉直接写训练脚本。我一般用下面几条命令把目录结构、文件数目和图片尺寸一次看全避免后续路径写错。# 解压数据集压缩包注意路径中的/tmp 在Linux 下是可写的 unzip rs_seg_dataset.zip -d ./data # 查看顶层目录结构 find ./data -maxdepth 2 -type d | sort # 统计 images 与 labels 下的文件数量是否一致 ls ./data/images | wc -l ls ./data/labels | wc -l # 抽样看一张图的尺寸和位深 python - PY from PIL import Image img Image.open(./data/images/sample_0001.tif) lab Image.open(./data/labels/sample_0001.png) print(img.size, img.mode, lab.size, lab.mode) PY逻辑说明find用来确认目录层级wc -l用于核对图像数与标签数最后一段Python代码检查TIFF遥感图像的尺寸、波段数以及标签图的模式。RGB图在PIL里是modeRGB单通道灰度标签是modeL或P如果标签是modeP需要读它的palette再转成数值ID。遥感图常见的是TIF/TIFF格式和多波段影像打交道时还要确认是否包含R、G、B之外的近红外波段这直接影响后面要不要做波段选择。参数说明上面代码里最需要留意的组合是“images数量labels数量”以及“标签mode是P或L”。如果发现images下是TIFF而labels下是JPG就要警惕标签被压缩过、边缘带噪声如果发现labels是RGB三通道图则先确认类别是否用颜色编码。颜色编码的标签需要一张色彩-类别映射表否则训练时模型输出的ID和可视化颜色对不上等于白忙。核对完文件结构之后第二步就是提取类别清单和像素占比。遥感语义分割数据集里通常有建筑、道路、水体、植被、裸地等类别也有数据只标前景和背景两类。用个小脚本统计每个类别ID出现了多少个像素这步能提前发现类别不均衡问题。import numpy as np from PIL import Image from collections import Counter label_path ./data/labels/sample_0001.png lab np.array(Image.open(label_path)) counter Counter(lab.flatten()) # 打印类别ID与对应像素数再除以总像素得到占比 for cls_id, cnt in sorted(counter.items()): print(fclass {cls_id}: {cnt} pixels, {cnt / lab.size:.4f})逻辑说明把标签图转成numpy数组后统计所有像素类别ID的出现频率。类别ID的0一般约定为背景如果某些不想要的类别占比极高后续训练时要考虑加权loss或重采样这会在第4章展开。参数说明如果某个类别ID大到超出类别总数比如255那通常是边界、忽略区域或标注时的padding值训练时要在loss里用ignore_index把它排除掉。如果类别ID不是从0开始连续编号还要先做重映射。2.2 图像与标签一一对应用文件名做硬校验很多遥感数据集是从不同批次的采集任务汇总来的名字可能是“影像编号时间戳传感器标识”的拼接很容易出现两个目录排序不一致的情况。靠肉眼检查不现实写一个自动校验脚本更可靠。# 提取两边的文件名去掉扩展名对比交集与差集 cd ./data comm -3 (ls images | sed s/\.[^.]*$// | sort) \ (ls labels | sed s/\.[^.]*$// | sort)逻辑说明comm -3输出两个集合中的差异项。如果没有任何输出说明图像和标签一一对应如果有输出则说明存在只有图没有标签、或者标签多出来的文件。参数说明sed s/.[^.]*$//用来去掉最后一个点号后的扩展名因为TIF和PNG的后缀不同校验时不能直接拿完整文件名对比。如果文件名里本身含点号如某些卫星产品号这条正则仍然只去掉最后一个后缀不会误伤。还有一种更隐蔽的问题文件名能对上但图像尺寸和标签尺寸不一样。我会把2.1里的尺寸检查扩展到全部样本挑出尺寸不一致的图import os from PIL import Image bad [] for name in os.listdir(./data/images): img_path os.path.join(./data/images, name) lab_name name.rsplit(., 1)[0] .png lab_path os.path.join(./data/labels, lab_name) if not os.path.exists(lab_path): bad.append((name, missing label)) continue if Image.open(img_path).size ! Image.open(lab_path).size: bad.append((name, size mismatch)) for item in bad: print(item)逻辑说明遍历每张图要求同名的标签存在且尺寸一致。这个检查脚本虽然简单但在后续用DataLoader读取时会省掉一整类崩溃。参数说明name.rsplit(., 1)[0]只会切最后一个点避免多后缀文件名处理错误。尺寸不一致经常出现在数据生产时标签做了下采样或投影转换遇到这种情况不能强行resize应回到原始生产任务里找到复查依据。3. 把大尺寸遥感图切块再喂给模型预处理与切图策略遥感影像和日常照片最大的区别是尺寸。一幅影像可能是几千乘几千像素直接把整张图缩放到512×512会丢失大量小目标细节直接整图训练又会让显存爆炸。所以遥感场景下的目标图像语义分割数据集在使用前几乎都要经过“切块patch”这一步。切块方式影响样本数量和模型能看到的上下文范围是数据使用里最值得花时间设计的环节。3.1 为什么不能整图缩放切块尺寸、步长与重叠我一般把切块尺寸定为512或640步长设置为尺寸的一半到四分之三。步长越小样本越多计算量越大步长太大又会把目标从中间切断让标签边缘不完整。带重叠的滑窗切法尤其适合大块连片的类别例如建筑屋顶和道路训练出的模型边界更稳。import numpy as np from PIL import Image import os def crop_patches(image, label, patch_size512, stride384, out_dir./patches): # 输入image与label都必须是大尺寸单张遥感图 os.makedirs(out_dir, exist_okTrue) h, w image.shape[:2] idx 0 for y in range(0, h - patch_size 1, stride): for x in range(0, w - patch_size 1, stride): img_patch image[y:ypatch_size, x:xpatch_size] lab_patch label[y:ypatch_size, x:xpatch_size] # 保存为npz按序号命名同时保留img和lab避免错位 np.savez(f{out_dir}/p_{idx:05d}.npz, imgimg_patch, lablab_patch) idx 1 # 读入遥感图像和标签RGB与单通道 img np.array(Image.open(./data/images/sample_0001.tif).convert(RGB)) lab np.array(Image.open(./data/labels/sample_0001.png)) crop_patches(img, lab)逻辑说明这个滑窗函数在y方向和x方向分别以stride循环保证每个patch尺寸固定。保存成npz的好处是后续读取快而且img和lab压在同一个文件里不会错位。如果用PNG保存则要分别写img_patch和lab_patch两个文件还要维持同名对应关系。参数说明patch_size512是一般8-12GB显存显卡跑DeepLabV3的安全尺寸如果显存只有6GB可以降到384。stride384意味着相邻patch有128像素重叠重叠部分会给数据增强带来天然的平移不变性。注意循环条件是range(0, h - patch_size 1, stride)如果图像高度不是patch_size的整数倍会丢弃底边和右边一圈像素要让这些区域不丢就需要在切块前对全图做padding。边角处理是新手最容易忽略的地方。常见做法是先把整张图pad到能被stride整除的尺寸再用反射填充或零填充补边缘。遥感图边缘地带通常包含轨道重叠或图像拼接的黑边零填充会在黑边区域生成大量背景样本反而干扰训练我倾向于先检测黑边并裁掉再做少量padding。黑边检测可以用行均值判断这个技巧在第5.3节会再展开。3.2 训练集、验证集怎么切防止同一地块泄漏遥感影像往往是同一架次飞过复盖大片区域采集得到的相邻切片会共享光谱特征甚至包含同一栋建筑的两部分。如果随机切分训练集和验证集同一块地物的不同patch会同时出现在两边导致验证指标虚高模型部署到新区域后泛化能力却下降。正确做法是按“地块”或“图像来源”分组而不是按patch随机分。import numpy as np from sklearn.model_selection import GroupShuffleSplit # 假设有1200个patch每20个patch来自同一张原图也就是60组 patch_ids np.arange(0, 1200) group_ids np.array([img_id // 20 for img_id in patch_ids]) split GroupShuffleSplit(n_splits1, test_size0.2, random_state42) train_idx, val_idx next(split.split(patch_ids, groupsgroup_ids)) print(ftrain patches: {len(train_idx)}, val patches: {len(val_idx)})逻辑说明GroupShuffleSplit保证同一分组的patch不会同时进入训练集和验证集。group_ids在这里采用整除方式模拟“每20个patch来自同一张原图”的分组实际使用时把patch文件名拆出原图编号即可。参数说明test_size0.2是常规留出比例如果类别分布差异大推荐使用分层分组切分即按每个group的主要类别做strata调整。遥感任务里验证集的构建讲究“按采集区域隔离”这个原则与模型评估的可信度直接相关。数据增强方面遥感语义分割常用的有不改变类别语义的旋转90度的倍数、水平翻转、亮度对比度扰动。不要随便用随机裁剪因为它会破坏已经切好的patch边缘也不要用随机擦除容易把建筑和道路的像素删掉造成标签与图像不一致。增强强度不宜过大遥感图本身的光谱一致性是标注时依赖的信息。归一化也要单独说。遥感影像不一定是标准0-255范围16位TIFF可能是0-65535训练前必须按数据集统计的均值和标准差归一化不能直接套用ImageNet的mean/std因为遥感光谱与自然照片差异很大。使用数据集的RGB均值而非ImageNet均值通常能更快收敛这也是5000张规模的数据集相对大模型预训练数据集的优势——你可以用自己的统计量校正分布。4. 选对语义分割模型和训练参数遥感场景的经验值数据预处理好了下一步是选模型。对5000张规模的数据集来说模型不能太小也不能过大太小学不到地物边界过大又容易过拟合。遥感语义分割的常用做法是先跑通U-Net或DeepLabV3再根据效果决定是否上Transformer结构。4.1 从U-Net到DeepLabV3再到SegFormer模型选型对比在遥感目标图像语义分割任务里三类模型比较常见模型特点显存占用适用场景U-Net编码器-解码器结构小样本也能训低单类别分割、快速验证DeepLabV3ASPP模块多尺度上下文强中多类别、不同尺寸地物混合SegFormerTransformer编码器长距离依赖好中高大范围连片地物、边界模糊场景U-Net的优势在于数据量不需要太大5000张patch足够训出一个像样的基线DeepLabV3的空洞空间金字塔池化ASPP在道路、水体这类尺度差异明显的类别上表现更好SegFormer对显存的要求高一些如果机器只有单卡可以先看前两者。顺带提醒一句遥感图像目标检测任务里常用的YOLO系列属于目标检测与语义分割不同前者输出框后者输出像素级掩码别把这两套流程混在一起训练。如果之后要把这套数据转成YOLOv8训练自己的检测模型需要从像素掩码提取连通域外接矩形那是另一套标注转换流程。作为落地判断假如数据集中标注类别只有四五类且分布比较均衡我一般先用DeepLabV3配ResNet50做基准如果类别超过10类或者含有细碎的小目标再升级到SegFormer。语义分割数据集制作成本高所以拿现成数据集做预训练再在自己的小样本场景上微调往往比从零标注数据划算得多。4.2 训练参数与损失函数类别不均衡、学习率与Batch Size遥感数据集的类别不均衡几乎是常态。水体面积往往远大于道路如果直接用交叉熵模型会偏向像素数多的类别道路边界会变得残缺。常见做法是在交叉熵上叠加Dice loss或者使用加权的交叉熵。import torch import torch.nn as nn import torch.nn.functional as F class SegLoss(nn.Module): def __init__(self, n_classes, ignore_index255): super().__init__() self.n_classes n_classes self.ignore_index ignore_index def forward(self, logits, target): # logits: [B, C, H, W], target: [B, H, W] ce F.cross_entropy(logits, target, ignore_indexself.ignore_index) # 把target转成one-hot用于计算Dice target_onehot F.one_hot(target, self.n_classes).permute(0, 3, 1, 2).float() probs F.softmax(logits, dim1) # 忽略 ignore_index 对应位置 mask (target ! self.ignore_index).unsqueeze(1).float() intersection (probs * target_onehot * mask).sum(dim(2, 3)) total (probs target_onehot) * mask dice (2.0 * intersection 1.0) / (total.sum(dim(2, 3)) 1.0) dice_loss 1.0 - dice.mean() return ce dice_loss逻辑说明类别不均衡的经典loss组合。CE负责像素级分类Dice负责缓解前景类别像素太少问题分母和分子都加平滑项避免某些类别在当前batch中完全没有出现时出现除零错误。参数说明ignore_index255用来排除标注时留下的边缘遮挡区和未标注区域如果数据集约定用0表示背景、1表示建筑、2表示道路那么传入n_classes3。F.one_hot会把类别ID转成one-hot向量数据维度从[H, W]变成[H, W, C]permute之后再与概率图逐元素运算。这里需要注意该目标必须是long型AMP混合精度训练时target不能是半精度。其他训练参数上我会给一组经验值patch_size512时batch_size设为8或16AdamW配初始学习率1e-4训练80到120个epoch学习率用poly策略衰减power设为0.9。5000张图切patch后通常能生成两三万个小图这个数据规模下不需要从头训练可以先加载在ImageNet上预训练的backbone权重。遥感图虽然和自然图光谱不同但浅层边缘、纹理特征的迁移仍然有效。用预训练权重时backbone第一层卷积如果因为输入波段数不一致而形状不匹配需要手动修改输入通道。5. 避坑手册遥感语义分割数据集训练时最常翻车的5个地方5.1 标签文件与图像文件错位loss怎么都降不下去现象训练loss在某个值附近震荡loss降得很慢可视化预测时建筑边缘错位严重车辆跑到房顶上。原因图像和标签来自不同的采集批次直接按文件名排序索引时文件名暗含的时间戳或传感器编号不一致导致图像的标签张冠李戴。解决用第2.2节的文件名校验脚本检查一一对应并把训练样本名和标签名放入同一个dict用相同key读取。不要依赖两个目录在磁盘上的排列顺序ls的输出顺序不等于文件逻辑顺序。5.2 类别像素占比悬殊导致道路评测指标上不去现象训练到中后期验证mIoU不再提升水体类别IoU很高道路类别IoU却很低。原因直接用了普通交叉熵没有加Dice loss也没有做类别重加权道路像素占比低被大块水体压制。解决先用第2.1节的统计脚本算出每个类别像素占比权重设为总像素数除以每类像素数的对数缩放对占比低于5%的类别适当提高权重但不要超过10倍否则模型会输出大量假阳性。或者直接使用第4.2节的CEDice组合loss。5.3 遥感图的黑色边框进入训练集现象模型在真实场景上把所有黑色区域都预测成背景或边缘预测出现条纹在阴影区域表现不稳。原因切patch前没有裁掉扫描仪边框和轨道重叠黑边黑边像素在训练集中占很高比例模型学会了“黑背景”。解决在滑窗循环前先做黑边检测按行和列计算像素均值把均值低于阈值的行/列裁掉阈值可以设成整图最大值的5%左右。如果是16位影像先转成浮点型再算阈值不要在整数域直接比较。5.4 验证集与训练集来自同一地块指标虚高现象验证mIoU高达85%以上一换到其他区域就掉到60%。原因验证patch与训练patch空间相邻模型记住了纹理模式而不是语义跨区域泛化自然失败。解决用GroupShuffleSplit按原图分组切分或者干脆按采集时间、航带划分验证集。遥感任务里“按区域隔离”比“按文件随机”更符合真实部署。5.5 多波段影像强行转RGB丢掉对训练最有用的信息现象把4波段TIF直接打开转成RGB训练模型在云覆盖、阴影区域的表现不稳水体和植被区分度差。原因近红外波段对植被、水体的区分能力很强转RGB时默认丢弃了这个波段。部分数据集的图像包含额外波段却被PIL的convert(RGB)强行丢弃。解决用rasterio或tifffile读取全部波段根据需要选择RGBNIR四通道输入或合成NDVI等指数通道再把backbone首层卷积输入通道数改为4并加载预训练权重。6. 用类别IoU与错误热力图复盘验证一套遥感分割数据集值不值得投入训练结束后单看mIoU并不能回答“这套数据集的标注质量到底如何”。我发现最能暴露问题的方式是分别计算每个类别的IoU并绘制预测错误的类别混淆矩阵。下面这段脚本统计混淆矩阵并输出每类的IoUimport numpy as np from sklearn.metrics import confusion_matrix def compute_iou_per_class(pred, label, n_classes): # pred和label都是flatten后的类别ID忽略255 mask label ! 255 pred, label pred[mask], label[mask] cm confusion_matrix(label, pred, labelslist(range(n_classes))).astype(np.float64) intersection np.diag(cm) union cm.sum(axis0) cm.sum(axis1) - intersection iou intersection / (union 1e-6) return iou # 以某个验证集的模型输出为例 pred np.random.randint(0, 4, size(512*512)) label np.random.randint(0, 4, size(512*512)) print(compute_iou_per_class(pred, label, 4))逻辑说明混淆矩阵对角线是正确分类像素数列求和加行求和再减对角线就是并集。这个脚本输出每个类别的IoU能快速看出是哪一类拉低了整体分数。参数说明n_classes必须和数据集的类别总数一致label ! 255掩码等价于在统计时排除ignore_index避免未知区域污染IoU。如果样本类别超过20类建议把混淆矩阵做成归一化的百分比矩阵否则数字大小差异太大看不出错分规律。如果想要更直观地看错误分布可以把混淆矩阵按每一类标签的样本数做行归一化转成一个热力图颜色越深的格子代表模型越容易把这一类错分成另一类。这一步能快速判断是边界误差还是语义混淆。除了IoU另一个值得看的指标是置信度直方图。语义分割模型在验证集上输出的平均置信度高但错误也高说明模型在过拟合置信度普遍低则说明标签噪声大或模型欠拟合。把两者结合可以决定下一步是“清洗标签”还是“换更强backbone”。我自己的习惯是每次拿到新的遥感语义分割数据集都会先花半天做数据体检再花两小时跑一个最小U-Net基线用评估结果决定是否值得投入更大模型。这个流程帮我在好几个项目里避免了“花半个月训练、最后发现换一个数据集效果一样”的无效投入。遥感数据和自然图像数据的差异比想象中大多看几套数据再动手标注走的弯路会少很多。希望这个流程能帮到你。本文还有配套的精品资源点击获取