★★★ 本文源自AlStudio社区精品项目,【点击此处】查看更多精品内容 >>>

1.项目背景:

1.1 遥感变化检测介绍

当今,遥感技术已经成为获取和分析地球空间信息的重要手段。在环境监测、资源调查、灾害预警等领域,遥感图像都发挥着不可替代的作用。然而,随着时间的推移,遥感图像中往往会出现各种异常变化,如植被覆盖度变化、建筑物位置变动、道路迁移等,这些变化会对相关领域的决策和管理产生重要影响。因此,如何快速准确地检测和识别遥感图像中的变化,提高其精度和可靠性,已成为遥感应用领域的一个重要研究方向。

此图为汶川映秀镇地震前后SAR图像,通过变化检测可以直观看出受灾前后图中地区是否有重大损害,对灾后建设等各项工作都有重要意义

1.2 变化检测基本流程

变化检测的基本流程包括特征提取、特征匹配、分类器训练和变化检测等步骤。这些步骤可以根据具体的应用场景和任务进行调整和优化。下图简单描述了变化检测的流程

1.3 变化检测常用数据集

LEVIR-CD 数据集

数据集 LEVIR-CD 由 637 个高分辨率(VHR,0.5m/px)的 Google 地球图像对组成,大小为 1024 × 1024 像素。这些时间跨度为5至14年,图像对土地利用有显著变化,尤其是建筑增加。LEVIR-CD 涵盖各种类型的建筑,如别墅住宅、高大公寓、小型车库和大型仓库。LjiEVIR-CD 总共包含 31,333 个单独的变化的实例。

下载地址:https://justchenhao.github.io/LEVIR/

论文地址:https://www.sciencedirect.com/science/article/abs/pii/S1077314219300992

Google 数据集

该数据集是在2006年至2019年之间拍摄的,覆盖了中国广州市的郊区。为了便于生成图像对,通过 BIGEMAP 软件,Google 地球服务采用了 19 个季节变化的 VHR 图像对,其中红色、绿色和蓝色三个波段,空间分辨率为 0.55 米,大小从 1006×1168 像素到 4936×5224 像素不等。侧重于建筑物

下载地址:https://github.com/daifeng2016/Change-Detection-Dataset-for-High-Resolution-Satellite-Imagery

论文地址:https://ieeexplore.ieee.org/document/9161009

SECOND数据集

一个良好注释的语义变化检测数据集,从多个平台和传感器收集 4662 对航空图像。这些图像组合分布在杭州、成都和上海等城市。每个图像的大小为 512 x 512,并在像素级别进行注释。第二类侧重于6个主要的陆地覆盖类,即非植被地表、树木、低植被、水、建筑和游乐场,它们经常与自然和人为的地理变化有关。

下载地址:http://www.captain-whu.com/PROJECT/SCD/

论文地址:https://arxiv.org/abs/2010.05687

2.PaddleRS介绍:

PaddleRS是百度飞桨、遥感科研院所及相关高校共同开发的基于飞桨的遥感影像智能解译开发套件,支持图像分割、目标检测、场景分类、变化检测、图像复原等常见遥感任务。PaddleRS致力于帮助遥感领域科研从业者快速完成算法的研发、验证和调优。同时,PaddleRS也期望助力投身于产业实践的开发者,便捷地实现从数据预处理到模型部署的全流程遥感深度学习应用。

PaddleRS具有以下五大特色:

丰富的视觉与遥感特色模型库: 集成飞桨四大视觉套件的成熟模型库,同时支持FarSeg、BIT、ChangeStar等众多遥感领域深度学习模型,覆盖图像分割、目标检测、场景分类、变化检测、图像复原等任务。

对遥感领域专有任务的支持: 支持包括变化检测在内的遥感领域特色任务,提供完善的训练、部署教程以及丰富的实践案例。

针对遥感影像大幅面性质的优化: 支持大幅面影像滑窗推理,使用内存延迟载入技术提升性能;支持对大幅面影像地理坐标信息的读写。

顾及遥感特性与地学知识的数据预处理: 针对遥感数据特点,提供对包含任意数量波段的数据以及多时相数据的预处理功能,支持影像配准、辐射校正、波段选择等遥感数据预处理方法,支持50余种遥感指数的提取与知识融入。

工业级训练与部署性能: 支持多进程异步I/O、多卡并行训练等加速策略,结合飞桨核心框架的显存优化功能,可大幅度减少模型的训练开销,帮助开发者以更低成本、更高效地完成遥感的开发和训练。

3.环境配置

#首先配置相关环境
![ ! -d "PaddleRS" ] && unzip -q data/data191076/PaddleRS-develop.zip && mv PaddleRS-develop PaddleRS
!pip install matplotlib==3.4 scikit-image pycocotools
!pip install --user opencv-contrib-python
!pip install -r PaddleRS/requirements.txt
!pip install -e PaddleRS/
#将PaddleRS的安装目录添加到sys.path
import sys
sys.path.append("/home/aistudio/PaddleRS")

