Remote Sensing Image Deep Learning Sample Pair Production Tutorial 3——Download training data from GEE

The previous article introduced common techniques for making deep learning sample pairs for remote sensing images. However, not all data is so regular in actual use. For example, the input data and labels may have inconsistent spatial ranges. Follow the official account GeodataAnalysisand reply to 20230526 to get sample data and codes. The codes of this series are all put together, and it is easier to understand the codes by running them.

When the spatial range of the input data and the label is inconsistent, it is necessary to consider whether the pixels of the two have one-to-one correspondence in space, and then use different methods to process the data:

  • When one-to-one correspondence is possible: directly extract the overlapping range of the two, and make labels based on the overlapping parts.
  • When one-to-one correspondence is not possible: resample to make one-to-one correspondence.

So in general, there are only three key steps, extracting the overlapping range, making labels according to the overlapping part using the method of Tutorial 1, and resampling. The following introduces these three points separately. If you want to know more about it, you can download the code and data and run it yourself. Here only the key steps are introduced, and there are not many specific introductions.

1 Calculate the overlapping range of two images

The two images required here must have one-to-one correspondence between pixels. For example, the neutralization of the sample data is an example where the LC08_L1TP_018030_20150907_20200908_02_T1_B1.TIFspatial LC08_L1TP_018030_20150923_20200908_02_T1_B1.TIFrange is inconsistent, but the pixels are one-to-one correspondence.

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 Make samples based on overlapping ranges

data preparation.

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)

Sample making.

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 resampling

The resolution of sample data 1 is 30 meters, and the resolution of sample data 2 is 480 meters (the land cover data downloaded in Tutorial 2). If there is a one-to-one correspondence between the two pixels, one pixel of the sample will cover 16 of the sample 1. pixels, but the current data is biased, so first resample example 2.

read data.

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

Obtain the coordinate information of Example 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)

Computes the number of rows and columns of the example after resampling.

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

Calculate the spatial extent after resampling for Example 2.

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

Calculate the GeoTransform after resampling in Example 2, that is, the six parameters of the affine transformation.

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]
)

Perform resampling, and save as 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)

Guess you like

Origin blog.csdn.net/weixin_44785184/article/details/130888295