Ciò richiederà sempre molto calcolo, specialmente se si desidera elaborare fino a 2000 punti. Sono sicuro che esistono già soluzioni altamente ottimizzate per questo tipo di pattern-matching, ma per trovarle devi capire come si chiama.
Dato che stai parlando di una nuvola di punti (dati sparsi) anziché di un'immagine, il mio metodo di correlazione incrociata non si applica (e sarebbe anche peggio dal punto di vista computazionale). Qualcosa come RANSAC probabilmente trova una corrispondenza rapidamente, ma non ne so molto.
Il mio tentativo di soluzione:
ipotesi:
- Vuoi trovare la migliore corrispondenza, non solo una partita libera o "probabilmente corretta"
- La corrispondenza avrà una piccola quantità di errore a causa del rumore nella misurazione o nel calcolo
- I punti sorgente sono complanari
- Tutti i punti di origine devono esistere nel target (= qualsiasi punto non corrispondente è una mancata corrispondenza per l'intero profilo)
Quindi dovresti essere in grado di prendere molte scorciatoie squalificando le cose e diminuendo i tempi di calcolo. In breve:
- scegli tre punti dalla fonte
- cerca tra punti target, trovando gruppi di 3 punti con la stessa forma
- quando viene trovata una corrispondenza di 3 punti, controlla tutti gli altri punti nel piano che definiscono per vedere se sono una corrispondenza ravvicinata
- se viene rilevata più di una corrispondenza di tutti i punti, scegliere quella con la somma più piccola dell'errore delle distanze 3D
Più dettagliato:
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)
Qualunque configurazione abbia l'errore meno quadrato per tutti gli altri punti è la migliore corrispondenza
Poiché stiamo lavorando con 3 punti di test vicini più vicini, è possibile semplificare la corrispondenza dei punti target controllando se si trovano entro un certo raggio. Se stiamo cercando un raggio di 1 da (0, 0), ad esempio, possiamo squalificare (2, 0) in base a x1 - x2, senza calcolare la distanza euclidea effettiva, per accelerare un po '. Ciò presuppone che la sottrazione sia più veloce della moltiplicazione. Esistono ricerche ottimizzate basate anche su un raggio fisso più arbitrario .
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)
In realtà, poiché dovrai calcolare tutti questi comunque, sia che tu trovi corrispondenze o meno, e poiché ti preoccupi solo dei vicini più vicini per questo passaggio, se hai la memoria è probabilmente meglio pre-calcolare questi valori usando un algoritmo ottimizzato . Qualcosa come una triangolazione di Delaunay o Pitteway , in cui ogni punto del bersaglio è collegato ai vicini più vicini. Conservali in una tabella, quindi cercali per ogni punto quando cerchi di adattare il triangolo sorgente a uno dei triangoli target.
Ci sono molti calcoli coinvolti, ma dovrebbe essere relativamente veloce poiché funziona solo sui dati, che è scarso, invece di moltiplicare molti zeri insignificanti come la correlazione incrociata dei dati volumetrici. Questa stessa idea funzionerebbe per il caso 2D se prima trovassi i centri dei punti e li memorizzassi come un insieme di coordinate.