4.数据集的准备

通过PaddleRS提供的数据集预处理工具完成数据集切分。在PadlleRS/tools/prepare_dataset中,有对levircd数据集进行处理的脚本文件prepare_levircd.py,其作用为将原始的1024x1024大小的影像切分为无重叠的256x256的小块

#解压数据集
!unzip -oq data/data136610/LEVIR-CD.zip -d data/data136610/
#采用paddlers自带工具包中的数据预处理脚本将数据集剪裁,并且指定输出位置,裁剪大小等参数

!python PaddleRS/tools/prepare_dataset/prepare_levircd.py \
    --in_dataset_dir data/data136610/LEVIR-CD \
    --out_dataset_dir data/data136610/levircd \
    --crop_size 256 \
    --crop_stride 256

裁剪样本大小为 256 × 256

5.模型构建

5.1 BIT-CD模型的构建


上图是BIT-CD架构概述。作者通过一个CNN骨干网络(ResNet)从输入图像对中提取高层语义特征,并且使用空间注意力将每个时间特征图转换成一组紧凑的语义tokens。然后使用一个transformer编码器在两个tokens集中建模上下文,得到了富有上下文的tokens被一个连体transformer解码器重新投影到像素级空间,以增强原始像素级特征。最终,作者从两个细化的特征图计算特征差异图像(FDIs),然后将它们送到浅层CNN以产生像素级变化预测。

论文地址:https://ieeexplore.ieee.org/document/9491802/

#模型构建(BIT)
import paddlers

model_BIT = paddlers.tasks.cd.BIT(
    # 模型输出类别数 变化检测为2分类任务,故输出类别为2
    num_classes=2,
    # 是否使用混合损失函数,默认使用交叉熵损失函数训练
    use_mixed_loss=False,
    # 模型输入通道数
    in_channels=3,
    # 模型使用的骨干网络,支持'resnet18'或'resnet34'
    backbone='resnet18',
    # 骨干网络中的resnet stage数量
    n_stages=4,
    # 是否使用tokenizer获取语义token
    use_tokenizer=True,
    # token的长度
    token_len=4,
    # 若不使用tokenizer,则使用池化方式获取token。此参数设置池化模式,有'max'和'avg'两种选项,分别对应最大池化与平均池化
    pool_mode='max',
    # 池化操作输出特征图的宽和高(池化方式得到的token的长度为pool_size的平方)
    pool_size=2,
    # 是否在Transformer编码器中加入位置编码(positional embedding)
    enc_with_pos=True,
    # Transformer编码器使用的注意力模块(attention block)个数
    enc_depth=1,
    # Transformer编码器中每个注意力头的嵌入维度(embedding dimension)
    enc_head_dim=64,
    # Transformer解码器使用的注意力模块个数
    dec_depth=8,
    # Transformer解码器中每个注意力头的嵌入维度
    dec_head_dim=8
)

5.2 SNUNet-CD模型的构建

上图是SNUNET-CD架构概述。作者提出了一种用于变化检测的稠密链接网络,即SNUNet-CD (siamese network和NestedUNet的组合),受DenseNet和NestedUNet的启发,设计了一个密集的连接的连体网络用于变更检测。通过编码器和解码器之间、解码器和解码器之间的密集跳过连接,它可以保持高分辨率、细粒度的表示。提出了集成通道关注模块(ECAM)的深度监控方法。通过ECAM,可以细化不同语义层次的最具代表性的特征,并用于最终的分类。

论文地址:https://ieeexplore.ieee.org/document/9355573

#构建SNUNet模型
import paddlers
#调用paddlers.tasks中的SNUNet
model_SNUNET = paddlers.tasks.cd.SNUNet()
#查看模型组网
model_SNUNET.net

5.3 CDNet模型的构建


CDNet,4个压缩块(contraction block)分别由CONV、BNORM、ReLU和max-pooling层组成。4个扩展块(expansion block)中每一个都是由一个指导解池(来自相对应contraction blcok的存储的池化指标)、CONV、BNORM和ReLU层组成。最后一层是一个线性运算器,后面是一个softmax分类器。作为一个预处理步骤,对输入的RGB图像进行通道方向的归一化处理。

论文地址:https://www.mdpi.com/2072-4292/11/20/2417

#构建cdnet网络
import paddlers
model_CDNET = paddlers.tasks.cd.CDNet
model_CDNET.net

5.4 STANet模型的构建

