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

使用numpy meshgrid裁剪图像多边形及尺寸匹配问题求助

解决使用NumPy Meshgrid和Matplotlib Path裁剪多边形区域的问题

我来帮你一步步解决这些问题,核心问题主要是坐标系统对齐、多边形点范围匹配和数组维度顺序这几个关键点:


1. 初始尝试:掩码边界不正确的修正

你的第一版代码里,问题大概率出在图像坐标与Matplotlib Path坐标的y轴方向差异:图像的y轴通常是从上到下递增(y=0是顶部),而Matplotlib Path的y轴是从下到上递增(y=0是底部)。所以需要把多边形的y坐标反转,对齐图像的坐标系。

另外,确保多边形点的顺序是连续的顺时针/逆时针闭合路径(你的点顺序是对的,但要确认没有交叉)。

修正后的代码:

import numpy as np
from matplotlib.path import Path

# 原图像尺寸(包含所有像素的数量)
img_width = 19542  # x从0到19541,共19542个像素
img_height = 14395 # y从0到14394,共14395个像素

# 目标裁剪区域的原图像坐标
xmin, xmax = 4692, 12720
ymin, ymax = 4273, 10117

# 多边形顶点(原图像坐标),反转y轴以匹配Path的坐标系
sar_ver = [
    (4692, img_height - 1 - 10117), 
    (12720, img_height - 1 - 10117), 
    (12658, img_height - 1 - 4274), 
    (4769, img_height - 1 - 4273), 
    (4692, img_height - 1 - 10117)
]

# 生成裁剪区域的网格(对应原图像的x,y坐标)
x_grid, y_grid = np.meshgrid(np.arange(xmin, xmax + 1), np.arange(ymin, ymax + 1))
# 转换为Path需要的坐标系(反转y轴)
y_grid_reversed = img_height - 1 - y_grid

# 扁平化并生成点集
points = np.vstack((x_grid.flatten(), y_grid_reversed.flatten())).T

# 创建路径并生成掩码
path = Path(sar_ver)
mask = path.contains_points(points)
mask = mask.reshape(x_grid.shape)  # shape: (5845, 8029) 与裁剪区域尺寸匹配

2. 更新尝试:掩码原点未偏移的修正

第二版代码的问题有两个:

  • 多边形顶点的x=16886超出了np.arange(nx)的范围(nx=16886对应x从0到16885),导致路径边界错误;
  • 没有明确对齐掩码与目标裁剪区域的坐标原点——如果掩码是针对裁剪后的子图像生成的,需要把多边形顶点的坐标减去裁剪区域的原图像原点。

假设你要裁剪原图像的(x0, y0)到(x0+nx-1, y0+ny-1)区域,修正后的代码:

import numpy as np
from matplotlib.path import Path
from PIL import Image

# 原图像尺寸
img_width = 19542
img_height = 14395

# 目标裁剪区域的原图像原点和尺寸
crop_x0, crop_y0 = 0, 0  # 假设从原图像左上角裁剪nx*ny的区域
nx, ny = 16886, 10079

# 多边形顶点(原图像坐标),转换为裁剪后子图像的相对坐标
sar_ver_original = [
    (16886, 1085), (15139, 2122), (14475, 5226), 
    (8419, 5601), (14046, 6876), (14147, 10079), 
    (16816, 3748), (16886, 1085)
]
# 转换为子图像的相对坐标(减去裁剪原点),同时反转y轴适配Path
sar_ver_relative = [
    (x - crop_x0, (img_height - 1 - y) - (img_height - 1 - (crop_y0 + ny - 1))) 
    for x, y in sar_ver_original
]

# 生成子图像的网格(相对坐标)
x_grid, y_grid = np.meshgrid(np.arange(nx), np.arange(ny))

# 扁平化并生成点集
points = np.vstack((x_grid.flatten(), y_grid.flatten())).T

# 创建路径并生成掩码
path = Path(sar_ver_relative)
mask = path.contains_points(points)
mask = mask.reshape((ny, nx))  # 与子图像shape一致:(10079, 16886)

# 转换为图像保存
mask_img = Image.fromarray((mask * 255).astype(np.uint8))
mask_img.save('grid_image.png')

3. 图像与掩码尺寸不匹配的解决

这个问题的核心是混淆了数组的维度顺序:图像数组的shape是(高度, 宽度),对应(y轴像素数, x轴像素数),而你在裁剪时错误地把x轴放在了第一维度。

另外,确保掩码和图像的shape完全一致后,再进行相乘操作。修正后的代码:

import numpy as np
from PIL import Image

# 加载原图像
binary_file_path = "your_file.bin"
img_width = 19542
img_height = 14395
im = np.fromfile(binary_file_path, dtype='>f4').astype(np.float32)
im = im.reshape((img_height, img_width))  # 注意:shape是(高度, 宽度)=(y, x)

# 假设已经生成了正确的掩码mask,shape与目标子图像一致:(10079, 16886)
# 先裁剪原图像到与掩码相同的尺寸
crop_y0, crop_y1 = 0, 10079
crop_x0, crop_x1 = 0, 16886
im_cropped = im[crop_y0:crop_y1, crop_x0:crop_x1]  # 第一维是y,第二维是x

# 掩码与图像相乘提取目标区域
bb_list = im_cropped * mask.astype(np.float32)

# 裁剪出非零区域(正确的维度顺序)
slice_rows = np.any(bb_list, axis=1)  # 按行(y轴)检查非零
slice_cols = np.any(bb_list, axis=0)  # 按列(x轴)检查非零

ymin, ymax = np.where(slice_rows)[0][[0, -1]]
xmin, xmax = np.where(slice_cols)[0][[0, -1]]

# 提取目标区域
answer = bb_list[ymin:ymax+1, xmin:xmax+1]

# 转换为图像保存(需要归一化到0-255范围)
int_ans = (answer / answer.max() * 255).astype(np.uint8)
fin_img = Image.fromarray(int_ans)
fin_img.save('test_this.jpeg')

关键注意事项总结

  • 坐标系统对齐:始终明确是使用原图像坐标还是裁剪后子图像的相对坐标,同时注意图像y轴与Matplotlib Path y轴的方向差异;
  • 维度顺序:图像数组的shape是(高度, 宽度)(y在前,x在后),所有网格、掩码的shape必须与此保持一致;
  • 多边形点范围:确保多边形顶点的坐标在生成的网格范围内,避免超出边界导致掩码错误。

内容的提问来源于stack exchange,提问作者Atihska

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:14:50