Это всегда потребует больших вычислений, особенно если вы хотите обработать до 2000 точек. Я уверен, что уже есть высокооптимизированные решения для такого типа сопоставления с образцом, но вы должны выяснить, как это называется, чтобы найти их.
Поскольку вы говорите о облаке точек (разреженных данных) вместо изображения, мой метод взаимной корреляции на самом деле не применяется (и будет еще хуже в вычислительном отношении). Что-то вроде RANSAC, вероятно, быстро находит совпадение, но я мало что знаю об этом.
Моя попытка решения:
Предположения:
- Вы хотите найти лучшее совпадение, а не просто проигрышное или «вероятно правильное» совпадение
- У совпадения будет небольшая ошибка из-за шума в измерениях или вычислениях
- Исходные точки копланарны
- Все исходные точки должны существовать в цели (= любая несогласованная точка является несовпадением для всего профиля)
Таким образом, вы должны быть в состоянии использовать много ярлыков, дисквалифицируя вещи и уменьшая время вычислений. Короче говоря:
- выбрать три точки из источника
- поиск по целевым точкам, поиск наборов из 3 точек одинаковой формы
- когда найдено совпадение из 3 точек, проверьте все остальные точки в плоскости, которую они определяют, чтобы увидеть, являются ли они близким совпадением
- если найдено более одного совпадения всех точек, выберите ту, в которой ошибка наименьшей суммы трехмерных расстояний
Более подробный:
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)
Какая конфигурация имеет наименьшую квадратичную ошибку для всех остальных точек, это лучшее совпадение
Поскольку мы работаем с 3 ближайшими соседними контрольными точками, сопоставление целевых точек можно упростить, проверив, находятся ли они в некотором радиусе. Например, при поиске радиуса 1 из (0, 0) мы можем дисквалифицировать (2, 0) на основе x1 - x2, не вычисляя фактическое евклидово расстояние, чтобы немного его ускорить. Это предполагает, что вычитание происходит быстрее, чем умножение. Есть оптимизированный поиск, основанный на большем произвольном фиксированном радиусе .
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= ( х1- х2)2+ ( у1- у2)2+ ( z1- з2)2----------------------------√
( 20002)
На самом деле, поскольку вам все равно придется вычислять все эти значения, находите ли вы совпадения или нет, и поскольку для этого шага вас интересуют только ближайшие соседи, если у вас есть память, вероятно, лучше предварительно рассчитать эти значения с использованием оптимизированного алгоритма. , Что-то вроде триангуляции Делоне или Питтеуэя , где каждая точка в цели связана с ее ближайшими соседями. Сохраните их в таблице, затем найдите их для каждой точки, пытаясь подогнать исходный треугольник к одному из целевых треугольников.
Требуется много вычислений, но они должны быть относительно быстрыми, так как они работают только с данными, которые являются редкими, вместо умножения большого количества бессмысленных нулей вместе, как может потребоваться взаимная корреляция объемных данных. Эта же идея будет работать для 2D-случая, если вы сначала нашли центры точек и сохранили их как набор координат.