Double precision for solvePnPRansac()
authorPhilLab <PhilLab@users.noreply.github.com>
Tue, 8 Jul 2014 09:52:42 +0000 (11:52 +0200)
committerPhilLab <PhilLab@users.noreply.github.com>
Tue, 8 Jul 2014 09:52:42 +0000 (11:52 +0200)
solvePnPRansac() and pnpTask() now accept object or image points with double precision.

modules/calib3d/src/solvepnp.cpp

index b0ef1d9..2b45524 100644 (file)
@@ -137,11 +137,13 @@ namespace cv
             CameraParameters camera;
         };
 
+        template <typename OpointType, typename IpointType>
         static void pnpTask(const vector<char>& pointsMask, const Mat& objectPoints, const Mat& imagePoints,
                      const Parameters& params, vector<int>& inliers, Mat& rvec, Mat& tvec,
                      const Mat& rvecInit, const Mat& tvecInit, Mutex& resultsMutex)
         {
-            Mat modelObjectPoints(1, MIN_POINTS_COUNT, CV_32FC3), modelImagePoints(1, MIN_POINTS_COUNT, CV_32FC2);
+            Mat modelObjectPoints(1, MIN_POINTS_COUNT, CV_MAKETYPE(DataDepth<OpointType>::value, 3));
+            Mat modelImagePoints(1, MIN_POINTS_COUNT, CV_MAKETYPE(DataDepth<IpointType>::value, 2));
             for (int i = 0, colIndex = 0; i < (int)pointsMask.size(); i++)
             {
                 if (pointsMask[i])
@@ -160,7 +162,7 @@ namespace cv
             for (int i = 0; i < MIN_POINTS_COUNT; i++)
                 for (int j = i + 1; j < MIN_POINTS_COUNT; j++)
                 {
-                    if (norm(modelObjectPoints.at<Vec3f>(0, i) - modelObjectPoints.at<Vec3f>(0, j)) < eps)
+                    if (norm(modelObjectPoints.at<Vec<OpointType,3>>(0, i) - modelObjectPoints.at<Vec<OpointType,3>>(0, j)) < eps)
                         num_same_points++;
                 }
             if (num_same_points > 0)
@@ -174,7 +176,7 @@ namespace cv
                      params.useExtrinsicGuess, params.flags);
 
 
-            vector<Point2f> projected_points;
+            vector<Point_<OpointType>> projected_points;
             projected_points.resize(objectPoints.cols);
             projectPoints(objectPoints, localRvec, localTvec, params.camera.intrinsics, params.camera.distortion, projected_points);
 
@@ -184,9 +186,10 @@ namespace cv
             vector<int> localInliers;
             for (int i = 0; i < objectPoints.cols; i++)
             {
-                Point2f p(imagePoints.at<Vec2f>(0, i)[0], imagePoints.at<Vec2f>(0, i)[1]);
+                //Although p is a 2D point it needs the same type as the object points to enable the norm calculation
+                Point_<OpointType> p(imagePoints.at<Vec<IpointType,2>>(0, i)[0], imagePoints.at<Vec<IpointType,2>>(0, i)[1]);
                 if ((norm(p - projected_points[i]) < params.reprojectionError)
-                    && (rotatedPoints.at<Vec3f>(0, i)[2] > 0)) //hack
+                    && (rotatedPoints.at<Vec<OpointType,3>>(0, i)[2] > 0)) //hack
                 {
                     localInliers.push_back(i);
                 }
@@ -206,6 +209,30 @@ namespace cv
             }
         }
 
+        static void pnpTask(const vector<char>& pointsMask, const Mat& objectPoints, const Mat& imagePoints,
+            const Parameters& params, vector<int>& inliers, Mat& rvec, Mat& tvec,
+            const Mat& rvecInit, const Mat& tvecInit, Mutex& resultsMutex)
+               {
+                       CV_Assert(objectPoints.depth() == CV_64F ||  objectPoints.depth() == CV_32F);
+                       CV_Assert(imagePoints.depth() == CV_64F ||  imagePoints.depth() == CV_32F);
+            const bool objectDoublePrecision = objectPoints.depth() == CV_64F;
+            const bool imageDoublePrecision = imagePoints.depth() == CV_64F;
+            if(objectDoublePrecision)
+            {
+                if(imageDoublePrecision)
+                    pnpTask<double, double>(pointsMask, objectPoints, imagePoints, params, inliers, rvec, tvec, rvecInit, tvecInit, resultsMutex);
+                else
+                    pnpTask<double, float>(pointsMask, objectPoints, imagePoints, params, inliers, rvec, tvec, rvecInit, tvecInit, resultsMutex);
+            }
+            else
+            {
+                if(imageDoublePrecision)
+                    pnpTask<float, double>(pointsMask, objectPoints, imagePoints, params, inliers, rvec, tvec, rvecInit, tvecInit, resultsMutex);
+                else
+                    pnpTask<float, float>(pointsMask, objectPoints, imagePoints, params, inliers, rvec, tvec, rvecInit, tvecInit, resultsMutex);
+            }
+        }
+
         class PnPSolver
         {
         public:
@@ -281,10 +308,10 @@ void cv::solvePnPRansac(InputArray _opoints, InputArray _ipoints,
     Mat cameraMatrix = _cameraMatrix.getMat(), distCoeffs = _distCoeffs.getMat();
 
     CV_Assert(opoints.isContinuous());
-    CV_Assert(opoints.depth() == CV_32F);
+    CV_Assert(opoints.depth() == CV_32F || opoints.depth() == CV_64F);
     CV_Assert((opoints.rows == 1 && opoints.channels() == 3) || opoints.cols*opoints.channels() == 3);
     CV_Assert(ipoints.isContinuous());
-    CV_Assert(ipoints.depth() == CV_32F);
+    CV_Assert(ipoints.depth() == CV_32F || ipoints.depth() == CV_64F);
     CV_Assert((ipoints.rows == 1 && ipoints.channels() == 2) || ipoints.cols*ipoints.channels() == 2);
 
     _rvec.create(3, 1, CV_64FC1);
@@ -320,7 +347,7 @@ void cv::solvePnPRansac(InputArray _opoints, InputArray _ipoints,
         if (flags != CV_P3P)
         {
             int i, pointsCount = (int)localInliers.size();
-            Mat inlierObjectPoints(1, pointsCount, CV_32FC3), inlierImagePoints(1, pointsCount, CV_32FC2);
+            Mat inlierObjectPoints(1, pointsCount, CV_MAKE_TYPE(opoints.depth(), 3)), inlierImagePoints(1, pointsCount, CV_MAKE_TYPE(ipoints.depth(), 2));
             for (i = 0; i < pointsCount; i++)
             {
                 int index = localInliers[i];