Cela va toujours nécessiter beaucoup de calculs, surtout si vous souhaitez traiter jusqu'à 2000 points. Je suis sûr qu'il existe déjà des solutions hautement optimisées pour ce type de correspondance de modèles, mais vous devez comprendre comment cela s'appelle afin de les trouver.
Puisque vous parlez d'un nuage de points (données clairsemées) au lieu d'une image, ma méthode de corrélation croisée ne s'applique pas vraiment (et serait encore pire sur le plan informatique). Quelque chose comme RANSAC trouve probablement une correspondance rapidement, mais je n'en sais pas grand-chose.
Ma tentative de solution:
Hypothèses:
- Vous voulez trouver la meilleure correspondance, pas seulement une correspondance lâche ou "probablement correcte"
- La correspondance aura une petite quantité d'erreur due au bruit dans la mesure ou le calcul
- Les points sources sont coplanaires
- Tous les points source doivent exister dans la cible (= tout point sans correspondance est une incompatibilité pour tout le profil)
Vous devriez donc pouvoir prendre beaucoup de raccourcis en disqualifiant les choses et en réduisant le temps de calcul. En bref:
- choisir trois points de la source
- rechercher dans les points cibles, trouver des ensembles de 3 points de même forme
- lorsqu'une correspondance de 3 points est trouvée, vérifiez tous les autres points dans le plan qu'ils définissent pour voir s'ils correspondent étroitement
- si plus d'une correspondance de tous les points est trouvée, choisissez celle avec la plus petite somme d'erreur de distances 3D
Plus détaillé:
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)
Quelle que soit la configuration qui présente le moins d'erreur quadratique pour tous les autres points, c'est la meilleure correspondance
Étant donné que nous travaillons avec 3 points de test voisins les plus proches, la correspondance des points cibles peut être simplifiée en vérifiant s'ils se trouvent dans un certain rayon. Si vous recherchez un rayon de 1 à partir de (0, 0), par exemple, nous pouvons disqualifier (2, 0) sur la base de x1 - x2, sans calculer la distance euclidienne réelle, pour l'accélérer un peu. Cela suppose que la soustraction est plus rapide que la multiplication. Il existe également des recherches optimisées basées sur un rayon fixe plus arbitraire .
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
ré= ( x1- x2)2+ ( y1- y2)2+ ( z1- z2)2----------------------------√
Le temps de calcul minimum serait si aucune correspondance à 2 points n'est trouvée. S'il y a 2000 points dans la cible, ce serait des calculs de distance de 2000 * 2000, bien que beaucoup soient disqualifiés par une soustraction, et les résultats des calculs précédents pourraient être stockés de sorte que vous n'avez qu'à faire = 1999000.( 20002)
En fait, puisque vous devrez de toute façon calculer tous ces éléments, que vous trouviez des correspondances ou non, et puisque vous ne vous souciez que des voisins les plus proches pour cette étape, si vous avez la mémoire, il est probablement préférable de pré-calculer ces valeurs à l'aide d'un algorithme optimisé . Quelque chose comme une triangulation de Delaunay ou Pitteway , où chaque point de la cible est connecté à ses voisins les plus proches. Stockez-les dans un tableau, puis recherchez-les pour chaque point lorsque vous essayez d'ajuster le triangle source à l'un des triangles cibles.
Il y a beaucoup de calculs impliqués, mais cela devrait être relativement rapide car il ne fonctionne que sur les données, ce qui est rare, au lieu de multiplier beaucoup de zéros sans signification, comme une corrélation croisée de données volumétriques impliquerait. Cette même idée fonctionnerait pour le cas 2D si vous trouviez d'abord les centres des points et les stockiez sous la forme d'un ensemble de coordonnées.