У меня проблема в моем приложении iOS, где я пытаюсь получить матрицу вида с помощью solvePnP и визуализировать 3D-куб с использованием современного OpenGL. В то время как мой код пытается визуализировать 3D-кубу непосредственно на верхней части обнаруженных маркеров, он, кажется, делает с определенным смещением от маркеров (см видео, например)OpenCV + OpenGL Использование posPnP-камеры - объект смещен от обнаруженного маркера
https://www.youtube.com/watch?v=HhP5Qr3YyGI&feature=youtu.be
(на правом нижнем угле изображение вы можете увидеть opencv-рендеринг гомографии вокруг маркера трекера. Остальная часть экрана представляет собой рендеринг рамки входного кадра камеры и 3d-куба в месте (0,0,0).
Куб вращается и правильно переводит всякий раз, когда я перемещаю маркер, хотя он очень говорит о том, что есть разница в масштабах переводов (IE, если я перемещаю свой маркер 5 см в реальном мире, он вряд ли движется на 1 см на экран)
это то, что я считаю, чтобы быть соответствующими частями коды, где ошибка может исходить от:
Извлечения матрицы вида из омографии:
AVCaptureDevice *deviceInput = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceFormat *format = deviceInput.activeFormat;
CMFormatDescriptionRef fDesc = format.formatDescription;
CGSize dim = CMVideoFormatDescriptionGetPresentationDimensions(fDesc, true, true);
const float cx = float(dim.width)/2.0;
const float cy = float(dim.height)/2.0;
const float HFOV = format.videoFieldOfView;
const float VFOV = ((HFOV)/cx)*cy;
const float fx = abs(float(dim.width)/(2 * tan(HFOV/180 * float(M_PI)/2)));
const float fy = abs(float(dim.height)/(2 * tan(VFOV/180 * float(M_PI)/2)));
Mat camIntrinsic = Mat::zeros(3, 3, CV_64F);
camIntrinsic.at<double>(0, 0) = fx;
camIntrinsic.at<double>(0, 2) = cx;
camIntrinsic.at<double>(1, 1) = fy;
camIntrinsic.at<double>(1, 2) = cy;
camIntrinsic.at<double>(2, 2) = 1.0;
std::vector<cv::Point3f> object3dPoints;
object3dPoints.push_back(cv::Point3f(-0.5f,-0.5f,0));
object3dPoints.push_back(cv::Point3f(+0.5f,-0.5f,0));
object3dPoints.push_back(cv::Point3f(+0.5f,+0.5f,0));
object3dPoints.push_back(cv::Point3f(-0.5f,+0.5f,0));
cv::Mat raux,taux;
cv::Mat Rvec, Tvec;
cv::solvePnP(object3dPoints, mNewImageBounds, camIntrinsic, Mat(),raux,taux); //mNewImageBounds are the 4 corner of the homography detected by perspectiveTransform (the green outline seen in the image)
raux.convertTo(Rvec,CV_32F);
taux.convertTo(Tvec ,CV_64F);
Mat Rot(3,3,CV_32FC1);
Rodrigues(Rvec, Rot);
// [R | t] matrix
Mat_<double> para = Mat_<double>::eye(4,4);
Rot.convertTo(para(cv::Rect(0,0,3,3)),CV_64F);
Tvec.copyTo(para(cv::Rect(3,0,1,3)));
Mat cvToGl = Mat::zeros(4, 4, CV_64F);
cvToGl.at<double>(0, 0) = 1.0f;
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;
para = cvToGl * para;
Mat_<double> modelview_matrix;
Mat(para.t()).copyTo(modelview_matrix); // transpose to col-major for OpenGL
glm::mat4 openGLViewMatrix;
for(int col = 0; col < modelview_matrix.cols; col++)
{
for(int row = 0; row < modelview_matrix.rows; row++)
{
openGLViewMatrix[col][row] = modelview_matrix.at<double>(col,row);
}
}
я сделал, что камера внутренней матрица содержит правильные значения, часть, которая преобразует opencv Mat в матрицу представления opengl, которую я считаю правильным, поскольку куб переводит и вращается в правильном направлении.
раз матрица вид вычисляется, я использую его, чтобы сделать куб следующим образом:
_projectionMatrix = glm::perspective<float>(radians(60.0f), fabs(view.bounds.size.width/view.bounds.size.height), 0.1f, 100.0f);
_cube_ModelMatrix = glm::translate(glm::vec3(0,0,0));
const mat4 MVP = _projectionMatrix * openGLViewMatrix * _cube_ModelMatrix;
glUniformMatrix4fv(glGetUniformLocation(_cube_program, "ModelMatrix"), 1, GL_FALSE, value_ptr(MVP));
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, BUFFER_OFFSET(0));
ли кто-нибудь может обнаружить свою ошибку?