Finden Sie die Drehung zwischen Punktmengen

8

Ich habe zwei Sätze ( sourcund target) von Punkten (x,y), die ich ausrichten möchte. Was ich bisher gemacht habe ist:

  • Finden Sie den Schwerpunkt jedes Punktesatzes
  • Verwenden Sie den Unterschied zwischen den Zentroiden-Übersetzungen, den Punkt in xundy

Ich möchte die beste Drehung (in Grad) finden, um die Punkte auszurichten .

Irgendeine Idee?

Der M-Code befindet sich unten (mit Darstellungen zur Visualisierung der Änderungen):

# Raw data
## Source data
sourc = matrix( 
     c(712,960,968,1200,360,644,84,360), # the data elements 
     nrow=2, byrow = TRUE)

## Target data
target = matrix( 
  c(744,996,980,1220,364,644,68,336), # the data elements 
  nrow=2, byrow = TRUE)

# Get the centroids
sCentroid <- c(mean(sourc[1,]), mean(sourc[2,])) # Source centroid
tCentroid <- c(mean(target[1,]), mean(target[2,])) # Target centroid

# Visualize the points
par(mfrow=c(2,2))
plot(sourc[1,], sourc[2,], col="green", pch=20, main="Raw Data",
     lwd=5, xlim=range(sourceX, targetX),
     ylim=range(sourceY, targetY))
points(target[1,], target[2,], col="red", pch=20, lwd=5)
points(sCentroid[1], sCentroid[2], col="green", pch=4, lwd=2)
points(tCentroid[1], tCentroid[2], col="red", pch=4, lwd=2)

# Find the translation
translation <- tCentroid - sCentroid
target[1,] <- target[1,] - translation[1]
target[2,] <- target[2,] - translation[2]

# Get the translated centroids
tCentroid <- c(mean(target[1,]), mean(target[2,])) # Target centroid

# Visualize the translation
plot(sourc[1,], sourc[2,], col="green", pch=20, main="After Translation",
     lwd=5, xlim=range(sourceX, targetX),
     ylim=range(sourceY, targetY))
points(target[1,], target[2,], col="red", pch=20, lwd=5)
points(sCentroid[1], sCentroid[2], col="green", pch=4, lwd=2)
points(tCentroid[1], tCentroid[2], col="red", pch=4, lwd=2)
Wiliam
quelle
5
Ich kann Ihren Code nicht lesen, aber die Operation, die Sie benötigen, heißt Procrustes-Rotation. Hast du davon gehört? Es funktioniert, wenn Punkte bereits gepaart sind (xi,yi). Zu den optionalen Operationen vor der Rotation gehören die Translation und Skalierung sowie die optionale Isoskalierung nach der Rotation.
ttnphns
3
Eine komplexe Regression wird den Job erledigen.
whuber
Ich habe gesehen, dass das System um 180 Grad gedreht wurde, dann die Paare (a,C),(b,D),(c,A),(d,B) Nachbarn werden - und das passt sogar besser als das Original (a,A),(b,B),(c,C),(d,D) (wo die kleinen Buchstaben für Vektor sourceund Großbuchstaben für Vektor stehen target) Ich habe diese Möglichkeit nicht erwähnt und ausdrücklich erlaubt oder nicht erlaubt gesehen. Bist du sicher, dass du das nicht besser passen willst?
Gottfried Helms

Antworten:

4

Dies kann mit dem Kabsch-Algorithmus erfolgen . Der Algorithmus findet die beste Schätzung der kleinsten Quadrate für die Rotation vonRXY wo R ist Rotationsmatrix, X und Y sind Ihre Ziel- und Quellmatrizen mit 2 Zeilen und n Spalten.

In [ 1 ] wird gezeigt, dass dieses Problem durch Singularwertzerlegung gelöst werden kann. Der Algorithmus ist wie folgt:

  1. Zentrieren Sie die Datensätze so, dass ihre Schwerpunkte auf dem Ursprung liegen.
  2. Berechnen Sie die "Kovarianz" -Matrix C=XYT.
  3. Erhalten Sie die Singularwertzerlegung von C=UDVT.
  4. Richtungseinstellung d=sign(det(C)).
  5. Dann die optimale Rotation R=V(100d)UT

Ich kenne keine Implementierung in R, deshalb habe ich unten eine kleine Funktion geschrieben.

Ihre ersten Punkte:

src <- matrix(c(712,960,968,1200,360,644,84,360), nrow=2, byrow=TRUE)
trg <- matrix(c(744,996,980,1220,364,644,68,336), nrow=2, byrow=TRUE)

Kabsch-Algorithmus in einer R-Funktion:

kabsch2d <- function(Y, X) {
  X   <- X-rowMeans(X)
  Y   <- Y-rowMeans(Y)
  C   <- X %*% t(Y)
  SVD <- svd(C)
  D   <- diag(c(1, sign(det(C))))
  t(SVD$v) %*% D %*% t(SVD$u)
}

Zentrieren Sie die Punkte:

src <- src-rowMeans(src)
trg <- trg-rowMeans(trg)

Rotation erhalten:

rot <- kabsch2d(src, trg)

Ergebnis (schwarz - Originalquelle, rot - ursprüngliches Ziel, grün - gedrehtes Ziel)

plot(t(src), col="black", pch=19)
points(t(trg), col="red", pch=19)
points(t(rot %*% trg), col="green", pch=19)

Geben Sie hier die Bildbeschreibung ein

[1] http://www.math.pku.edu.cn/teachers/yaoy/Fall2011/arun.pdf

Karolis Koncevičius
quelle
1
+1. Die Antwort könnte jedoch noch viel besser sein, wenn Sie einen Diskurs darüber aufnehmen, wie das Algo mit dem bekannten Rotationsproblem von Procrustes zusammenhängt.
ttnphns
1

Ich habe dies mit einer iterativen Optimalsuche gemacht und 2 Versionen getestet.
Ich habe die ursprünglichen Arrays genommen und sie zentriert, indem ich diese Arrays cSRCund nannte cTAR. Dann habe ich eine Schleife mit Winkeln gemachtφ zwischen 0 und 2π und für jeden Winkel berechnete ich das Fehlerkriterium unter Verwendung der Differenz zwischen den gedrehten D=rot(cSRC,φ)cTAR.

  1. In Version 1) habe ich als Kriterium die Quadratsumme aller Einträge in genommen D wie

    err1=k=14((Dk,1)2+(Dk,2)2)
    und der Winkel φbei dem der minimale Fehler aufgetreten ist, entspricht der kabsch2dProzedur in der Antwort von @Karolis.
  2. In Version 2) habe ich als Kriterium die Summe der absoluten Entfernungen genommen, dh die Summe

    err2=k=14(Dk,1)2+(Dk,2)2
    und bekam einen etwas anderen Drehwinkel φ für den kleinsten Fehler.

Ich weiß nicht, welches Kriterium besser zu Ihren Bedürfnissen passt.

Hier sind einige Ergebnisse aus dem Protokoll.

version 1version 2φ0.048953040.05093647rotation[0.998802040.048933490.048933490.99880204][0.998703020.050914440.050914440.99870302]distances[6.800772660.862097392.799245519.337825000.613095226.941565204.614622373.25835719][6.780177510.370624043.357873079.365748741.164591156.953245274.586895592.78312752]
Gottfried Helms
quelle