Python:填充空心对象

时间:2012-07-07 15:45:17

标签: python python-2.7

我正在编写一个脚本来计算任意随机形状3D对象的体积。我不在乎物体是否是空心的我需要计算它的总体积。 我拥有的数据模型是一个带有1和0的3D表(像素直方图)。显然,对象是零,零是我们什么都没有。要计算一个填充良好的物体的体积,就像将所有包含一个像素的像素相加并乘以像素体积一样容易。 另一方面,主要的困难仍然是我们有一个空心物体,所以我们有零包围的零。因此,应用我在此描述的直接方法不再有效。我们需要做的是用一个填充所有对象区域。这是一个2D示例,因此您可以理解我的意思

2D表:

0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 1 1 1 1 1 1 0 0 0 
0 0 1 1 0 0 0 1 1 1 0 0 
0 0 0 1 0 0 1 0 0 0 0 0 
0 0 1 0 0 0 0 1 0 0 0 0 
0 0 1 0 0 0 0 1 0 0 0 0 
0 0 1 1 1 1 1 1 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 

我需要将其转换为此

0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 1 1 1 1 1 1 0 0 0 
0 0 1 1 1 1 1 1 1 1 0 0
0 0 0 1 1 1 1 0 0 0 0 0 
0 0 1 1 1 1 1 1 0 0 0 0 
0 0 1 1 1 1 1 1 0 0 0 0 
0 0 1 1 1 1 1 1 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 

5 个答案:

答案 0 :(得分:4)

如果您使用scipy,则可以使用binary_fill_holes在一行中执行此操作。 这适用于n维。以您的示例:

import numpy as np
from scipy import ndimage
shape=np.array([
    [0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,1,1,1,1,1,1,0,0,0],
    [0,0,1,1,0,0,0,1,1,1,0,0],
    [0,0,0,1,0,0,1,0,0,0,0,0],
    [0,0,1,0,0,0,0,1,0,0,0,0],
    [0,0,1,0,0,0,0,1,0,0,0,0],
    [0,0,1,1,1,1,1,1,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0]
    ])
shape[ndimage.binary_fill_holes(shape)] = 1
#Output:
[[0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 1 1 1 1 1 1 0 0 0]
 [0 0 1 1 1 1 1 1 1 1 0 0]
 [0 0 0 1 1 1 1 0 0 0 0 0]
 [0 0 1 1 1 1 1 1 0 0 0 0]
 [0 0 1 1 1 1 1 1 0 0 0 0]
 [0 0 1 1 1 1 1 1 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0]]

答案 1 :(得分:2)

标准flood fill应该可以扩展到三个维度。来自维基百科,大纲中的二维版本:​​

1. If the color of node is not equal to target-color, return.
 2. Set the color of node to replacement-color.
 3. Perform Flood-fill (one step to the west of node, target-color, replacement-color).
    Perform Flood-fill (one step to the east of node, target-color, replacement-color).
    Perform Flood-fill (one step to the north of node, target-color, replacement-color).
    Perform Flood-fill (one step to the south of node, target-color, replacement-color).
 4. Return.

请注意,在步骤3中,您将跟踪所有相邻的单元格。如果你改变它以找到3-d中的所有相邻单元格并像以前一样运行它应该很好地工作。

答案 2 :(得分:1)

matrix=[
    [0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,1,1,1,1,1,1,0,0,0],
    [0,0,1,1,0,0,0,1,1,1,0,0],
    [0,0,0,1,0,0,1,0,0,0,0,0],
    [0,0,1,0,0,0,0,1,0,0,0,0],
    [0,0,1,0,0,0,0,1,0,0,0,0],
    [0,0,1,1,1,1,1,1,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0]
    ]

def fill (x,y):
    global matrix
    if ( x==len (matrix)
             or y==len (matrix[0])
             or x==-1
             or y==-1
             or matrix[x][y]==1 ):
            return
    else:
        matrix[x][y]=1
        fill (x+1,y)
        fill (x-1,y)
        fill (x,y+1)
        fill (x,y-1)

fill (4,4)

for i in matrix:
    print i

答案 3 :(得分:1)

不直观且难以阅读,但紧凑:

matrix = [[0, 0, 0, 0, 0, 0],
          [0, 0, 1, 0, 1, 0],
          [0, 1, 0, 0, 0, 1],
          [0, 0, 0, 0, 0, 0]]

ranges = [1 in m and range(m.index(1), len(m)-list(reversed(m)).index(1)) or None for m in matrix]
result = [[ranges[j] is not None and i in ranges[j] and 1 or 0 for i,a in enumerate(m)] for j,m in enumerate(matrix)]

result
[[0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 0],
 [0, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0]]

答案 4 :(得分:0)

假设你正在谈论填充voxel形状之类的东西,为什么你不能只做这样的事情(把它当作简化2D情况的伪代码示例,因为我不知道什么数据你正在使用的结构 - 也许是numpy.array? - 所以我只是把一个假设的“列表列表作为一个矩阵”,我没有考虑在遍历它时修改一个iterable的问题等等。 ):

for i, row in enumerate(matrix):
    last_filled_voxel_j = false
    for j, voxel in enumerate(row):
        if voxel:
            if last_filled_voxel != false:
                fill_matrix(matrix, i, last_filled_voxel_j, j)
            last_filled_voxel_j = j

...假设fill_matrix(matrix, row, column_start, column_end)只填充了不包括column_startcolumn_end之间的体素行。

我想这可能不是您正在寻找的答案,但是您可以在实际需要之前扩展与我伪编码不同的东西吗?我们可以提供更多帮助吗?