计算数组中组件/对象的数量
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 存储和计算属性的组件的对象数组?