Dies ist immer sehr rechenintensiv, insbesondere wenn Sie bis zu 2000 Punkte verarbeiten möchten. Ich bin mir sicher, dass es bereits hochoptimierte Lösungen für diese Art des Mustervergleichs gibt, aber Sie müssen erst herausfinden, wie es heißt, um sie zu finden.
Da es sich nicht um ein Bild, sondern um eine Punktwolke (spärliche Daten) handelt, trifft meine Kreuzkorrelationsmethode nicht wirklich zu (und wäre rechnerisch noch schlimmer). So etwas wie RANSAC findet wahrscheinlich schnell eine Übereinstimmung, aber ich weiß nicht viel darüber.
Mein Lösungsversuch:
Annahmen:
- Sie möchten die beste Übereinstimmung finden, nicht nur eine lockere oder "wahrscheinlich richtige" Übereinstimmung
- Die Übereinstimmung weist aufgrund von Rauschen bei der Messung oder Berechnung einen geringen Fehler auf
- Quellpunkte sind koplanar
- Alle Quellenpunkte in Ziel vorhanden sein muss (= jeder unerreichter Punkt ist eine Nichtübereinstimmung für das gesamte Profil)
Sie sollten also in der Lage sein, viele Abkürzungen zu verwenden, indem Sie Dinge disqualifizieren und die Rechenzeit verkürzen. Zusamenfassend:
- Wähle drei Punkte aus der Quelle
- Durchsuchen Sie die Zielpunkte und finden Sie Sätze von 3 Punkten mit derselben Form
- Wenn eine Übereinstimmung von 3 Punkten gefunden wird, überprüfen Sie alle anderen Punkte in der Ebene, die sie definieren, um festzustellen, ob es sich um eine enge Übereinstimmung handelt
- Wird mehr als eine Übereinstimmung aller Punkte gefunden, wählen Sie diejenige mit der geringsten Summe der 3D-Abstandsfehler
Genauer:
pick a point from the source for testing s1 = (x1, y1)
Find nearest point in source s2 = (x2, y2)
d12 = (x1-x2)^2 + (y1-y2)^2
Find second nearest point in source s3 = (x3, y3)
d13 = (x1-x3)^2 + (y1-y3)^2
d23 = (x2-x3)^2 + (y2-y3)^2
for all (x,y,z) test points t1 in target:
# imagine s1 and t1 are coincident
for all other points t2 in target:
if distance from test point > d12:
break out of loop and try another t2 point
if distance ≈ d12:
# imagine source is now rotated so that s1 and s2 are collinear with t1 and t2
for all other points t3 in target:
if distance from t1 > d13 or from t2 > d23:
break and try another t3
if distance from t1 ≈ d13 and from t2 ≈ d23:
# Now you've found matching triangles in source and target
# align source so that s1, s2, s3 are coplanar with t1, t2, t3
project all source points onto this target plane
for all other points in source:
find nearest point in target
measure distance from source point to target point
if it's not within a threshold:
break and try a new t3
else:
sum errors of all matched points for this configuration (defined by t1, t2, t3)
Welche Konfiguration den kleinsten Fehlerquadrat für alle anderen Punkte aufweist, ist die beste Übereinstimmung
Da wir mit 3 Testpunkten für den nächsten Nachbarn arbeiten, können übereinstimmende Zielpunkte vereinfacht werden, indem überprüft wird, ob sie sich innerhalb eines bestimmten Radius befinden. Wenn wir zum Beispiel aus (0, 0) nach einem Radius von 1 suchen, können wir (2, 0) basierend auf x1 - x2 disqualifizieren, ohne den tatsächlichen euklidischen Abstand zu berechnen, um ihn etwas zu beschleunigen. Dies setzt voraus, dass die Subtraktion schneller ist als die Multiplikation. Es gibt auch optimierte Suchen, die auf einem willkürlicheren festen Radius basieren .
function is_closer_than(x1, y1, z1, x2, y2, z2, distance):
if abs(x1 - x2) or abs(y1 - y2) or abs(z1 - z2) > distance:
return False
return (x1 - x2)^2 + (y1 - y2)^2 + (z1 - z2)^2 > distance^2 # sqrt is slow
d= ( x1- x2)2+ ( y1- y2)2+ ( z1- z2)2----------------------------√
( 20002)
Da Sie diese ohnehin alle berechnen müssen, unabhängig davon, ob Sie Übereinstimmungen finden oder nicht, und da Sie sich für diesen Schritt nur um die nächsten Nachbarn kümmern, ist es wahrscheinlich besser, diese Werte mit einem optimierten Algorithmus vorab zu berechnen, wenn Sie über den Speicher verfügen . So etwas wie eine Delaunay- oder Pitteway-Triangulation , bei der jeder Punkt im Ziel mit den nächsten Nachbarn verbunden ist. Speichern Sie diese in einer Tabelle und suchen Sie sie für jeden Punkt, wenn Sie versuchen, das Quellendreieck an eines der Zieldreiecke anzupassen.
Es sind viele Berechnungen erforderlich, aber es sollte relativ schnell gehen, da nur die Daten verarbeitet werden, die dünn sind, anstatt viele bedeutungslose Nullen miteinander zu multiplizieren, wie dies bei einer Kreuzkorrelation von Volumendaten der Fall wäre. Dieselbe Idee würde für den 2D-Fall funktionieren, wenn Sie zuerst die Mittelpunkteder Punkte fanden und sie als Satz von Koordinaten speicherten.