两个图像之间重叠标签的数量 - Python / NumPy

时间:2017-08-25 17:45:47

标签: python opencv numpy image-processing computer-vision

我正在尝试使用opencv来解决以下问题。作为输入,我将有两个png文件,每个像素设置为0到10之间的值。对于11个值中的每一个,我想看看两个输入文件之间有多少像素重叠。例如,假设img1.png将像素(0,0)到(0,26)设置为值3. img2.png具有像素(0,2)到(0,30)和(1,0)到(1,5)设置为3.因此img1有27个像素设置为3. img2有35个像素设置为3.其中,有25个重叠像素,即从(0,2)到(0)的像素0,26)。

我想要的是一种快速提取此信息的方法:0-10值的像素重叠多少?每个图像有多少像素值0-10?使用此信息,我想为每个值制定某种重叠分数。

我天真地知道,我可以在每个图像上逐个像素地查看,并使用累加器计算此信息。但似乎这会非常慢,opencv允许对图像进行numpy数组索引,所以我知道可能有一种加速这些计算的方法。但是,我不熟悉opencv或numpy,我不太清楚如何解决这个问题。

目前将此视为参考:http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_core/py_basic_ops/py_basic_ops.html

1 个答案:

答案 0 :(得分:2)

方法#1:第一种方法将涉及以下步骤:

  • 获取两个数组(图像数组)之间相等的掩码。

  • 获取其中一个数组与标签范围之间相等的掩码。

  • 最后得到前两个步骤中获得的两个数组之间的张量和减少,给出了所有标签的计数。

因此,我们将有一个向量化解决方案 ab - 使用NumPy broadcastingnp.einsum进行张量和减少,就像这样 -

def overlap_count(a, b, num_label):
    eq_mask = a==b
    id_mask = a == np.arange(num_label)[:,None, None]
    count = np.einsum('ij,aij->a',eq_mask, id_mask.astype(int))
    return count

示例运行 -

In [95]: a
Out[95]: 
array([[0, 1, 2, 1],
       [2, 0, 2, 2],
       [0, 1, 1, 0]])

In [96]: b
Out[96]: 
array([[0, 0, 1, 1],
       [1, 1, 1, 0],
       [1, 0, 1, 0]])

In [97]: overlap_count(a, b, num_label=3)
Out[97]: array([2, 2, 0])

方法#2:我们可以使用np.bincount改进内存效率的第一种方法,从而提高性能。这个想法是 - 我们可以避免创建庞大的数组id_mask,而是通过eq_mask的缩放版本来计算。此缩放版本将通过其中一个数组的值进行缩放。现在,这会为0标记的像素计算更多的数量,因此我们会分别计算这些像素。

因此,第二种方法看起来像这样 -

def overlap_count_improved(a, b, num_label):
    eq_mask = a==b
    r = a * eq_mask
    count = np.bincount(r.ravel())
    count[0] = (eq_mask*(a == 0)).sum() 
    # or count[0] = np.einsum('ij,ij->', eq_mask, (a==0).astype(int))
    return count