Восстановление позы из основной матрицы дает противоречивый признак вектора перевода

У меня есть три представления с точечными соответствиями, и я хочу вычислить положение камеры во втором и третьем представлениях. Поэтому я генерирую случайный набор данных (без шума), содержащий точки в разных видах с известным вращением и перемещением камеры во втором и третьем виде относительно первого вида. Сначала я генерирую случайные 2D-точки в первом виде, затем назначаю случайные (положительные) глубины для получения соответствующих 3D-точек и, наконец, использую случайно сгенерированные повороты и перемещения для проецирования этих 3D-точек во второй и третий вид.

Сначала я вычисляю трифокальный тензор (см. Hartley & Zisserman, Multiple View Geometry Chapter 15). Затем я следую подходу, описанному в этом ответе, чтобы получить повороты R_i и переводы t_i второго и третьего представления. .

Расчет всегда дает правильный поворот, но, к сожалению, знак векторов переноса не всегда правильный. t2 и t3 имеют правильный масштаб, но иногда (!) случается, когда я использую новый случайно сгенерированный набор данных, знак переворачивается по отношению к истинным переводам , например:

Наземная правда:

R2 = [0.9942   -0.0998    0.0393
      0.1069    0.9541   -0.2798
     -0.0096    0.2823    0.9593]
t2 = [0.4267
      0.3747
      0.3544]
R3 = [0.9764   -0.0626    0.2069
      0.1358    0.9222   -0.3622
      -0.1681    0.3817    0.9089]
t3 = [0.3963
      0.0285
      0.2093]

Вывод моего алгоритма (с переводом, определенным в масштабе):

R2 = [0.994229 -0.0998196  0.0393062
      0.106851   0.954105  -0.279761
     -0.00957664   0.282346   0.959265]
t2 = [-0.637428
      -0.559842
      -0.529398]
R3 = [0.976367 -0.0625748   0.206861
      0.135829    0.92217  -0.362151
      -0.168099    0.38169   0.908876]
t3 = [-0.591991
      -0.0426261
      -0.312637]

Сравнивая наземную правду и мой вывод t2 и t3, мы видим, что они идентичны в масштабе (и в этом примере инвертированы по знаку), т.е. правда и мой алгоритм дают:

for ground truth:
[ 1.0768
 13.1338
  1.6933]

for my algorithm:
[ 1.0768
 13.1338
  1.6933]

Мой первый вопрос: что может быть причиной этого несоответствия знака векторов перевода? (особенно учитывая тот факт, что в остальном результаты верны).

Мой второй вопрос: откуда берутся эти формулы, приведенные в приведенном выше связанном ответе, шаг 4? У меня есть книга "Multiple View Geometry" Hartley & Zisserman, но я не смог найти там описанный алгоритм.

Вот фрагмент кода моей реализации шага 4 алгоритма в приведенной выше ссылке (с использованием библиотеки Eigen, я не хочу использовать OpenCV) для нахождения правильного решения вращения R и вектора переноса t из основной матрицы E, при заданном трехмерном однородном 2D-точечном соответствии p1, p2 и p3:

getPoseFromEssentialMat(Matrix3d E)
{
  Matrix3d W, U, V;
  W << 0.0, -1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0;

  // calculate the SVD of the essential matrix
  JacobiSVD<MatrixXd> svdE(E, ComputeThinU | ComputeThinV);
  // if det(U) < 0 -> U = -U, if det(V) < 0 -> V = -V
  U = svdE.matrixU();
  if (U.determinant() < 0.0)
  {
    U *= -1.0;
  }
  V = svdE.matrixV();
  if (V.determinant() < 0.0)
  {
    V *= -1.0;
  }

  R = U * W * V.transpose();
  t = U.col(2);

  findCorrectSolution(R, t, W, U, V);
}


findCorrectSolution(Matrix3d& R, Vector3d& t, Matrix3d W, Matrix3d U, Matrix3d V)
{
  MatrixXd P(3, 4); // P = [R | t]
  P.block(0, 0, 3, 3) = R;
  P.col(3) = t;

  Vector3d Rtpt = R.transpose() * t;
  Matrix3d M = crossProductMatrix(Rtpt);
  Vector3d X_1 = M * K_inv_ * p1; // point in 1. view

  Vector3d X_i = M * R.transpose() * K_inv_ * pi; // point in i. view

  if (X_1(2) * X_i(2) < 0.0) // depth components
  {
    R = U * W.transpose() * V.transpose();
    Rtpt = R.transpose() * t;
    M = crossProductMatrix(Rtpt);
    X_1 = M * K_inv_ * p1;
  }
  if (X_1(2) < 0.0) // depth of 1. 3D point
 {
    t = -t;
 }

person takahashi    schedule 09.07.2015    source источник