リモートセンシング画像ディープラーニングサンプルペア作成チュートリアル 3——GEE からトレーニング データをダウンロード

前回の記事では、リモート センシング画像用のディープ ラーニング サンプル ペアを作成するための一般的な手法を紹介しましたが、実際の使用ではすべてのデータがそれほど規則的であるわけではなく、たとえば、入力データとラベルの空間範囲が一貫していない場合があります。公式アカウントをフォローしてGeodataAnalysis20230526にリプライするとサンプルデータとコードが入手できます このシリーズのコードは全てまとめてあり、実際に実行してみると理解しやすくなります。

入力データとラベルの空間範囲が一致しない場合は、2 つのピクセルが空間内で 1 対 1 対応するかどうかを検討し、さまざまな方法を使用してデータを処理する必要があります。

  • 1対1の対応が可能な場合:両者の重複範囲を直接抽出し、重複部分に基づいてラベルを作成します。
  • 1対1対応できない場合:リサンプリングして1対1対応させます。

したがって、基本的に重要なステップは、重複範囲の抽出、チュートリアル 1 の方法を使用した重複部分に応じたラベルの作成、およびリサンプリングの 3 つだけです。以下では、これら 3 つのポイントを個別に紹介します。さらに詳しく知りたい場合は、コードとデータをダウンロードして自分で実行してください。ここでは重要な手順のみを紹介し、具体的な紹介はあまりありません。

1 2枚の画像の重なる範囲を計算する

ここで必要となる 2 つの画像は、ピクセルが 1 対 1 に対応している必要があり、たとえば、サンプル データの無力化は、空間範囲が一致していないものの、ピクセルが 1 対LC08_L1TP_018030_20150907_20200908_02_T1_B1.TIF1LC08_L1TP_018030_20150923_20200908_02_T1_B1.TIFに対応している例です。

def overlap(src1, src2):
    gt = src1.transform
    w, h = src1.width, src1.height
    src1_extent = (gt[2], gt[2]+gt[0]*w, gt[5], gt[5]+gt[4]*h)
    
    gt = src2.transform
    w, h = src2.width, src2.height
    src2_extent = (gt[2], gt[2]+gt[0]*w, gt[5], gt[5]+gt[4]*h)

    mask_extent = (
        max((src1_extent[0], src2_extent[0])), # west
        min((src1_extent[1], src2_extent[1])), # east
        min((src1_extent[2], src2_extent[2])), # north
        max((src1_extent[3], src2_extent[3]))  # south
    )

    min_row, min_col = src1.index(mask_extent[0], mask_extent[2])
    max_row, max_col = src1.index(mask_extent[1], mask_extent[3])
    src1_window = Window.from_slices((min_row, max_row), (min_col, max_col))

    min_row, min_col = src2.index(mask_extent[0], mask_extent[2])
    max_row, max_col = src2.index(mask_extent[1], mask_extent[3])
    src2_window = Window.from_slices((min_row, max_row), (min_col, max_col))

    src1_array = src1.read(1, window=src1_window)
    src2_array = src2.read(1, window=src2_window)

    src1_mask = np.ones(shape=src1_array.shape[-2:])
    mask = src1_array==src1.nodata
    src1_mask[mask] = 0
    src2_mask = np.ones(shape=src2_array.shape[-2:])
    mask = src2_array==src2.nodata
    src2_mask[mask] = 0

    mask = (src1_mask == 1) & (src2_mask == 1)

    transform = from_bounds(mask_extent[0], mask_extent[-1], mask_extent[1], 
                            mask_extent[-2], mask.shape[1], mask.shape[0])

    return src1_window, src2_window, mask, transform

2 重複する範囲に基づいてサンプルを作成する

データの準備。

ids = ['LC08_L1TP_018030_20150907_20200908_02_T1', 'LC08_L1TP_018030_20150923_20200908_02_T1']
id_types = ['img', 'label']

img_src = rio.open(f'./data/{
      
      ids[0]}/{
      
      ids[0]}_B1.TIF')
label_src = rio.open(f'./data/{
      
      ids[1]}/{
      
      ids[1]}_B1.TIF')

img_window, label_window, mask, transform = overlap(img_src, label_src)

サンプル作り。

image_size, slide = 256, 256
# 用于记录每个影像块的位置
df = pd.DataFrame(columns=['patch', 'id', 'row', 'col', 'image_size', 'type'])

patch_num = 0
patch_pair = 1

height, width = mask.shape
for row in range((height - image_size) // slide + 1):
    for col in range((width - image_size) // slide + 1):
        for window, id, id_type in zip([img_window, label_window], ids, id_types):
            patch_row = window.row_off + row*slide
            patch_col = window.col_off + col*slide
            mask_patch = mask[row*slide: row*slide + image_size, 
                              col*slide: col*slide + image_size]
            if not np.all(mask_patch):
                break
            df.loc[patch_num, 'patch'] = patch_pair
            df.loc[patch_num, 'type'] = id_type
            df.loc[patch_num, 'id'] = id
            df.loc[patch_num, 'row'] = patch_row
            df.loc[patch_num, 'col'] = patch_col
            if patch_num % 2 == 1:
                patch_pair += 1
            patch_num += 1
df['image_size'] = image_size
df.head()

3 リサンプリング

サンプル データ 1 の解像度は 30 メートル、サンプル データ 2 の解像度は 480 メートル (チュートリアル 2 でダウンロードした土地被覆データ)、2 つのピクセルが 1 対 1 で対応している場合、サンプル データ 1 の解像度は 480 メートルです。サンプルはサンプル 1 の 16 ピクセルをカバーしますが、現在のデータには偏りがあるため、最初に例 2 をリサンプルします。

データを読み取ります。

src1 = rio.open(path1)
src2 = rio.open(path2)

例1の座標情報を取得します。

gt = src1.transform
w, h = src1.width, src1.height
src1_extent = (gt[2], gt[2]+gt[0]*w, gt[5], gt[5]+gt[4]*h)

リサンプリング後の例の行数と列数を計算します。

src2_res = src2.transform[0]
src2_w = (src1_extent[1] - src1_extent[0]) // src2_res
src2_h = (src1_extent[2] - src1_extent[3]) // src2_res

例 2 のリサンプリング後の空間範囲を計算します。

src2_extent = [src1_extent[0], src1_extent[0]+src2_w*src2_res,
               src1_extent[2], src1_extent[2]-src2_h*src2_res]

例 2 のリサンプリング後の GeoTransform、つまりアフィン変換の 6 つのパラメーターを計算します。

dst_transform, dst_width, dst_height = calculate_default_transform(
    src_crs=src2.crs,
    dst_crs=src2.crs,
    width=src2_w,
    height=src2_h,
    left=src2_extent[0],
    bottom=src2_extent[3],
    right=src2_extent[1],
    top=src2_extent[2]
)

リサンプリングを実行し、tif として保存します。

dst_array = np.empty((dst_height, dst_width), dtype=np.uint8)
reproject(
    # 源文件参数
    source=src2.read(1),
    src_crs=src2.crs,
    src_transform=src2.transform,
    # 目标文件参数
    destination=dst_array,
    dst_transform=dst_transform,
    dst_crs=src2.crs,
    num_threads=1
)
array_to_tif('reproject.tif', dst_array, src2.crs, dst_transform)

おすすめ

転載: blog.csdn.net/weixin_44785184/article/details/130888295