Eigen и SVD, чтобы найти наилучшую плоскость подгонки с учетом набора точек

учитывая набор из N точек в 3D-пространстве, я пытаюсь найти наилучшую подходящую плоскость, используя SVD и Eigen.

мой алгоритм:

  1. центр данных указывает вокруг (0,0,0).
  2. форма 3XN матрица координат точек.
  3. вычислить SVD матрицы.
  4. установите наименьший сингулярный вектор, соответствующий наименьшему сингулярному значению, как Нормаль плоскости.
  5. установить расстояние от источника до плоскости нормальный∙центроид.

Я не могу понять, как использовать модуль SVD Eigen найти наименьший сингулярный вектор, соответствующий наименьшему сингулярному значению матрицы координат точек.

пока у меня есть этот код (шаги 1, 2 и 5 алгоритма):

Eigen::Matrix<float, 3, 1> mean = points.rowwise().mean();
const Eigen::Matrix3Xf points_centered = points.colwise() - mean;

int setting = Eigen::ComputeThinU | Eigen::ComputeThinV;
Eigen::JacobiSVD<Eigen::Matrix3Xf> svd = points_centered.jacobiSvd(setting);

Eigen::Vector3d normal = **???**

double d = normal.dot(mean);

2 ответов


обозначив U = svd.matrixU() векторы U.col(0) и U.col(1) определяет основание вашей плоскости и U.col(2) - это нормально для вашего самолета.

U.col(0) также определяет направление с наибольшим стандартным отклонением.

вы должны использовать флаг ComputeFullU вместо ComputeThinU чтобы иметь правильные размеры, даже если ваши точки являются копланарными.


ваша проблема заключается в том, как сделать наименее квадратную подгонку с помощью модуля Eigen JacobiSVD. Вот ссылке С более полезным примером. Основная идея наименьшего квадрата заключается в том, что вы сначала берете разность векторов всех N-1 точек с одной из N точек, а затем пытаетесь аппроксимировать все такие N-1 векторы как линейную комбинацию двух базисных векторов, которые определяют 2D-плоскость.