Ce n'est pas la meilleure solution, mais c'est une solution. J'aimerais apprendre de meilleures techniques:
Si elles ne devaient pas faire l'objet d'une rotation ou d'une réduction, vous pouvez utiliser une simple corrélation croisée des images. Il y aura un pic lumineux partout où la petite image apparaît dans la grande image.
Vous pouvez accélérer la corrélation croisée en utilisant une méthode FFT, mais si vous faites simplement correspondre une image source petite à une image cible grande, la méthode multiplication-ajout force-brute est parfois (généralement) plus rapide.
La source:
Cible:
Corrélation croisée:
Les deux points lumineux sont les emplacements qui correspondent.
Mais vous n'avez un paramètre de rotation dans votre image par exemple, de sorte que ne fonctionnera pas par lui - même. Si seule la rotation est autorisée, et non la mise à l'échelle, il est toujours possible d'utiliser la corrélation croisée, mais vous devez effectuer une corrélation croisée, faire pivoter la source, la corréler avec l'image cible entière, la faire pivoter à nouveau, etc. toutes les rotations.
Notez que cela ne trouvera pas forcément jamais l'image. Si l'image source est un bruit aléatoire et que la cible est un bruit aléatoire, vous ne le trouverez pas à moins de chercher exactement au bon angle. Dans des situations normales, il le trouvera probablement, mais cela dépend des propriétés de l’image et des angles de recherche.
Cette page montre un exemple de la procédure à suivre, mais ne donne pas l'algorithme.
Tout décalage dont la somme est supérieure à un seuil est une correspondance. Vous pouvez calculer la qualité de la correspondance en corrélant l'image source avec elle-même et en divisant toutes vos sommes par ce nombre. Un match parfait sera 1.0.
Cela demandera beaucoup de temps, cependant, et il existe probablement de meilleures méthodes pour faire correspondre les motifs de points (ce que j'aimerais connaître).
Exemple rapide Python utilisant la méthode de niveaux de gris et de FFT:
from __future__ import division
from pylab import *
import Image
import ImageOps
source_file = 'dots source.png'
target_file = 'dots target.png'
# Load file as grayscale with white dots
target = asarray(ImageOps.invert(Image.open(target_file).convert('L')))
close('all')
figure()
imshow(target)
gray()
show()
source_Image = ImageOps.invert(Image.open(source_file).convert('L'))
for angle in (0, 180):
source = asarray(source_Image.rotate(angle, expand = True))
best_match = max(fftconvolve(source[::-1,::-1], source).flat)
# Cross-correlation using FFT
d = fftconvolve(source[::-1,::-1], target, mode='same')
figure()
imshow(source)
# This only finds a single peak. Use something that finds multiple peaks instead:
peak_x, peak_y = unravel_index(argmax(d),shape(d))
figure()
plot(peak_y, peak_x,'ro')
imshow(d)
# Keep track of all these matches:
print angle, peak_x, peak_y, d[peak_x,peak_y] / best_match
Bitmaps 1 couleur
Pour les bitmaps à une couleur, cela serait toutefois beaucoup plus rapide. La corrélation croisée devient:
- Placez l'image source sur l'image cible
- Déplacer l'image source de 1 pixel
- ET au niveau du bit ET tous les pixels superposés
- additionner tous les 1
- ...
Sertir une image en niveaux de gris sur une image binaire peut ensuite suffire.
Nuage de points
Si la source et la cible sont toutes deux des motifs de points, une méthode plus rapide consisterait à trouver les centres de chaque point (corrélation croisée une fois avec un point connu, puis à rechercher les pics) et à les stocker sous la forme d'un ensemble de points, puis à faire correspondre la source. pour cibler en faisant pivoter, en traduisant et en trouvant l'erreur des moindres carrés entre les points les plus proches dans les deux ensembles.