Trouver une sous-image à l'intérieur d'un Numpy image
J'ai deux tableaux Numpy (3 dimensions uint8) converti à partir PIL images.
Je veux savoir si la première image contient la deuxième image, et si oui, trouver les coordonnées du coin haut-gauche de pixels à l'intérieur de la première image où le match est.
Est-il un moyen de le faire uniquement dans Numpy, dans une façon assez rapide, plutôt que de l'aide (4! très lent) pur Python boucles?
Exemple 2D:
a = numpy.array([
[0, 1, 2, 3],
[4, 5, 6, 7],
[8, 9, 10, 11]
])
b = numpy.array([
[2, 3],
[6, 7]
])
Comment faire quelque chose comme cela?
position = a.find(b)
position
serait alors (0, 2)
.
OriginalL'auteur Etienne Perot | 2011-10-06
Vous devez vous connecter pour publier un commentaire.
Cela peut être fait à l'aide de scipy est correlate2d et puis, à l'aide de argmax de trouver le pic de corrélation croisée.
Voici une explication plus complète de la mathématique et des idées, et quelques exemples.
Si vous voulez rester dans la pure Numpy et même pas utiliser scipy, ou si les images sont grandes, vous seriez probablement mieux à l'aide d'une FFT approche fondée sur les corrélations croisées.
Edit: La question spécifiquement demandé un pur Numpy solution. Mais si vous pouvez utiliser OpenCV, ou d'autres outils de traitement d'image, il est évidemment plus facile à utiliser l'un de ces. Un exemple est donné par PiQuer ci-dessous, que je vous recommande si vous pouvez l'utiliser.
OriginalL'auteur tom10
Je fais cela avec OpenCV's
matchTemplate
fonction. Il y a un super binding python pour OpenCV qui utilise numpy en interne, de sorte que les images sont juste des tableaux numpy. Par exemple, supposons que vous avez un 100x100 pixel BGR fichier testimage.bmp. Nous prenons un 10x10 sous-image à la position (30,30) et le trouver dans l'original.De sortie:
Vous pouvez choisir entre plusieurs algorithmes pour correspondre le modèle de l'original,
cv2.TM_CCOEFF_NORMED
est juste l'un d'eux. Voir la documentation pour plus de détails, certains algorithmes indiquer matchs à minima, d'autres comme des maxima dans le tableau résultat. Un mot d'avertissement: OpenCV utilise BGR canal de commande par défaut, donc soyez prudent, par exemple, lorsque vous comparez une image que vous avez chargé aveccv2.imread
à une image vous avez converti à partir du DIP de numpy. Vous pouvez toujours utilisercv2.cvtColor
pour convertir entre les formats.Pour trouver tous matches au-dessus d'un seuil donné
confidence
, j'utilise quelque chose le long des lignes de la ce de l'extrait de la correspondance des coordonnées de mon tableau résultat:Cela donne un n-uplet de tableaux de longueur 2, chacune correspondant à coordonner.
Juste par curiosité et non pour voler quelques rep de tom10 ;), pourquoi ne pouvez-vous pas changer la accepté de répondre? Je suis nouveau sur stackoverflow, mais dans ma propre première question que j'ai posté il indique que je peux "basculer" les accepté de répondre, et d'autres questions sur meta.stackoverflow.com montrer que doit possible d'accepter à nouveau.
modifier: Parce que le compte que j'ai demandé cette question n'est pas la même que mon compte courant. J'ai perdu le contrôle de l'OpenID de domaine utilisé pour vous connecter à l'autre compte, donc je ne peux pas connecter et de les modifier.
dois dire que c'est la meilleure solution que j'ai trouvé sur ce sujet. bien la peine d'investir du temps dans OpenCV. Merci
ce ne la ligne " template = image[30:40,30:40,:]' faire?
OriginalL'auteur PiQuer
Je viens de terminer l'écriture autonome de mise en œuvre de corrélation croisée normalisée pour la N-dimensions des tableaux. Vous pouvez l'obtenir à partir de ici.
Cross-corrélation est calculée soit directement, à l'aide de
scipy.ndimage.correlate
, ou dans le domaine de fréquence, à l'aide descipy.fftpack.fftn
/ifftn
selon selon ce qui sera le plus rapide pour l'entrée tailles.OriginalL'auteur ali_m
Vous pouvez réellement réduire ce problème à une simple chaîne de caractères de recherche à l'aide d'un
regex
comme la suite de la mise en œuvre - accepte deuxPIL.Image
objets et trouve les coordonnées de laneedle
dans lehaystack
. C'est sur 127x plus rapide que d'utiliser un pixel-par-pixel de recherche..
ne correspond pas à des retours à la ligne par défaut. Fixé par la préfixation de la regex avec(?s)
ou de la compilation avecre.DOTALL
.merci pour les commentaires!
OriginalL'auteur Ben