计算数组中组件/对象的数量

Posted

技术标签:

【中文标题】计算数组中组件/对象的数量【英文标题】:Counting the number of components/objects in an array 【发布时间】:2021-08-30 05:49:35 【问题描述】:

我想知道什么是计算矩阵中组件数量的好方法。假设一个构成一个组件,而零构成背景。所以在下面的数组中有 4 个组件:

a = np.array([
    [1,1,0,0,0,0,0,0],
    [1,1,1,0,0,0,1,0],
    [0,1,0,0,0,1,1,1],
    [0,0,0,0,0,1,1,1],
    [0,1,0,0,0,0,1,0],
    [0,0,0,1,1,0,0,0],
    [0,0,1,1,0,0,0,0]])

我知道我可以像这样使用 Scipy 做到这一点:

from scipy.ndimage import label

labeled_array, num_features = label(a)

num_features 会给我正确答案 4。

我将如何自己实现它?我在问正确的技术是什么。最好我想用矩阵运算(例如 Numpy 解决方案)来实现这一点。因此,我没有单独检查每个值的 for 循环。

我问这个是因为最后我想在 Tensorflow 中实现解决方案,这样整个事情都是可区分的。通过这种方式,我可以在图像分割问题的损失函数中添加组件的数量作为一个术语,这是我的最终目标。

我想到了使用形态腐蚀来缩小矩阵中的组件,直到只剩下 1 个。然后我可以只取数组的总和来计算组件的数量。不幸的是,如果我侵蚀了一个孤立的[[0,0,0],[0,1,0],[0,0,0]],它将删除它([[0,0,0],[0,0,0],[0,0,0]])。如果我重复侵蚀,它会继续下去,直到没有剩下的组件。我还认为我可以使用骨架化,以保证始终保持中心点?但我不确定这是否是正确的技术,以及我将如何实现它。

我想知道是否有人对这个问题有任何想法或知道如何解决它。任何意见将不胜感激!

【问题讨论】:

【参考方案1】:

这可以使用洪水填充算法在线性时间内完成。这是一个例子:

count = 0
for i in range(a.shape[0]):
    for j in range(a.shape[1]):
        if a[i, j] == 1:
            floodFill(a, i, j)
            count += 1

虽然此解决方案使用循环,但您可以使用 Numba 或 Cython 来降低函数调用和循环的成本。生成的代码应该非常快。

在 Numpy 中没有洪水填充算法,但在 OpenCV 或 scikit-image 等几个图像包中都有一个。只要您使用 Cython 或 Numba 来加速它,您就可以编写自己的实现。

实际上,此操作称为分段,AFAIK 可以直接在 OpenCV 中一次性完成。应用后,您可以使用 Numpy 操作轻松计算标记区域(使用 count = len(np.unique(segmentedResult.flatten())) 之类的东西。

我非常怀疑曾经在这里仅使用基于矩阵的 Numpy 函数可以编写高效代码。假设它可以正常工作,形态侵蚀方法将花费二次时间。一个好的标量算法有时可以胜过任何向量化的低效算法。

【讨论】:

以上是关于计算数组中组件/对象的数量的主要内容,如果未能解决你的问题,请参考以下文章

计算数组中不同元素数量的最快方法

VueJs 组件的 Prop 相关计算属性对对象数组 Prop 更改没有反应

如何循环遍历传递给具有 Vuex 存储和计算属性的组件的对象数组?

Javascript - 计算对象数组中的重复项并将计数存储为新对象

编辑从计算属性返回的数组中的对象

计算存储为 Hive 字符串列的 JSON 数组中的对象数