7
votes

Manière rapide de tourner une image étiquetée dans un dictionnaire de {label: [coordonnées]}

dire que j'ai étiqueté une image avec scipy.ndimage.mesutions.Label Comme: XXX PRE>

Qu'est-ce qu'un moyen rapide de collecter les coordonnées appartenant à chaque étiquette? C'est à dire. Quelque chose comme: p> xxx pré>

Je travaille avec des images comportant ~ 15 000 x 5 000 pixels de taille, et environ la moitié des pixels de chaque image sont étiquetés (c.-à-d. Non-zéro). p>

plutôt que d'itération à travers l'image entière avec nditer code>, serait-il plus rapide de faire quelque chose comme np.where (étiquette IMG ==) code> pour chaque Étiquette? P>

Edit: p>

Quel algorithme est le plus rapide dépend de la taille de l'image marquée par rapport au nombre d'étiquettes qu'il a. Warren Weckesser et Salvador Dali / Bhat's Méthodes de Irshad (qui sont basés sur np.nonzero code> et np.where code>) tous semblent à échelle linéairement avec le nombre d'étiquettes, alors que l'itération de Chaque élément d'image avec nditer code> échelle évidemment linéairement avec la taille de l'image marquée. p>

Les résultats d'un petit test: P>

size: 1000 x 1000, num_labels: 10
weckesser ... 0.214357852936s 
dali ... 0.650229930878s 
nditer ... 6.53645992279s 


size: 1000 x 1000, num_labels: 100
weckesser ... 0.936990022659s 
dali ... 1.33582305908s 
nditer ... 6.81486487389s 


size: 1000 x 1000, num_labels: 1000
weckesser ... 8.43906402588s 
dali ... 9.81333303452s 
nditer ... 7.47897100449s 


size: 1000 x 1000, num_labels: 10000
weckesser ... 100.405524015s 
dali ... 118.17239809s 
nditer ... 9.14583897591s


5 commentaires

np.where (iMG == étiquette) (ou équivalent np.nonzero (étiquette IMG ==) ) sera plus rapide que itérant avec nditer . Cependant, avez-vous réellement besoin des indices? Si vous souhaitez extraire des valeurs d'un autre tableau, data [iMG == Label] sera plus rapide que i, j = np.where (étiquette IMG ==); Data [j, j] .


@Joekington s'avère np.where ne sera pas toujours plus rapide que itération. Je viens de faire des modifications à ma question qui le reflètent.


Avez-vous éliminé l'utilisation de np.unique des réponses de Salvador Dali et Bhat Irshad?


@Warrenweckesser oui


Related: alternative plus rapide à numpy.where?


4 Réponses :


2
votes

Vous pouvez faire quelque chose comme ceci (let img est votre original nd.array) xxx

qui vous donnera ce que vous voulez: < Pré> xxx

si cela sera plus rapide - est à la hauteur de la référence à déterminer.

par Warren's Suggestion, je n'ai pas besoin d'utiliser unique et de faire xxx


1 commentaires

Parce que img a été calculé à l'aide de scipy.ndimage.mesurements.label () , il n'est pas nécessaire d'appeler np.unique (img) pour obtenir ses valeurs uniques. Nous savons déjà que les valeurs sont 0, 1, 2, ..., num_labels . Num_Labels est également connu, car il s'agit de la deuxième valeur de retour de l'étiquette () . Vous pouvez donc remplacer np.unique (IMG) [1:] avec la plage (1, num_labels + 1) .



0
votes

Essayez ceci:

>>> z
array([[0, 1, 0, 0, 0, 0],
       [0, 1, 0, 0, 0, 0],
       [0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 3, 0],
       [2, 2, 0, 0, 0, 0],
       [2, 2, 0, 0, 0, 0]])
>>> {i:zip(*np.where(z==i)) for i in np.unique(z) if i}
{1: [(0, 1), (1, 1), (2, 1)], 2: [(4, 0), (4, 1), (5, 0), (5, 1)], 3: [(3, 4)]}


3 commentaires

Pourquoi avez-vous besoin si je à la fin de votre compréhension?


Consultez mon commentaire à la réponse de @ Salvadordali sur l'utilisation de np.unique (img) . Vous pouvez remplacer pour i dans np.unique (z) si i avec pour i in gamme (1, num_labels + 1) .


Oh je vois. Le si je exclut les pixels étiquetés comme 0s.



4
votes

Voici une possibilité: xxx

J'ai appelé ce script get_label_indices.py . Voici un échantillon exécutif: xxx


3 commentaires

Je pense que votre méthode est la plus rapide des solutions proposées, mais je n'ai pas encore eu de tests en profondeur. Étonnamment, pour un grand nombre d'étiquettes (environ 30 000), il semble que cela semble itérant à travers chaque pixel d'image (environ 75 000 000 d'entre eux) finissent par être plus rapide. Quand je fais des comparaisons approfondies, je vais mettre à jour ma question avec ce que je trouve.


Je viens de faire une comparaison plus détaillée. Lemme sais ce que tu penses.


@bennlich belle comparaison. J'ai soupçonné que la performance dépendrait fortement de la densité des étiquettes et du nombre d'étiquettes uniques.



0
votes

Ceci est fondamentalement une opération argsort code>, avec quelques travaux supplémentaires pour obtenir le format souhaité:

def sorting_based(img, nlabels):
    img_flat = img.ravel()

    label_counts = np.bincount(img_flat)
    lin_idx = np.argsort(img_flat)[label_counts[0]:]
    coor = np.column_stack(np.unravel_index(lin_idx, img.shape))

    ptr = np.cumsum(label_counts[1:-1])
    out = dict(enumerate(np.split(coor, ptr), start=1))

    return out


0 commentaires