cv::solvePnPRansac возвращает тождественную матрицу
Я хочу найти позу объекта с учетом соответствия 3D-2D, используя cv::solvePnPRansac. Мои соответствия могут иметь выбросы, поэтому я не хочу использовать cv::solvePnP. Я использовал 3D-2D соответствия снимка, сделанного с камеры в OpenGL. Таким образом, после обратного проецирования я обнаружил, что матрица вращения, возвращенная после использования solvePnP, верна. Но когда я использую solvePnPRansac, я получаю единичную матрицу и нулевой вектор перевода. Пожалуйста помоги! Я использовал следующий код. Заранее спасибо!
// Parameters to solvePnP
Mat camera_mat(3, 3, CV_64FC1);
Mat distCoeffs(4, 1, CV_64FC1);
Mat rvec(3, 1, CV_64FC1);
Mat tvec(3, 1, CV_64FC1);
Mat d(3, 3, CV_64FC1);
vector<Point3f> list_points3d_model_match;
vector<Point2f> list_points2d_scene_match;
while(map >> u >> v >> x >> y >> z)
{
Point2f ip = Point2f(u, v);
Point3f sp = Point3f(x, y, z);
// cout << x << " " << y << " " << z << endl;
list_points3d_model_match.push_back(sp);
list_points2d_scene_match.push_back(ip);
}
camera_mat.at<double>(0, 0) = 600;
camera_mat.at<double>(1, 1) = 600;
camera_mat.at<double>(0, 2) = WIDTH / 2;
camera_mat.at<double>(1, 0) = HEIGHT / 2;
camera_mat.at<double>(3, 3) = 1;
// solvePnP( list_points3d_model_match, list_points2d_scene_match, camera_mat, distCoeffs, rvec, tvec,
// useExtrinsicGuess, CV_ITERATIVE);
tvec.at<float>(0) = 0;
tvec.at<float>(1) = 0;
tvec.at<float>(2) = 2;
d.at<float>(0, 0) = 1;
d.at<float>(1, 2) = -1;
d.at<float>(2, 1) = 1;
Rodrigues(d, rvec);
solvePnPRansac(list_points3d_model_match, list_points2d_scene_match, camera_mat, distCoeffs, rvec, tvec, false, CV_ITERATIVE);
Rodrigues(rvec, d);
double* _r = d.ptr<double>();
printf("rotation mat: \n %.3f %.3f %.3f\n%.3f %.3f %.3f\n%.3f %.3f %.3f\n",
_r[0],_r[1],_r[2],_r[3],_r[4],_r[5],_r[6],_r[7],_r[8]);
}
cout << "translation vec:\n" << tvec << endl;
Я получаю следующий вывод после запуска кода.
rotation mat:
1.000 0.000 0.000
0.000 1.000 0.000
0.000 0.000 1.000
translation vec:
[0; 0; 0]
2 ответа
Ваша матрица камеры неверна. Ваш код должен читать:
camera_mat.at<double>(0, 0) = 600;
camera_mat.at<double>(1, 1) = 600;
camera_mat.at<double>(0, 2) = WIDTH / 2;
camera_mat.at<double>(1, 2) = HEIGHT / 2;
camera_mat.at<double>(3, 3) = 1;
У меня раньше была такая же проблема, и дело не в неправильном наборе матрицы камеры.
Изменить объявление
Mat camera_mat(3, 3, CV_64FC1);
Mat distCoeffs(4, 1, CV_64FC1);
в CV_32FC1
и не давать начальный размер Mat tvec
а также Mat d
,