Определить позу камеры?

Я пытаюсь определить позу камеры на основе реперного маркера, найденного в сцене.

Фидуциал: http://tinypic.com/view.php?pic=4r6k3q&s=8#.VNLnWTVVK1E

Текущий процесс:

  1. Используйте SIFT для обнаружения функций
  2. Используйте SIFT для извлечения дескриптора
  3. Используйте FLANN для сопоставления
  4. Найдите гомографию с помощью CV_RANSAC
  5. Определите углы реперного знака
  6. Определите углы реперного знака в сцене с помощью перспективыTransform ()
  7. Нарисуйте линии по углам (т. Е. Докажите, что он нашел репер в сцене.
  8. Запустить калибровку камеры
  9. Результаты калибровки нагрузки (матрица камеры и коэффициенты искажения)

Сейчас пытаюсь понять позу камеры. Я пытался использовать:

void resolvePnP (const Mat & objectPoints, const Mat & imagePoints, const Mat & cameraMatrix, const Mat & distCoeffs, Mat & rvec, Mat & tvec, bool useExtrinsicGuess = false)

куда:

  • obectPoints - реперные углы
  • imagePoints - это опорные углы сцены.
  • cameraMatrix - это калибровка
  • distCoeffs от калибровки
  • rvec и tvec должны быть возвращены мне из этой функции

Однако, когда я запускаю это, я получаю ошибку дампа ядра, поэтому я не уверен, что делаю неправильно.

Я не нашел очень хорошей документации по resolvePNP () - я неправильно понял функцию или входные параметры?

Ценю вашу помощь

Обновление Вот мой процесс:

OrbFeatureDetector detector; //Orb seems more accurate than SIFT
vector<KeyPoint> keypoints1, keypoints2; 

detector.detect(marker_im, keypoints1);
detector.detect(scene_im, keypoints2);

Mat display_marker_im, display_scene_im;
drawKeypoints(marker_im, keypoints1, display_marker_im, Scalar(0,0,255));
drawKeypoints(scene_im, keypoints2, display_scene_im, Scalar(0,0,255));

SiftDescriptorExtractor extractor;
Mat descriptors1, descriptors2;

extractor.compute( marker_im, keypoints1, descriptors1 );
extractor.compute( scene_im, keypoints2, descriptors2 );

BFMatcher matcher; //BF seems to match better than FLANN
vector< DMatch > matches;
matcher.match( descriptors1, descriptors2, matches );

Mat img_matches;
drawMatches( marker_im, keypoints1, scene_im, keypoints2,
    matches, img_matches, Scalar::all(-1), Scalar::all(-1),
    vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );

vector<Point2f> obj, scene;
for (int i = 0; i < matches.size(); i++) {
    obj.push_back(keypoints1[matches[i].queryIdx].pt);
    scene.push_back(keypoints2[matches[i].trainIdx].pt);
}

Mat H;
H = findHomography(obj, scene, CV_RANSAC);

//Get corners of fiducial
vector<Point2f> obj_corners(4);
obj_corners[0] = cvPoint(0,0);
obj_corners[1] = cvPoint(marker_im.cols, 0);
obj_corners[2] = cvPoint(marker_im.cols, marker_im.rows);
obj_corners[3] = cvPoint(0, marker_im.rows);
vector<Point2f> scene_corners(4);

perspectiveTransform(obj_corners, scene_corners, H);

FileStorage fs2("cal.xml", FileStorage::READ);

Mat cameraMatrix, distCoeffs;
fs2["Camera_Matrix"] >> cameraMatrix;
fs2["Distortion_Coefficients"] >> distCoeffs;

Mat rvec, tvec;

//same points as object_corners, just adding z-axis (0)
vector<Point3f> objp(4);
objp[0] = cvPoint3D32f(0,0,0);
objp[1] = cvPoint3D32f(gray.cols, 0, 0);
objp[2] = cvPoint3D32f(gray.cols, gray.rows, 0);
objp[3] = cvPoint3D32f(0, gray.rows, 0);

solvePnPRansac(objp, scene_corners, cameraMatrix, distCoeffs, rvec, tvec );

Mat rotation, viewMatrix(4, 4, CV_64F);
Rodrigues(rvec, rotation);

for(int row=0; row<3; ++row)
{
   for(int col=0; col<3; ++col)
   {
      viewMatrix.at<double>(row, col) = rotation.at<double>(row, col);
   }
   viewMatrix.at<double>(row, 3) = tvec.at<double>(row, 0);
}

viewMatrix.at<double>(3, 3) = 1.0f;

cout << "rotation: " << rotation << endl;
cout << "viewMatrix: " << viewMatrix << endl;

person P3d0r    schedule 05.02.2015    source источник


Ответы (1)


Итак, solvePnP() дает вам матрицу перехода от кадра модели (т.е. куба) к кадру камеры (это называется матрицей вида).

Входные параметры:

  • objectPoints - Массив точек объекта в пространстве координат объекта, 3xN / Nx3 1-канальный или 1xN / Nx1 3-канальный, где N - количество точек. std::vector<cv::Point3f> также можно передать здесь. Точки трехмерны, но поскольку они находятся в системе координат образца (реперного маркера), то установка является плоской, так что Z-координата каждой точки входного объекта равна 0,
  • imagePoints - Массив соответствующих точек изображения, 2xN / Nx2 1-канальный или 1xN / Nx1 2-канальный, где N - количество точек. std::vector<cv::Point2f> также можно передать здесь,
  • intrinsics: матрица камеры (фокусное расстояние, главная точка),
  • distortion: коэффициенты искажения, нулевые коэффициенты искажения принимаются, если он пустой,
  • rvec: выходной вектор вращения
  • tvec: выходной вектор трансляции

Построение матрицы просмотра происходит примерно так:

cv::Mat rvec, tvec;
cv::solvePnP(objectPoints, imagePoints, intrinsics, distortion, rvec, tvec);
cv::Mat rotation, viewMatrix(4, 4, CV_64F);
cv::Rodrigues(rvec, rotation);

for(int row=0; row<3; ++row)
{
   for(int col=0; col<3; ++col)
   {
      viewMatrix.at<double>(row, col) = rotation.at<double>(row, col);
   }

   viewMatrix.at<double>(row, 3) = tvec.at<double>(row, 0);
}

viewMatrix.at<double>(3, 3) = 1.0f;

Кроме того, можете ли вы поделиться своим кодом и сообщением об ошибке?

person Kornel    schedule 05.02.2015
comment
Это находит внешние параметры калибровочной доски. Я пытался найти позу камеры на основе реперного маркера. Или я вас неправильно понимаю? - person P3d0r; 05.02.2015
comment
Корнель - так что, если я хочу найти положение (xyz) камеры относительно реперной точки, я бы взял реперную точку xyz, повернул на основе матрицы вращения, а затем перевел? - person P3d0r; 06.02.2015
comment
Извините за опоздание с ответом. Поэтому для оценки позы у вас должен быть калибровочный образец с известной трехмерной геометрией и положением на плоскости изображения (например, ваш реперный образец). cv::solvePnP() найдет желаемую позу объекта из соответствий точек 3D-2D, поэтому выходные данные этой функции (rvecs и tvecs) переносят точки из системы координат модели в систему координат камеры. Если вы хотите найти положение камеры относительно реперного образца, вам следует инвертировать преобразование. - person Kornel; 09.02.2015
comment
и еще кое-что, в вашем случае это положение исправления рисунка и плавает ли камера вокруг него? - person Kornel; 09.02.2015
comment
Плавающая камера вокруг фиксированного шаблона - person P3d0r; 09.02.2015
comment
Итак, Родригес (Rotation.t (), rvecCam) и tvecCam = -rotation.t () * tvec получили мне положение камеры и поворот относительно реперной точки? Если это так, возвращаемые значения не выдерживают критики. Я дважды проверил свою калибровку - person P3d0r; 09.02.2015