]> rtime.felk.cvut.cz Git - opencv.git/commitdiff
added cv::getOptimalNewCameraMatrix + extended variant of cv::stereoRectify
authorvp153 <vp153@73c94f0f-984f-4a5f-82bc-2d8db8d8ee08>
Thu, 10 Dec 2009 01:59:38 +0000 (01:59 +0000)
committervp153 <vp153@73c94f0f-984f-4a5f-82bc-2d8db8d8ee08>
Thu, 10 Dec 2009 01:59:38 +0000 (01:59 +0000)
git-svn-id: https://code.ros.org/svn/opencv/trunk@2403 73c94f0f-984f-4a5f-82bc-2d8db8d8ee08

opencv/include/opencv/cv.h
opencv/include/opencv/cv.hpp
opencv/include/opencv/cxcore.hpp
opencv/src/cv/cvcalibration.cpp
opencv/src/cxcore/cxpersistence.cpp
opencv/tests/cv/src/optflow.cpp

index 354e128e995f7b7fad1ebbcebe0765aa534b9653..4625b70f19a64fcee9dbef1673f8b6f7abc00aa3 100644 (file)
@@ -1307,6 +1307,17 @@ CVAPI(void) cvUndistortPoints( const CvMat* src, CvMat* dst,
                                const CvMat* dist_coeffs,
                                const CvMat* R CV_DEFAULT(0),
                                const CvMat* P CV_DEFAULT(0));
+    
+/* Computes the optimal new camera matrix according to the free scaling parameter alpha:
+   alpha=0 - only valid pixels will be retained in the undistorted image
+   alpha=1 - all the source image pixels will be retained in the undistorted image
+*/
+CVAPI(void) cvGetOptimalNewCameraMatrix( const CvMat* camera_matrix,
+                                         const CvMat* dist_coeffs,
+                                         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) );
 
 /* Converts rotation vector to rotation matrix or vice versa */
 CVAPI(int) cvRodrigues2( const CvMat* src, CvMat* dst,
@@ -1453,7 +1464,11 @@ CVAPI(void) cvStereoRectify( const CvMat* camera_matrix1, const CvMat* camera_ma
                              CvSize image_size, const CvMat* R, const CvMat* T,
                              CvMat* R1, CvMat* R2, CvMat* P1, CvMat* P2,
                              CvMat* Q CV_DEFAULT(0),
-                             int flags CV_DEFAULT(CV_CALIB_ZERO_DISPARITY) );
+                             int flags CV_DEFAULT(CV_CALIB_ZERO_DISPARITY),
+                             double alpha CV_DEFAULT(-1),
+                             CvSize new_image_size CV_DEFAULT(cvSize(0,0)),
+                             CvRect* valid_pix_ROI1 CV_DEFAULT(0),
+                             CvRect* valid_pix_ROI2 CV_DEFAULT(0));
 
 /* Computes rectification transformations for uncalibrated pair of images using a set
    of point correspondences */
index f251223bf146ca4284d132b6290d279202fd0808..96c67bf2543211fb34dc93490c35221687478a10 100644 (file)
@@ -379,6 +379,9 @@ CV_EXPORTS void undistort( const Mat& src, Mat& dst, const Mat& cameraMatrix,
 CV_EXPORTS void initUndistortRectifyMap( const Mat& cameraMatrix, const Mat& distCoeffs,
                            const Mat& R, const Mat& newCameraMatrix,
                            Size size, int m1type, Mat& map1, Mat& map2 );
+CV_EXPORTS Mat getOptimalNewCameraMatrix( const Mat& cameraMatrix, const Mat& distCoeffs,
+                                          Size imageSize, double alpha, Size newImgSize,
+                                          Rect* validPixROI=0);
 CV_EXPORTS Mat getDefaultNewCameraMatrix( const Mat& cameraMatrix, Size imgsize=Size(),
                                           bool centerPrincipalPoint=false );
 
@@ -840,6 +843,14 @@ CV_EXPORTS void stereoRectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,
                                Size imageSize, const Mat& R, const Mat& T,
                                Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,
                                int flags=CALIB_ZERO_DISPARITY );
+    
+CV_EXPORTS void stereoRectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,
+                              const Mat& cameraMatrix2, const Mat& distCoeffs2,
+                              Size imageSize, const Mat& R, const Mat& T,
+                              Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,
+                              double alpha, Size newImageSize=Size(),
+                              Rect* validPixROI1=0, Rect* validPixROI2=0,
+                              int flags=CALIB_ZERO_DISPARITY );
 
 CV_EXPORTS bool stereoRectifyUncalibrated( const Mat& points1,
                                            const Mat& points2,
index 419d185515b4b3d1dfe6147506738c441d26c999..00d521cc79049d952f98f69176e8fb3549048ad3 100644 (file)
@@ -2035,8 +2035,8 @@ public:
     };
 
     KDTree();
