VVVVV 2 Жалоба Опубликовано January 5, 2014 Пытаюсь спроецировать чайник на маркер (шахматную доску) при помощи OpenCV и OpenGL. Как делаю: * получаю изображение с камеры; * нахожу шаблон при помощиc vFindChessboardCorners; * вызываю solvePnp, передав туда матрицу камеры, коэффициенты дисторсии (получил их, используя пример calibration из OpenGL), координаты объекта в 3D, и полученные точки. * зная, что матрицы OpenCV и OpenGL не совпадают, конвертирую матрицу и передаю её в GL_MODELVIEW. Проблема: неправильно определяются углы и перенос (см. картинку). Также: что я должен передать в качестве objectPoints в solvePnp? Я не до конца понимаю суть этих координат. Что я получаю: Код: void process() { frame = cvQueryFrame(capture); cvFlip(frame, frame, 1); IplImage * gray = cvCreateImage(cvGetSize(frame), frame->depth, 1); cvCvtColor(frame, gray, CV_BGR2GRAY); int cornerCount = 0; int found = cvFindChessboardCorners(frame, patternSize, patternCorners, &cornerCount, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS); cvFindCornerSubPix(gray, patternCorners, PATTERN_SQUARES_COUNT, patternSize,cvSize(-1,-1), cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 )); if( cornerCount == PATTERN_SQUARES_COUNT) { CvPoint2D32f patternPlane[4]; CvPoint2D32f imagePlane[4]; imagePlane[0].x = 0; imagePlane[0].y = 0; imagePlane[1].x = 640; imagePlane[1].y = 0; imagePlane[2].x = 640.0f; imagePlane[2].y = 480.0f; imagePlane[3].x = 0; imagePlane[3].y = 480.0f; patternPlane[0].x = patternCorners[0].x; patternPlane[0].y = patternCorners[0].y; patternPlane[1].x = patternCorners[4].x; patternPlane[1].y = patternCorners[4].y; patternPlane[2].x = patternCorners[19].x; patternPlane[2].y = patternCorners[19].y; patternPlane[3].x = patternCorners[15].x; patternPlane[3].y = patternCorners[15].y; cvGetPerspectiveTransform(imagePlane, patternPlane, warpMatrix); cvLine(frame, cvPoint(patternPlane[0].x,patternPlane[0].y) , cvPoint(patternPlane[1].x, patternPlane[1].y), CV_RGB(255, 0, 0)); cvLine(frame, cvPoint(patternPlane[1].x,patternPlane[1].y) , cvPoint(patternPlane[2].x, patternPlane[2].y), CV_RGB(255, 0, 0)); cvLine(frame, cvPoint(patternPlane[2].x,patternPlane[2].y) , cvPoint(patternPlane[3].x, patternPlane[3].y), CV_RGB(255, 0, 0)); cvLine(frame, cvPoint(patternPlane[3].x,patternPlane[3].y) , cvPoint(patternPlane[0].x, patternPlane[0].y), CV_RGB(255, 0, 0)); cv::Mat rvec(3,1,cv::DataType<double>::type); cv::Mat tvec(3,1,cv::DataType<double>::type); std::vector<cv::Point3d> objectPoints(4); std::vector<cv::Point2d> imagePoints(4); for( int i = 0; i < 4; ++i) { imagePoints[i].x = patternPlane[i].x; imagePoints[i].y = patternPlane[i].y; } objectPoints[0] = cv::Point3d(-0.5, -0.5, 0); objectPoints[1] = cv::Point3d(-0.5, 0.5, 0); objectPoints[2] = cv::Point3d(0.5, 0.5, 0); objectPoints[3] = cv::Point3d(0.5, -0.5, 0); cv::Mat distCoeffs = cv::Mat(5, 1, cv::DataType<double>::type); distCoeffs.at<double>(0) = -1.8436299045609152e+000; distCoeffs.at<double>(1) = 9.4006548737354095e+001; distCoeffs.at<double>(2) = 5.3534809112582196e-002; distCoeffs.at<double>(3) = 3.6660383502917997e-002; distCoeffs.at<double>(4) = -1.4544803056488936e+003; cv::Mat camMat = cv::Mat(3, 3, cv::DataType<double>::type); cv::setIdentity(camMat); camMat.at<double>(0, 0) = 1.4940995863136072e+003; camMat.at<double>(0, 1) = 0; camMat.at<double>(0, 2) = 3.2909815768239292e+002; camMat.at<double>(1, 0) = 0; camMat.at<double>(1, 1) = 1.5489456829024023e+003; camMat.at<double>(1, 2) = 1.9730921217312456e+002; camMat.at<double>(2, 0) = 0; camMat.at<double>(2, 1) = 0; camMat.at<double>(2, 2) = 1; cv::solvePnP(objectPoints, imagePoints, camMat, distCoeffs, rvec, tvec); DebugPrint("Rotation: %f %f %f\n", (float)rvec.at<double>(0), (float)rvec.at<double>(1), (float)rvec.at<double>(2)); DebugPrint("Translation: %f %f %f\n", tvec.at<double>(0), tvec.at<double>(1), tvec.at<double>(2)); std::vector<cv::Point3f> axisPoints(8); std::vector<cv::Point2f> cubePoints(8); axisPoints[0].x = 0; axisPoints[0].y = 0; axisPoints[0].z = 0; axisPoints[1].x = 0; axisPoints[1].y = 0; axisPoints[1].z = 1; axisPoints[2].x = 1; axisPoints[2].y = 0; axisPoints[2].z = 1; axisPoints[3].x = 1; axisPoints[3].y = 0; axisPoints[3].z = 0; axisPoints[4].x = 0; axisPoints[4].y = -1; axisPoints[4].z = 0; axisPoints[5].x = 0; axisPoints[5].y = -1; axisPoints[5].z = 1; axisPoints[6].x = 1; axisPoints[6].y = -1; axisPoints[6].z = 1; axisPoints[7].x = 1; axisPoints[7].y = -1; axisPoints[7].z = 0; cv::projectPoints(axisPoints, rvec, tvec, camMat, distCoeffs, cubePoints); cvLine(frame, cubePoints[0], cubePoints[1], CV_RGB(0, 255, 0), 2); cvLine(frame, cubePoints[1], cubePoints[2], CV_RGB(0, 255, 0), 2); cvLine(frame, cubePoints[2], cubePoints[3], CV_RGB(0, 255, 0), 2); cvLine(frame, cubePoints[3], cubePoints[0], CV_RGB(0, 255, 0), 2); cvLine(frame, cubePoints[4], cubePoints[5], CV_RGB(255, 0, 0), 2); cvLine(frame, cubePoints[5], cubePoints[6], CV_RGB(255, 0, 0), 2); cvLine(frame, cubePoints[6], cubePoints[7], CV_RGB(255, 0, 0), 2); cvLine(frame, cubePoints[7], cubePoints[4], CV_RGB(255, 0, 0), 2); cvLine(frame, cubePoints[4], cubePoints[0], CV_RGB(0, 0, 255), 2); cvLine(frame, cubePoints[6], cubePoints[2], CV_RGB(0, 0, 255), 2); cvLine(frame, cubePoints[7], cubePoints[3], CV_RGB(0, 0, 255), 2); cvLine(frame, cubePoints[5], cubePoints[1], CV_RGB(0, 0, 255), 2); tvec.at<double>(0, 0) *= -1; cv::Mat R(3, 3, CV_64FC1); cv::Rodrigues(rvec, R); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(50, 1.3, 1.0, 1000); gluLookAt(0, 0, -10, 0, 0, 0, 1, 0, 0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); float mat44[16] = {(float)R.at<double>(0, 0), (float)R.at<double>(0, 1), (float)R.at<double>(0, 2), 0, (float)R.at<double>(1, 0), (float)R.at<double>(1, 1), (float)R.at<double>(1, 2), 0, (float)R.at<double>(2, 0), (float)R.at<double>(2, 1), (float)R.at<double>(2, 2), 0, tvec.at<double>(0), tvec.at<double>(1), tvec.at<double>(2), 1}; glLoadMatrixf(mat44); } cvShowImage(WINDOW_CAPTURE_NAME, frame); cvReleaseImage(&gray); gray = NULL; glutPostRedisplay(); } Я уже гуглил, нашел темы, вроде http://stackoverflow.com/questions/19612704/opencv-opengl-proper-camera-pose-using-solvepnp или http://stackoverflow.com/questions/18637494/camera-position-in-world-coordinate-from-cvsolvepnp или http://stackoverflow.com/questions/10313040/opencv-rotation-translation-vector-to-opengl-modelview-matrix?rq=1 , но ни одна из этих ссылок мне не помогла. Что же я делаю не так? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано January 5, 2014 Тут смотрели?: http://code.opencv.org/projects/opencv/wiki/Posit Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
VVVVV 2 Жалоба Опубликовано January 5, 2014 Сделал просто glRotatef((rvec.at<double>(0) * 180) / 3.141592, 1, 0, 0); glRotatef((rvec.at<double>(1) * 180) / 3.141592, 0, 1, 0); glRotatef((rvec.at<double>(2) * 180) / 3.141592, 0, 0, 1); Много лучше не стало - углы нестабильно определяются правильно, перенос совсем неправильно работает. Тут смотрели?: http://code.opencv.org/projects/opencv/wiki/Posit Посмотрел, пытаюсь обпилить исходник под своб задачу. Но это все же не то, ведь мне интересно, где ошибка в моем коде и как её устранить. Прозреваю, что что-то не так именно с конверсией матрицы или неправильно заданными физическими координатам объекта (почему я так думаю: cv::projectPoints работает же). Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано January 5, 2014 А матрица проекции у вас из каких соображений при помощи LookAt формируется? И попробуйте умножать на не раздраконенную Родригисом матрицу, а на полную (поворот и перенос вместе). Помню что-то пробовал с углами делать, тоже вроде бы все скакало. По поводу переноса, попробуйте поменять порядок операций переноса и поворота. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
VVVVV 2 Жалоба Опубликовано January 6, 2014 Поменял код - много лучше не стало. void process() { frame = cvQueryFrame(capture); IplImage * gray = cvCreateImage(cvGetSize(frame), frame->depth, 1); cvCvtColor(frame, gray, CV_BGR2GRAY); int cornerCount = 0; int found = cvFindChessboardCorners(frame, patternSize, patternCorners, &cornerCount, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS); cvFindCornerSubPix(gray, patternCorners, PATTERN_SQUARES_COUNT, patternSize,cvSize(-1,-1), cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 )); if( cornerCount == PATTERN_SQUARES_COUNT) { CvPoint2D32f patternPlane[4]; patternPlane[0].x = patternCorners[0].x; patternPlane[0].y = patternCorners[0].y; patternPlane[1].x = patternCorners[15].x; patternPlane[1].y = patternCorners[15].y; patternPlane[2].x = patternCorners[19].x; patternPlane[2].y = patternCorners[19].y; patternPlane[3].x = patternCorners[4].x; patternPlane[3].y = patternCorners[4].y; cv::Mat tvec(3,1,cv::DataType<double>::type); cv::Mat rvec(3,1,cv::DataType<double>::type); std::vector<cv::Point3d> objectPoints(4); std::vector<cv::Point2d> imagePoints(4); for( int i = 0; i < 4; ++i) { imagePoints[i].x = patternPlane[i].x; imagePoints[i].y = patternPlane[i].y; } objectPoints[0] = cv::Point3d(-1, 1, 0); objectPoints[1] = cv::Point3d(-1, -1, 0); objectPoints[2] = cv::Point3d(1, -1, 0); objectPoints[3] = cv::Point3d(1, 1, 0); cv::Mat distCoeffs = cv::Mat(5, 1, cv::DataType<double>::type); distCoeffs.at<double>(0) = -1.8436299045609152e+000; distCoeffs.at<double>(1) = 9.4006548737354095e+001; distCoeffs.at<double>(2) = 5.3534809112582196e-002; distCoeffs.at<double>(3) = 3.6660383502917997e-002; distCoeffs.at<double>(4) = -1.4544803056488936e+003; cv::Mat camMat = cv::Mat(3, 3, cv::DataType<double>::type); cv::setIdentity(camMat); camMat.at<double>(0, 0) = 1.4940995863136072e+003; camMat.at<double>(0, 1) = 0; camMat.at<double>(0, 2) = 3.2909815768239292e+002; camMat.at<double>(1, 0) = 0; camMat.at<double>(1, 1) = 1.5489456829024023e+003; camMat.at<double>(1, 2) = 1.9730921217312456e+002; camMat.at<double>(2, 0) = 0; camMat.at<double>(2, 1) = 0; camMat.at<double>(2, 2) = 1; cv::solvePnP(objectPoints, imagePoints, camMat, distCoeffs, rvec, tvec); DebugPrint("Rotation: %f %f %f\n", (float)rvec.at<double>(0), (float)rvec.at<double>(1), (float)rvec.at<double>(2)); DebugPrint("Translation: %f %f %f\n", tvec.at<double>(0), tvec.at<double>(1), tvec.at<double>(2)); std::vector<cv::Point3f> axisPoints(4); std::vector<cv::Point2f> cubePoints(4); axisPoints[0].x = 0; axisPoints[0].y = 0; axisPoints[0].z = 0; axisPoints[1].x = 1; axisPoints[1].y = 0; axisPoints[1].z = 0; axisPoints[2].x = 0; axisPoints[2].y = -1; axisPoints[2].z = 0; axisPoints[3].x = 0; axisPoints[3].y = 0; axisPoints[3].z = 1; cv::projectPoints(axisPoints, rvec, tvec, camMat, distCoeffs, cubePoints); cvLine(frame, cubePoints[0], cubePoints[1], CV_RGB(255, 0, 0), 2); cvLine(frame, cubePoints[0], cubePoints[2], CV_RGB(0, 255, 0), 2); cvLine(frame, cubePoints[0], cubePoints[3], CV_RGB(0, 0, 255), 2); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(50, 640/480, 1.0, 1000); float proj[16] = { 2*1.4940995863136072e+003/640, 0, (640 - 2 * 3.2909815768239292e+002) / 640, 0, 0, 2 * 1.5489456829024023e+003 / 480, (480 - 2 * 1.9730921217312456e+002) / 480, 0, 0, 0, (-1000 - 1)/(1000 - 1), -2*1000*1/(1000 - 1), 0, 0, -1, 0 }; glLoadMatrixf(proj); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); rvec.at<double>(1) = -1.0 * rvec.at<double>(1); rvec.at<double>(2) = -1.0 * rvec.at<double>(2); cv::Mat rotMat(3, 3, CV_64FC1); cv::Rodrigues(rvec, rotMat); float mat44[16] = {(float)rotMat.at<double>(0, 0), (float)rotMat.at<double>(0, 1), (float)rotMat.at<double>(0, 2), 0, (float)rotMat.at<double>(1, 0), (float)rotMat.at<double>(1, 1), (float)rotMat.at<double>(1, 2), 0, (float)rotMat.at<double>(2, 0), (float)rotMat.at<double>(2, 1), (float)rotMat.at<double>(2, 2), 0, tvec.at<double>(0), -tvec.at<double>(1), -tvec.at<double>(2), 1}; glLoadMatrixf(mat44); } cvShowImage(WINDOW_CAPTURE_NAME, frame); cvFlip(frame, frame, 0); glBindTexture( GL_TEXTURE_2D, backgroundId ); glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); gluBuild2DMipmaps(GL_TEXTURE_2D,3,frame->width, frame->height, GL_BGR_EXT,GL_UNSIGNED_BYTE, frame->imageData); cvReleaseImage(&gray); gray = NULL; glutPostRedisplay(); } Получаю: И попробуйте умножать на не раздраконенную Родригисом матрицу, а на полную (поворот и перенос вместе). Не совсем понял вас, пожалуйста, поясните. Помню что-то пробовал с углами делать, тоже вроде бы все скакало. Уж лучше бы оно скакало, "дрыгания"-то можно подавить, а тут трансформируется неправильно. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано January 6, 2014 Интересный мануал по матрицам поворота: http://www.cs.rpi.edu/~trink/Courses/RobotManipulation/lectures/lecture6.pdf Я имел ввиду использовать не матрицу вида 0 -wz wy wz 0 -wx -wy wx 0[/code] (вы из нее углы получаете, затем извращенным способом (glRotate) формируете матрицу преобразования). Можно взять непосредственно матрицу 4х4, полученную из POSIT, и использовать ее для преобразования координат (взять установить единичную, затем умножить на пролученную от POSIT). У меня был такой кусок кода [code] glMatrixMode(GL_PROJECTION); glLoadMatrixf(&posit.projectionMatrix[0]); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Делаем отражение в зеркале glScalef(-1.0f, -1.0f, -1.0f); posit.posePOSIT[12] *= -1; // X posit.posePOSIT[13] *= -1; // Y glMultMatrixf(posit.posePOSIT); //************************************* Draw3DObject(textureFrontID,textureLeftID); Мой класс POSIT: posit.rar Писал все это 3 года назад, многое уже забыл. 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
BeS 53 Жалоба Опубликовано January 6, 2014 Советую почитать книгу Mastering OpenCV. Там целая глава посвящена работе с маркерами при помощи OpenCV&OpenGL Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
VVVVV 2 Жалоба Опубликовано January 8, 2014 Сделал таки. void process() { frame = cvQueryFrame(capture); IplImage * gray = cvCreateImage(cvGetSize(frame), frame->depth, 1); cvCvtColor(frame, gray, CV_BGR2GRAY); int cornerCount = 0; int found = cvFindChessboardCorners(frame, patternSize, patternCorners, &cornerCount, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS); cvFindCornerSubPix(gray, patternCorners, PATTERN_SQUARES_COUNT, patternSize,cvSize(-1,-1), cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 )); if( cornerCount == PATTERN_SQUARES_COUNT) { CvPoint2D32f patternPlane[4]; patternPlane[0].x = patternCorners[0].x; patternPlane[0].y = patternCorners[0].y; patternPlane[1].x = patternCorners[15].x; patternPlane[1].y = patternCorners[15].y; patternPlane[2].x = patternCorners[19].x; patternPlane[2].y = patternCorners[19].y; patternPlane[3].x = patternCorners[4].x; patternPlane[3].y = patternCorners[4].y; cv::Mat tvec(3,1,cv::DataType<double>::type); cv::Mat rvec(3,1,cv::DataType<double>::type); std::vector<cv::Point3d> objectPoints(4); std::vector<cv::Point2d> imagePoints(4); for( int i = 0; i < 4; ++i) { imagePoints[i].x = patternPlane[i].x; imagePoints[i].y = patternPlane[i].y; } objectPoints[0] = cv::Point3d(-1, 0, 1); objectPoints[1] = cv::Point3d(-1, 0, -1); objectPoints[2] = cv::Point3d(1, 0, -1); objectPoints[3] = cv::Point3d(1, 0, 1); cv::Mat distCoeffs = cv::Mat(5, 1, cv::DataType<double>::type); distCoeffs.at<double>(0) = -1.8436299045609152e+000; distCoeffs.at<double>(1) = 9.4006548737354095e+001; distCoeffs.at<double>(2) = 5.3534809112582196e-002; distCoeffs.at<double>(3) = 3.6660383502917997e-002; distCoeffs.at<double>(4) = -1.4544803056488936e+003; cv::Mat camMat = cv::Mat(3, 3, cv::DataType<double>::type); cv::setIdentity(camMat); camMat.at<double>(0, 0) = 1.4940995863136072e+003; camMat.at<double>(0, 1) = 0; camMat.at<double>(0, 2) = 3.2909815768239292e+002; camMat.at<double>(1, 0) = 0; camMat.at<double>(1, 1) = 1.5489456829024023e+003; camMat.at<double>(1, 2) = 1.9730921217312456e+002; camMat.at<double>(2, 0) = 0; camMat.at<double>(2, 1) = 0; camMat.at<double>(2, 2) = -1; cv::solvePnP(objectPoints, imagePoints, camMat, distCoeffs, rvec, tvec); std::vector<cv::Point3f> axisPoints(4); std::vector<cv::Point2f> cubePoints(4); axisPoints[0].x = 0; axisPoints[0].y = 0; axisPoints[0].z = 0; axisPoints[1].x = 1; axisPoints[1].y = 0; axisPoints[1].z = 0; axisPoints[2].x = 0; axisPoints[2].y = -1; axisPoints[2].z = 0; axisPoints[3].x = 0; axisPoints[3].y = 0; axisPoints[3].z = 1; cv::projectPoints(axisPoints, rvec, tvec, camMat, distCoeffs, cubePoints); cvLine(frame, cubePoints[0], cubePoints[1], CV_RGB(255, 0, 0), 2); cvLine(frame, cubePoints[0], cubePoints[2], CV_RGB(0, 255, 0), 2); cvLine(frame, cubePoints[0], cubePoints[3], CV_RGB(0, 0, 255), 2); glMatrixMode(GL_PROJECTION); gluPerspective(50, 640/480, 1.0, 1000); float f_x = 1.4940995863136072e+003; float f_y = 1.5489456829024023e+003; float c_x = 3.2909815768239292e+002; float c_y = 1.9730921217312456e+002; float fx = -2.0 * f_x / 640; float fy = 2.0 * f_y / 480; float cx = 2.0 * c_x / 640 - 1; float cy = 2.0 * c_y / 480 - 1; float fn = -(100 + 1) / (100 - 1); float fcn = -2.0 * 100 * 1 / (100 - 1); float proj[16] = { fx, 0, cx, 0, 0, fy, cy, 0, 0, 0, fn, fcn, 0, 0, -1, 0 }; glLoadMatrixf(proj); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); cv::Mat rotMat(3, 3, CV_64FC1); cv::Rodrigues(rvec, rotMat); float mat44[16] = {(float)rotMat.at<double>(0, 0), (float)rotMat.at<double>(0, 1), (float)rotMat.at<double>(0, 2), 0, (float)rotMat.at<double>(1, 0), (float)rotMat.at<double>(1, 1), (float)rotMat.at<double>(1, 2), 0, (float)rotMat.at<double>(2, 0), (float)rotMat.at<double>(2, 1), (float)rotMat.at<double>(2, 2), 0, tvec.at<double>(0), tvec.at<double>(1), -tvec.at<double>(2), 1}; glLoadMatrixf(mat44); glRotatef(180, 0, 1, 0); } cvShowImage(WINDOW_CAPTURE_NAME, frame); cvReleaseImage(&gray); gray = NULL; glutPostRedisplay(); } Mastering OpenCV Полистал. Интересная книга, эдакий сбрник рецептов, "смотрите, при помощи OpenCV можно сделать такие-то прикалюхи". 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
VVVVV 2 Жалоба Опубликовано January 19, 2014 А в каких попугаях возвращяется вектор переноса? Получаю что-то вроде x: 0.14 y: -0,91 z: -30, из которых доверие вызывает только z, а по остальным двум осям положение объекта не соответствует маркеру. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано January 20, 2014 Вероятно в координатах OpenGL-евской проекции, определяемой матрицей проекции. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
VVVVV 2 Жалоба Опубликовано January 28, 2014 Это я почему спрашиваю: объект "гуляет" по маркеру. Отсюда я делаю вывод, что его система координат установлена неправильно. И чего-то совсем я не понимаю, что пошло не так. Интернет имеет мне заявить, будто все нормально, но это не так. Иллюстрация. Код. void CameraCalibration::getOpenGlProjectionMatrix(float farPlane, float nearPlane, float width, float height, float *matrix[16]) { (*matrix)[0] = -2.0 * cameraMatrix.at<double>(0, 0) / width; // fx (*matrix)[1] = 0; (*matrix)[2] = 2.0 * cameraMatrix.at<double>(0, 2) / (width - 1); // cx (*matrix)[3] = 0; (*matrix)[4] = 0; (*matrix)[5] = 2.0 * cameraMatrix.at<double>(1, 1) / height; // fy (*matrix)[6] = 2.0 * cameraMatrix.at<double>(1, 2) / (height - 1); // cy (*matrix)[7] = 0; (*matrix)[8] = 0; (*matrix)[9] = 0; (*matrix)[10] = -(farPlane + nearPlane) / (farPlane - nearPlane); // fn (*matrix)[11] = -2.0 * farPlane * nearPlane / (farPlane - nearPlane); // fcn (*matrix)[12] = 0; (*matrix)[13] = 0; (*matrix)[14] = -1; (*matrix)[15] = 0; } void PoseEstimator::convertToOpenGlMatrix(cv::Mat& rvec, cv::Mat& tvec, float * openglMatrix[16]) { cv::Mat rotMat(3, 3, CV_64FC1); cv::Rodrigues(rvec, rotMat); rotMat = rotMat.t(); (*openglMatrix)[0] = rotMat.at<double>(0, 0); (*openglMatrix)[1] = rotMat.at<double>(0, 1); (*openglMatrix)[2] = rotMat.at<double>(0, 2); (*openglMatrix)[3] = 0; (*openglMatrix)[4] = rotMat.at<double>(1, 0); (*openglMatrix)[5] = rotMat.at<double>(1, 1); (*openglMatrix)[6] = rotMat.at<double>(1, 2); (*openglMatrix)[7] = 0; (*openglMatrix)[8] = rotMat.at<double>(2, 0); (*openglMatrix)[9] = rotMat.at<double>(2, 1); (*openglMatrix)[10] = rotMat.at<double>(2, 2); (*openglMatrix)[11] = 0; //tvec = -rotMat.t() * tvec; double x = -tvec.at<double>(0); double y = -tvec.at<double>(1); double z = -tvec.at<double>(2); (*openglMatrix)[12] = x; (*openglMatrix)[13] = y; (*openglMatrix)[14] = z; (*openglMatrix)[15] = 1; printf("x: %f y: %f z: %f\n", x, y, z); } Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
VVVVV 2 Жалоба Опубликовано January 29, 2014 Голова моя слепая, матрица проекции задана неправильно! Первая же ссылка в гугле: http://www.songho.ca/opengl/gl_projectionmatrix.html Вот этот код работает: void CameraCalibration::getOpenGlProjectionMatrix(float farPlane, float nearPlane, float width, float height, float *matrix[16]) { (*matrix)[0] = 2.0 * cameraMatrix.at<double>(0, 0) / width; (*matrix)[1] = 0; (*matrix)[2] = 0; (*matrix)[3] = 0; (*matrix)[4] = 0; (*matrix)[5] = 2.0 * cameraMatrix.at<double>(1, 1) / height; (*matrix)[6] = 0; (*matrix)[7] = 0; (*matrix)[8] = 2.0 * (cameraMatrix.at<double>(0, 2) / width) - 1; (*matrix)[9] = 2.0 * (cameraMatrix.at<double>(1, 2) / height) - 1; (*matrix)[10] = -(farPlane + nearPlane) / (farPlane - nearPlane); (*matrix)[11] = -1; (*matrix)[12] = 0; (*matrix)[13] = 0; (*matrix)[14] = -2.0 * farPlane * nearPlane / (farPlane - nearPlane);; (*matrix)[15] = 0; } Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
VVVVV 2 Жалоба Опубликовано January 29, 2014 Однако, при попытке расположить маркер точно напротив камеры, объект проецируется неправильно. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
VVVVV 2 Жалоба Опубликовано April 16, 2014 Другая вещь, которую я не могу понять, это почему не удается создать иллюзию присутствия объекта на маркере. Если выводить линии через cvProjectPoints, все нормально, нарисованное как бы "прилипает" к центру маркера, что ожидаемо и понятно. А вот с выводом модельки такого не получается, несмотря на то, что углы и трансляция вычисляется верно. Я подозреваю, что дело в fov, но ведь я использую матрицу проекции камеры! Сейчас я пытаюсь подобрать нужный fov и понять, что не так. Что же я пропустил? На поясняющей картнике видно, что моделька трансформируется верно, но к маркеру не прилипает и иллюзия разрушается. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано April 16, 2014 А может просто камера фокус подстраивает, вот fov и плавает. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано April 17, 2014 что значит не прилипает? стул вроде как стоит на плоскости. кстати вы это делаете на чистом opencv? вроде был еще ARToolKit. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
VVVVV 2 Жалоба Опубликовано April 17, 2014 Камера без автофокуса. что значит не прилипает? стул вроде как стоит на плоскости. Попробую пояснить. Что я ожидаю: крусло жестко привязано к центру маркера и остается в центре его при любых поворотах. Что я получаю: На картинке "А" видно кресло на маркере, оно не в центре, ну да ладно, может координаты модельки такие. Теперь, когда я повернул маркер (рисунок "Б"), кресло повернется на тот же угол, но как бы "сдвинется" с маркера. кстати вы это делаете на чистом opencv? вроде был еще ARToolKit. Есть обязательно, но я не преследую какой-либо практической цели, просто интересное развлечение. Напишу сюда решение, если пойму как создать эту иллюзию. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
VVVVV 2 Жалоба Опубликовано April 17, 2014 А все оказалось очень просто: 1. Центр объектов был в (0; 0; 0). 2. Координаты модели (первый параметр solvePnP) надо было задавать так, чтобы центр модели был в (0; 0; 0) Что происходило: Маркер как бы разделял объект пополам, но его изображение это просто видео в ортогональной проекции, так что "невидимая" часть объекта оставалась видимой. Отсюда и эффект "гуляния". 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах