填充的3D numpy蒙版

时间:2018-09-25 12:13:45

标签: python-2.7 numpy geometry

我有一个二进制(0-1)3D numpy数组,我打算将其用于遮罩3D图像。此刻的面具位于圆柱体区域。面的两个中心是两个任意点,并且轴不平行于x,y或z。 我该如何用纯的numpy解决方案填充圆柱体?

2 个答案:

答案 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算法是简单的解决方案。