2017-08-25 140 views
1

我正在嘗試使用opencv解決以下問題。作爲輸入,我將有兩個PNG文件,每個像素設置爲0到10之間的值。對於11個值中的每一個,我想看看兩個輸入文件之間有多少像素重疊。例如,假設img1.png將像素(0,0)到(0,26)的值設置爲3. img2.png具有像素(0,2)到(0,30)和(1,0)到(1,5)設置爲值3.因此,img1具有設置爲3的27個像素。img2具有設置爲3的35個像素。其中,有25個重疊像素,即從(0,2)至( 0.26)。計數兩個圖像之間的重疊標籤 - Python/NumPy

我想要的是一種快速提取此信息的方法: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

回答

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 
+0

過了好一會兒,我聽不懂你在這裏做什麼,但是這是要對問題的一個非常聰明的辦法。非常感謝你的幫助! –