Dies ist nicht die beste Lösung, aber es ist eine Lösung. Ich möchte von besseren Techniken lernen:
Wenn sie nicht gedreht oder skaliert würden, könnten Sie eine einfache Kreuzkorrelation der Bilder verwenden. Überall dort, wo das kleine Bild im großen Bild auftritt, wird es einen hellen Peak geben.
Sie können die Kreuzkorrelation mit einer FFT-Methode beschleunigen. Wenn Sie jedoch nur ein kleines Quellbild mit einem großen Zielbild abgleichen, ist die Brute-Force-Multiplikations- und Additionsmethode manchmal (normalerweise) schneller.
Quelle:
Ziel:
Kreuzkorrelation:
Die beiden hellen Punkte sind die Orte, die übereinstimmen.
Sie haben jedoch einen Rotationsparameter in Ihrem Beispielbild, sodass dies für sich allein nicht funktioniert. Wenn nur eine Drehung und keine Skalierung zulässig ist, kann die Kreuzkorrelation weiterhin verwendet werden. Sie müssen jedoch die Quelle kreuzkorrelieren, drehen, mit dem gesamten Zielbild kreuzkorrelieren, erneut drehen usw. für alle Umdrehungen.
Beachten Sie, dass das Bild dadurch nicht unbedingt gefunden wird. Handelt es sich bei dem Quellbild um zufälliges Bildrauschen und bei dem Ziel um zufälliges Bildrauschen, werden Sie es nur finden, wenn Sie genau im richtigen Winkel suchen. Unter normalen Umständen wird es wahrscheinlich gefunden, aber es hängt von den Bildeigenschaften und den Winkeln ab, in denen Sie suchen.
Diese Seite zeigt ein Beispiel, wie es gemacht wird, gibt aber keinen Algorithmus an.
Jeder Offset, bei dem die Summe über einem bestimmten Schwellenwert liegt, ist eine Übereinstimmung. Sie können die Güte der Übereinstimmung berechnen, indem Sie das Quellbild mit sich selbst korrelieren und alle Ihre Summen durch diese Zahl dividieren. Eine perfekte Übereinstimmung wird 1.0 sein.
Dies ist jedoch sehr rechenintensiv, und es gibt wahrscheinlich bessere Methoden zum Abgleichen von Punktmustern (über die ich gerne etwas wissen würde).
Schnelles Python-Beispiel mit Graustufen- und FFT-Methode:
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
1-Farben-Bitmaps
Bei 1-Farben-Bitmaps wäre dies jedoch viel schneller. Kreuzkorrelation wird:
- Platzieren Sie das Quellbild über dem Zielbild
- Quellbild um 1 Pixel verschieben
- bitweise UND alle überlappenden Pixel
- summiere alle 1s
- ...
Wenn Sie ein Graustufenbild auf Binärwert beschränken, ist dies möglicherweise ausreichend.
Punktwolke
Wenn die Quelle und das Ziel beide Punktmuster sind, besteht eine schnellere Methode darin, die Mitten jedes Punkts zu finden (einmal mit einem bekannten Punkt kreuzkorrelieren und dann die Peaks suchen) und sie als Satz von Punkten zu speichern und dann mit der Quelle abzugleichen zum Zielen drehen, verschieben und den Fehler der kleinsten Quadrate zwischen den nächstgelegenen Punkten in den beiden Mengen finden.