遥感图像小白--2--图像分割

推荐网站:GitHub - satellite-image-deep-learning/techniques: Techniques for deep learning with satellite & aerial imagery

一、语义分割

语义分割是一种为图像中的每个像素分配单个标签的技术,允许识别包含相同目标类的图像区域以及区域之间的边界。

800948b9df114341983590718d28bef2.png

该图像已被手动注释。在此图像中,每种颜色代表一个类,图像中的所有像素都被分配一个类。

图像分割常见用例:

  • 在图像中标记土地使用和土地覆盖【多类标记】
  • 在背景下识别单个类别【eg.分割洪水或火灾】

图像分割的板块主要有几大类:

  • 道路和建筑物
  • 植被,通常是农作物或树木
  • 水、海岸线和洪水
  • 火灾、烟雾和燃烧区域
  • 山崩
  • 冰川
  • 大型人造结构,包括太阳能板和游泳池

二、两种提供注释的方式 

 1.像素级别蒙版(Masks)

掩码文件与所注释的图像大小相同,每个像素值都是 0 到 255 范围内的整数。如果任务是区分背景和洪水区域,则掩码图像将使用像素值 0 来表示背景,并使用另一个值(例如 255)来表示洪水区域。掩码图像附带一个文本文件,其中列出了像素值到类值的映射 — 这通常是转储到 json 文件的 python 字典。

2.多边形边界(Geometries)

使用多边形或边界框来表示图像中的对象区域。这些多边形通常是由多个点(顶点)构成的。

假设我们有一张包含汽车的图像,并且我们想要用一个多边形来标记汽车的轮廓。

  • 输入图像: 一张包含汽车的图像。

  • 多边形边界: 我们用汽车轮廓上的顶点来表示汽车区域,例如用四个点组成一个多边形来标记汽车的区域。 

 三、数据库

1.Awesome_Satellite_Benchmark_Datasets 存储库 

chrieke/awesome-satellite-imagery-datasets: 🛰️ List of satellite image training datasets with annotations for computer vision and deep learning (github.com)

c3bcedf540754de9a3dd70f75579747a.png

2.torchgeo

torchgeo 支持的数据集包括 BigEarthNet、Landsat、Sentinel-2、ChesapeakeCVPR 等。 

from torchgeo.datasets import Landsat8
dataset = Landsat8(root="path_to_dataset")

microsoft/torchgeo: TorchGeo: datasets, samplers, transforms, and pre-trained models for geospatial data (github.com)

34a942049ff04a7d9d2f1d9f8f5863ec.png

3.mmsegmentation

open-mmlab/mmsegmentation: OpenMMLab Semantic Segmentation Toolbox and Benchmark. (github.com)

  • 集成数据集mmsegmentation 支持自定义和公开的分割数据集,用户可以根据需求将卫星数据集加载进来进行分割任务。
  • 使用场景:适合需要快速集成模型和数据集的研究者,特别是已经在使用 MMLab 系列工具的用户。

 4.Dubai 数据集

Semantic segmentation of aerial imagery (kaggle.com)

Dubai 数据集是一个适用于学习和研究的小型数据集,通常包含城市区域的遥感图像。它特别适合初学者和小型研究项目。

四、选择和训练模型

1.fastai 中的 unet_learner

视觉学习者 – fastai

Unet 有很多实现方式,我们来看一下fastai 中的 unet_learner【执行迁移学习和实验不同的预训练编码器变得非常简单,但在分割指标上却非常有限(仅支持 DiceJaccard 指标)

 unet_learner (dls, arch, normalize=True, n_out=None, pretrained=True,
               weights=None, config=None, loss_func=None,
               opt_func=<function Adam>, lr=0.001, splitter=None,
               cbs=None, metrics=None, path=None, model_dir='models',
               wd=None, wd_bn_bias=False, train_bn=True, moms=(0.95, 0.85,
               0.95), cut=None, n_in=3, blur=False, blur_final=True,
               self_attention=False, y_range=None, last_cross=True,
               bottle=False, act_cls=<class
               'torch.nn.modules.activation.ReLU'>, init=<function
               kaiming_normal_>, norm_type=None)

(1)dls(DataLoaders)

  • 说明:传入 dls 是必需的,它包含了训练和验证集的数据加载器。通常可以通过 DataBlockImageDataLoaders 创建。

(2)arch(Architecture)

  • 说明:表示用于 Unet 的编码器部分的神经网络架构(例如 resnet34resnet50)。这将作为 Unet 的编码器,负责特征提取。

(3)normalize

  • 类型bool
  • 默认值True
  • 说明:是否对输入数据进行标准化处理。通常情况下,在使用预训练模型时需要进行标准化。

