SpacetySliceTools/tools/test.py

98 lines
4.1 KiB
Python
Raw Normal View History

2025-09-22 02:07:45 +00:00
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请提供更多细节。