我正在尝试使用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
答案 0 :(得分:2)
方法#1:第一种方法将涉及以下步骤:
获取两个数组(图像数组)之间相等的掩码。
获取其中一个数组与标签范围之间相等的掩码。
最后得到前两个步骤中获得的两个数组之间的张量和减少,给出了所有标签的计数。
因此,我们将有一个向量化解决方案 ab - 使用NumPy broadcasting
和np.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