(4)n_out

  • 类型NoneType
  • 默认值None
  • 说明:输出通道的数量,通常与分割任务的类别数相匹配。如果设置为 None,fastai 会自动推断输出的大小。

(5)pretrained

  • 类型bool
  • 默认值True
  • 说明:是否加载预训练的编码器权重。设置为 True 时,编码器将从 ImageNet 等数据集预训练的模型中加载权重。

(6)weights

  • 类型NoneType
  • 默认值None
  • 说明:你可以提供自定义的预训练权重。如果没有指定,则使用默认的权重(如 ImageNet 权重)。

(7)config

  • 类型NoneType
  • 默认值None
  • 说明:用于自定义模型配置。如果需要对模型的结构进行更复杂的修改,可以传入自定义的配置字典。

(8)loss_func

  • 类型NoneType
  • 默认值None
  • 说明:指定损失函数。如果不提供,fastai 会根据任务自动选择合适的损失函数(例如,分类问题会使用交叉熵损失)。

(9)opt_func

  • 类型function
  • 默认值Adam
  • 说明:指定优化器。默认为 Adam 优化器,但可以替换为其他优化器,如 SGD

(10)lr(Learning Rate)

  • 类型float
  • 默认值0.001
  • 说明:初始学习率,控制参数更新的步长。

(11)splitter

  • 类型NoneType
  • 默认值None
  • 说明:指定如何分割模型的参数以应用不同的学习率。例如,可以为编码器和解码器部分应用不同的学习率。

(12)cbs(Callbacks)

  • 类型NoneType
  • 默认值None
  • 说明:回调函数列表,用于在训练过程中执行一些额外操作,如早停或学习率调度器。

(13)metrics

  • 类型NoneType
  • 默认值None
  • 说明:评估模型的指标列表,例如 DiceIoU,用于分割任务。

(14)path

  • 类型NoneType
  • 默认值None
  • 说明:指定模型保存路径。

(15)model_dir

  • 类型str
  • 默认值'models'
  • 说明:模型保存目录。

(16)wd(Weight Decay)

  • 类型NoneType
  • 默认值None
  • 说明:权重衰减,用于正则化,防止过拟合。

(17)wd_bn_bias

  • 类型bool
  • 默认值False
  • 说明:是否对 BatchNorm 和偏置参数应用权重衰减。

(18)train_bn

  • 类型bool
  • 默认值True
  • 说明:是否在冻结模型时继续训练 BatchNorm 层。通常在微调时 BatchNorm 层需要继续更新。

(19)moms(Momentum)

  • 类型tuple
  • 默认值(0.95, 0.85, 0.95)
  • 说明:用于一周期学习率调度的动量值。

(20)cut

  • 类型NoneType
  • 默认值None
  • 说明:控制模型编码器的截断点,可以指定在哪一层切断编码器并连接到 Unet 的解码器部分。

(21)n_in

  • 类型int
  • 默认值3
  • 说明:输入图像的通道数,通常 RGB 图像为 3 通道。

(22)blur

  • 类型bool
  • 默认值False
  • 说明:是否在上采样过程中对解码器输出应用模糊操作。

(23)blur_final

  • 类型bool
  • 默认值True
  • 说明:是否在最后一层上采样过程中应用模糊操作。

(24)self_attention

  • 类型bool
  • 默认值False
  • 说明:是否在模型中使用自注意力机制。

(25)y_range

  • 类型NoneType
  • 默认值None
  • 说明:输出值的范围,用于回归任务中约束模型的输出。

(26)last_cross

  • 类型bool
  • 默认值True
  • 说明:是否在 Unet 的最后一层使用横向连接,以增强信息流。

(27)bottle

  • 类型bool
  • 默认值False
  • 说明:是否在编码器中加入瓶颈层,用于减少模型参数数量。

(28)act_cls

  • 类型type
  • 默认值ReLU
  • 说明:指定激活函数类型,默认为 ReLU

(29)init

  • 类型function
  • 默认值kaiming_normal_
  • 说明:指定权重初始化方法,默认为 kaiming_normal_

(30)norm_type

  • 类型NoneType
  • 默认值None
  • 说明:指定归一化类型,可以选择 BatchNormLayerNorm

代码示例:

1) 路径与数据准备

image_P.jpgimage.jpg 的语义分割标签图像,其中 _P 后缀表示该图像的分割掩码

