Взвешенный наименьший квадрат - подгонка плоскости к трехмерной точке - PullRequest
5 голосов
/ 12 февраля 2012

Я подгоняю плоскость к трехмерной точке, заданной методом наименьших квадратов. У меня уже есть алгоритм для этого, но я хочу изменить его, чтобы использовать взвешенный метод наименьших квадратов. Это означает, что у меня есть вес для каждой точки (чем больше вес, тем ближе должна быть плоскость к точке).

Текущий алгоритм (без веса) выглядит так:

Рассчитать сумму:

for(Point3D p3d : pointCloud) {
    pos = p3d.getPosition();
    fSumX += pos[0];
    fSumY += pos[1];
    fSumZ += pos[2];
    fSumXX += pos[0]*pos[0];
    fSumXY += pos[0]*pos[1];
    fSumXZ += pos[0]*pos[2];
    fSumYY += pos[1]*pos[1];
    fSumYZ += pos[1]*pos[2];
}

чем сделать матрицы:

double[][] A = {
    {fSumXX, fSumXY, fSumX},
    {fSumXY, fSumYY, fSumY},
    {fSumX,  fSumY,  pointCloud.size()}
};

double[][] B =  {
    {fSumXZ},
    {fSumYZ},
    {fSumZ}
};

, чем решить Ax = B, и 3 составляющие решения являются коэффициентами подобранной равнины ...

Итак, не могли бы вы помочь мне, как изменить это, чтобы использовать веса? Спасибо!

Ответы [ 3 ]

9 голосов
/ 12 февраля 2012

Интуиция

Точка x на плоскости, определяемой нормалью n, и точка на плоскости p подчиняется: n.(x - p) = 0. Если точка y не лежит на плоскости, n.(y -p) не будет равна нулю, поэтому полезным способом определения стоимости является |n.(y - p)|^2. Это квадрат расстояния y от плоскости.

При равных весах вы хотите найти n, который минимизирует общую квадратическую ошибку при суммировании по точкам:

f(n) = sum_i | n.(x_i - p) |^2

Теперь предполагается, что мы знаем некоторую точку p, лежащую на плоскости. Мы можем легко вычислить единицу как центроид, который является просто компонентным средним для точек в облаке точек и всегда будет лежать в плоскости наименьших квадратов.

Решение

Давайте определим матрицу M, где каждая строка является ith точкой x_i минус центроид c, мы можем переписать:

f(n) = | M n |^2

Вы должны быть в состоянии убедить себя, что эта версия умножения матриц такая же, как сумма в предыдущем уравнении.

Затем вы можете взять разложение по сингулярному значению из M, и тогда нужный вам n будет задан правым единственным вектором M, который соответствует наименьшему единственному значению.

Чтобы включить вес, вам просто нужно определить вес w_i для каждой точки. Вычислите c как средневзвешенное значение точек и измените sum_i | n.(x_i - c) |^2 на sum_i | w_i * n.(x_i - c) |^2, а матрицу M аналогичным образом. Затем решите, как и раньше.

2 голосов
/ 12 февраля 2012

Умножьте каждый член в каждой сумме на соответствующий вес.Например:

fSumZ += weight * pos[2];
fSumXX += weight * pos[0]*pos[0];

Поскольку pointCloude.size() является суммой 1 для всех точек, ее следует заменить суммой всех весов.

0 голосов
/ 12 февраля 2012

Начните с переопределения вычисления ошибки наименьших квадратов.Формула пытается минимизировать сумму квадратов ошибок.Умножьте квадратичную ошибку на функцию двух точек, которая уменьшается с расстоянием.Затем попытайтесь минимизировать взвешенную сумму квадратов ошибок и выведите из этого коэффициенты.

...