Bildregistrierung mit python und Kreuz-Korrelation
Habe ich zwei Bilder, die zeigen exaktly die gleichen Inhalte: 2D-Gauß-förmigen Flecken. Ich nenne diese beiden 16-bit-png-Dateien "Links.png" und "rechts.png". Aber wie Sie gewonnen werden durch eine leicht unterschiedliche optische Aufbau, die entsprechenden stellen (physikalisch die gleichen sind) erscheinen in leicht unterschiedlichen Positionen. Bedeutung der rechten Seite ist leicht gestreckt, verzerrt, oder so, in einer nicht-linearen Weise. Daher würde ich mag, um die transformation von Links nach rechts.
Also für jedes pixel auf der linken Seite, mit seinen x - und y-Koordinate möchte ich eine Funktion die mir die Komponenten des Verschiebungs-Vektor, der die Punkte zu den entsprechenden pixel auf der rechten Seite.
In einem früheren Ansatz habe ich versucht, die Positionen der entsprechenden Punkte zu erhalten, die relativen Abstände deltaX und deltaY. Diese Entfernungen dann habe ich eingebaut, um die taylor-expansion bis zur zweiten Ordnung von T(x,y) gibt mir die x - und y-Komponenten des Verschiebungs-Vektors, der für jedes pixel (x,y) auf der linken Seite, zeigen auf die entsprechenden pixel (x',y') auf der rechten Seite.
Um eine mehr Allgemeine Ergebnis möchte ich nutzen, normalisierte Kreuz-Korrelation. Dafür habe ich vermehren jeder pixelvalue von Links mit einem entsprechenden pixelvalue von rechts und die Summe über diese Produkte. Die transformation, die ich Suche, sollte die Verbindung der Pixel maximiert wird die Summe. Also, wenn die Summe maximzied, ich weiß, dass ich multipliziert die entsprechenden Pixel.
Ich wirklich viel versucht, aber nicht geschafft. Meine Frage ist, ob jemand von Euch eine Idee hat, oder hat jemals etwas ähnliches gemacht.
import numpy as np
import Image
left = np.array(Image.open('left.png'))
right = np.array(Image.open('right.png'))
# for normalization (http://en.wikipedia.org/wiki/Cross-correlation#Normalized_cross-correlation)
left = (left - left.mean()) / left.std()
right = (right - right.mean()) / right.std()
Bitte lassen Sie mich wissen, wenn ich kann diese Frage klar. Ich habe noch zu überprüfen, so stellen Sie Fragen mit Hilfe von latex.
Danke Ihnen sehr für die Eingabe.
[linken Seite.png] http://i.stack.imgur.com/oSTER.png
[Recht.png] http://i.stack.imgur.com/Njahj.png
Ich fürchte, in den meisten Fällen 16-bit-Bilder erscheinen nur schwarz (zumindest auf Systemen, die ich verwende) 🙁 aber es gibt natürlich Daten.
UPDATE 1
Ich versuche clearify meine Frage. Ich bin auf der Suche für ein Vektor-Feld mit displacement-Vektoren, die Punkt von jedem pixel in der linken.png um die entsprechenden pixel in der rechten Seite.png. Mein problem ist, ich bin mir nicht sicher über die Einschränkungen, die ich habe.
wo Vektor r (Komponenten x und y) Punkte um einen pixel in der linken.png und vector r-prime (Komponenten x prim und y-prime) Punkte, um die entsprechenden pixel in der rechten Seite.png. zu jedem r gibt es eine Verschiebungs-Vektor.
Was ich früher war, das fand ich manuell Komponenten der Vektor-Feld d und montiert Sie zu einem polynom zweiten Grades:
Also habe ich eingebaut:
und
Macht das Sinn für Sie? Ist es möglich, dass alle delta-x(x,y) und delta-y(x,y) mit Kreuz-Korrelation? Die Kreuzkorrelation maximiert werden sollte, wenn das entsprechende Pixel sind miteinander verbunden, durch die Verschiebungs-Vektoren, richtig?
UPDATE 2
Also der Algorithmus, den ich dachte, ist wie folgt:
- Verformen Recht.png
- Erhalten die Wert cross-Korrelation
- Verformen Recht.png weiter
- Erhalten die Wert cross-Korrelation und Vergleich zum Wert vor
- Wenn er größer ist, gute Verformung, wenn nicht, wiederholen Sie die Verformung und etwas anderes tun
- Nach maximzied der Kreuz-Korrelation Wert, wissen, was die Verformung es ist 🙂
Über Verformung: könnte man tun, zunächst eine Verschiebung entlang der x - und y-Richtung zu maximieren Kreuz-Korrelation, die dann in einem zweiten Schritt dehnen oder komprimieren Sie die x - und y-abhängig und in einem Dritten Schritt verformen quadratische x - und y abhängig ist, und wiederholen Sie dieses Verfahren iterativ?? Ich habe wirklich ein problem mit integer-Koordinaten. Glaubst du, ich hätte zu interpolieren das Bild erhalten Sie eine kontinuierliche Verteilung?? Ich denke noch einmal über diese 🙁 vielen Dank an alle fürs mitmachen 🙂
- keine Hilfe? Ich bin ein bisschen festgefahren auf dieses 🙁 Hoffe, es ist nicht einfach lächerlich?
- Wie kann ich als latex-code interpretiert?
- Sie können nicht nativ als stackoverflow nicht unterstützt Latex interpretation als Mathe.se: meta.stackexchange.com/questions/4152/...
- Danke Daan. Schauen Sie bitte auf meine Update 2 🙂
Du musst angemeldet sein, um einen Kommentar abzugeben.
OpenCV (und mit ihm die python-Opencv Bindung) hat eine StarDetector - Klasse, die implementiert dieser Algorithmus.
Als alternative könnten Sie einen Blick auf die OpenCV - SIFT Klasse, das steht für Scale Invariant Feature Transform.
Update
Bezug auf Ihren Kommentar, ich verstehe, dass die "richtige" transformation der Maximierung der Kreuzkorrelation zwischen den Bildern, aber ich verstehe nicht, wie man wählen Sie die Reihe von Veränderungen, über die zu maximieren. Vielleicht, wenn Sie wissen, die Koordinaten von drei matching-Punkte (entweder durch einige Heuristiken oder durch die Wahl durch hand), und wenn Sie erwarten, dass Affinität, Sie könnte so etwas wie cv2.getAffineTransform eine gute Initiale transformation für Ihre Maximierung Prozess. Von dort konnte man mit kleinen zusätzlichen Transformationen, die eine Reihe über die zu maximieren. Aber dieser Ansatz erscheint mir neu zu erfinden, etwas, das SIFT kümmern konnte.
Tatsächlich verwandeln Sie Ihr test-Bild, das Sie verwenden können,cv2.warpAffine, die sich auch kümmern kann, Randwerte (z.B. pad mit 0). Zur Berechnung der Kreuz-Korrelation, die Sie nutzen könnten scipy.signal.correlate2d.
Update
Ihrem neuesten update in der Tat die Klärung einiger Punkte für mich. Aber ich denke, dass ein Vektorfeld der Verschiebungen ist nicht die natürlichste Sache zu suchen, und dies ist auch, wo das Missverständnis herkommt. Ich dachte mehr entlang der Linien von einem globalen transformation T, die angewendet auf einen beliebigen Punkt (x,y) im linken Bild gibt (x',y')=T(x,y) auf der rechten Seite, aber T hat die gleiche analytische form für jedes pixel. Dies könnte beispielsweise eine Kombination von Verschiebung, Drehung, Skalierung, vielleicht einige der perspektivischen transformation. Ich kann nicht sagen, ob es realistisch ist oder nicht, um Hoffnung zu finden, wie eine transformation, dies ist abhängig von Ihrer Einstellung, aber wenn die Szene ist physikalisch die gleichen sind auf beiden Seiten würde ich sagen, es ist vernünftig, zu erwarten, dass einige affine transformation. Dies ist der Grund, warum ich vorgeschlagen cv2.getAffineTransform. Es ist natürlich trivial zu berechnen, Ihre verschiebungsvektorfeld aus wie ein T, wie das ist nur T(x,y)-(x,y).
Der große Vorteil wäre, dass Sie nur sehr wenige Freiheitsgrade für Ihre transformation, anstelle von, ich würde behaupten, 2N Freiheitsgrade in der verschiebungsvektorfeld, wobei N die Anzahl der hellen stellen.
Ob es tatsächlich eine affine transformation, würde ich vorschlagen, einige algorithmen wie diese:
Update
Scheint es cv2.getAffineTransform erwartet eine schwierige input Datentyp 'float32'. Nehmen wir an, die Quelle-Koordinaten sind
(sxi,syi)
- und Ziel -(dxi,dyi)
miti=0,1,2
, dann, was Sie brauchen, istIch glaube nicht, dass eine Kreuz-Korrelation wird hier nicht helfen, denn es gibt nur einen einzigen besten shift für das gesamte Bild. Es gibt drei alternativen würde ich prüfen:
Tun, eine Kreuz-Korrelation von sub-Clustern von Punkten. Nehmen Sie zum Beispiel die drei Punkte oben rechts und finden die optimale x-y-Verschiebung mittels Kreuzkorrelation. Dies gibt Ihnen die grobe Transformation für die Links oben. Wiederholen Sie dies für so viele Cluster wie Sie können, um zu erhalten eine vernünftige Karte Ihrer Transformationen. Passen Sie diese mit Ihrem Taylor expansion, und erhalten Sie möglicherweise ziemlich nahe. Allerdings haben Sie Ihre Kreuz-Korrelation die arbeiten in irgendeiner Weise, der Unterschied in der Verschiebung zwischen den spots muss kleiner sein als die Höhe der Stelle, sonst kannst du nie bekommen, werden alle Punkte in einem cluster überlappen, gleichzeitig mit einem einzigen Hubraum. Unter diesen Bedingungen, der option 2 könnte besser geeignet sein.
Wenn die Verschiebungen sind relativ klein (was ich denke, ist eine Bedingung für die Möglichkeit 1), dann können wir davon ausgehen, dass für einen gegebenen Punkt im linken Bild, der nächste Punkt im rechten Bild die entsprechende Stelle. So, für jeden Punkt im linken Bild, wir finden den nächsten Ort in das Rechte Bild und verwenden, die wie die Verschiebung in diesem Ort. Von den 40-etwas gut verteilt Verschiebung von Vektoren wir erhalten einen angemessenen Annäherung an die tatsächliche Verschiebung durch den Einbau Ihres Taylor expansion.
Dies ist wahrscheinlich die langsamste Methode, aber vielleicht die robustesten, wenn große Verschiebungen (und option 2 so nicht funktioniert): verwenden Sie so etwas wie einen evolutionären Algorithmus zu finden, der Verdrängung. Gelten eine zufällige transformation, berechnen Sie die restlichen Fehler (möglicherweise müssen Sie definieren diese als Summe der kleinsten Entfernung zwischen den Flecken in Ihrem ursprünglichen und transformierten Bild), und verbessern Sie Ihre transformation mit diesen Ergebnissen. Wenn Ihre Verschiebungen sind ziemlich groß Sie müssen möglicherweise eine sehr Breite Suche wie Sie erhalten wahrscheinlich eine Reihe von lokalen minima, die in Ihrer Landschaft.
Ich würde versuchen, option 2, wie es scheint, Ihre Verschiebungen sind vielleicht klein genug, um leicht assoziieren einen Punkt im linken Bild mit einem Punkt im rechten Bild.
Update
Ich davon aus, dass deine Optik induzieren, nicht lineare Verzerrungen und mit zwei separaten beampaths (verschiedene Filter, die in jedem?) wird die Beziehung zwischen den beiden Bildern, noch mehr nicht-linear. Die affine transformation PiQuer schlägt vor, könnte ein sinnvoller Ansatz, aber kann wohl nie vollständig decken die tatsächlichen Verzerrungen.
Ich denke, Ihr Ansatz, die Anpassung zu einer low-order Taylor-Polynom ist in Ordnung. Dies funktioniert für alle meine Anwendungen mit ähnlichen Bedingungen. Höchste Bestellungen sollten wohl so etwas wie xy^2 und x^2y; etwas höher als dass Sie nicht bemerkt wird.
Alternativ können Sie in der Lage zu Kalibrieren, die Verzerrungen für jedes Bild zuerst, und dann machen Sie Ihre Experimente. Auf diese Weise sind Sie nicht abhängig von der Verteilung Sie Punkte, können aber in hoher Auflösung Referenz Bild, um die beste Beschreibung Ihrer transformation.
Option 2 oben steht immer noch als mein Vorschlag, um die beiden Bilder zu überlagern. Dies kann vollständig automatisiert werden und ich bin mir nicht sicher, was Sie meinen, wenn Sie möchten, eine mehr Allgemeine Ergebnis.
Update 2
Ihr Kommentar, dass Sie Schwierigkeiten haben, zu übereinstimmenden Punkten in den beiden Bildern. Wenn dies der Fall ist, denke ich, Ihre iterative Kreuz-Korrelations-Ansatz vielleicht nicht sehr robust sein entweder. Sie haben sehr kleine Punkte, so dass überschneidungen zwischen Ihnen wird nur auftreten, wenn der Unterschied zwischen den beiden Bildern ist klein.
Im Prinzip gibt es nichts falsch mit Ihrem Lösungsvorschlag, aber ob es funktioniert oder nicht hängt stark von der Größe der Verformungen und die Robustheit Ihrer Optimierungs-Algorithmus. Wenn Sie beginnen mit sehr wenig überlappen, dann kann es schwer zu finden einen guten Ausgangspunkt für Ihre Optimierung. Wenn Sie jedoch über ausreichend überlappen, um mit zu beginnen, dann sollten Sie in der Lage zu finden, die Verformung pro Punkt zuerst, aber in einem Kommentar, auf den Sie hinweisen, dass dies nicht funktioniert.
Vielleicht können Sie sich für eine gemischte Lösung: finden Sie die Kreuz-Korrelation der Cluster von Punkten zu bekommen, Ausgangspunkt für Ihre Optimierung, und dann zwicken die Verformung mit so etwas wie das Verfahren, das Sie beschreiben in Ihrem update. Also:
Möchten Sie vielleicht einen Blick auf bunwarpj das bereits tut, was Sie zu tun versuchen. Es ist kein python, aber ich benutze es in genau diesem Zusammenhang. Exportieren Sie können eine nur-text-spline-transformation und verwenden Sie es, wenn Sie so tun möchten.