提出了一种新的基于孪生网络的时空注意神经网络。与以往方法不同的是,利用时空依赖性。设计了一种CD自注意力机制来对时空关系进行建模,在特征提取过程中增加了一个CD自注意力模块。自我注意模块计算任意两个像素在不同时间和位置之间的注意权重,并使用它们来生成更具区别性的特征。由于目标可能会有不同的尺度,将图像分割成多尺度的子区域,并在每个子区域引入自注意,这样就可以在不同尺度捕获时空依赖性,从而生成更好的表示,以适应各种大小的对象。

论文地址:https://www.mdpi.com/2072-4292/12/10/1662

5.5 FCCDN模型的构建

FCCDN通过约束双时态特征提取和特征融合中的特征。更多具体来说,提出了一种用于更改检测任务。在主干的中心,我们设计了一个非本地特征金字塔网络,用于提取和融合多尺度特征。至保险丝双时态特征以一种稳健的方式,我们建立了一个基于密集连接的有限元分析-ture融合模块。此外,基于自我监督学习的策略提出了一种基于自我监督学习的策略来约束特征学习。

论文地址:https://arxiv.org/pdf/2105.10860.pdf

import paddlers
model_FCCDN = paddlers.tasks.cd.FCCDN
model_FCCDN.net

5.6 P2V模型的构建

P2V出了一个相应的时间更明确和复杂的建模,建立一对视频变更检测(P2V-CD)工作。首先,一个带有丰富时间的伪过渡视频信息是从输入图像对构建的,解释
CD作为视频理解的问题。然后,两个解耦编码器用于空间和时间识别过渡的类型,编码器横向连接.相互晋升

论文地址:https://ieeexplore.ieee.org/document/9975266/

import paddlers
model_P2V = paddlers.tasks.cd.P2V
model_P2V.net

6.构建并处理数据集

#构建数据集并且进行数据处理
import paddlers.transforms as tf

# 使用Compose组合多种变换方式。Compose中包含的变换将按顺序串行执行
train_transforms = tf.Compose([
    # 读取数据
    tf.DecodeImg(),
    # 随机裁剪
    tf.RandomCrop(
        # 裁剪区域将被缩放到256x256
        crop_size=256,
        # 将裁剪区域的横纵比固定为1
        aspect_ratio=[1.0, 1.0],
        # 裁剪区域相对原始影像长宽比例在一定范围内变动,最小不低于原始长宽的0.8
        scaling=[0.8, 1.0]
    ),
    # 以50%的概率实施随机水平翻转
    tf.RandomHorizontalFlip(prob=0.5),
    # 以50%的概率实施随机垂直翻转
    tf.RandomVerticalFlip(prob=0.5),
    # 数据归一化到[-1,1]
    tf.Normalize(
        mean=[0.5, 0.5, 0.5],
        std=[0.5, 0.5, 0.5]
    ),
    # 挑选训练过程中需要用到的数据,并按照指定顺序排列
    tf.ArrangeChangeDetector('train')
])
eval_transforms = tf.Compose([
    tf.DecodeImg(),
    # 在验证阶段,输入原始尺寸影像,对输入影像仅进行归一化处理
    # 验证阶段与训练阶段的数据归一化方式必须相同
    tf.Normalize(
        mean=[0.5, 0.5, 0.5],
        std=[0.5, 0.5, 0.5]
    ),
    # 挑选验证过程中需要用到的数据,并按照指定顺序排列
    tf.ArrangeChangeDetector('eval')
])
#实例化数据集
import os.path as osp

# 处理后数据集所在目录
DATA_DIR = "/home/aistudio/data/data136610/levircd/"

train_dataset = paddlers.datasets.CDDataset(
    data_dir=DATA_DIR,
    file_list=osp.join(DATA_DIR, 'train.txt'),
    transforms=train_transforms,
    label_list=None,
    # 使用4个辅助进程加载数据
    num_workers=4,
    shuffle=True,
    # 将取值为{0,255}的标签自动归一化到{0,1}
    binarize_labels=True
)
val_dataset = paddlers.datasets.CDDataset(
    data_dir=DATA_DIR,
    file_list=osp.join(DATA_DIR, 'val.txt'),
    transforms=eval_transforms,
    label_list=None,
    num_workers=0,
    shuffle=False,
    binarize_labels=True
)

7.配置超参数并训练模型

以SNUNet为例

import paddle

# 制定定步长学习率衰减策略
lr_scheduler = paddle.optimizer.lr.StepDecay(
    0.001,
    step_size=5000,
    # 学习率衰减系数,这里指定每次减半
    gamma=0.5
)