-    KDTree(const Mat& _points, bool copyPoints=true);
-    void build(const Mat& _points, bool copyPoints=true);
+    KDTree(const Mat& _points, bool copyAndReorderPoints=false);
+    void build(const Mat& _points, bool copyAndReorderPoints=false);
 
     int findNearest(const float* vec, int K, int Emax, int* neighborsIdx,
                     Mat* neighbors=0, float* dist=0) const;
index 7aa98097ecd60de7000ea8d659b7921d4173f50c..b5f713d72e35ff9a49e54fee6944dbd14c8f38d0 100644 (file)
@@ -2313,11 +2313,56 @@ double cvStereoCalibrate( const CvMat* _objectPoints, const CvMat* _imagePoints1
 }
 
 
+static void
+icvGetRectangles( const CvMat* cameraMatrix, const CvMat* distCoeffs,
+                 const CvMat* R, const CvMat* newCameraMatrix, CvSize imgSize,
+                 cv::Rect_<float>& inner, cv::Rect_<float>& outer )
+{
+    const int N = 9;
+    int x, y, k;
+    cv::Ptr<CvMat> _pts = cvCreateMat(1, N*N, CV_32FC2);
+    CvPoint2D32f* pts = (CvPoint2D32f*)(_pts->data.ptr);
+    
+    for( y = k = 0; y < N; y++ )
+        for( x = 0; x < N; x++ )
+            pts[k++] = cvPoint2D32f((float)x*imgSize.width/(N-1),
+                                    (float)y*imgSize.height/(N-1));
+    
+    cvUndistortPoints(_pts, _pts, cameraMatrix, distCoeffs, R, newCameraMatrix);
+    
+    float iX0=-FLT_MAX, iX1=FLT_MAX, iY0=-FLT_MAX, iY1=FLT_MAX;
+    float oX0=FLT_MAX, oX1=-FLT_MAX, oY0=FLT_MAX, oY1=-FLT_MAX;
+    // find the inscribed rectangle.
+    // the code will likely not work with extreme rotation matrices (R) (>45%)
+    for( y = k = 0; y < N; y++ )
+        for( x = 0; x < N; x++ )
+        {
+            CvPoint2D32f p = pts[k++];
+            oX0 = MIN(oX0, p.x);
+            oX1 = MAX(oX1, p.x);
+            oY0 = MIN(oY0, p.y);
+            oY1 = MAX(oY1, p.y);
+            
+            if( x == 0 )
+                iX0 = MAX(iX0, p.x);
+            if( x == N-1 )
+                iX1 = MIN(iX1, p.x); 
+            if( y == 0 )
+                iY0 = MAX(iY0, p.y);
+            if( y == N-1 )
+                iY1 = MIN(iY1, p.y);
+        }
+    inner = cv::Rect_<float>(iX0, iY0, iX1-iX0, iY1-iY0);
+    outer = cv::Rect_<float>(oX0, oY0, oX1-iX0, oY1-iY0);
+}  
+
+
 void cvStereoRectify( const CvMat* _cameraMatrix1, const CvMat* _cameraMatrix2,
                       const CvMat* _distCoeffs1, const CvMat* _distCoeffs2,
                       CvSize imageSize, const CvMat* _R, const CvMat* _T,
                       CvMat* _R1, CvMat* _R2, CvMat* _P1, CvMat* _P2,
-                      CvMat* _Q, int flags )
+                      CvMat* _Q, int flags, double alpha, CvSize newImgSize,
+                      CvRect* roi1, CvRect* roi2 )
 {
     double _om[3], _t[3], _uu[3]={0,0,0}, _r_r[3][3], _pp[3][4];
     double _ww[3], _wr[3][3], _z[3] = {0,0,0}, _ri[3][3];
@@ -2432,6 +2477,73 @@ void cvStereoRectify( const CvMat* _cameraMatrix1, const CvMat* _cameraMatrix2,
     _pp[1][2] = cc_new[1].y;
     _pp[idx][3] = _t[idx]*fc_new; // baseline * focal length
     cvConvert(&pp, _P2);
+    
+    if( alpha >= 0 )
+    {
+        alpha = MIN(alpha, 1.);
+        
+        cv::Rect_<float> inner1, inner2, outer1, outer2;
+        icvGetRectangles( _cameraMatrix1, _distCoeffs1, _R1, _P1, imageSize, inner1, outer1 );
+        icvGetRectangles( _cameraMatrix2, _distCoeffs2, _R2, _P2, imageSize, inner2, outer2 );
+        
+        newImgSize = newImgSize.width*newImgSize.height == 0 ? newImgSize : imageSize;
+        double cx1_0 = cc_new[0].x;
+        double cy1_0 = cc_new[0].y;
+        double cx2_0 = cc_new[1].x;
+        double cy2_0 = cc_new[1].y;
+        double cx1 = newImgSize.width*cx1_0/imageSize.width;
+        double cy1 = newImgSize.height*cy1_0/imageSize.height;
+        double cx2 = newImgSize.width*cx2_0/imageSize.width;
+        double cy2 = newImgSize.height*cy2_0/imageSize.height;
+        
+        double s0 = std::max(std::max(std::max((double)cx1/(cx1_0 - inner1.x), (double)cy1/(cy1_0 - inner1.y)),
+                            (double)(newImgSize.width - cx1)/(inner1.x + inner1.width - cx1_0)),
+                        (double)(newImgSize.height - cy1)/(inner1.y + inner1.height - cy1_0));
+        s0 = std::max(std::max(std::max(std::max((double)cx2/(cx2_0 - inner2.x), (double)cy2/(cy2_0 - inner2.y)),
+                         (double)(newImgSize.width - cx2)/(inner2.x + inner2.width - cx2_0)),
+                     (double)(newImgSize.height - cy2)/(inner2.y + inner2.height - cy2_0)),
+                 s0);
+        
+        double s1 = std::min(std::min(std::min((double)cx1/(cx1_0 - outer1.x), (double)cy1/(cy1_0 - outer1.y)),
+                            (double)(newImgSize.width - cx1)/(outer1.x + outer1.width - cx1_0)),
+                        (double)(newImgSize.height - cy1)/(outer1.y + outer1.height - cy1_0));
+        s1 = std::min(std::min(std::min(std::min((double)cx2/(cx2_0 - outer2.x), (double)cy2/(cy2_0 - outer2.y)),
+                         (double)(newImgSize.width - cx2)/(outer2.x + outer2.width - cx2_0)),
+                     (double)(newImgSize.height - cy2)/(outer2.y + outer2.height - cy2_0)),
+                 s1);
+        
+        double s = s0*(1 - alpha) + s1*alpha;
+        fc_new *= s;
+        cc_new[0] = cvPoint2D64f(cx1, cy1);
+        cc_new[1] = cvPoint2D64f(cx2, cy2);
+        
+        cvmSet(_P1, 0, 0, fc_new);
+        cvmSet(_P1, 1, 1, fc_new);
+        cvmSet(_P1, 0, 2, cx1);
+        cvmSet(_P1, 1, 2, cy1);
+        
+        cvmSet(_P2, 0, 0, fc_new);
+        cvmSet(_P2, 1, 1, fc_new);
+        cvmSet(_P2, 0, 2, cx2);
+        cvmSet(_P2, 1, 2, cy2);
+        cvmSet(_P2, idx, 3, s*cvmGet(_P2, idx, 3));
+        
+        if(roi1)
+        {
+            *roi1 = cv::Rect(cvCeil((inner1.x - cx1_0)*s + cx1),
+                         cvCeil((inner1.y - cy1_0)*s + cy1),
+                         cvFloor(inner1.width*s), cvFloor(inner1.height*s))
+                & cv::Rect(0, 0, newImgSize.width, newImgSize.height);
+        }
+        
+        if(roi2)
+        {
+            *roi2 = cv::Rect(cvCeil((inner2.x - cx2_0)*s + cx2),
+                         cvCeil((inner2.y - cy2_0)*s + cy2),
+                         cvFloor(inner2.width*s), cvFloor(inner2.height*s))
+                & cv::Rect(0, 0, newImgSize.width, newImgSize.height);
+        }
+    }
 
     if( _Q )
     {
@@ -2447,6 +2559,52 @@ void cvStereoRectify( const CvMat* _cameraMatrix1, const CvMat* _cameraMatrix2,
         cvConvert( &Q, _Q );
     }
 }
+                        
+
+void cvGetOptimalNewCameraMatrix( const CvMat* cameraMatrix, const CvMat* distCoeffs,
+                                  CvSize imgSize, double alpha,
+                                  CvMat* newCameraMatrix, CvSize newImgSize,
+                                  CvRect* validPixROI )
+{
+    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 _M = cvMat(3, 3, CV_64F, M);
+    cvConvert(cameraMatrix, &_M);
+    
+    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(&_M, newCameraMatrix);
+    
+    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;
+    }
+}
 
 
 CV_IMPL int
@@ -3078,6 +3236,28 @@ void cv::stereoRectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,
         imageSize, &_R, &_T, &_R1, &_R2, &_P1, &_P2, &_Q, flags );
 }
 
