Проблема с порядком вращения и трансляции в openCV с SolvePnP

У меня есть 3D-рендеринг openGL и камера, смотрящая на шахматную доску. 3D-рендеринг отображает небольшое перекрестие на трехмерной шахматной доске, на которое указывает камера с 3D-рендерингом. Когда камера в реальной жизни движется, перекрестие и 3D-камера должны двигаться одинаково. Мои переводы работают отлично. Но мои вращения всегда вращаются вокруг начала шахматной доски, а не вокруг ее текущего положения. Я знаю, что это означает неправильный порядок умножения матриц. Но я не знаю, где это. Насколько я знаю, процедура, которой я следовал, должна работать.

Это основной процесс, которому я следую:

  • SolvePnP -> получить rvec и tvec
  • rodrigues -> rvec для RMatrix
  • транспонировать RMatrix (-RMatrix * tvec) -> чтобы получить TVector
  • CVpose =

[RMatrix TVector(0) ... TVector(1) ... TVector(2) 0, 0, 0, 1 ]

  • транспонировать (CVpose) -> получить CVpose '
  • назначить CVpose 'элемент за элементом в GLpose

Мой фактический код для этого раздела:

solvePnP(Mat(boardPoints), Mat(imagePoints),intrinsics, distortion,rvec, tvec, false);
//calculate camera pose
Rodrigues(rvec, rotM); // rotM is camera rotation matrix
RTMat = rotM.t();

//create full transform matrix
for(int row = 0; row < 3; row++){
    for(int col = 0; col < 3; col++){
        CVpose.at<double>(row,col) = RTMat.at<double>(row,col);
    }
    CVpose.at<double>(row, 3) = (tvec.at<double>(row, 0));
}
CVpose.at<double>(3, 3) = 1.0f;

// invert axes for openGL
cvToGl.at<double>(0, 0) = 1.0f; // Invert the x axis
cvToGl.at<double>(1, 1) = -1.0f; // Invert the y axis
cvToGl.at<double>(2, 2) = 1.0f; // invert the z axis
cvToGl.at<double>(3, 3) = 1.0f;

CVpose =  cvToGl * CVpose;

//assign CVpose to GLpose with col major and row major notation taken into account
for(int row = 0; row < 4; row++){
    for(int col = 0; col < 4; col++){
        GLpose[col][row] = GLpose.at<double>(row,col);
    }
}

//rotate camera to face chessboard in GL
GLpose= glm::rotate(GLpose, 180.0f, vec3(1.0f, 0.0f, 0.0f))  ;`

Я что-то упустил? При необходимости дам дополнительную информацию.


person Grim    schedule 22.11.2014    source источник


Ответы (1)


Я решил эту проблему с помощью следующей процедуры:

  1. SolvePnP () -> получить rvec и tvec
  2. rodrigues () -> rvec в RMatrix
  3. транспонировать RMatrix -> RTMatrix
  4. (-RTMatrix * tvec) -> получить TVector
  5. создать идентификатор openGL 4x4 matirx -> (я назвал его GLtransform)
  6. GLtransform = glm :: translate () -> перевести по TVector
  7. GLtransform = glm :: rotate () -> повернуть на rvec
  8. GLtransform = glm :: rotate () -> rotate, чтобы исправить совместимость между осями CV и GL
  9. Нарисуйте GLtransform
person Grim    schedule 21.01.2015