Как использовать вектор вращения OpenCV и перевод с OpenGL ES в Android?
Я работаю над базовым дополненным реальным приложением на Android. То, что я сделал до сих пор, - это обнаружить квадрат с opencv, а затем использовать cvFindExtrinsicCameraParams2() Я вычислил вектор вращения и перевода. Для этого я использовал 4 точки объекта, которые являются только углами квадрата вокруг (0,0,0) и 4 углами квадрата изображения.
Это дает мне довольно хорошую матрицу вращения и перевода. Я также вычислил матрицу вращения cvRodrigues2(), так как использование этого проще, чем вектор вращения. Пока я использую их, чтобы нарисовать некоторые точки на изображении, все работает нормально. Однако мой следующий шаг - передать эти векторы и матрицу обратно в java, а затем использовать их с OpenGL для рисования квадрата в OpenGLView. Квадрат должен быть точно вокруг квадрата в изображении, который отображается за OpenGLView.
Моя проблема в том, что я не могу найти правильный способ использования матрицы вращения и вектора перевода в OpenGL. Я начал с точно таких же объектов, что и для функций openCV. Затем я применил матрицу вращения и вектор трансляции практически любым возможным способом, о котором я мог думать. К сожалению, ни один из этих подходов не дает результата, который в любом случае приближается к тому, на что я надеялся. Может ли кто-нибудь сказать мне, как правильно их использовать?
До сих пор "самые близкие" результаты, которые я получил, были при случайном умножении всей матрицы на -1. Но большую часть времени квадраты по-прежнему выглядят зеркально, повернуты или повернуты на 180 градусов. Поэтому я думаю, что это был просто удачный удар, но не правильный подход.
Ответы
Ответ 1
Хорошо, после некоторого тестирования я, наконец, смог заставить его работать. Хотя я этого не понимаю... он "работает". Для тех, кому это нужно в будущем, это мое решение.
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%, я думаю, что это ответ на мой вопрос.
Ответ 2
Метод Пандоро действительно работает! В случае, если кто-то задается вопросом "как преобразовать вектор вращения в матрицу вращения" здесь, как я это сделал. Кстати, я использовал их в OpenGL 2, а не в ES.
// use the rotation vector generated from OpenCV cvFindExtrinsicCameraParams2()
float rv[] = {rotation->data.fl[0], rotation->data.fl[1], rotation->data.fl[2] };
// use the translation vector generated from OpenCV 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};
Удачи!