fix: 掩膜降采样计算 — 杜绝 1m 分辨率下 10.5M Point 对象 OOM/假死

真凶定位: prepare_shared_context 第 2982-2988 行
  grid_xx.ravel() → 10.5M 坐标点
  [Point(x,y) for ...] → 创建 10.5M 个 shapely Point (~2 GB)
  within(boundary.unary_union) → 10.5M 次几何测试 O(N×M)
  → 此处假死/卡死/内存爆炸,Kriging 从未开始执行

修复: 掩膜降采样到 ~50K 点 (约 100m 等效分辨率) 计算,
  结果通过 np.kron 升采样回原始分辨率。
  掩膜是布尔值,精度损失可忽略;
  np.kron 的 C 向量化升采样 <1 秒。
This commit is contained in:
duxin
2026-07-08 14:22:34 +08:00
parent 3f023cffd4
commit b8f0625bd9

View File

@ -2978,14 +2978,31 @@ class ContentMapper:
print(f"[共享上下文] 网格: {nx}×{ny} = {nx*ny}")
# ⑥ 水域掩膜布尔矩阵(只此一次
# ⑥ 水域掩膜布尔矩阵(降采样到 ~100m 分辨率计算,避免 1m 下千万级 Point 对象 OOM
mask = None
if boundary_gdf is not None:
mask_pts = np.column_stack((grid_xx.ravel(), grid_yy.ravel()))
_MASK_TARGET_POINTS = 50000 # 掩膜降采样目标点数
_mask_step = max(1, int(np.sqrt(grid_xx.size / _MASK_TARGET_POINTS)))
if _mask_step > 1:
mask_xx = grid_xx[::_mask_step, ::_mask_step]
mask_yy = grid_yy[::_mask_step, ::_mask_step]
print(f"[共享上下文] 掩膜降采样 {_mask_step}×"
f"{mask_xx.shape[1]}×{mask_xx.shape[0]} = {mask_xx.size:,}")
else:
mask_xx, mask_yy = grid_xx, grid_yy
mask_pts = np.column_stack((mask_xx.ravel(), mask_yy.ravel()))
mask_gdf = gpd.GeoDataFrame(
geometry=[Point(x, y) for x, y in mask_pts], crs=self.output_crs
)
mask = mask_gdf.within(boundary_gdf.unary_union).values.reshape(grid_xx.shape)
mask_lowres = mask_gdf.within(boundary_gdf.unary_union).values.reshape(mask_xx.shape)
# 升采样回原始分辨率(最近邻,掩膜是布尔值)
if _mask_step > 1:
mask = np.kron(mask_lowres, np.ones((_mask_step, _mask_step), dtype=bool))
# 裁剪到精确原始尺寸
mask = mask[:grid_xx.shape[0], :grid_xx.shape[1]]
else:
mask = mask_lowres
print(f"[共享上下文] 水域掩膜: {int(mask.sum())}/{mask.size} 点在水域内")
return (grid_xx, grid_yy, mask, bounds, boundary_gdf)