Python numpy 数组——关闭最小区域

标签 python numpy mathematical-morphology

我有一个代表图像的 2D bool numpy 数组,我在其上调用 skimage.measure.label标记每个分段区域,给我一个 int [0,500] 的二维数组;该数组中的每个值代表该像素的区域标签。我现在想删除最小的区域。例如,如果我的输入数组的形状是 (n, n),我希望所有 < m 像素的标记区域都包含在更大的周围区域中。例如,如果 n=10 和 m=5,我的输入可能是,

0, 0, 0, 0, 0, 0, 0, 1, 1, 1
0, 0, 0, 0, 0, 0, 0, 1, 1, 1
0, 0, 7, 8, 0, 0, 0, 1, 1, 1
0, 0, 0, 0, 0, 0, 0, 1, 1, 1
0, 0, 0, 0, 0, 2, 2, 2, 1, 1
4, 4, 4, 4, 2, 2, 2, 2, 1, 1
4, 6, 6, 4, 2, 2, 2, 3, 3, 3
4, 6, 6, 4, 5, 5, 5, 3, 3, 5
4, 4, 4, 4, 5, 5, 5, 5, 5, 5
4, 4, 4, 4, 5, 5, 5, 5, 5, 5

然后输出是,

0, 0, 0, 0, 0, 0, 0, 1, 1, 1
0, 0, 0, 0, 0, 0, 0, 1, 1, 1
0, 0, 0, 0, 0, 0, 0, 1, 1, 1  # 7 and 8 are replaced by 0
0, 0, 0, 0, 0, 0, 0, 1, 1, 1
0, 0, 0, 0, 0, 2, 2, 2, 1, 1
4, 4, 4, 4, 2, 2, 2, 2, 1, 1
4, 4, 4, 4, 2, 2, 2, 3, 3, 3  # 6 is gone, but 3 remains
4, 4, 4, 4, 5, 5, 5, 3, 3, 5
4, 4, 4, 4, 5, 5, 5, 5, 5, 5
4, 4, 4, 4, 5, 5, 5, 5, 5, 5

我研究了 skimage 形态学操作,包括 binary closing ,但似乎都不适用于我的用例。有什么建议吗?

最佳答案

您可以通过对每个标签对应的 bool 区域执行二元膨胀来实现此目的。通过这样做,您将找到每个区域的邻居数量。然后,您可以使用它根据需要替换值。

示例代码:

import numpy as np
import scipy.ndimage

m = 5

arr = [[0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
       [0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
       [0, 0, 7, 8, 0, 0, 0, 1, 1, 1],
       [0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
       [0, 0, 0, 0, 0, 2, 2, 2, 1, 1],
       [4, 4, 4, 4, 2, 2, 2, 2, 1, 1],
       [4, 6, 6, 4, 2, 2, 2, 3, 3, 3],
       [4, 6, 6, 4, 5, 5, 5, 3, 3, 5],
       [4, 4, 4, 4, 5, 5, 5, 5, 5, 5],
       [4, 4, 4, 4, 5, 5, 5, 5, 5, 5]]
arr = np.array(arr)
nval = np.max(arr) + 1

# Compute number of occurances of each number
counts, _ = np.histogram(arr, bins=range(nval + 1))

# Compute the set of neighbours for each number via binary dilation
c = np.array([scipy.ndimage.morphology.binary_dilation(arr == i)
              for i in range(nval)])

# Loop over the set of arrays with bad count and update them to the most common
# neighbour
for i in filter(lambda i: counts[i] < m, range(nval)):
    arr[arr == i] = np.argmax(np.sum(c[:, arr == i], axis=1))

这给出了预期的结果:

>>> arr.tolist()
[[0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 2, 2, 2, 1, 1],
 [4, 4, 4, 4, 2, 2, 2, 2, 1, 1],
 [4, 4, 4, 4, 2, 2, 2, 3, 3, 3],
 [4, 4, 4, 4, 5, 5, 5, 3, 3, 5],
 [4, 4, 4, 4, 5, 5, 5, 5, 5, 5],
 [4, 4, 4, 4, 5, 5, 5, 5, 5, 5]]

关于Python numpy 数组——关闭最小区域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46043048/

相关文章:

image-processing - 带有零结构元素的腐 eclipse /扩张图像

python - 过滤要替换为其列索引的值

numpy - 方程组,非平方

c++ - 在 C、C++ 中实现腐 eclipse 、膨胀

image-processing - 图像膨胀和腐 eclipse 的实现

python - NumPy 直方图 - ValueError 范围参数必须是有限的 - 输入数组没问题

python - 如何让PyPI自动安装依赖

python - flask-mongoengine 中的聚合

python - 如何使用 pandas groupby.filter 保留至少一个值小于 24 的组

python - 调整具有特定值的数组的大小