import rasterio from rasterio.windows import Window import geopandas as gpd from shapely.geometry import box import numpy as np import os # 参数设置 image_path = 'path/to/your/image.tif' # 替换为您的影像路径(20000x20000) shapefile_path = 'path/to/your/shapefile.shp' # 替换为您的图斑Shapefile路径 output_dir = 'path/to/output/tiles' # 输出切片目录 tile_size = 1024 # 固定切片大小 max_overlap_ratio = 0.2 # 重叠小于20% min_step = int(tile_size * (1 - max_overlap_ratio)) # 最小步长 ≈820 # 创建输出目录 os.makedirs(output_dir, exist_ok=True) # 读取影像 with rasterio.open(image_path) as src: image_width, image_height = src.width, src.height assert image_width == 20000 and image_height == 20000, "影像大小不匹配" transform = src.transform # 地理变换矩阵 # 读取图斑数据(假设CRS一致) gdf = gpd.read_file(shapefile_path) # 确保图斑CRS与影像一致,如果不一致需转换:gdf = gdf.to_crs(src.crs) # 初始化切片列表,避免重叠过多 generated_windows = [] for idx, row in gdf.iterrows(): geom = row.geometry # 获取单个图斑多边形 # 计算图斑的边界框 (minx, miny, maxx, maxy) - 像素坐标 minx, miny, maxx, maxy = geom.bounds bbox_width = maxx - minx bbox_height = maxy - miny # 如果图斑太大,无法放入单个1024x1024切片,需处理(这里简单跳过,您可修改) if bbox_width > tile_size or bbox_height > tile_size: print(f"图斑 {idx} 太大 ({bbox_width}x{bbox_height}),跳过或需多切片处理") continue # 计算覆盖完整图斑的最小窗口:居中扩展到1024x1024 center_x = (minx + maxx) / 2 center_y = (miny + maxy) / 2 half_tile = tile_size / 2 win_minx = max(0, center_x - half_tile) win_miny = max(0, center_y - half_tile) win_maxx = min(image_width, center_x + half_tile) win_maxy = min(image_height, center_y + half_tile) # 调整以确保正好1024x1024(如果边界不足,padding或调整) if win_maxx - win_minx < tile_size: win_minx = max(0, win_maxx - tile_size) if win_maxy - win_miny < tile_size: win_miny = max(0, win_maxy - tile_size) proposed_window = Window(win_minx, win_miny, tile_size, tile_size) # 检查与现有窗口的重叠,确保<20% too_much_overlap = False for existing_win in generated_windows: # 计算重叠区域 overlap_x = max(0, min(win_minx + tile_size, existing_win.col_off + tile_size) - max(win_minx, existing_win.col_off)) overlap_y = max(0, min(win_miny + tile_size, existing_win.row_off + tile_size) - max(win_miny, existing_win.row_off)) overlap_area = overlap_x * overlap_y if overlap_area > (tile_size * tile_size * max_overlap_ratio): too_much_overlap = True break if too_much_overlap: # 如果重叠太大,调整位置(这里简单跳过,您可实现更复杂的调整,如偏移步长) print(f"图斑 {idx} 的窗口重叠过多,跳过或调整") continue # 添加到列表 generated_windows.append(proposed_window) # 裁剪并保存切片 tile_data = src.read(window=proposed_window) tile_meta = src.meta.copy() tile_meta.update({ 'width': proposed_window.width, 'height': proposed_window.height, 'transform': rasterio.windows.transform(proposed_window, src.transform) }) output_path = os.path.join(output_dir, f'tile_{idx}.tif') with rasterio.open(output_path, 'w', **tile_meta) as dst: dst.write(tile_data) print(f"生成切片 {output_path},覆盖图斑 {idx}") print(f"总共生成 {len(generated_windows)} 个切片") # 注意:这个代码确保每个切片包含至少一个完整图斑,但可能有图斑被多个切片覆盖(如果重叠允许)。如果需要覆盖所有图斑的最优 tiling,请提供更多细节。