Да се ​​определи позата на камерата?

Опитвам се да определя позата на камерата въз основа на референтен маркер, намерен в сцена.

Fiducial: http://tinypic.com/view.php?pic=4r6k3q&s=8#.VNLnWTVVK1E

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

  1. Използвайте SIFT за откриване на функции
  2. Използвайте SIFT за извличане на дескриптори
  3. Използвайте FLANN за съвпадение
  4. Намерете хомографията с помощта на CV_RANSAC
  5. Идентифицирайте ъглите на фидуциала
  6. Идентифицирайте ъглите на фидуциала в сцената с помощта на perspectiveTransform()
  7. Начертайте линии около ъглите (т.е. докажете, че е намерил опорното в сцената
  8. Стартирайте калибриране на камерата
  9. Заредете резултатите от калибрирането (cameraMatrix и коефициенти на изкривяване)

Сега се опитвам да разбера позата на камерата. Опитах се да използвам:

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

където:

  • obecPoints са опорните ъгли
  • imagePoints са опорните ъгли в сцената
  • cameraMatrix е от калибриране
  • distCoeffs е от калибриране
  • rvec и tvec трябва да ми бъдат върнати от тази функция

Въпреки това, когато стартирам това, получавам грешка в изхвърлянето на ядрото, така че не съм сигурен какво правя неправилно.

Не намерих много добра документация за solvePNP() - не съм ли разбрал погрешно функцията или входните параметри?

Оценявам помощта ти

Актуализация Ето моя процес:

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> също може да бъде предадено тук. Точките са 3D, но тъй като са в координатна система на шаблон (на опорния маркер), тогава платформата е равнинна, така че 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
Извинете, че се забавих с отговора. Така че за оценка на поза трябва да имате шаблон за калибриране с известна 3D геометрия и позиция в равнината на изображението (напр. вашият опорен модел). cv::solvePnP() ще намери желаната поза на обекта от съответствията на 3D-2D точки, така че изходът на тази функция (rvecs и tvecs) пренася точки от координатната система на модела към координатната система на камерата. Ако искате да намерите относителната позиция на камерата спрямо опорния модел, трябва да обърнете трансформацията. - person Kornel; 09.02.2015
comment
и още нещо, във вашия случай е позицията на фиксирането на модела и камерата плава ли около него? - person Kornel; 09.02.2015
comment
Плаваща камера около фиксиран модел - person P3d0r; 09.02.2015
comment
И така, Rodrigues(rotation.t(), rvecCam) и tvecCam = -rotation.t()*tvec ми дават позицията и въртенето на камерата спрямо фидуциала? Ако е така, стойностите, които се връщат, не държат вода. Проверих два пъти калибрирането си - person P3d0r; 09.02.2015