2017-08-25 2 views
1

J'essaie d'utiliser opencv pour résoudre le problème suivant. En entrée, j'aurai deux fichiers png avec chaque pixel à une valeur comprise entre 0 et 10. Pour chacune des 11 valeurs, je veux voir combien de pixels de chevauchement il y a entre les deux fichiers d'entrée. Par exemple, disons que img1.png a les pixels (0,0) à (0,26) mis à la valeur 3. img2.png a les pixels (0,2) à (0,30) et (1,0) à travers (1,5) a une valeur de 3. Donc, img1 a 27 pixels à 3. Img2 a 35 pixels à 3. Parmi ceux-ci, il y a 25 pixels qui se chevauchent, à savoir les pixels de (0,2) à (0,26).Nombre d'étiquettes qui se chevauchent entre deux images - Python/NumPy

Ce que je veux est un moyen d'extraire rapidement cette information: Combien de pixels se chevauchent pour les valeurs 0-10? Combien de pixels chaque image a-t-elle avec les valeurs 0-10? En utilisant cette information, je veux formuler une sorte de score de chevauchement pour chaque valeur. Je sais que naïvement, je pourrais regarder pixel par pixel à chaque image, et compter cette information en utilisant des accumulateurs. Mais il semble que ce serait très lent, et opencv permet l'indexation de tableaux numpy pour les images, donc je sais qu'il y a probablement un moyen d'accélérer ces calculs. Cependant, je ne suis pas familier avec opencv ou numpy, et je ne suis pas sûr de savoir comment s'y prendre.

Actuellement à la recherche cela comme référence: http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_core/py_basic_ops/py_basic_ops.html

Répondre

2

Approche # 1: Première approche impliquerait les étapes suivantes:

  • Obtenez le masque de l'égalité entre les deux tableaux (tableaux d'images) . Obtenez le masque d'égalité entre l'un des tableaux et la gamme d'étiquettes.

  • Enfin obtenir la réduction somme-tenseur entre les deux tableaux obtenus dans les deux étapes précédentes, ce qui nous donne le nombre de toutes les étiquettes.

Ainsi, nous aurions une solution vectorisé ab -en utilisant NumPy broadcasting et np.einsum pour la somme de réduction de tenseur, comme si -

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 

run échantillon -

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]) 

Approche n ° 2: Nous pouvons améliorer la première approche sur l'efficacité de la mémoire et par conséquent performance avec np.bincount. L'idée étant - Nous pourrions éviter de créer le grand tableau id_mask, en faisant plutôt le compte sur la version à l'échelle de eq_mask. Cette version mise à l'échelle serait mise à l'échelle par les valeurs de l'un des tableaux. Maintenant, cela ferait beaucoup plus de compter pour les pixels marqués 0, donc nous compterions pour ceux séparément.

Ainsi, cette seconde approche ressemblerait à quelque chose comme ça -

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

Il a fallu un certain temps pour moi de comprendre ce que vous faites ici, mais c'est une façon vraiment intelligente d'aller sur le problème. Merci beaucoup pour l'aide! –