2

我正在编写一个脚本来计算任何随机形状的 3D 对象的体积。我不在乎物体是否是空心的,我需要计算它的总体积。我拥有的数据模型是一个带有 1 和 0 的 3D 表(像素直方图)。显然是物体所在的地方,而零是我们一无所有的地方。要计算填充良好的对象的体积,只需将所有包含 1 的像素相加并乘以像素体积即可。另一方面,主要的困难仍然是我们有一个空心物体,所以我们有一个被一个包围的零。因此,应用我在此描述的直接方法不再有效。我们需要做的是用 1 填充所有对象区域。这是一个 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 
4

5 回答 5

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]]
于 2012-07-07T19:38:41.583 回答
2

标准的洪水填充应该可以扩展到三个维度。来自维基百科,2-d 版本的大纲:

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 中查找所有相邻单元格并像以前一样运行它应该可以很好地工作。

于 2012-07-07T16:00:44.630 回答
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
于 2012-07-07T16:15:03.100 回答
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]]
于 2012-07-07T16:25:22.143 回答
0

假设您正在谈论诸如填充体素形状之类的事情,为什么您不能这样做(将其作为简化 2D 案例的伪代码示例,因为我不知道您使用的是什么数据结构-也许一个numpy.array? - 所以我只是将一个假设的“列表列表作为矩阵”,并且我没有考虑在遍历它时修改可迭代对象的问题等):

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_startand column_end

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

于 2012-07-07T16:09:30.653 回答