使用rasterio实现栅格重叠窗口读取与无重叠窗口写入的问题
栅格重叠窗口读取+无重叠写入调整方案
你的核心问题是读取时使用了带重叠的窗口,但写入时直接输出了完整的重叠区域数据,没有裁剪掉边缘重叠部分,也没有对应到原图的正确无重叠位置写入。
调整步骤
1. 修改分块生成逻辑
在生成重叠读取窗口的同时,同步生成每个块对应的无重叠写入窗口,以及处理后数组的裁剪索引:
- 读取窗口:带重叠,用于加载数据做计算,避免边缘伪影
- 写入窗口:无重叠,对应原图中该块的实际写入位置
- 裁剪索引:用于从计算完成的带重叠数组中,抠出中间无重叠的部分
2. 修改写入逻辑
不要为每个块单独创建输出文件,全程只打开一次目标文件,将裁剪后的无重叠数据写入到对应的窗口位置即可。
修改后完整代码
from itertools import product import rasterio from rasterio import windows from rasterio.crs import CRS def overlapping_windows(src, overlap, block_width, block_height): """ 生成带重叠的读取窗口、无重叠的写入窗口、以及数组裁剪索引 :param src: rasterio打开的源文件对象 :param overlap: 重叠像素数 :param block_width: 无重叠块的宽度 :param block_height: 无重叠块的高度 """ col_offsets = range(0, src.width, block_width) row_offsets = range(0, src.height, block_height) big_window = windows.Window(0, 0, src.width, src.height) for col_off, row_off in product(col_offsets, row_offsets): # 1. 计算带重叠的读取窗口 read_col_off = max(0, col_off - overlap) read_row_off = max(0, row_off - overlap) read_width = block_width + overlap * 2 read_height = block_height + overlap * 2 read_window = windows.Window( read_col_off, read_row_off, read_width, read_height ).intersection(big_window) # 2. 计算无重叠的写入窗口(对应原图位置) write_width = min(block_width, src.width - col_off) write_height = min(block_height, src.height - row_off) write_window = windows.Window( col_off, row_off, write_width, write_height ) # 3. 计算处理后数组的裁剪索引:从带重叠的数组中抠出无重叠部分 crop_row_start = row_off - read_row_off crop_row_end = crop_row_start + write_height crop_col_start = col_off - read_col_off crop_col_end = crop_col_start + write_width yield read_window, write_window, (crop_row_start, crop_row_end, crop_col_start, crop_col_end) def process_image(src_img, dst_img, overlap, block_width, block_height, epsg, band_id=1): # 先获取源文件元信息,目标文件和源文件坐标系、尺寸完全一致 with rasterio.open(src_img) as src: out_meta = src.meta.copy() out_meta.update({ 'driver': 'GTiff', 'tiled': True, 'compress': None, 'crs': CRS.from_epsg(epsg) }) # 全程只打开一次目标文件 with rasterio.open(dst_img, 'w', **out_meta) as dst: for read_window, write_window, crop_idx in overlapping_windows(src, overlap, block_width, block_height): # 读取带重叠的窗口数据 src_data = src.read(band_id, window=read_window) # 此处替换为你的实际处理逻辑 dst_data = src_data ** 2 # 裁剪出无重叠部分 crop_row_start, crop_row_end, crop_col_start, crop_col_end = crop_idx write_data = dst_data[crop_row_start:crop_row_end, crop_col_start:crop_col_end] # 写入到目标文件对应的无重叠窗口位置 dst.write(write_data, band_id, window=write_window) return 0 # 调用示例 if __name__ == "__main__": process_image( src_img="输入.tif", dst_img="输出.tif", overlap=1, # 重叠1像素 block_width=256, # 无重叠块宽256 block_height=256, # 无重叠块高256 epsg=4326 # 目标坐标系EPSG )
关键修改说明
- 去掉了原代码中循环内重复创建输出文件的逻辑,避免每个块生成单独文件的错误
- 写入时通过
window参数指定写入位置,保证所有无重叠块刚好拼接成完整的输出影像,无重叠也无空隙 - 自动处理边缘块的裁剪逻辑,边缘处没有足够重叠区域时也不会出现索引错误
内容的提问来源于stack exchange,提问作者FJ_Abbasi
相关产品推荐
相关产品推荐