+void cv::stereoRectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,
+                        const Mat& cameraMatrix2, const Mat& distCoeffs2,
+                        Size imageSize, const Mat& R, const Mat& T,
+                        Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,
+                        double alpha, Size newImageSize,
+                        Rect* validPixROI1, Rect* validPixROI2,
+                        int flags )
+{
+    int rtype = CV_64F;
+    R1.create(3, 3, rtype);
+    R2.create(3, 3, rtype);
+    P1.create(3, 4, rtype);
+    P2.create(3, 4, rtype);
+    Q.create(4, 4, rtype);
+    CvMat _cameraMatrix1 = cameraMatrix1, _distCoeffs1 = distCoeffs1;
+    CvMat _cameraMatrix2 = cameraMatrix2, _distCoeffs2 = distCoeffs2;
+    CvMat _R = R, _T = T, _R1 = R1, _R2 = R2, _P1 = P1, _P2 = P2, _Q = Q;
+    cvStereoRectify( &_cameraMatrix1, &_cameraMatrix2, &_distCoeffs1, &_distCoeffs2,
+                    imageSize, &_R, &_T, &_R1, &_R2, &_P1, &_P2, &_Q, flags,
+                    alpha, newImageSize, (CvRect*)validPixROI1, (CvRect*)validPixROI2);
+}
+
 bool cv::stereoRectifyUncalibrated( const Mat& points1, const Mat& points2,
                                     const Mat& F, Size imgSize,
                                     Mat& H1, Mat& H2, double threshold )
