遥感影像深度学习样本对制作教程1

本文结合实例详细讲解了如何使用Python制作遥感影像深度学习样本对,关注公众号GeodataAnalysis,回复20230427获取示例数据和代码。

受到计算机内存限制,深度学习算法无法直接对大幅影像和标签图像进行训练,因此需要对影像和标签图像进行再处理,将制作好的城市绿地影像和对应标签图像裁剪成一系列相同尺寸的小图像放入模型训练。

常用的裁剪方法有规则格网裁剪和滑动窗口裁剪。规则格网裁剪,也称棋盘裁剪,顾名思义就是将影像裁剪成棋盘形状固定尺寸的小图像,该方法得到的图像比较规则,但是缺点是获取的图像数量较少,如下图a所示;滑动窗口裁剪在格网裁剪的基础上加以改进,通过设置指定的滑动间距进行滑动裁剪。滑动窗口裁剪相比规则格网裁剪可以获得更多的样本数量,能够充分利用城市绿地样本数据集,如下图b所示。

可见,只要将滑动窗口裁剪的滑动间隔设为和图像尺寸相同,那么滑动窗口裁剪就等同于规则裁剪。因此,本文只介绍滑动窗口裁剪。

首先导入必须的包,其中pandas用于存储每个裁剪影像块(patch)的信息,rasterio用于读取和保存栅格影像数据。

import os
import numpy as np
import pandas as pd
import rasterio as rio
from rasterio.windows import Window
from rasterio.transform import from_bounds

确定裁剪影像块的信息

遥感影像深度学习用到的数据一般是公开的,为了方便把自己训练模型的所用的数据分享给别人,不用分享整个数据集,记录每个影像块的信息,分享这个信息就很方便。而且,这也方便后续处理,如从这些影像块中进行筛选去除不合格的影像块。

首先确定影像块尺寸,和滑动间隔。

image_size = 256
slide = 256

读取输入数据和样本数据,判断二者的transform是否相同。若相同,则说明其空间范围一直,分辨率一致,最后记录二者的宽和高。测试数据为landsat 8数据,各个波段分开存储,输入数据和标签数据用的是同一个,仅作为示例。id相当于这副影像的身份信息,可以利用它通过公开渠道下载这幅影像。

# 打开模型输入数据
id1 = 'LC08_L1TP_018030_20150907_20200908_02_T1'
src1 = rio.open(f'./data/{id1}/{id1}_B1.TIF')
# 打开标签数据
id2 = 'LC08_L1TP_018030_20150907_20200908_02_T1'
src2 = rio.open(f'./data/{id2}/{id2}_B1.TIF')

assert src1.transform == src2.transform
# 读取影像的高度和宽度
height, width = src1.height, src1.width

输入数据往往具有nodata值,在训练模型我们有时并不想要输入数据包含nodata值,这时候就需要先创建一个掩膜,记录哪些像元是nodata,用于后续的裁剪。

# 根据输入数据创建掩膜
mask = np.full(shape=(height, width), fill_value=False)
data = src1.read(1)
# 所有空值区域设为True
mask[data==src1.nodata] = True

创建一个pandas的DataFrame,用于记录影像块的信息。

df = pd.DataFrame(columns=['patch', 'id', 'row', 'col', 'image_size', 'type'])

计算每个影像块在整幅影像的相对位置,即影像块的左上角的像元位于整幅影像的第几行第几列。并判断这个影像块是否包含nodata值,决定是否保留。

patct_num = 1
num = 0