path = untar_data(URLs.CAMVID_TINY)
fnames = get_image_files(path/'images')
def label_func(x): return path/'labels'/f'{x.stem}_P{x.suffix}'
codes = np.loadtxt(path/'codes.txt', dtype=str)
  • untar_data(URLs.CAMVID_TINY):从 fastai 的 URLs 中下载并解压缩 CAMVID_TINY 数据集,这是一个小型的用于语义分割的城市场景数据集。
  • get_image_files(path/'images'):获取数据集中所有图像的文件路径。
  • label_func(x):定义一个函数来获取图像对应的标签文件路径。例如,假设图像名为 image.jpg,标签文件名则为 image_P.jpg
  • codes:从 codes.txt 文件中读取类别标签,通常是用于表示分割任务中每个类的名称。

 2)构建 DataLoaders

dls = SegmentationDataLoaders.from_label_func(path, fnames, label_func, codes=codes)
  • SegmentationDataLoaders.from_label_func:构建用于分割任务的数据加载器。通过文件路径和标签函数将图像与其对应的标签进行配对,并进行批量化处理。
  • codes=codes:指定分割任务的类别标签。

3) 创建 Unet 学习器

learn = unet_learner(dls, models.resnet34, loss_func=CrossEntropyLossFlat(axis=1), y_range=(0,1))

2.功能更完善的分割库:segmentation_models.pytorch。

该库包含了一系列现代模型,并且受益于一个简单的 API,使得快速实验变得容易。Unet 的一个局限是它的区域边界往往比较粗糙,因此通过单一 API 来实验广泛的模型组合是非常有用的。

安装依赖(AI生成):

pip install segmentation-models-pytorch
pip install torch torchvision

代码示例(AI生成):

import torch
import segmentation_models_pytorch as smp
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision.datasets import VOCSegmentation

# 1. 加载数据集 (以Pascal VOC数据集为例)
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Resize((256, 256))
])

train_dataset = VOCSegmentation(root='./data', year='2012', image_set='train', download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=4, shuffle=True)

# 2. 创建Unet模型,使用ResNet34作为编码器
model = smp.Unet(
    encoder_name="resnet34",        # 使用ResNet34作为编码器
    encoder_weights="imagenet",     # 使用ImageNet预训练权重
    in_channels=3,                  # 输入的通道数 (RGB图像)
    classes=21                      # 输出类别数(与数据集一致)
)

# 3. 定义损失函数和优化器
loss_fn = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.0001)

# 4. 训练模型(简单的训练循环)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)

for epoch in range(5):  # 训练5个epoch
    model.train()
    for images, masks in train_loader:
        images, masks = images.to(device), masks['mask'].to(device)
        
        optimizer.zero_grad()       # 清除上次的梯度
        outputs = model(images)     # 前向传播
        loss = loss_fn(outputs, masks)  # 计算损失
        loss.backward()             # 反向传播
        optimizer.step()            # 更新模型参数

    print(f"Epoch [{epoch+1}/5], Loss: {loss.item()}")

print("训练完成")

3.TorchGeo 中的 SemanticSegmentationTask

安装依赖(AI生成):

pip install torchgeo

代码示例(AI生成):

import torch
from torchgeo.datasets import LandCoverAI
from torchgeo.models import SemanticSegmentationTask
from torch.utils.data import DataLoader
import pytorch_lightning as pl

# 1. 加载遥感数据集(例如 LandCover.ai)
train_dataset = LandCoverAI(split="train", root="data/")
val_dataset = LandCoverAI(split="val", root="data/")

# 2. 创建数据加载器
train_loader = DataLoader(train_dataset, batch_size=8, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=8, shuffle=False)

# 3. 定义分割任务
task = SemanticSegmentationTask(
    model="unet",  # 使用 UNet 模型
    in_channels=3,  # 输入通道数 (RGB)
    num_classes=5,  # 输出类别数
)

# 4. 使用 PyTorch Lightning 进行训练
trainer = pl.Trainer(max_epochs=10, gpus=1 if torch.cuda.is_available() else 0)
trainer.fit(task, train_dataloaders=train_loader, val_dataloaders=val_loader)

print("训练完成")

4.现代模型SegNeXt

这篇论文提供了在 iSAID 遥感数据集上的模型性能对比。

SegNeXt: Rethinking Convolutional Attention Design for Semantic Segmentation (nips.cc)

五、实例分割

定义:实例分割不仅要区分不同的类别,还需要识别每个类别中的具体实例。

六、全景分割

全景分割结合了语义分割和实例分割的思想,它同时需要为图像中的所有像素进行分类,并区分对象实例。

1ec4c169c0f5496aadeca4175dade1d3.png

 (A) 原始图像、(B) 语义分割、(C)实例分割、 (D) 全景分割 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值