You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rasterio裁剪后栅格较掩膜栅格各维度大1像素问题咨询

问题

我拥有两个尺寸不同的栅格,需将较大栅格裁剪至与较小栅格的x/y维度(而非仅经纬度范围)完全匹配。现有代码接近实现需求,但裁剪后的栅格各维度仍比掩膜栅格大1像素(754x879 vs 753x878)。为何两者维度不一致?

另外发现两个输入栅格的transform略有差异,是否因此导致栅格范围一致但维度不同?

附代码:

import rasterio
import geopandas as gpd
from shapely.geometry import box
from rasterio.mask import raster_geometry_mask
import json

masking_raster = rasterio.open(path/to/file)
raster_to_mask = rasterio.open(path/to/file)

bbox = box(*masking_raster.bounds)
geo = gpd.GeoDataFrame({'geometry': bbox}, index=[0], crs=val_file.crs)
bbox_json = json.loads(gdf.to_json())['features'][0]['geometry']

masked_array, out_transform, window = raster_geometry_mask(val_file, shapes=[bbox_json], crop=True, all_touched=False)
print("masking raster shape: ", masking_raster.shape)
# masking raster shape:  (753, 878)
print("resulting masked array shape: ", masked_array.shape)
# resulting masked array shape:  (754, 879)
分析与解决

核心原因

  • Transform差异导致像素错位:两个栅格的transform参数不一致,意味着像素网格的原点或分辨率存在细微偏差。用掩膜栅格的边界框裁剪时,目标栅格的像素无法与掩膜栅格完全对齐,裁剪范围会额外包含边界处的一行/列像素,最终维度多1。
  • all_touched=False的判定逻辑:该参数仅保留完全落在边界内的像素,但由于transform偏差,边界附近的目标栅格像素可能处于“部分包含”的临界状态,反而被纳入结果,导致维度增加。

精准匹配维度的解决方案

直接利用掩膜栅格的行列范围进行窗口裁剪,跳过边界框计算,确保维度完全一致:

import rasterio

masking_raster = rasterio.open("path/to/masking_raster.tif")
raster_to_mask = rasterio.open("path/to/raster_to_mask.tif")

# 基于掩膜栅格的宽高创建精确窗口
target_window = rasterio.windows.Window.from_slices(
    (0, masking_raster.height),
    (0, masking_raster.width)
)

# 读取目标栅格的对应窗口区域,同时获取匹配的transform
cropped_data = raster_to_mask.read(window=target_window)
output_transform = rasterio.windows.transform(target_window, raster_to_mask.transform)

# 验证维度
print("masking raster shape: ", masking_raster.shape)
print("cropped array shape: ", cropped_data.shape[1:])  # 忽略波段维度,只看行列

跨CRS场景的处理

如果两个栅格的坐标系(CRS)不同,需要先将目标栅格重投影到掩膜栅格的CRS和transform参数,再裁剪:

from rasterio.warp import calculate_default_transform, reproject, Resampling

masking_raster = rasterio.open("path/to/masking_raster.tif")
raster_to_mask = rasterio.open("path/to/raster_to_mask.tif")

# 强制对齐到掩膜栅格的尺寸、transform和CRS
dst_crs = masking_raster.crs
dst_transform = masking_raster.transform
dst_width, dst_height = masking_raster.width, masking_raster.height

# 重投影并保存
with rasterio.open(
    "aligned_raster.tif", "w",
    driver="GTiff",
    height=dst_height,
    width=dst_width,
    count=raster_to_mask.count,
    dtype=raster_to_mask.dtypes[0],
    crs=dst_crs,
    transform=dst_transform,
) as dst_dataset:
    for band_idx in range(1, raster_to_mask.count + 1):
        reproject(
            source=rasterio.band(raster_to_mask, band_idx),
            destination=rasterio.band(dst_dataset, band_idx),
            src_transform=raster_to_mask.transform,
            src_crs=raster_to_mask.crs,
            dst_transform=dst_transform,
            dst_crs=dst_crs,
            resampling=Resampling.nearest,  # 根据需求选择重采样方式
        )

内容的提问来源于stack exchange,提问作者Darren C.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 19:23:18