Trouver la traduction et de l'échelle sur deux ensembles de points pour obtenir des moindres carrés de l'erreur dans leur distance?
J'ai deux ensembles de points 3D (original et reconstruit) et de la correspondance d'informations sur les paires qui point à partir d'un ensemble représente la deuxième. J'ai besoin de trouver 3D de traduction et de facteur d'échelle qui transforme reconstruire, de sorte que la somme des carrés des distances seraient moins (rotation serait sympa aussi, mais les points sont tournés de la même façon, donc ce n'est pas la principale priorité et peut être omis dans un souci de simplicité et de rapidité). Et donc ma question est, est - ce résolu et disponible quelque part sur Internet? Personnellement, je voudrais utiliser la méthode des moindres carrés, mais je n'ai pas beaucoup de temps (et même si je suis assez bon en maths, je ne l'utilise pas souvent, donc il serait préférable pour moi de l'éviter), donc je voudrais utiliser une autre solution si elle existe. Je préfère la solution en C++, par exemple à l'aide d'OpenCV, mais seul algorithme est assez bon.
Si ce n'est pas la solution, je vais calculer ça par moi-même, je ne veux pas vous dérange tant.
SOLUTION: (à partir de vos réponses)
Pour moi, c'est Kabsch alhorithm;
Base info: http://en.wikipedia.org/wiki/Kabsch_algorithm
Solution générale: http://nghiaho.com/?page_id=671
N'EST TOUJOURS PAS RÉSOLU:
J'ai aussi besoin d'échelle. L'échelle des valeurs de SVD ne sont pas compréhensibles pour moi; quand j'ai besoin de mettre à l'échelle de 1 à 4 pour tous les axes (estimés par moi), SVD échelle est d'environ [2000, 200, 20], ce qui n'est pas aider du tout.
Evgeny Kluev: merci beaucoup, on dirait que c'est elle. Je vais essayer de poster les résultats (il faudra un certain temps; j'ai d'autres choses à mettre en œuvre). Par la façon dont, heureusement pour moi, OpenCV contient SVD de la calculatrice, ce qui simplifie beaucoup les choses.
Evgeny Kluev: je m'en excuse profondément pour répondre si tard: j'ai eu de plus en plus important de projets. Je voudrais vous demander, comment dois-je interpréter les facteurs d'échelle? Ces chiffres sont vraiment de gros (200 - 2000) ou de petite taille (~0.5) mais de mon jugement, l'échelle doit être d'environ 1 à 4. Et aussi, les facteurs d'échelle sont souvent différentes pour les différents axes (par exemple [2000, 200, 20]).
En fait il n'y a aucun moyen d'obtenir des facteurs d'échelle directement à partir de valeurs singulières. Mon erreur. Désolé. SVD basée sur l'algorithme peut s'appliquer ici, mais je ne sais pas comment. En tout cas, le froid essayez plus générale Itératif point le plus proche de l'algorithme.
Avez-vous regardé ma réponse ci-dessous? Vous obtenez l'échelle de Eigen ainsi eigen.tuxfamily.org/dox/... bien sûr, cela suppose que vous avez les correspondances
OriginalL'auteur | 2012-11-17
Vous devez vous connecter pour publier un commentaire.
Puisque vous êtes déjà à l'aide de Kabsch algorithme, il suffit de jeter un coup d'oeil à Umeyama du papier qui s'étend à elle pour obtenir de l'échelle. Tout ce que vous devez faire est d'obtenir l'écart-type de vos points et de calculer l'échelle:
où
D
est la diagonale de la matrice de décomposition SVD dans la rotation de l'estimation et deS
est soit la matrice d'identité ou[1 1 -1]
matrice diagonale, selon le signe du déterminant de laUV
(Kabsch utilise pour corriger les reflets dans les rotations). Donc, si vous avez[2000, 200, 20]
, multipliez le dernier élément de +-1 (selon le signe du déterminant de laUV
), de la somme et diviser par l'écart-type de vos points pour obtenir de l'échelle.Vous pouvez recycler le code suivant, qui est à l'aide de la Eigen bibliothèque:
eh bien, pour être honnête, je n'ai pas l'échelle de la matrice de covariance (comme vous pouvez le voir dans le code). L'algorithme serait probablement travailler avec elle, mais l'échelle de calcul ne serait pas. Un grand nombre de D ne sont pas forcément problématique, comme l'échelle dépend aussi de l'écart-type, qui peut être grande (ou petite) par lui-même, indépendamment de l'échelle. Merci pour les éloges.
Comme une note côté, certaines personnes préfèrent Corne de l'algorithme. Il est très similaire à Kabsch, à l'exception qu'il se décompose d'une matrice de 4x4 et la sortie est un quaternion. Pour moi, il ne semble légèrement plus coûteux à calculer donc je m'en tiens à Kabsch et convertir la matrice de 3x3 à un Quaternion par la suite. Je ne suis pas tout à fait sûr si il ya une version de la Corne de l'algorithme qui récupère l'échelle.
Merci pour la réponse très. J'en ai fait 20 lignes de Python de la mise en œuvre de la totalité du problème ici, que j'ai essayé de tune pour aider à la compréhension.
OriginalL'auteur the swine
Vous pourriez vouloir essayer ICP (Iterative closest point).
Étant donné deux ensembles de points 3d, il vous dira la transformation (rotation + translation) pour aller à partir du premier jeu de la seconde.
Si vous êtes intéressé par un de c++ léger de la mise en œuvre, essayez libicp.
Bonne chance!
L'ICP est inutilement trop compliqué et lent si les correspondances entre les points sont connus. Pour Kabsch vous connaissez déjà les correspondances entre les points. ICP peut correspondre à deux ensembles de points (nombre de points, ne se chevauchent partiellement formes,...), mais, bien sûr, le prix beaucoup plus élevé et avec le risque de ne pas converger vers la meilleure solution.
OriginalL'auteur Nacho
Commencer avec la traduction des deux ensembles de points. De sorte que leur centre de gravité coïncide avec l'origine du système de coordonnées. Le vecteur de Translation est juste la différence entre ces centroïdes.
Maintenant, nous avons deux ensembles de coordonnées représentés comme des matrices P et Q. Un ensemble de points qui peuvent être obtenus à partir de l'autre par l'application d'un opérateur linéaire (qui effectue à la fois l'échelle et la rotation). Cet opérateur est représenté par une matrice de 3x3 X:
P * X = Q
Trouver la bonne échelle/rotation nous avons juste besoin de résoudre cette équation matricielle, trouver X, puis de le décomposer en plusieurs matrices, chacune représentant certains d'échelle ou de rotation.
Un simple (mais probablement pas numériquement stable) façon de le résoudre est de multiplier les deux parties de l'équation de la matrice transposée P (pour se débarrasser de non-matrices carrées), puis multiplier les deux parties de l'équation à l'inverse de la PT * P:
PT * P * X = PT * Q
X = (PT * P)-1 * PT * Q
L'application de Décomposition en valeurs singulières à matrice X donne deux matrices de rotation et une matrice avec des facteurs d'échelle:
X = U * S * V
Ici S est une matrice diagonale avec des facteurs d'échelle (une échelle pour chaque coordonnée), U et V sont des matrices de rotation, on tourne correctement les points de sorte qu'ils peuvent être mis à l'échelle le long des axes de coordonnées, l'autre tourne une fois de plus à aligner leur orientation par rapport au deuxième ensemble de points.
Exemple (2D points sont utilisés pour des raisons de simplicité):
Après la résolution de l'équation:
Après la décomposition SVD:
Ici SVD a correctement reconstruite à toutes les manipulations j'ai effectué sur la matrice P pour obtenir la matrice Q: rotation de l'angle de 0,75, à l'échelle de l'axe X par 4, à l'échelle de l'axe Y par 3, rotation de l'angle de -0.25.
Si des ensembles de points sont effectués de manière uniforme (le facteur d'échelle est égal par chaque axe), cette procédure peut être considérablement simplifiée.
Suffit d'utiliser Kabsch algorithme pour obtenir la traduction/valeurs de rotation. Puis effectuer ces de translation et de rotation (centroïdes devrait coïncider avec l'origine du système de coordonnées). Ensuite, pour chaque paire de points (et pour chaque coordonnée) estimation La régression linéaire. Linéaire coefficient de régression est exactement le facteur d'échelle.
dans le 2D cas, il est trivial: les composants de la matrice sont juste sin et cos de l'angle. en 3D cas: axe de rotation est déterminée par le vecteur propre, alors vous trouver l'angle entre un vecteur perpendiculaire à l'axe et le même vecteur transformé par la matrice de rotation. Voir les détails dans wikipédia.
Merci, Evgeny, en particulier pour le lien Wikipédia. Dans votre exemple, comment avez-vous déterminer si l'utilisation de -0.7317 ou 0.7317 pour le cosinus?
Honnêtement, je ne sais pas. Le problème est que certaines lignes de la matrice à partir de SVD sont annulés, et je ne sais pas qui. La seule manière d'utiliser ces données (sans creuser plus profondément dans le problème) est d'essayer les deux possibilités, appliquer la rotation à des points et de voir laquelle est la bonne.
OriginalL'auteur Evgeny Kluev
De points 3D, le problème est connu comme l'Orientation Absolue problème. Une implémentation c++ est disponible à partir de Eigen http://eigen.tuxfamily.org/dox/group__Geometry__Module.html#gab3f5a82a24490b936f8694cf8fef8e60 et papier http://web.stanford.edu/class/cs273/refs/umeyama.pdf
vous pouvez l'utiliser via opencv en convertissant les matrices de eigen avec cv::cv2eigen() appelle.
OriginalL'auteur bendervader
Une bonne explication Trouver optimal de rotation et de translation entre les correspondants des points 3D
Le code est dans matlab, mais il est trivial de convertir à opengl en utilisant le cv::SVD fonction
Cette approche ne fonctionnera qu'avec l'égalité de la taille des nuages. Normalement, vous connaissez les nuages font la même échelle, je n'ai pas essayé, mais il y a une approche à l'échelle de google.com/...
OriginalL'auteur Martin Beckett
Le général de transformation, ainsi que l'échelle peut être récupéré via L'Analyse De Procrustes. Il fonctionne grâce à une superposition des objets sur le dessus de chaque autre et tente d'estimer la transformation de ce paramètre. Il a été utilisé dans le cadre de l'ICP, de nombreuses fois. En fait, votre préférence, Kabash algorithme est un cas particulier de cette.
En outre, la Corne de l'alignement de l'algorithme basé sur les quaternions) on trouve aussi une très bonne solution, tout en étant très efficace. Un Matlab mise en œuvre est également disponible.
OriginalL'auteur Tolga Birdal
Échelle peut être déduit sans SVD, si vos points sont uniformément de façon uniforme dans toutes les directions (je ne pouvais pas faire sens de la SVD-s à l'échelle de la matrice). Voici comment j'ai résolu le même problème:
Mesurer des distances de chaque point à d'autres points dans le nuage de points pour obtenir un 2d tableau des distances, où l'entrée (i,j) est la norme(point_i-point_j). Faire la même chose pour l'autre point de nuage, de sorte que vous obtenez deux tables, une pour origine et l'autre pour reconstruits points.
Diviser toutes les valeurs dans un tableau par les valeurs correspondantes dans l'autre table. Parce que les points correspondent les uns aux autres, les distances en faire trop. Idéalement, le tableau a toutes les valeurs sont égales les unes aux autres, et c'est à cette échelle.
La valeur médiane de la les divisions devraient être assez proche de l'échelle que vous recherchez. La valeur moyenne est proche, mais j'ai choisi médian juste pour exclure les valeurs aberrantes.
Maintenant, vous pouvez utiliser la valeur de l'échelle pour l'échelle de tout le reconstruit points et ensuite de procéder à l'estimation de la rotation.
Astuce: Si il y a trop de points dans le nuage de points de calculer des distances entre chacun d'eux, puis un petit sous-ensemble de distances de travail, trop, aussi longtemps que c'est le même sous-ensemble pour les deux nuages de points. Idéalement, juste une distance paire pourrait fonctionner si il n'y a pas de bruit de mesure, électronique.g quand un nuage de points est directement dérivé de l'autre, juste en tournant.
OriginalL'auteur Rasmus
vous pouvez également utiliser ScaleRatio ICP proposé par BaoweiLin
Le code peut être trouvé sur github
OriginalL'auteur user3654844