added centerPrincipalPoint=false to getOptimalNewCameraMatrix (ticket #1199)
authorVadim Pisarevsky <no@email>
Thu, 7 Jul 2011 21:38:21 +0000 (21:38 +0000)
committerVadim Pisarevsky <no@email>
Thu, 7 Jul 2011 21:38:21 +0000 (21:38 +0000)
modules/calib3d/doc/camera_calibration_and_3d_reconstruction.rst
modules/calib3d/include/opencv2/calib3d/calib3d.hpp
modules/calib3d/src/calibration.cpp
modules/python/src1/api

index d3d3332..b82a3b2 100644 (file)
@@ -780,11 +780,12 @@ getOptimalNewCameraMatrix
 -----------------------------
 Returns the new camera matrix based on the free scaling parameter.
 
-.. ocv:function:: Mat getOptimalNewCameraMatrix( InputArray cameraMatrix, InputArray distCoeffs, Size imageSize, double alpha, Size newImageSize=Size(), Rect* validPixROI=0)
+.. ocv:function:: Mat getOptimalNewCameraMatrix( InputArray cameraMatrix, InputArray distCoeffs, Size imageSize, double alpha, Size newImageSize=Size(), Rect* validPixROI=0, bool centerPrincipalPoint=false)
 
-.. ocv:pyfunction:: cv2.getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, alpha[, newImgSize]) -> retval, validPixROI
+.. ocv:pyfunction:: cv2.getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, alpha[, newImgSize[, centerPrincipalPoint]]) -> retval, validPixROI
+
+.. ocv:cfunction:: void cvGetOptimalNewCameraMatrix( const CvMat* cameraMatrix, const CvMat* distCoeffs, CvSize imageSize, double alpha, CvMat* newCameraMatrix, CvSize newImageSize=cvSize(0, 0), CvRect* validPixROI=0, int centerPrincipalPoint=0)
 
-.. ocv:cfunction:: void cvGetOptimalNewCameraMatrix( const CvMat* cameraMatrix, const CvMat* distCoeffs, CvSize imageSize, double alpha, CvMat* newCameraMatrix, CvSize newImageSize=cvSize(0, 0), CvRect* validPixROI=0 )
 .. ocv:pyoldfunction:: cv.GetOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, alpha, newCameraMatrix, newImageSize=(0, 0), validPixROI=0) -> None
 
     :param cameraMatrix: Input camera matrix.
@@ -800,6 +801,8 @@ Returns the new camera matrix based on the free scaling parameter.
     :param newImageSize: Image size after rectification. By default,it is set to  ``imageSize`` .
 
     :param validPixROI: Optional output rectangle that outlines all-good-pixels region in the undistorted image. See  ``roi1, roi2``  description in  :ocv:func:`StereoRectify` .
+
+    :param centerPrincipalPoint: Optional flag that indicates whether in the new camera matrix the principal point should be at the image center or not. By default, the principal point is chosen to best fit a subset of the source image (determined by ``alpha``) to the corrected image.
     
 The function computes and returns
 the optimal new camera matrix based on the free scaling parameter. By varying  this parameter, you may retrieve only sensible pixels ``alpha=0`` , keep all the original image pixels if there is valuable information in the corners ``alpha=1`` , or get something in between. When ``alpha>0`` , the undistortion result is likely to have some black pixels corresponding to "virtual" pixels outside of the captured distorted image. The original camera matrix, distortion coefficients, the computed new camera matrix, and ``newImageSize`` should be passed to
