用唯一值填充3D NUMPY阵列中的横向不连续轮廓

guicsvcw  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(79)

我有一个3d numpy数组,x,y和深度作为维度。这是一个包含各种对象标签的二进制数组。这些标签目前不是唯一的(所有对象的标签都是1),但它们表示的对象彼此之间是唯一的。我用二进制数组提取了每个物体的轮廓。我的目标是为每个等高线区域指定唯一的值。
对于一个简单的2d示例,我将创建一个具有横向不连续轮廓的numpy数组,类似于真实的数据:

countour_array = np.array([[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,1,1,1,1,1,1,1],
                           [0,0,0,0,0,0,0,0,0,0,0,0,0],
                           [1,1,1,1,1,0,0,0,0,0,0,0,0],
                           [0,0,0,0,0,1,0,0,0,0,0,0,0],
                           [0,0,0,0,1,0,0,0,0,0,0,0,0],
                           [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],
                           [1,1,1,1,1,1,1,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]])

字符串
以及contour_array的matplotlib图,以便于查看:


的数据
这就是预期的输出:

mask_array = np.array([[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,1,1,1,1,1,1,1],
                       [1,1,1,1,1,1,1,1,1,1,1,1,1],
                       [2,2,2,2,2,1,1,1,1,1,1,1,1],
                       [2,2,2,2,2,2,1,1,1,1,1,1,1],
                       [2,2,2,2,2,1,1,1,1,1,1,1,1],
                       [2,2,2,2,1,1,1,1,1,1,1,1,1],
                       [1,1,1,1,1,1,1,1,1,1,1,1,1],
                       [3,3,3,3,3,3,3,3,3,3,3,3,3],
                       [3,3,3,3,3,3,3,3,3,3,3,3,3],
                       [3,3,3,3,3,3,3,3,3,3,3,3,3]])


以及mask_array的matplotlib图,以便于查看:



您可以看到有4个需要标记的唯一对象。标签#2嵌入在标签#1内并且在x方向上横向不连续。标签#1在到达标签#3时也停止。

**编辑:**边界值需要与下面的填充值相同。参见掩模阵列图像。

上面的

是一个2d二进制数组,显示了从实际数据集中提取的轮廓i。正如你所看到的,这些轮廓在x空间中并不总是连续的。

我所尝试的

我的第一次尝试是迭代数据中的每一列,应用.cumsum()生成唯一值,然后使用push()向前填充每一列的数据。代码如下:

# create an empty array for the labels
mask_array = np.zeros_like(contour_array)
# determine shape of data for iteration
xx, yy, d = contour_array.shape
# loop through 3d array
for x in range(xx):
    for y in range(yy):
        # apply cumsum() to assign unique values to each object
        mask_array[x,y,:] = contour_array[x,y,:].cumsum()*contour_array[x,y,:]
        # replace zeros with nulls for for forward fill
        mask_array[x,y,:] = np.where(mask_array[x,y,:] == 0, np.nan, mask_array[x,y,:])
        # apply push to each column to create labels
        mask_array[x,y,:] = push(mask_array[x,y,:])
        # fill remaining nulls with 0
        mask_array[np.isnan(mask_array)] = 0.0


虽然我的代码可能很慢,但如果对象或层在x空间中是连续的,这将工作,但因为它们是不连续的,所以输出是不连续的,并且错过了嵌入对象和连续层之间的变化。

  • 我的第二次尝试 * 是使用上面的代码应用numpy sliding_window_view()移动窗口来尝试捕获横向变化。我真的不能得到这个操作和代码是不好的。
  • 最后 *,我一直在研究使用cv2.fillPoly(),但不确定这是正确的道路。
b4wnujal

b4wnujal1#

可以使用简单的整体填充来标记每个对象的主体,然后清理边界值。

import skimage.segmentation

newval = countour_array.max() + 1
for idx in np.ndindex(countour_array.shape):
    if countour_array[idx] == 0:
        skimage.segmentation.flood_fill(countour_array, idx, newval,
                                        connectivity=1, in_place=True)
        newval += 1

# assign the border values to the object directly below
for idx in np.ndindex(countour_array.shape):
    if countour_array[idx] == 1:
        assert idx[0] < countour_array.shape[0]
        countour_array[idx] = countour_array[idx[0]+1, idx[1]]

# normalize object IDs so they start at zero
countour_array -= 2

个字符

相关问题