# 构造AdamW优化器
optimizer = paddle.optimizer.AdamW(
    learning_rate=lr_scheduler,
    parameters=model.net.parameters()
)
# 执行模型训练
# 使用者若想训练其他模型,将SNUNET替换成自己想训练的模型即可,但需在前一步构建好想使用的模型,再通过train进行训练
model_SNUNET.train(
    num_epochs=20,
    train_dataset=train_dataset,
    train_batch_size=8,
    eval_dataset=val_dataset,
    optimizer=optimizer,
    save_interval_epochs=10,
    # 每多少次迭代记录一次日志
    log_interval_steps=200,
    save_dir='exp/',#根据需要修改名称保存不同模型的权重,但代码可以共用,注意评估加载模型时注意文件名保持一致避免模型不同导致数据的问题
    # 是否使用early stopping策略,当精度不再改善时提前终止训练
    early_stop=False,
    # 是否启用VisualDL日志功能
    use_vdl=True,
    # 指定从某个检查点继续训练
    resume_checkpoint=None
)

8.构建测试集并评估模型

以SNUNet为例

from paddlers.tasks import load_model

# 构建测试集
test_dataset = paddlers.datasets.CDDataset(
    data_dir=DATA_DIR,
    file_list=osp.join(DATA_DIR, 'test.txt'),
    transforms=eval_transforms,
    label_list=None,
    num_workers=0,
    shuffle=False,
    binarize_labels=True
)

# 加载验证集上最佳模型
model = load_model("exp/best_model")#根据需要更改文件名验证不同模型

# 验证模型在测试集上效果
res = model.evaluate(test_dataset)

# 打印评价指标
print(f"\nIoU={res['iou']*100:.2f}%, F1={res['f1']*100:.2f}%")

9.模型导出推理并可视化结果

#使用PaddleRS提供的export_model.py脚本进行模型导出。通过--fixed_input_shape选项指定输入张量形状。
!python PaddleRS/deploy/export/export_model.py --model_dir=exp/best_model --save_dir=exp/best_model/static --fixed_input_shape [-1,3,256,256]
#构建预测器
predictor = paddlers.deploy.Predictor('exp/best_model/static', use_gpu=True)
import numpy as np
from PIL import Image
from matplotlib import pyplot as plt

%matplotlib inline

#获取推理结果并可视化
T1_PATH = "data/data136610/levircd/LEVIR-CD/test/A/test_1/test_1_3.png"
T2_PATH = "data/data136610/levircd/LEVIR-CD/test/B/test_1/test_1_3.png"
GT_PATH = "data/data136610/levircd/LEVIR-CD/test/label/test_1/test_1_3.png"


test_transforms = tf.Compose([
    tf.DecodeImg(),
    tf.Normalize(
        mean=[0.5, 0.5, 0.5],
        std=[0.5, 0.5, 0.5]
    ),
    tf.ArrangeChangeDetector('test')
])

pred = predictor.predict(
    # 以二元组形式输入两个时相的影像
    (T1_PATH, T2_PATH), 
    transforms=test_transforms
)

import numpy as np
from PIL import Image
from matplotlib import pyplot as plt


# 从左到右依次显示:第一时相影像、第二时相影像、模型推理结果以及真值标签
plt.figure(figsize=(9, 3), constrained_layout=True)
plt.subplot(141)
plt.imshow(Image.open(T1_PATH))
plt.gca().set_axis_off()
plt.title("Image1")
plt.subplot(142)
plt.imshow(Image.open(T2_PATH))
plt.gca().set_axis_off()
plt.title("Image2")
plt.subplot(143)
plt.imshow((pred['label_map']*255).astype('uint8'))
plt.gca().set_axis_off()
plt.title("Pred")
plt.subplot(144)
plt.imshow((np.asarray(Image.open(GT_PATH))*255).astype('uint8'))
plt.gca().set_axis_off()
plt.title("GT")

plt.show()
------------------ Inference Time Info ----------------------
total_time(ms): 39.300000000000004, img_num: 1, batch_size: 1
average latency time(ms): 39.30, QPS: 25.445293
preprocess_time_per_im(ms): 10.20, inference_time_per_batch(ms): 29.00, postprocess_time_per_im(ms): 0.10

.10

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fniF7uEa-1681617966714)(main_files/main_30_1.png)]

10.总结

以下为本次特训营所要求的验收结果,分别采取6种不同的模型对LEVIRCD数据集进行训练并评估模型精度

epoch均为20,其余超参数相同

在20轮次的训练当中,SNUNet模型表现最好,BIT,P2V次之,但理论上来说P2V的模型更加强大,由于时间原因训练轮次不足,未发挥出模型的强大性能,用户可根据自身需要增加epoch以及batchsize,进行更多参数的调整来发挥模型更高的性能,来达到提升精度的目的

模型BITSNUNetCDNETSTANetFCCDNP2V
精度87.97%89.00%83.16%83.40%81.49%87.92%

本项目参考了古代飞的一些关于paddlers的训练教程

感谢我的老哥同时也是好师傅KeyK孔佬的耐心指导与帮助

本文中模型介绍及网络架构图片参考孔佬的github,请狠狠的star传送门https://github.com/kongdebug
本文章为转载
原文连接

Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