@@ -3100,4 +3280,20 @@ void cv::reprojectImageTo3D( const Mat& disparity,
     cvReprojectImageTo3D( &_disparity, &__3dImage, &_Q, handleMissingValues );
 }
 
+
+cv::Mat cv::getOptimalNewCameraMatrix( const Mat& cameraMatrix, const Mat& distCoeffs,
+                                   Size imgSize, double alpha, Size newImgSize,
+                                   Rect* validPixROI )
+{
+    Mat newCameraMatrix(3, 3, cameraMatrix.type());
+    CvMat _cameraMatrix = cameraMatrix,
+        _distCoeffs = distCoeffs,
+        _newCameraMatrix = newCameraMatrix;
+    cvGetOptimalNewCameraMatrix(&_cameraMatrix, &_distCoeffs, imgSize,
+                                alpha, &_newCameraMatrix,
+                                newImgSize, (CvRect*)validPixROI);
+    return newCameraMatrix;
+}
+
+
 /* End of file. */
index 0a75c936f40c2b27034c8c911b32a91293682a72..9d60f34ca7f74deff6db6341d8c281a940f6336f 100644 (file)
@@ -5028,7 +5028,7 @@ FileNodeIterator::FileNodeIterator(const CvFileStorage* _fs,
         int node_type = _node->tag & FileNode::TYPE_MASK;
         fs = _fs;
         container = _node;
-        if( node_type == FileNode::SEQ || node_type == FileNode::MAP )
+        if( !(_node->tag & FileNode::USER) && (node_type == FileNode::SEQ || node_type == FileNode::MAP) )
         {
             cvStartReadSeq( _node->data.seq, &reader );
             remaining = FileNode(_fs, _node).size();
index 4f3a5a2d958fef71352d86ef98f82d776fb6ac85..1f933bd7fd0c6ed10e4c5c049083793eb383dd21 100644 (file)
@@ -248,7 +248,7 @@ bool CV_OptFlowTest::runDense(const Point& d)
     //waitKey();   \r
 \r
     const double thres = 0.2;\r
-    if (errorLK > thres || errorBM > thres || errorFB > thres || errorFBG > thres /*|| errorHS > thres /**/)\r
+    if (errorLK > thres || errorBM > thres || errorFB > thres || errorFBG > thres /*|| errorHS > thres */)\r
     {        \r
         ts->set_failed_test_info(CvTS::FAIL_MISMATCH);\r
         return false;\r