我有一个二进制(0-1)3D numpy数组,我打算将其用于遮罩3D图像。此刻的面具位于圆柱体区域。面的两个中心是两个任意点,并且轴不平行于x,y或z。 我该如何用纯的numpy解决方案填充圆柱体?
答案 0 :(得分:1)
鉴于圆柱为凸形,可以遍历除1维之外的所有维,并将问题简化为1D。在那里(在1D模式下),编写一种有效的方法来填补空白很容易,因为本质上所有需要的就是找到边界的位置(可以用numpy.where()
完成),然后从中填充所有内容。最小和最大坐标。
这是针对N维问题在pymrt.geometry.fill_convex()
中实现的(pypi
版本中尚不可用,需要从Bitbucket存储库中获取)。
免责声明,我是它的主要作者。
简而言之,(简化的)代码(适用于3D)如下所示:
def fill_convex(arr):
for i in range(arr.shape[1]):
for j in range(arr.shape[2]):
mask = slice(None), slice(i, i + 1), slice(j, j + 1)
line = arr[mask]
k = np.where(line > 0)[0]
if len(k):
start, stop = np.min(k), np.max(k)
line[start:stop] = 1
return arr
要在实际的混凝土(但是是2D而非圆柱形/椭圆形)示例中看到此效果,
import numpy as np
import pymrt as mrt
import pymrt.geometry
# generate a convex border (although it is not elliptical)
points = ((1, 1), (0, 6), (5, 4), (4, 2))
line_points = tuple(x for x in mrt.geometry.bresenham_lines(points, True))
arr = mrt.geometry.render_at((8, 8), line_points)
print(arr.astype(int))
# [[0 0 0 0 1 1 1 0]
# [0 1 1 1 0 0 1 0]
# [0 1 0 0 0 1 0 0]
# [0 0 1 0 0 1 0 0]
# [0 0 1 0 1 0 0 0]
# [0 0 0 1 1 0 0 0]
# [0 0 0 0 0 0 0 0]
# [0 0 0 0 0 0 0 0]]
# fill everything inside the convex shape
arr = mrt.geometry.fill_convex(arr)
print(arr.astype(int)
# [[0 0 0 0 1 1 1 0]
# [0 1 1 1 1 1 1 0]
# [0 1 1 1 1 1 0 0]
# [0 0 1 1 1 1 0 0]
# [0 0 1 1 1 0 0 0]
# [0 0 0 1 1 0 0 0]
# [0 0 0 0 0 0 0 0]
# [0 0 0 0 0 0 0 0]]
答案 1 :(得分:0)
如果已标记了表面单元,并且没有其他信息,则逐层扫描阵列以获取第一个标记单元(如果已知,则获取一些表面单元)。
标记A [z,y,x]表面单元后,在最后一个维度(x)1d数组中填充线,直到遇到新的标记单元为止。
然后在同一顶层(相同的z,靠近y和x)中找到相邻标记的单元格,并重复填充线,直到整个部分(椭圆形或切割的椭圆形)被填充,然后继续下一个z层>
修改
也许我使问题复杂化了,FloodFill算法是简单的解决方案。