关于图像分割(Python)的类别合并:卫星图像领域适配技术咨询
卫星图像分割任务类别合并实现思路
以下是不同场景下的可落地方案,可根据你的开发流程选择适配:
1. 离线标签预处理方案
适合数据量不大、不需要频繁调整类别合并规则的场景:
- 先梳理原数据集的类别ID映射关系,例如原映射为
{0: 'background', 1: 'Roads', 2: 'Buildings', 3: 'Vegetation'} - 定义新的类别映射规则,将需要合并的类别映射到同一个ID,例如将原ID1、2都映射为新ID1,后续类别ID对应顺延,得到新映射
{0: 'background', 1: 'Roads_Buildings', 2: 'Vegetation'} - 单通道掩码图处理可直接用numpy批量替换像素值,示例代码:
import numpy as np from PIL import Image old_label = np.array(Image.open("source_label.png")) # 批量替换类别ID new_label = np.where(old_label == 2, 1, old_label) new_label = np.where(old_label == 3, 2, new_label) Image.fromarray(new_label).save("processed_label.png")
- 若是COCO格式的JSON标注,直接遍历所有annotations条目替换category_id,同步更新categories字段的类别列表即可。
2. 训练时动态合并方案
适合需要做多组消融实验、不想额外存储预处理后标签的场景:
- 重写数据集类的
__getitem__方法,读取原始标签后实时做类别ID映射,不需要修改原始数据集,调整合并规则仅需修改映射表即可,示例代码:
def __getitem__(self, idx): img = self.load_img(idx) old_label = self.load_label(idx) # 合并映射表,key为原类别ID,value为新类别ID merge_map = {0:0, 1:1, 2:1, 3:2} new_label = torch.zeros_like(old_label) for old_id, new_id in merge_map.items(): new_label[old_label == old_id] = new_id return img, new_label
3. 损失计算阶段合并方案
适合领域适配场景中不需要显式修改标签的情况:
- 计算损失前对模型输出的logits做通道合并,无需改动数据加载逻辑,适配性更强,示例代码:
import torch.nn.functional as F logits = model(img) # 输出维度 [B, 4, H, W],对应4个原始类别 # 合并Roads、Buildings对应的第1、2通道(索引从0开始) merged_logits = torch.stack([ logits[:,0,:,:], logits[:,1,:,:] + logits[:,2,:,:], logits[:,3,:,:] ], dim=1) # 合并后输出维度 [B, 3, H, W] loss = F.cross_entropy(merged_logits, label)
注意事项
- 合并类别前要确认两类标注的质量,避免标注误差叠加影响模型效果
- 评估阶段要同步修改类别映射规则,保证训练、评估的类别体系一致
内容的提问来源于stack exchange,提问作者Priyanka Mishra
相关产品推荐
相关产品推荐

