OpenCV获得旋转基准标记(Aruco)的距离

时间:2016-11-16 10:37:30

标签: opencv rotation distance marker aruco

(在iOS中)我需要确定到可以旋转的基准标记的距离。

我正在使用Aruco库,到目前为止我已经在iOS中实现了标记检测和姿势估计,但我真正需要的是从相机到该标记的距离。

我见过一些例子,你可以使用标记的实际尺寸,相机的焦距和标记屏幕上的尺寸来计算距离,但这并未考虑应用于标记的任何旋转

当我对姿势估计工作时,我“猜测”应该可以取消旋转标记的角点,然后使用这些点的边界框,以及实际尺寸和相机焦距。虽然我不完全确定这是正确的,或者如何实现它。

这是我第一次使用OpenCV,所以我现在只是在猜测。

非常感谢任何和所有帮助。

非常感谢

1 个答案:

答案 0 :(得分:0)

我在项目中使用下面的代码来检测相机和标记之间的Z距离。我不确定它是否完全正确,但它给出了可接受的结果。

Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
detectorParams->doCornerRefinement = true;

Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME(kMarkerDictionaryID));

Mat camMatrix, distCoeffs;

if (!readCameraParameters(kCameraParametersFile, camMatrix, distCoeffs)) {

    // ...

    return;
}

VideoCapture inputVideo;
inputVideo.open(kCameraID);

while (inputVideo.grab()) {

    Mat image;

    inputVideo.retrieve(image);

    vector< int > ids;
    vector< vector< Point2f > > corners;
    vector< Vec3d > rvecs, tvecs;

    aruco::detectMarkers(image, dictionary, corners, ids, detectorParams);

    if (ids.size() > 0) {

        aruco::estimatePoseSingleMarkers(corners, kMarkerLengthInMeters, camMatrix, distCoeffs, rvecs, tvecs);

        for (unsigned int i = 0; i < ids.size(); i++) {

            // if (ids[i] != kMarkerID)
            //     continue;

            // Calc camera pose
            Mat R;
            Rodrigues(rvecs[i], R);
            Mat cameraPose = -R.t() * (Mat)tvecs[i];

            double x = cameraPose.at<double>(0,0);
            double y = cameraPose.at<double>(0,1);
            double z = cameraPose.at<double>(0,2);

            // So z is the distance between camera and marker 

            // Or if you need rotation invariant offsets
            // x = tvecs[i][0];
            // y = tvecs[i][0];
            // z = tvecs[i][0];

            cout << "X: " << x << " Y: " << y << " Z: " << z << endl;

            aruco::drawAxis(image, camMatrix, distCoeffs, rvecs[i], tvecs[i], kMarkerLengthInMeters * 0.5f);
        }

        aruco::drawDetectedMarkers(image, corners, resultIds);
    }

   resize(image, image, Size(image.cols / 2, image.rows / 2));
   imshow("out", image);
   char key = (char)waitKey(kWaitTimeInmS);
   if (key == 27) break;
}