for row in range((height - image_size) // slide + 1):
    for col in range((width - image_size) // slide + 1):
        # 读取每个patch的在输入数据的nodata掩膜
        mask_patch = mask[row*slide: row*slide + image_size, 
                          col*slide: col*slide + image_size]
        # 若这个影像块包含nodata,舍弃
        if np.any(mask_patch):
            continue
        # 保存输入影像块
        df.loc[num, 'patch'] = patct_num
        df.loc[num, 'id'] = id1
        df.loc[num, 'row'] = row * slide
        df.loc[num, 'col'] = col * slide
        df.loc[num, 'image_size'] = image_size
        df.loc[num, 'type'] = 'img'
        num += 1
        # 保存标签影像块
        df.loc[num, 'patch'] = patct_num
        df.loc[num, 'id'] = id2
        df.loc[num, 'row'] = row * slide
        df.loc[num, 'col'] = col * slide
        df.loc[num, 'image_size'] = image_size
        df.loc[num, 'type'] = 'label'
        num += 1
        patct_num += 1

划分训练集、验证集、测试集

以下代码按照6:2:2的比例将数据划分为训练集、验证集和测试集。

train_ratio = 6
valid_ratio = 2
test_ratio = 2
split = ['train']*train_ratio*2 + ['val'] * valid_ratio*2 + ['test']*test_ratio*2
split = split * (df.shape[0] // (train_ratio + valid_ratio + test_ratio) + 1)
split = split[:df.shape[0]]
df['split'] = split

根据记录信息裁剪影像块

用于将numpy数组转换为GeoTiff文件保存的函数.

# numpy数组转tif
def array_to_tif(out_path, arr, crs, transform):
    # 获取数组的形状
    if arr.ndim==2:
        count = 1
        height, width = arr.shape
    elif arr.ndim==3:
        count = arr.shape[0]
        _, height, width = arr.shape
    else:
        raise ValueError
    
    with rio.open(out_path, 'w', 
                  driver='GTiff', 
                  height=height, width=width, 
                  count=count, 
                  dtype=arr.dtype, 
                  crs=crs, 
                  transform=transform) as dst:
        # 写入数据到输出文件
        if count==1:
            dst.write(arr, 1)
        else:
            for i in range(count):
                dst.write(arr[i, ...], i+1)

确定需要处理哪一个波段,目前测试数据的各个波段是分开的,后续的文章会介绍分波段存储的文件合并为一个文件。

band = 1

打开记录中的整幅影像,虽然测试中只用了一景影像,即输入和标签是相同的,但实际工作中可能会有很多景,相当于很多个id。注意,这里打开数据并不是将影像的数据读入内存,只是提供一个读取这幅影像数据的入口。

id_l8_srcs = {}
data_dir = './data'
for id in df['id'].unique():
    id_path = os.path.join(data_dir, id, id+f'_B{band}.TIF')
    id_l8_srcs[id] = rio.open(id_path)

创建训练集、验证集、测试集的输出文件夹,并在其中创建标签和输入数据的文件夹。

out_dir = './dataset'

for split in df['split'].unique():
    for type in df['type'].unique():
        split_dir = os.path.join(out_dir, split, type)
        os.makedirs(split_dir, exist_ok=True)

裁剪影像块,并将其保存到它该带待的位置。注意,这里保存的每个影像块都是具有空间坐标信息的,而不只是一个图片,这样就为一些预处理等操作提供了便利。

for patch in df.itertuples():
    l8_src = id_l8_srcs[patch.id]
    # 影像块的窗口
    win = Window.from_slices((patch.row, patch.row+patch.image_size), 
                             (patch.col, patch.col+patch.image_size))
    # 读取影像块的值
    l8_patch_array = l8_src.read(1, window=win)
    # 计算影像块的空间范围
    west, north = l8_src.xy(patch.row, patch.col, offset='ul')
    east, south = l8_src.xy(patch.row+patch.image_size, 
                            patch.col+patch.image_size, offset='ul')
    transform = from_bounds(west, south, east, north, 
                            patch.image_size, patch.image_size)
    # 保存影像块
    out_path = os.path.join(out_dir, patch.split, 
                            patch.type, f'{patch.patch}.TIF')
    array_to_tif(out_path, l8_patch_array, l8_src.crs, transform)

裁剪后的影像块示例:

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
ArcGIS是一款功能强大的地理信息系统软件,在遥感影像深度学习样本制作方面也有一定的应用。当我们需要进行遥感影像深度学习样本制作时,可以利用ArcGIS进行以下步骤: 1. 数据准备:首先,需要获取遥感影像数据集。可以从卫星、航空等数据源中获取高分辨率的图像数据。将数据导入ArcGIS软件进行进一步的处理。 2. 图像预处理:在进行深度学习样本制作之前,需要对图像进行预处理,以便提高深度学习算法的准确性。ArcGIS提供了一系列的图像处理工具,可以进行去噪、边缘增强、图像增强等操作,以提高图像质量。 3. 样本标注:通过在ArcGIS中使用标注工具,我们可以对遥感影像进行目标区域的标注。例如,如果我们想要制作一个遥感影像分类模型,我们可以将图像中不同类别的目标区域进行标注,如建筑物、森林、湖泊等。 4. 数据集划分:将标注好的样本数据集划分为训练集、验证集和测试集。通常,训练集用于训练深度学习模型,验证集用于选择最佳模型和调整参数,测试集用于评估模型的性能。 5. 样本导出:将标注好的样本数据集导出为合适的格式,以便与深度学习框架进行无缝集成。ArcGIS支持将样本数据导出为常见的格式,如GeoTIFF、Shapefile等。 总之,利用ArcGIS进行遥感影像深度学习样本制作可以提供一种方便而高效的方法。通过该软件的图像处理和标注工具,我们可以快速准确地制作出符合我们需求的样本数据集,为后续的深度学习算法提供有力的支持。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值