DataProcessToolProgram/tools/SpacetySliceDataTools/test.py

98 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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请提供更多细节。