boîte englobante d'un tableau numpy
Supposons que vous avez un 2D tableau numpy avec certaines valeurs aléatoires et environnant les zéros.
Exemple "incliné rectangle":
import numpy as np
from skimage import transform
img1 = np.zeros((100,100))
img1[25:75,25:75] = 1.
img2 = transform.rotate(img1, 45)
Maintenant, je veux trouver le plus petit rectangle englobant pour tous les non-nulle de données. Par exemple:
a = np.where(img2 != 0)
bbox = img2[np.min(a[0]):np.max(a[0])+1, np.min(a[1]):np.max(a[1])+1]
Quel serait le plus rapide moyen de parvenir à ce résultat? Je suis sûr qu'il ya une meilleure façon de faire depuis le np.où la fonction prend un peu de temps et si je suis par exemple à l'aide de 1000x1000 ensembles de données.
Edit: il Devrait également travailler en 3D...
OriginalL'auteur a.smiet | 2015-07-14
Vous devez vous connecter pour publier un commentaire.
On peut grossièrement réduire de moitié le temps d'exécution en utilisant
np.any
à réduire le nombre de lignes et de colonnes qui contiennent des valeurs non nulles de 1D vecteurs, plutôt que de trouver l'indice de toutes les valeurs non nulles à l'aide denp.where
:Quelques repères:
L'extension de cette approche à la 3D cas implique la mise en œuvre de la réduction le long de chaque paire d'axes:
Il est facile de généraliser ce N dimensions en utilisant la
itertools.combinations
pour itérer sur chaque combinaison unique d'axes pour effectuer la réduction de plus de:Si vous connaissez les coordonnées des coins de la boîte englobante originale, l'angle de rotation et le centre de rotation, vous pouvez obtenir les coordonnées de l'image de la boîte englobante coins directement par le calcul de l'correspondant transformation affine de la matrice et ponctuant avec l'entrée de coordonnées:
Cela fonctionne très légèrement plus rapide que l'utilisation
np.any
pour votre petit exemple de tableau:Cependant, puisque la vitesse de cette méthode est indépendante de la taille de l'entrée de tableau, il peut être beaucoup plus rapide pour les grandes baies.
L'extension de l'approche de transformation de la 3D est un peu plus compliqué, en ce que la rotation a maintenant trois composants différents (l'un autour de l'axe x, l'un autour de l'axe y et un sur l'axe des z), mais la méthode de base est la même:
J'ai essentiellement juste modifié la fonction ci-dessus à l'aide de la matrice de rotation des expressions de ici - je n'ai pas eu le temps d'écrire un test encore, donc à utiliser avec précaution.
Merci beaucoup!
est une très bonne solution, surtout si il y a un grand nombre de lignes vides, des colonnes, sur un ordre de grandeur plus rapide que: stackoverflow.com/a/4809040/483620, mais je suppose que le rendement serait similaire ou pire, dans le cas extrême où il n'y a pas non nulle lignes/colonnes.
Je serais surpris si la solution pouvait battre
bbox2
, même pour de très grandes entièrement réseaux denses. Dans cette solution, l'entrée et la sortie des tableaux pournp.argwhere
augmentation quadratiquement avec la taille du tableau, alors qu'elles n'augmentent de façon linéaire pournp.where
dansbbox2
. Un hack qui pourrait le rendre encore plus rapide serait d'utilisernp.argmax(rows)
etrows.size - 1 - np.argmax(rows[::-1])
plutôt quenp.where
pour obtenir le premier et le dernier des valeurs non nulles dansrows
etcols
.J'ai trouvé un bug possible dans le présent code. xmin, ymin et zmin doit être ajouté -1, et xmax, ymax et zmax devrait être ajouté +1.
OriginalL'auteur ali_m
Voici un algorithme pour le calcul de la boîte englobante pour N dimensions des tableaux,
qui peut être utilisé avec la 2D, la 3D, etc tableaux comme suit,
Bien que le remplacement de la
np.diff
etnp.nonzero
appels par unnp.where
peut-être mieux.OriginalL'auteur rth
J'ai été capable de faire sortir un peu plus de performance par le remplacement de
np.where
avecnp.argmax
et de travailler sur un booléen masque.Il était environ 10 µs plus vite pour moi que la bbox2 de la solution ci-dessus sur la même référence. Il devrait également être un moyen de simplement utiliser le résultat de argmax pour trouver le non-zéro de lignes et de colonnes, en évitant la recherche supplémentaire fait en utilisant
np.any
, mais cela peut nécessiter des problèmes de l'indexation que je n'étais pas en mesure de travailler efficacement avec de simples vectorisé code.OriginalL'auteur Allan Zelener