index 83361bd..2234bbc 100644 (file)
@@ -120,7 +120,8 @@ CVAPI(void) cvGetOptimalNewCameraMatrix( const CvMat* camera_matrix,
                                          CvSize image_size, double alpha,
                                          CvMat* new_camera_matrix,
                                          CvSize new_imag_size CV_DEFAULT(cvSize(0,0)),
-                                         CvRect* valid_pixel_ROI CV_DEFAULT(0) );
+                                         CvRect* valid_pixel_ROI CV_DEFAULT(0),
+                                         int center_principal_point CV_DEFAULT(0));
 
 /* Converts rotation vector to rotation matrix or vice versa */
 CVAPI(int) cvRodrigues2( const CvMat* src, CvMat* dst,
@@ -622,7 +623,7 @@ CV_EXPORTS_W float rectify3Collinear( InputArray cameraMatrix1, InputArray distC
 //! returns the optimal new camera matrix
 CV_EXPORTS_W Mat getOptimalNewCameraMatrix( InputArray cameraMatrix, InputArray distCoeffs,
                                             Size imageSize, double alpha, Size newImgSize=Size(),
-                                            CV_OUT Rect* validPixROI=0);
+                                            CV_OUT Rect* validPixROI=0, bool centerPrincipalPoint=false);
 
 //! converts point coordinates from normal pixel coordinates to homogeneous coordinates ((x,y)->(x,y,1))
 CV_EXPORTS_W void convertPointsToHomogeneous( InputArray src, OutputArray dst );
index a35aa7d..df5e464 100644 (file)
@@ -2529,46 +2529,81 @@ void cvStereoRectify( const CvMat* _cameraMatrix1, const CvMat* _cameraMatrix2,
 void cvGetOptimalNewCameraMatrix( const CvMat* cameraMatrix, const CvMat* distCoeffs,
                                   CvSize imgSize, double alpha,
                                   CvMat* newCameraMatrix, CvSize newImgSize,
-                                  CvRect* validPixROI )
+                                  CvRect* validPixROI, int centerPrincipalPoint )
 {
     cv::Rect_<float> inner, outer;
-    icvGetRectangles( cameraMatrix, distCoeffs, 0, cameraMatrix, imgSize, inner, outer );
-
     newImgSize = newImgSize.width*newImgSize.height != 0 ? newImgSize : imgSize;
 
     double M[3][3];
     CvMat matM = cvMat(3, 3, CV_64F, M);
     cvConvert(cameraMatrix, &matM);
 
-    double cx0 = M[0][2];
-    double cy0 = M[1][2];
-    double cx = (newImgSize.width-1)*0.5;
-    double cy = (newImgSize.height-1)*0.5;
-
-    double s0 = std::max(std::max(std::max((double)cx/(cx0 - inner.x), (double)cy/(cy0 - inner.y)),
-                        (double)cx/(inner.x + inner.width - cx0)),
-                    (double)cy/(inner.y + inner.height - cy0));
-    double s1 = std::min(std::min(std::min((double)cx/(cx0 - outer.x), (double)cy/(cy0 - outer.y)),
-                        (double)cx/(outer.x + outer.width - cx0)),
-                    (double)cy/(outer.y + outer.height - cy0));
-    double s = s0*(1 - alpha) + s1*alpha;
-
-    M[0][0] *= s;
-    M[1][1] *= s;
-    M[0][2] = cx;
-    M[1][2] = cy;
-    cvConvert(&matM, newCameraMatrix);
+    if( centerPrincipalPoint )
+    {
+        double cx0 = M[0][2];
+        double cy0 = M[1][2];
+        double cx = (newImgSize.width-1)*0.5;
+        double cy = (newImgSize.height-1)*0.5;
+
+        icvGetRectangles( cameraMatrix, distCoeffs, 0, cameraMatrix, imgSize, inner, outer );
+        double s0 = std::max(std::max(std::max((double)cx/(cx0 - inner.x), (double)cy/(cy0 - inner.y)),
+                                      (double)cx/(inner.x + inner.width - cx0)),
+                             (double)cy/(inner.y + inner.height - cy0));
+        double s1 = std::min(std::min(std::min((double)cx/(cx0 - outer.x), (double)cy/(cy0 - outer.y)),
+                                      (double)cx/(outer.x + outer.width - cx0)),
+                             (double)cy/(outer.y + outer.height - cy0));
+        double s = s0*(1 - alpha) + s1*alpha;
 
-    if( validPixROI )
+        M[0][0] *= s;
+        M[1][1] *= s;
+        M[0][2] = cx;
+        M[1][2] = cy;
+
+        if( validPixROI )
+        {
+            inner = cv::Rect_<float>((float)((inner.x - cx0)*s + cx),
+                                     (float)((inner.y - cy0)*s + cy),
+                                     (float)(inner.width*s),
+                                     (float)(inner.height*s));
+            cv::Rect r(cvCeil(inner.x), cvCeil(inner.y), cvFloor(inner.width), cvFloor(inner.height));
+            r &= cv::Rect(0, 0, newImgSize.width, newImgSize.height);
+            *validPixROI = r;
+        }
+    }
+    else
     {
-        inner = cv::Rect_<float>((float)((inner.x - cx0)*s + cx),
-                             (float)((inner.y - cy0)*s + cy),
-                             (float)(inner.width*s),
-                             (float)(inner.height*s));
-        cv::Rect r(cvCeil(inner.x), cvCeil(inner.y), cvFloor(inner.width), cvFloor(inner.height));
-        r &= cv::Rect(0, 0, newImgSize.width, newImgSize.height);
-        *validPixROI = r;
+        // Get inscribed and circumscribed rectangles in normalized
+        // (independent of camera matrix) coordinates
+        icvGetRectangles( cameraMatrix, distCoeffs, 0, 0, imgSize, inner, outer );
+
+        // Projection mapping inner rectangle to viewport
+        double fx0 = (newImgSize.width  - 1) / inner.width;
+        double fy0 = (newImgSize.height - 1) / inner.height;
+        double cx0 = -fx0 * inner.x;
+        double cy0 = -fy0 * inner.y;
+
+        // Projection mapping outer rectangle to viewport
+        double fx1 = (newImgSize.width  - 1) / outer.width;
+        double fy1 = (newImgSize.height - 1) / outer.height;
+        double cx1 = -fx1 * outer.x;
+        double cy1 = -fy1 * outer.y;
+
+        // Interpolate between the two optimal projections
+        M[0][0] = fx0*(1 - alpha) + fx1*alpha;
+        M[1][1] = fy0*(1 - alpha) + fy1*alpha;
+        M[0][2] = cx0*(1 - alpha) + cx1*alpha;
+        M[1][2] = cy0*(1 - alpha) + cy1*alpha;
+
+        if( validPixROI )
+        {
+            icvGetRectangles( cameraMatrix, distCoeffs, 0, newCameraMatrix, imgSize, inner, outer );
+            cv::Rect r = inner;
+            r &= cv::Rect(0, 0, newImgSize.width, newImgSize.height);
+            *validPixROI = r;
+        }
     }
+
+    cvConvert(&matM, newCameraMatrix);
 }
 
 
@@ -3520,7 +3555,7 @@ bool cv::stereoRectifyUncalibrated( InputArray _points1, InputArray _points2,
 cv::Mat cv::getOptimalNewCameraMatrix( InputArray _cameraMatrix,
                                        InputArray _distCoeffs,
                                        Size imgSize, double alpha, Size newImgSize,
-                                       Rect* validPixROI )
+                                       Rect* validPixROI, bool centerPrincipalPoint )
 {
     Mat cameraMatrix = _cameraMatrix.getMat(), distCoeffs = _distCoeffs.getMat();
     CvMat c_cameraMatrix = cameraMatrix, c_distCoeffs = distCoeffs;
@@ -3530,7 +3565,7 @@ cv::Mat cv::getOptimalNewCameraMatrix( InputArray _cameraMatrix,
     
     cvGetOptimalNewCameraMatrix(&c_cameraMatrix, &c_distCoeffs, imgSize,
                                 alpha, &c_newCameraMatrix,
-                                newImgSize, (CvRect*)validPixROI);
+                                newImgSize, (CvRect*)validPixROI, (int)centerPrincipalPoint);
     return newCameraMatrix;
 }
 
index 9936407..c760ec2 100644 (file)
@@ -1342,6 +1342,7 @@ GetOptimalNewCameraMatrix
   CvMat newCameraMatrix
   CvSize newImageSize cvSize(0,0)
   CvRect* validPixROI NULL
+  int centerPrincipalPoint 0
 InitIntrinsicParams2D
   CvMat objectPoints
   CvMat imagePoints