Как использовать вектор вращения и перевода OpenCV с OpenGL ES в Android?
Я работаю над основным приложением дополненной реальности на Android. То, что я сделал до сих пор, это обнаружить квадрат с opencv, а затем с помощью cvFindExtrinsicCameraParams2() я вычислил вектор вращения и перевода. Для этого я использовал 4 точки объекта, которые являются только углами квадрата вокруг (0,0,0) и 4 углами квадрата на изображении.
Это дает мне довольно хорошую матрицу вращения и перевода. Я также рассчитал матрицу вращения с cvRodrigues2() поскольку использовать это проще, чем вектор вращения. Пока я использую их для рисования некоторых точек на изображении, все работает нормально. Однако мой следующий шаг-передать эти векторы и матрицу обратно на java, а затем использовать их с OpenGL для рисования квадрата в OpenGLView. Квадрат должен быть точно вокруг квадрата на изображении, которое отображается за OpenGLView.
моя проблема в том, что я не могу найти правильный способ использования матрицы вращения и вектора перевода в использование OpenGL. Я начал с тех же точек объекта, что и для функций openCV. Затем я применил матрицу вращения и вектор перевода практически любым возможным способом, который мог придумать. К сожалению, ни один из этих подходов не дает результата, который в любом случае близок к тому, на что я надеялся. Может ли кто-нибудь сказать мне, как правильно их использовать?
до сих пор" ближайшие " результаты, которые я получил, были при случайном умножении всей матрицы на -1. Но большую часть времени квадраты все еще выглядят зеркальное или поворачивать на 180 градусов. Так что я думаю, это был просто удачный удар, но не правильный подход.
2 ответов
хорошо после еще нескольких тестов мне наконец удалось заставить его работать. Пока я этого не понимаю... это "работает". Для всех, кому нужно будет сделать это в будущем, вот мое решение.
float rv[3]; // the rotation vector
float rotMat[9]; // rotation matrix
float tv[3]; // translation vector.
rv[1]=-1.0f * rv[1]; rv[2]=-1.0f * rv[2];
//Convert the rotation vector into a matrix here.
//Complete matrix ready to use for OpenGL
float RTMat[] = {rotMat[0], rotMat[3], rotMat[6], 0.0f,
rotMat[1], rotMat[4], rotMat[7], 0.0f,
rotMat[2], rotMat[5], rotMat[8], 0.0f,
tv[0], -tv[1], -tv[2], 1.0f};
Как сказал genpfault в своем комментарии, все должно быть транспонировано с OpenGL, так как OpenGL нужен порядок столбцов. (Спасибо за комментарий, я уже видел эту страницу раньше.) Кроме того, угол поворота y и z, а также перевод y и z должны быть умножены по -1. Вот что я нахожу немного странным. Почему только те, а не значения x тоже?
это работает так, как я должен догадываться. Но углы не совпадают. Я думаю, это вызвано некоторыми неправильными конфигурациями openGLView. Поэтому, хотя я все еще не на 100% доволен своим решением, я думаю, что это ответ на мой вопрос.
метод пандоро действительно работает! Если кому-то интересно "как преобразовать вектор вращения в матрицу вращения", вот как я это сделал. Кстати, я использовал их в OpenGL 2, а не ES.
// use the rotation vector generated from OpenCV's cvFindExtrinsicCameraParams2()
float rv[] = {rotation->data.fl[0], rotation->data.fl[1], rotation->data.fl[2] };
// use the translation vector generated from OpenCV's cvFindExtrinsicCameraParams2()
float tv[] = {translation->data.fl[0], translation->data.fl[1], translation->data.fl[2]} ;
float rm[9];
// rotation matrix
CvMat* rotMat = cvCreateMat (3, 3, CV_32FC1);
// rotation vectors can be converted to a 3-by-3 rotation matrix
// by calling cvRodrigues2() - Source: O'Reilly Learning OpenCV
cvRodrigues2(rotation, rotMat, NULL);
for(int i=0; i<9; i++){
rm[i] = rotMat->data.fl[i];
}
rv[1]=-1.0f * rv[1]; rv[2]=-1.0f * rv[2];
//Convert the rotation vector into a matrix here.
//Complete matrix ready to use for OpenGL
float RTMat[] = {rm[0], rm[3], rm[6], 0.0f,
rm[1], rm[4], rm[7], 0.0f,
rm[2], rm[5], rm[8], 0.0f,
tv[0], -tv[1], -tv[2], 1.0f};
удачи!