Home | History | Annotate | Download | only in src
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                        Intel License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2009, Intel Corporation and others, all rights reserved.
     14 // Third party copyrights are property of their respective owners.
     15 //
     16 // Redistribution and use in source and binary forms, with or without modification,
     17 // are permitted provided that the following conditions are met:
     18 //
     19 //   * Redistribution's of source code must retain the above copyright notice,
     20 //     this list of conditions and the following disclaimer.
     21 //
     22 //   * Redistribution's in binary form must reproduce the above copyright notice,
     23 //     this list of conditions and the following disclaimer in the documentation
     24 //     and/or other materials provided with the distribution.
     25 //
     26 //   * The name of Intel Corporation may not be used to endorse or promote products
     27 //     derived from this software without specific prior written permission.
     28 //
     29 // This software is provided by the copyright holders and contributors "as is" and
     30 // any express or implied warranties, including, but not limited to, the implied
     31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     32 // In no event shall the Intel Corporation or contributors be liable for any direct,
     33 // indirect, incidental, special, exemplary, or consequential damages
     34 // (including, but not limited to, procurement of substitute goods or services;
     35 // loss of use, data, or profits; or business interruption) however caused
     36 // and on any theory of liability, whether in contract, strict liability,
     37 // or tort (including negligence or otherwise) arising in any way out of
     38 // the use of this software, even if advised of the possibility of such damage.
     39 //
     40 //M*/
     41 
     42 #include "precomp.hpp"
     43 #include "opencv2/calib3d/calib3d_c.h"
     44 
     45 // cvCorrectMatches function is Copyright (C) 2009, Jostein Austvik Jacobsen.
     46 // cvTriangulatePoints function is derived from icvReconstructPointsFor3View, originally by Valery Mosyagin.
     47 
     48 // HZ, R. Hartley and A. Zisserman, Multiple View Geometry in Computer Vision, Cambridge Univ. Press, 2003.
     49 
     50 
     51 
     52 // This method is the same as icvReconstructPointsFor3View, with only a few numbers adjusted for two-view geometry
     53 CV_IMPL void
     54 cvTriangulatePoints(CvMat* projMatr1, CvMat* projMatr2, CvMat* projPoints1, CvMat* projPoints2, CvMat* points4D)
     55 {
     56     if( projMatr1 == 0 || projMatr2 == 0 ||
     57       projPoints1 == 0 || projPoints2 == 0 ||
     58       points4D == 0)
     59       CV_Error( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
     60 
     61     if( !CV_IS_MAT(projMatr1) || !CV_IS_MAT(projMatr2) ||
     62       !CV_IS_MAT(projPoints1) || !CV_IS_MAT(projPoints2) ||
     63       !CV_IS_MAT(points4D) )
     64       CV_Error( CV_StsUnsupportedFormat, "Input parameters must be matrices" );
     65 
     66     int numPoints = projPoints1->cols;
     67 
     68     if( numPoints < 1 )
     69         CV_Error( CV_StsOutOfRange, "Number of points must be more than zero" );
     70 
     71     if( projPoints2->cols != numPoints || points4D->cols != numPoints )
     72         CV_Error( CV_StsUnmatchedSizes, "Number of points must be the same" );
     73 
     74     if( projPoints1->rows != 2 || projPoints2->rows != 2)
     75         CV_Error( CV_StsUnmatchedSizes, "Number of proj points coordinates must be == 2" );
     76 
     77     if( points4D->rows != 4 )
     78         CV_Error( CV_StsUnmatchedSizes, "Number of world points coordinates must be == 4" );
     79 
     80     if( projMatr1->cols != 4 || projMatr1->rows != 3 ||
     81        projMatr2->cols != 4 || projMatr2->rows != 3)
     82         CV_Error( CV_StsUnmatchedSizes, "Size of projection matrices must be 3x4" );
     83 
     84     // preallocate SVD matrices on stack
     85     cv::Matx<double, 4, 4> matrA;
     86     cv::Matx<double, 4, 4> matrU;
     87     cv::Matx<double, 4, 1> matrW;
     88     cv::Matx<double, 4, 4> matrV;
     89 
     90     CvMat* projPoints[2] = {projPoints1, projPoints2};
     91     CvMat* projMatrs[2] = {projMatr1, projMatr2};
     92 
     93     /* Solve system for each point */
     94     for( int i = 0; i < numPoints; i++ )/* For each point */
     95     {
     96         /* Fill matrix for current point */
     97         for( int j = 0; j < 2; j++ )/* For each view */
     98         {
     99             double x,y;
    100             x = cvmGet(projPoints[j],0,i);
    101             y = cvmGet(projPoints[j],1,i);
    102             for( int k = 0; k < 4; k++ )
    103             {
    104                 matrA(j*2+0, k) = x * cvmGet(projMatrs[j],2,k) - cvmGet(projMatrs[j],0,k);
    105                 matrA(j*2+1, k) = y * cvmGet(projMatrs[j],2,k) - cvmGet(projMatrs[j],1,k);
    106             }
    107         }
    108         /* Solve system for current point */
    109         cv::SVD::compute(matrA, matrW, matrU, matrV);
    110 
    111         /* Copy computed point */
    112         cvmSet(points4D,0,i,matrV(3,0));/* X */
    113         cvmSet(points4D,1,i,matrV(3,1));/* Y */
    114         cvmSet(points4D,2,i,matrV(3,2));/* Z */
    115         cvmSet(points4D,3,i,matrV(3,3));/* W */
    116     }
    117 
    118 #if 0
    119     double err = 0;
    120     /* Points was reconstructed. Try to reproject points */
    121     /* We can compute reprojection error if need */
    122     {
    123         int i;
    124         CvMat point3D;
    125         double point3D_dat[4];
    126         point3D = cvMat(4,1,CV_64F,point3D_dat);
    127 
    128         CvMat point2D;
    129         double point2D_dat[3];
    130         point2D = cvMat(3,1,CV_64F,point2D_dat);
    131 
    132         for( i = 0; i < numPoints; i++ )
    133         {
    134             double W = cvmGet(points4D,3,i);
    135 
    136             point3D_dat[0] = cvmGet(points4D,0,i)/W;
    137             point3D_dat[1] = cvmGet(points4D,1,i)/W;
    138             point3D_dat[2] = cvmGet(points4D,2,i)/W;
    139             point3D_dat[3] = 1;
    140 
    141             /* !!! Project this point for each camera */
    142             for( int currCamera = 0; currCamera < 2; currCamera++ )
    143             {
    144                 cvMatMul(projMatrs[currCamera], &point3D, &point2D);
    145 
    146                 float x,y;
    147                 float xr,yr,wr;
    148                 x = (float)cvmGet(projPoints[currCamera],0,i);
    149                 y = (float)cvmGet(projPoints[currCamera],1,i);
    150 
    151                 wr = (float)point2D_dat[2];
    152                 xr = (float)(point2D_dat[0]/wr);
    153                 yr = (float)(point2D_dat[1]/wr);
    154 
    155                 float deltaX,deltaY;
    156                 deltaX = (float)fabs(x-xr);
    157                 deltaY = (float)fabs(y-yr);
    158                 err += deltaX*deltaX + deltaY*deltaY;
    159             }
    160         }
    161     }
    162 #endif
    163 }
    164 
    165 
    166 /*
    167  *	The Optimal Triangulation Method (see HZ for details)
    168  *		For each given point correspondence points1[i] <-> points2[i], and a fundamental matrix F,
    169  *		computes the corrected correspondences new_points1[i] <-> new_points2[i] that minimize the
    170  *		geometric error d(points1[i],new_points1[i])^2 + d(points2[i],new_points2[i])^2 (where d(a,b)
    171  *		is the geometric distance between points a and b) subject to the epipolar constraint
    172  *		new_points2' * F * new_points1 = 0.
    173  *
    174  *		F_			:	3x3 fundamental matrix
    175  *		points1_	:	1xN matrix containing the first set of points
    176  *		points2_	:	1xN matrix containing the second set of points
    177  *		new_points1	:	the optimized points1_. if this is NULL, the corrected points are placed back in points1_
    178  *		new_points2	:	the optimized points2_. if this is NULL, the corrected points are placed back in points2_
    179  */
    180 CV_IMPL void
    181 cvCorrectMatches(CvMat *F_, CvMat *points1_, CvMat *points2_, CvMat *new_points1, CvMat *new_points2)
    182 {
    183     cv::Ptr<CvMat> tmp33;
    184     cv::Ptr<CvMat> tmp31, tmp31_2;
    185     cv::Ptr<CvMat> T1i, T2i;
    186     cv::Ptr<CvMat> R1, R2;
    187     cv::Ptr<CvMat> TFT, TFTt, RTFTR;
    188     cv::Ptr<CvMat> U, S, V;
    189     cv::Ptr<CvMat> e1, e2;
    190     cv::Ptr<CvMat> polynomial;
    191     cv::Ptr<CvMat> result;
    192     cv::Ptr<CvMat> points1, points2;
    193     cv::Ptr<CvMat> F;
    194 
    195     if (!CV_IS_MAT(F_) || !CV_IS_MAT(points1_) || !CV_IS_MAT(points2_) )
    196         CV_Error( CV_StsUnsupportedFormat, "Input parameters must be matrices" );
    197     if (!( F_->cols == 3 && F_->rows == 3))
    198         CV_Error( CV_StsUnmatchedSizes, "The fundamental matrix must be a 3x3 matrix");
    199     if (!(((F_->type & CV_MAT_TYPE_MASK) >> 3) == 0 ))
    200         CV_Error( CV_StsUnsupportedFormat, "The fundamental matrix must be a single-channel matrix" );
    201     if (!(points1_->rows == 1 && points2_->rows == 1 && points1_->cols == points2_->cols))
    202         CV_Error( CV_StsUnmatchedSizes, "The point-matrices must have one row, and an equal number of columns" );
    203     if (((points1_->type & CV_MAT_TYPE_MASK) >> 3) != 1 )
    204         CV_Error( CV_StsUnmatchedSizes, "The first set of points must contain two channels; one for x and one for y" );
    205     if (((points2_->type & CV_MAT_TYPE_MASK) >> 3) != 1 )
    206         CV_Error( CV_StsUnmatchedSizes, "The second set of points must contain two channels; one for x and one for y" );
    207     if (new_points1 != NULL) {
    208         CV_Assert(CV_IS_MAT(new_points1));
    209         if (new_points1->cols != points1_->cols || new_points1->rows != 1)
    210             CV_Error( CV_StsUnmatchedSizes, "The first output matrix must have the same dimensions as the input matrices" );
    211         if (CV_MAT_CN(new_points1->type) != 2)
    212             CV_Error( CV_StsUnsupportedFormat, "The first output matrix must have two channels; one for x and one for y" );
    213     }
    214     if (new_points2 != NULL) {
    215         CV_Assert(CV_IS_MAT(new_points2));
    216         if (new_points2->cols != points2_->cols || new_points2->rows != 1)
    217             CV_Error( CV_StsUnmatchedSizes, "The second output matrix must have the same dimensions as the input matrices" );
    218         if (CV_MAT_CN(new_points2->type) != 2)
    219             CV_Error( CV_StsUnsupportedFormat, "The second output matrix must have two channels; one for x and one for y" );
    220     }
    221 
    222     // Make sure F uses double precision
    223     F.reset(cvCreateMat(3,3,CV_64FC1));
    224     cvConvert(F_, F);
    225 
    226     // Make sure points1 uses double precision
    227     points1.reset(cvCreateMat(points1_->rows,points1_->cols,CV_64FC2));
    228     cvConvert(points1_, points1);
    229 
    230     // Make sure points2 uses double precision
    231     points2.reset(cvCreateMat(points2_->rows,points2_->cols,CV_64FC2));
    232     cvConvert(points2_, points2);
    233 
    234     tmp33.reset(cvCreateMat(3,3,CV_64FC1));
    235     tmp31.reset(cvCreateMat(3,1,CV_64FC1)), tmp31_2.reset(cvCreateMat(3,1,CV_64FC1));
    236     T1i.reset(cvCreateMat(3,3,CV_64FC1)), T2i.reset(cvCreateMat(3,3,CV_64FC1));
    237     R1.reset(cvCreateMat(3,3,CV_64FC1)), R2.reset(cvCreateMat(3,3,CV_64FC1));
    238     TFT.reset(cvCreateMat(3,3,CV_64FC1)), TFTt.reset(cvCreateMat(3,3,CV_64FC1)), RTFTR.reset(cvCreateMat(3,3,CV_64FC1));
    239     U.reset(cvCreateMat(3,3,CV_64FC1));
    240     S.reset(cvCreateMat(3,3,CV_64FC1));
    241     V.reset(cvCreateMat(3,3,CV_64FC1));
    242     e1.reset(cvCreateMat(3,1,CV_64FC1)), e2.reset(cvCreateMat(3,1,CV_64FC1));
    243 
    244     double x1, y1, x2, y2;
    245     double scale;
    246     double f1, f2, a, b, c, d;
    247     polynomial.reset(cvCreateMat(1,7,CV_64FC1));
    248     result.reset(cvCreateMat(1,6,CV_64FC2));
    249     double t_min, s_val, t, s;
    250     for (int p = 0; p < points1->cols; ++p) {
    251         // Replace F by T2-t * F * T1-t
    252         x1 = points1->data.db[p*2];
    253         y1 = points1->data.db[p*2+1];
    254         x2 = points2->data.db[p*2];
    255         y2 = points2->data.db[p*2+1];
    256 
    257         cvSetZero(T1i);
    258         cvSetReal2D(T1i,0,0,1);
    259         cvSetReal2D(T1i,1,1,1);
    260         cvSetReal2D(T1i,2,2,1);
    261         cvSetReal2D(T1i,0,2,x1);
    262         cvSetReal2D(T1i,1,2,y1);
    263         cvSetZero(T2i);
    264         cvSetReal2D(T2i,0,0,1);
    265         cvSetReal2D(T2i,1,1,1);
    266         cvSetReal2D(T2i,2,2,1);
    267         cvSetReal2D(T2i,0,2,x2);
    268         cvSetReal2D(T2i,1,2,y2);
    269         cvGEMM(T2i,F,1,0,0,tmp33,CV_GEMM_A_T);
    270         cvSetZero(TFT);
    271         cvGEMM(tmp33,T1i,1,0,0,TFT);
    272 
    273         // Compute the right epipole e1 from F * e1 = 0
    274         cvSetZero(U);
    275         cvSetZero(S);
    276         cvSetZero(V);
    277         cvSVD(TFT,S,U,V);
    278         scale = sqrt(cvGetReal2D(V,0,2)*cvGetReal2D(V,0,2) + cvGetReal2D(V,1,2)*cvGetReal2D(V,1,2));
    279         cvSetReal2D(e1,0,0,cvGetReal2D(V,0,2)/scale);
    280         cvSetReal2D(e1,1,0,cvGetReal2D(V,1,2)/scale);
    281         cvSetReal2D(e1,2,0,cvGetReal2D(V,2,2)/scale);
    282         if (cvGetReal2D(e1,2,0) < 0) {
    283             cvSetReal2D(e1,0,0,-cvGetReal2D(e1,0,0));
    284             cvSetReal2D(e1,1,0,-cvGetReal2D(e1,1,0));
    285             cvSetReal2D(e1,2,0,-cvGetReal2D(e1,2,0));
    286         }
    287 
    288         // Compute the left epipole e2 from e2' * F = 0  =>  F' * e2 = 0
    289         cvSetZero(TFTt);
    290         cvTranspose(TFT, TFTt);
    291         cvSetZero(U);
    292         cvSetZero(S);
    293         cvSetZero(V);
    294         cvSVD(TFTt,S,U,V);
    295         cvSetZero(e2);
    296         scale = sqrt(cvGetReal2D(V,0,2)*cvGetReal2D(V,0,2) + cvGetReal2D(V,1,2)*cvGetReal2D(V,1,2));
    297         cvSetReal2D(e2,0,0,cvGetReal2D(V,0,2)/scale);
    298         cvSetReal2D(e2,1,0,cvGetReal2D(V,1,2)/scale);
    299         cvSetReal2D(e2,2,0,cvGetReal2D(V,2,2)/scale);
    300         if (cvGetReal2D(e2,2,0) < 0) {
    301             cvSetReal2D(e2,0,0,-cvGetReal2D(e2,0,0));
    302             cvSetReal2D(e2,1,0,-cvGetReal2D(e2,1,0));
    303             cvSetReal2D(e2,2,0,-cvGetReal2D(e2,2,0));
    304         }
    305 
    306         // Replace F by R2 * F * R1'
    307         cvSetZero(R1);
    308         cvSetReal2D(R1,0,0,cvGetReal2D(e1,0,0));
    309         cvSetReal2D(R1,0,1,cvGetReal2D(e1,1,0));
    310         cvSetReal2D(R1,1,0,-cvGetReal2D(e1,1,0));
    311         cvSetReal2D(R1,1,1,cvGetReal2D(e1,0,0));
    312         cvSetReal2D(R1,2,2,1);
    313         cvSetZero(R2);
    314         cvSetReal2D(R2,0,0,cvGetReal2D(e2,0,0));
    315         cvSetReal2D(R2,0,1,cvGetReal2D(e2,1,0));
    316         cvSetReal2D(R2,1,0,-cvGetReal2D(e2,1,0));
    317         cvSetReal2D(R2,1,1,cvGetReal2D(e2,0,0));
    318         cvSetReal2D(R2,2,2,1);
    319         cvGEMM(R2,TFT,1,0,0,tmp33);
    320         cvGEMM(tmp33,R1,1,0,0,RTFTR,CV_GEMM_B_T);
    321 
    322         // Set f1 = e1(3), f2 = e2(3), a = F22, b = F23, c = F32, d = F33
    323         f1 = cvGetReal2D(e1,2,0);
    324         f2 = cvGetReal2D(e2,2,0);
    325         a = cvGetReal2D(RTFTR,1,1);
    326         b = cvGetReal2D(RTFTR,1,2);
    327         c = cvGetReal2D(RTFTR,2,1);
    328         d = cvGetReal2D(RTFTR,2,2);
    329 
    330         // Form the polynomial g(t) = k6*t + k5*t + k4*t + k3*t + k2*t + k1*t + k0
    331         // from f1, f2, a, b, c and d
    332         cvSetReal2D(polynomial,0,6,( +b*c*c*f1*f1*f1*f1*a-a*a*d*f1*f1*f1*f1*c ));
    333         cvSetReal2D(polynomial,0,5,( +f2*f2*f2*f2*c*c*c*c+2*a*a*f2*f2*c*c-a*a*d*d*f1*f1*f1*f1+b*b*c*c*f1*f1*f1*f1+a*a*a*a ));
    334         cvSetReal2D(polynomial,0,4,( +4*a*a*a*b+2*b*c*c*f1*f1*a+4*f2*f2*f2*f2*c*c*c*d+4*a*b*f2*f2*c*c+4*a*a*f2*f2*c*d-2*a*a*d*f1*f1*c-a*d*d*f1*f1*f1*f1*b+b*b*c*f1*f1*f1*f1*d ));
    335         cvSetReal2D(polynomial,0,3,( +6*a*a*b*b+6*f2*f2*f2*f2*c*c*d*d+2*b*b*f2*f2*c*c+2*a*a*f2*f2*d*d-2*a*a*d*d*f1*f1+2*b*b*c*c*f1*f1+8*a*b*f2*f2*c*d ));
    336         cvSetReal2D(polynomial,0,2,( +4*a*b*b*b+4*b*b*f2*f2*c*d+4*f2*f2*f2*f2*c*d*d*d-a*a*d*c+b*c*c*a+4*a*b*f2*f2*d*d-2*a*d*d*f1*f1*b+2*b*b*c*f1*f1*d ));
    337         cvSetReal2D(polynomial,0,1,( +f2*f2*f2*f2*d*d*d*d+b*b*b*b+2*b*b*f2*f2*d*d-a*a*d*d+b*b*c*c ));
    338         cvSetReal2D(polynomial,0,0,( -a*d*d*b+b*b*c*d ));
    339 
    340         // Solve g(t) for t to get 6 roots
    341         cvSetZero(result);
    342         cvSolvePoly(polynomial, result, 100, 20);
    343 
    344         // Evaluate the cost function s(t) at the real part of the 6 roots
    345         t_min = DBL_MAX;
    346         s_val = 1./(f1*f1) + (c*c)/(a*a+f2*f2*c*c);
    347         for (int ti = 0; ti < 6; ++ti) {
    348             t = result->data.db[2*ti];
    349             s = (t*t)/(1 + f1*f1*t*t) + ((c*t + d)*(c*t + d))/((a*t + b)*(a*t + b) + f2*f2*(c*t + d)*(c*t + d));
    350             if (s < s_val) {
    351                 s_val = s;
    352                 t_min = t;
    353             }
    354         }
    355 
    356         // find the optimal x1 and y1 as the points on l1 and l2 closest to the origin
    357         tmp31->data.db[0] = t_min*t_min*f1;
    358         tmp31->data.db[1] = t_min;
    359         tmp31->data.db[2] = t_min*t_min*f1*f1+1;
    360         tmp31->data.db[0] /= tmp31->data.db[2];
    361         tmp31->data.db[1] /= tmp31->data.db[2];
    362         tmp31->data.db[2] /= tmp31->data.db[2];
    363         cvGEMM(T1i,R1,1,0,0,tmp33,CV_GEMM_B_T);
    364         cvGEMM(tmp33,tmp31,1,0,0,tmp31_2);
    365         x1 = tmp31_2->data.db[0];
    366         y1 = tmp31_2->data.db[1];
    367 
    368         tmp31->data.db[0] = f2*pow(c*t_min+d,2);
    369         tmp31->data.db[1] = -(a*t_min+b)*(c*t_min+d);
    370         tmp31->data.db[2] = f2*f2*pow(c*t_min+d,2) + pow(a*t_min+b,2);
    371         tmp31->data.db[0] /= tmp31->data.db[2];
    372         tmp31->data.db[1] /= tmp31->data.db[2];
    373         tmp31->data.db[2] /= tmp31->data.db[2];
    374         cvGEMM(T2i,R2,1,0,0,tmp33,CV_GEMM_B_T);
    375         cvGEMM(tmp33,tmp31,1,0,0,tmp31_2);
    376         x2 = tmp31_2->data.db[0];
    377         y2 = tmp31_2->data.db[1];
    378 
    379         // Return the points in the matrix format that the user wants
    380         points1->data.db[p*2] = x1;
    381         points1->data.db[p*2+1] = y1;
    382         points2->data.db[p*2] = x2;
    383         points2->data.db[p*2+1] = y2;
    384     }
    385 
    386     if( new_points1 )
    387         cvConvert( points1, new_points1 );
    388     if( new_points2 )
    389         cvConvert( points2, new_points2 );
    390 }
    391 
    392 void cv::triangulatePoints( InputArray _projMatr1, InputArray _projMatr2,
    393                             InputArray _projPoints1, InputArray _projPoints2,
    394                             OutputArray _points4D )
    395 {
    396     Mat matr1 = _projMatr1.getMat(), matr2 = _projMatr2.getMat();
    397     Mat points1 = _projPoints1.getMat(), points2 = _projPoints2.getMat();
    398 
    399     if((points1.rows == 1 || points1.cols == 1) && points1.channels() == 2)
    400         points1 = points1.reshape(1, static_cast<int>(points1.total())).t();
    401 
    402     if((points2.rows == 1 || points2.cols == 1) && points2.channels() == 2)
    403         points2 = points2.reshape(1, static_cast<int>(points2.total())).t();
    404 
    405     CvMat cvMatr1 = matr1, cvMatr2 = matr2;
    406     CvMat cvPoints1 = points1, cvPoints2 = points2;
    407 
    408     _points4D.create(4, points1.cols, points1.type());
    409     CvMat cvPoints4D = _points4D.getMat();
    410 
    411     cvTriangulatePoints(&cvMatr1, &cvMatr2, &cvPoints1, &cvPoints2, &cvPoints4D);
    412 }
    413 
    414 void cv::correctMatches( InputArray _F, InputArray _points1, InputArray _points2,
    415                          OutputArray _newPoints1, OutputArray _newPoints2 )
    416 {
    417     Mat F = _F.getMat();
    418     Mat points1 = _points1.getMat(), points2 = _points2.getMat();
    419 
    420     CvMat cvPoints1 = points1, cvPoints2 = points2;
    421     CvMat cvF = F;
    422 
    423     _newPoints1.create(points1.size(), points1.type());
    424     _newPoints2.create(points2.size(), points2.type());
    425     CvMat cvNewPoints1 = _newPoints1.getMat(), cvNewPoints2 = _newPoints2.getMat();
    426 
    427     cvCorrectMatches(&cvF, &cvPoints1, &cvPoints2, &cvNewPoints1, &cvNewPoints2);
    428 }
    429