Home | History | Annotate | Download | only in test
      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) 2000, Intel Corporation, 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 "test_precomp.hpp"
     43 #include "opencv2/calib3d/calib3d_c.h"
     44 
     45 using namespace cv;
     46 using namespace std;
     47 
     48 int cvTsRodrigues( const CvMat* src, CvMat* dst, CvMat* jacobian )
     49 {
     50     int depth;
     51     int i;
     52     float Jf[27];
     53     double J[27];
     54     CvMat _Jf, matJ = cvMat( 3, 9, CV_64F, J );
     55 
     56     depth = CV_MAT_DEPTH(src->type);
     57 
     58     if( jacobian )
     59     {
     60         assert( (jacobian->rows == 9 && jacobian->cols == 3) ||
     61                 (jacobian->rows == 3 && jacobian->cols == 9) );
     62     }
     63 
     64     if( src->cols == 1 || src->rows == 1 )
     65     {
     66         double r[3], theta;
     67         CvMat _r = cvMat( src->rows, src->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(src->type)), r);
     68 
     69         assert( dst->rows == 3 && dst->cols == 3 );
     70 
     71         cvConvert( src, &_r );
     72 
     73         theta = sqrt(r[0]*r[0] + r[1]*r[1] + r[2]*r[2]);
     74         if( theta < DBL_EPSILON )
     75         {
     76             cvSetIdentity( dst );
     77 
     78             if( jacobian )
     79             {
     80                 memset( J, 0, sizeof(J) );
     81                 J[5] = J[15] = J[19] = 1;
     82                 J[7] = J[11] = J[21] = -1;
     83             }
     84         }
     85         else
     86         {
     87             // omega = r/theta (~[w1, w2, w3])
     88             double itheta = 1./theta;
     89             double w1 = r[0]*itheta, w2 = r[1]*itheta, w3 = r[2]*itheta;
     90             double alpha = cos(theta);
     91             double beta = sin(theta);
     92             double gamma = 1 - alpha;
     93             double omegav[] =
     94             {
     95                 0, -w3, w2,
     96                 w3, 0, -w1,
     97                 -w2, w1, 0
     98             };
     99             double A[] =
    100             {
    101                 w1*w1, w1*w2, w1*w3,
    102                 w2*w1, w2*w2, w2*w3,
    103                 w3*w1, w3*w2, w3*w3
    104             };
    105             double R[9];
    106             CvMat _omegav = cvMat(3, 3, CV_64F, omegav);
    107             CvMat matA = cvMat(3, 3, CV_64F, A);
    108             CvMat matR = cvMat(3, 3, CV_64F, R);
    109 
    110             cvSetIdentity( &matR, cvRealScalar(alpha) );
    111             cvScaleAdd( &_omegav, cvRealScalar(beta), &matR, &matR );
    112             cvScaleAdd( &matA, cvRealScalar(gamma), &matR, &matR );
    113             cvConvert( &matR, dst );
    114 
    115             if( jacobian )
    116             {
    117                 // m3 = [r, theta]
    118                 double dm3din[] =
    119                 {
    120                     1, 0, 0,
    121                     0, 1, 0,
    122                     0, 0, 1,
    123                     w1, w2, w3
    124                 };
    125                 // m2 = [omega, theta]
    126                 double dm2dm3[] =
    127                 {
    128                     itheta, 0, 0, -w1*itheta,
    129                     0, itheta, 0, -w2*itheta,
    130                     0, 0, itheta, -w3*itheta,
    131                     0, 0, 0, 1
    132                 };
    133                 double t0[9*4];
    134                 double dm1dm2[21*4];
    135                 double dRdm1[9*21];
    136                 CvMat _dm3din = cvMat( 4, 3, CV_64FC1, dm3din );
    137                 CvMat _dm2dm3 = cvMat( 4, 4, CV_64FC1, dm2dm3 );
    138                 CvMat _dm1dm2 = cvMat( 21, 4, CV_64FC1, dm1dm2 );
    139                 CvMat _dRdm1 = cvMat( 9, 21, CV_64FC1, dRdm1 );
    140                 CvMat _dRdm1_part;
    141                 CvMat _t0 = cvMat( 9, 4, CV_64FC1, t0 );
    142                 CvMat _t1 = cvMat( 9, 4, CV_64FC1, dRdm1 );
    143 
    144                 // m1 = [alpha, beta, gamma, omegav; A]
    145                 memset( dm1dm2, 0, sizeof(dm1dm2) );
    146                 dm1dm2[3] = -beta;
    147                 dm1dm2[7] = alpha;
    148                 dm1dm2[11] = beta;
    149 
    150                 // dm1dm2(4:12,1:3) = [0 0 0 0 0 1 0 -1 0;
    151                 //                     0 0 -1 0 0 0 1 0 0;
    152                 //                     0 1 0 -1 0 0 0 0 0]'
    153                 //                     -------------------
    154                 //                     0 0 0  0 0 0 0 0 0
    155                 dm1dm2[12 + 6] = dm1dm2[12 + 20] = dm1dm2[12 + 25] = 1;
    156                 dm1dm2[12 + 9] = dm1dm2[12 + 14] = dm1dm2[12 + 28] = -1;
    157 
    158                 double dm1dw[] =
    159                 {
    160                     2*w1, w2, w3, w2, 0, 0, w3, 0, 0,
    161                     0, w1, 0, w1, 2*w2, w3, 0, w3, 0,
    162                     0, 0, w1, 0, 0, w2, w1, w2, 2*w3
    163                 };
    164 
    165                 CvMat _dm1dw = cvMat( 3, 9, CV_64FC1, dm1dw );
    166                 CvMat _dm1dm2_part;
    167 
    168                 cvGetSubRect( &_dm1dm2, &_dm1dm2_part, cvRect(0,12,3,9) );
    169                 cvTranspose( &_dm1dw, &_dm1dm2_part );
    170 
    171                 memset( dRdm1, 0, sizeof(dRdm1) );
    172                 dRdm1[0*21] = dRdm1[4*21] = dRdm1[8*21] = 1;
    173 
    174                 cvGetCol( &_dRdm1, &_dRdm1_part, 1 );
    175                 cvTranspose( &_omegav, &_omegav );
    176                 cvReshape( &_omegav, &_omegav, 1, 1 );
    177                 cvTranspose( &_omegav, &_dRdm1_part );
    178 
    179                 cvGetCol( &_dRdm1, &_dRdm1_part, 2 );
    180                 cvReshape( &matA, &matA, 1, 1 );
    181                 cvTranspose( &matA, &_dRdm1_part );
    182 
    183                 cvGetSubRect( &_dRdm1, &_dRdm1_part, cvRect(3,0,9,9) );
    184                 cvSetIdentity( &_dRdm1_part, cvScalarAll(beta) );
    185 
    186                 cvGetSubRect( &_dRdm1, &_dRdm1_part, cvRect(12,0,9,9) );
    187                 cvSetIdentity( &_dRdm1_part, cvScalarAll(gamma) );
    188 
    189                 matJ = cvMat( 9, 3, CV_64FC1, J );
    190 
    191                 cvMatMul( &_dRdm1, &_dm1dm2, &_t0 );
    192                 cvMatMul( &_t0, &_dm2dm3, &_t1 );
    193                 cvMatMul( &_t1, &_dm3din, &matJ );
    194 
    195                 _t0 = cvMat( 3, 9, CV_64FC1, t0 );
    196                 cvTranspose( &matJ, &_t0 );
    197 
    198                 for( i = 0; i < 3; i++ )
    199                 {
    200                     _t1 = cvMat( 3, 3, CV_64FC1, t0 + i*9 );
    201                     cvTranspose( &_t1, &_t1 );
    202                 }
    203 
    204                 cvTranspose( &_t0, &matJ );
    205             }
    206         }
    207     }
    208     else if( src->cols == 3 && src->rows == 3 )
    209     {
    210         double R[9], A[9], I[9], r[3], W[3], U[9], V[9];
    211         double tr, alpha, beta, theta;
    212         CvMat matR = cvMat( 3, 3, CV_64F, R );
    213         CvMat matA = cvMat( 3, 3, CV_64F, A );
    214         CvMat matI = cvMat( 3, 3, CV_64F, I );
    215         CvMat _r = cvMat( dst->rows, dst->cols, CV_MAKETYPE(CV_64F, CV_MAT_CN(dst->type)), r );
    216         CvMat matW = cvMat( 1, 3, CV_64F, W );
    217         CvMat matU = cvMat( 3, 3, CV_64F, U );
    218         CvMat matV = cvMat( 3, 3, CV_64F, V );
    219 
    220         cvConvert( src, &matR );
    221         cvSVD( &matR, &matW, &matU, &matV, CV_SVD_MODIFY_A + CV_SVD_U_T + CV_SVD_V_T );
    222         cvGEMM( &matU, &matV, 1, 0, 0, &matR, CV_GEMM_A_T );
    223 
    224         cvMulTransposed( &matR, &matA, 0 );
    225         cvSetIdentity( &matI );
    226 
    227         if( cvNorm( &matA, &matI, CV_C ) > 1e-3 ||
    228             fabs( cvDet(&matR) - 1 ) > 1e-3 )
    229             return 0;
    230 
    231         tr = (cvTrace(&matR).val[0] - 1.)*0.5;
    232         tr = tr > 1. ? 1. : tr < -1. ? -1. : tr;
    233         theta = acos(tr);
    234         alpha = cos(theta);
    235         beta = sin(theta);
    236 
    237         if( beta >= 1e-5 )
    238         {
    239             double dtheta_dtr = -1./sqrt(1 - tr*tr);
    240             double vth = 1/(2*beta);
    241 
    242             // om1 = [R(3,2) - R(2,3), R(1,3) - R(3,1), R(2,1) - R(1,2)]'
    243             double om1[] = { R[7] - R[5], R[2] - R[6], R[3] - R[1] };
    244             // om = om1*vth
    245             // r = om*theta
    246             double d3 = vth*theta;
    247 
    248             r[0] = om1[0]*d3; r[1] = om1[1]*d3; r[2] = om1[2]*d3;
    249             cvConvert( &_r, dst );
    250 
    251             if( jacobian )
    252             {
    253                 // var1 = [vth;theta]
    254                 // var = [om1;var1] = [om1;vth;theta]
    255                 double dvth_dtheta = -vth*alpha/beta;
    256                 double d1 = 0.5*dvth_dtheta*dtheta_dtr;
    257                 double d2 = 0.5*dtheta_dtr;
    258                 // dvar1/dR = dvar1/dtheta*dtheta/dR = [dvth/dtheta; 1] * dtheta/dtr * dtr/dR
    259                 double dvardR[5*9] =
    260                 {
    261                     0, 0, 0, 0, 0, 1, 0, -1, 0,
    262                     0, 0, -1, 0, 0, 0, 1, 0, 0,
    263                     0, 1, 0, -1, 0, 0, 0, 0, 0,
    264                     d1, 0, 0, 0, d1, 0, 0, 0, d1,
    265                     d2, 0, 0, 0, d2, 0, 0, 0, d2
    266                 };
    267                 // var2 = [om;theta]
    268                 double dvar2dvar[] =
    269                 {
    270                     vth, 0, 0, om1[0], 0,
    271                     0, vth, 0, om1[1], 0,
    272                     0, 0, vth, om1[2], 0,
    273                     0, 0, 0, 0, 1
    274                 };
    275                 double domegadvar2[] =
    276                 {
    277                     theta, 0, 0, om1[0]*vth,
    278                     0, theta, 0, om1[1]*vth,
    279                     0, 0, theta, om1[2]*vth
    280                 };
    281 
    282                 CvMat _dvardR = cvMat( 5, 9, CV_64FC1, dvardR );
    283                 CvMat _dvar2dvar = cvMat( 4, 5, CV_64FC1, dvar2dvar );
    284                 CvMat _domegadvar2 = cvMat( 3, 4, CV_64FC1, domegadvar2 );
    285                 double t0[3*5];
    286                 CvMat _t0 = cvMat( 3, 5, CV_64FC1, t0 );
    287 
    288                 cvMatMul( &_domegadvar2, &_dvar2dvar, &_t0 );
    289                 cvMatMul( &_t0, &_dvardR, &matJ );
    290             }
    291         }
    292         else if( tr > 0 )
    293         {
    294             cvZero( dst );
    295             if( jacobian )
    296             {
    297                 memset( J, 0, sizeof(J) );
    298                 J[5] = J[15] = J[19] = 0.5;
    299                 J[7] = J[11] = J[21] = -0.5;
    300             }
    301         }
    302         else
    303         {
    304             r[0] = theta*sqrt((R[0] + 1)*0.5);
    305             r[1] = theta*sqrt((R[4] + 1)*0.5)*(R[1] >= 0 ? 1 : -1);
    306             r[2] = theta*sqrt((R[8] + 1)*0.5)*(R[2] >= 0 ? 1 : -1);
    307             cvConvert( &_r, dst );
    308 
    309             if( jacobian )
    310                 memset( J, 0, sizeof(J) );
    311         }
    312 
    313         if( jacobian )
    314         {
    315             for( i = 0; i < 3; i++ )
    316             {
    317                 CvMat t = cvMat( 3, 3, CV_64F, J + i*9 );
    318                 cvTranspose( &t, &t );
    319             }
    320         }
    321     }
    322     else
    323     {
    324         assert(0);
    325         return 0;
    326     }
    327 
    328     if( jacobian )
    329     {
    330         if( depth == CV_32F )
    331         {
    332             if( jacobian->rows == matJ.rows )
    333                 cvConvert( &matJ, jacobian );
    334             else
    335             {
    336                 _Jf = cvMat( matJ.rows, matJ.cols, CV_32FC1, Jf );
    337                 cvConvert( &matJ, &_Jf );
    338                 cvTranspose( &_Jf, jacobian );
    339             }
    340         }
    341         else if( jacobian->rows == matJ.rows )
    342             cvCopy( &matJ, jacobian );
    343         else
    344             cvTranspose( &matJ, jacobian );
    345     }
    346 
    347     return 1;
    348 }
    349 
    350 
    351 void cvtest::Rodrigues(const Mat& src, Mat& dst, Mat* jac)
    352 {
    353     CvMat _src = src, _dst = dst, _jac;
    354     if( jac )
    355         _jac = *jac;
    356     cvTsRodrigues(&_src, &_dst, jac ? &_jac : 0);
    357 }
    358 
    359 
    360 static void test_convertHomogeneous( const Mat& _src, Mat& _dst )
    361 {
    362     Mat src = _src, dst = _dst;
    363     int i, count, sdims, ddims;
    364     int sstep1, sstep2, dstep1, dstep2;
    365 
    366     if( src.depth() != CV_64F )
    367         _src.convertTo(src, CV_64F);
    368 
    369     if( dst.depth() != CV_64F )
    370         dst.create(dst.size(), CV_MAKETYPE(CV_64F, _dst.channels()));
    371 
    372     if( src.rows > src.cols )
    373     {
    374         count = src.rows;
    375         sdims = src.channels()*src.cols;
    376         sstep1 = (int)(src.step/sizeof(double));
    377         sstep2 = 1;
    378     }
    379     else
    380     {
    381         count = src.cols;
    382         sdims = src.channels()*src.rows;
    383         if( src.rows == 1 )
    384         {
    385             sstep1 = sdims;
    386             sstep2 = 1;
    387         }
    388         else
    389         {
    390             sstep1 = 1;
    391             sstep2 = (int)(src.step/sizeof(double));
    392         }
    393     }
    394 
    395     if( dst.rows > dst.cols )
    396     {
    397         CV_Assert( count == dst.rows );
    398         ddims = dst.channels()*dst.cols;
    399         dstep1 = (int)(dst.step/sizeof(double));
    400         dstep2 = 1;
    401     }
    402     else
    403     {
    404         assert( count == dst.cols );
    405         ddims = dst.channels()*dst.rows;
    406         if( dst.rows == 1 )
    407         {
    408             dstep1 = ddims;
    409             dstep2 = 1;
    410         }
    411         else
    412         {
    413             dstep1 = 1;
    414             dstep2 = (int)(dst.step/sizeof(double));
    415         }
    416     }
    417 
    418     double* s = src.ptr<double>();
    419     double* d = dst.ptr<double>();
    420 
    421     if( sdims <= ddims )
    422     {
    423         int wstep = dstep2*(ddims - 1);
    424 
    425         for( i = 0; i < count; i++, s += sstep1, d += dstep1 )
    426         {
    427             double x = s[0];
    428             double y = s[sstep2];
    429 
    430             d[wstep] = 1;
    431             d[0] = x;
    432             d[dstep2] = y;
    433 
    434             if( sdims >= 3 )
    435             {
    436                 d[dstep2*2] = s[sstep2*2];
    437                 if( sdims == 4 )
    438                     d[dstep2*3] = s[sstep2*3];
    439             }
    440         }
    441     }
    442     else
    443     {
    444         int wstep = sstep2*(sdims - 1);
    445 
    446         for( i = 0; i < count; i++, s += sstep1, d += dstep1 )
    447         {
    448             double w = s[wstep];
    449             double x = s[0];
    450             double y = s[sstep2];
    451 
    452             w = w ? 1./w : 1;
    453 
    454             d[0] = x*w;
    455             d[dstep2] = y*w;
    456 
    457             if( ddims == 3 )
    458                 d[dstep2*2] = s[sstep2*2]*w;
    459         }
    460     }
    461 
    462     if( dst.data != _dst.data )
    463         dst.convertTo(_dst, _dst.depth());
    464 }
    465 
    466 
    467 void
    468 test_projectPoints( const Mat& _3d, const Mat& Rt, const Mat& A, Mat& _2d, RNG* rng, double sigma )
    469 {
    470     CV_Assert( _3d.isContinuous() );
    471 
    472     double p[12];
    473     Mat P( 3, 4, CV_64F, p );
    474     gemm(A, Rt, 1, Mat(), 0, P);
    475 
    476     int i, count = _3d.cols;
    477 
    478     Mat noise;
    479     if( rng )
    480     {
    481         if( sigma == 0 )
    482             rng = 0;
    483         else
    484         {
    485             noise.create( 1, _3d.cols, CV_64FC2 );
    486             rng->fill(noise, RNG::NORMAL, Scalar::all(0), Scalar::all(sigma) );
    487         }
    488     }
    489 
    490     Mat temp( 1, count, CV_64FC3 );
    491 
    492     for( i = 0; i < count; i++ )
    493     {
    494         const double* M = _3d.ptr<double>() + i*3;
    495         double* m = temp.ptr<double>() + i*3;
    496         double X = M[0], Y = M[1], Z = M[2];
    497         double u = p[0]*X + p[1]*Y + p[2]*Z + p[3];
    498         double v = p[4]*X + p[5]*Y + p[6]*Z + p[7];
    499         double s = p[8]*X + p[9]*Y + p[10]*Z + p[11];
    500 
    501         if( !noise.empty() )
    502         {
    503             u += noise.at<Point2d>(i).x*s;
    504             v += noise.at<Point2d>(i).y*s;
    505         }
    506 
    507         m[0] = u;
    508         m[1] = v;
    509         m[2] = s;
    510     }
    511 
    512     test_convertHomogeneous( temp, _2d );
    513 }
    514 
    515 
    516 /********************************** Rodrigues transform ********************************/
    517 
    518 class CV_RodriguesTest : public cvtest::ArrayTest
    519 {
    520 public:
    521     CV_RodriguesTest();
    522 
    523 protected:
    524     int read_params( CvFileStorage* fs );
    525     void fill_array( int test_case_idx, int i, int j, Mat& arr );
    526     int prepare_test_case( int test_case_idx );
    527     void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
    528     double get_success_error_level( int test_case_idx, int i, int j );
    529     void run_func();
    530     void prepare_to_validation( int );
    531 
    532     bool calc_jacobians;
    533     bool test_cpp;
    534 };
    535 
    536 
    537 CV_RodriguesTest::CV_RodriguesTest()
    538 {
    539     test_array[INPUT].push_back(NULL);  // rotation vector
    540     test_array[OUTPUT].push_back(NULL); // rotation matrix
    541     test_array[OUTPUT].push_back(NULL); // jacobian (J)
    542     test_array[OUTPUT].push_back(NULL); // rotation vector (backward transform result)
    543     test_array[OUTPUT].push_back(NULL); // inverse transform jacobian (J1)
    544     test_array[OUTPUT].push_back(NULL); // J*J1 (or J1*J) == I(3x3)
    545     test_array[REF_OUTPUT].push_back(NULL);
    546     test_array[REF_OUTPUT].push_back(NULL);
    547     test_array[REF_OUTPUT].push_back(NULL);
    548     test_array[REF_OUTPUT].push_back(NULL);
    549     test_array[REF_OUTPUT].push_back(NULL);
    550 
    551     element_wise_relative_error = false;
    552     calc_jacobians = false;
    553 
    554     test_cpp = false;
    555 }
    556 
    557 
    558 int CV_RodriguesTest::read_params( CvFileStorage* fs )
    559 {
    560     int code = cvtest::ArrayTest::read_params( fs );
    561     return code;
    562 }
    563 
    564 
    565 void CV_RodriguesTest::get_test_array_types_and_sizes(
    566     int /*test_case_idx*/, vector<vector<Size> >& sizes, vector<vector<int> >& types )
    567 {
    568     RNG& rng = ts->get_rng();
    569     int depth = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;
    570     int i, code;
    571 
    572     code = cvtest::randInt(rng) % 3;
    573     types[INPUT][0] = CV_MAKETYPE(depth, 1);
    574 
    575     if( code == 0 )
    576     {
    577         sizes[INPUT][0] = cvSize(1,1);
    578         types[INPUT][0] = CV_MAKETYPE(depth, 3);
    579     }
    580     else if( code == 1 )
    581         sizes[INPUT][0] = cvSize(3,1);
    582     else
    583         sizes[INPUT][0] = cvSize(1,3);
    584 
    585     sizes[OUTPUT][0] = cvSize(3, 3);
    586     types[OUTPUT][0] = CV_MAKETYPE(depth, 1);
    587 
    588     types[OUTPUT][1] = CV_MAKETYPE(depth, 1);
    589 
    590     if( cvtest::randInt(rng) % 2 )
    591         sizes[OUTPUT][1] = cvSize(3,9);
    592     else
    593         sizes[OUTPUT][1] = cvSize(9,3);
    594 
    595     types[OUTPUT][2] = types[INPUT][0];
    596     sizes[OUTPUT][2] = sizes[INPUT][0];
    597 
    598     types[OUTPUT][3] = types[OUTPUT][1];
    599     sizes[OUTPUT][3] = cvSize(sizes[OUTPUT][1].height, sizes[OUTPUT][1].width);
    600 
    601     types[OUTPUT][4] = types[OUTPUT][1];
    602     sizes[OUTPUT][4] = cvSize(3,3);
    603 
    604     calc_jacobians = cvtest::randInt(rng) % 3 != 0;
    605     if( !calc_jacobians )
    606         sizes[OUTPUT][1] = sizes[OUTPUT][3] = sizes[OUTPUT][4] = cvSize(0,0);
    607 
    608     for( i = 0; i < 5; i++ )
    609     {
    610         types[REF_OUTPUT][i] = types[OUTPUT][i];
    611         sizes[REF_OUTPUT][i] = sizes[OUTPUT][i];
    612     }
    613     test_cpp = (cvtest::randInt(rng) & 256) == 0;
    614 }
    615 
    616 
    617 double CV_RodriguesTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int j )
    618 {
    619     return j == 4 ? 1e-2 : 1e-2;
    620 }
    621 
    622 
    623 void CV_RodriguesTest::fill_array( int test_case_idx, int i, int j, Mat& arr )
    624 {
    625     if( i == INPUT && j == 0 )
    626     {
    627         double r[3], theta0, theta1, f;
    628         Mat _r( arr.rows, arr.cols, CV_MAKETYPE(CV_64F,arr.channels()), r );
    629         RNG& rng = ts->get_rng();
    630 
    631         r[0] = cvtest::randReal(rng)*CV_PI*2;
    632         r[1] = cvtest::randReal(rng)*CV_PI*2;
    633         r[2] = cvtest::randReal(rng)*CV_PI*2;
    634 
    635         theta0 = sqrt(r[0]*r[0] + r[1]*r[1] + r[2]*r[2]);
    636         theta1 = fmod(theta0, CV_PI*2);
    637 
    638         if( theta1 > CV_PI )
    639             theta1 = -(CV_PI*2 - theta1);
    640 
    641         f = theta1/(theta0 ? theta0 : 1);
    642         r[0] *= f;
    643         r[1] *= f;
    644         r[2] *= f;
    645 
    646         cvtest::convert( _r, arr, arr.type() );
    647     }
    648     else
    649         cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr );
    650 }
    651 
    652 
    653 int CV_RodriguesTest::prepare_test_case( int test_case_idx )
    654 {
    655     int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
    656     return code;
    657 }
    658 
    659 
    660 void CV_RodriguesTest::run_func()
    661 {
    662     CvMat v2m_jac, m2v_jac;
    663 
    664     if( calc_jacobians )
    665     {
    666         v2m_jac = test_mat[OUTPUT][1];
    667         m2v_jac = test_mat[OUTPUT][3];
    668     }
    669 
    670     if( !test_cpp )
    671     {
    672         CvMat _input = test_mat[INPUT][0], _output = test_mat[OUTPUT][0], _output2 = test_mat[OUTPUT][2];
    673         cvRodrigues2( &_input, &_output, calc_jacobians ? &v2m_jac : 0 );
    674         cvRodrigues2( &_output, &_output2, calc_jacobians ? &m2v_jac : 0 );
    675     }
    676     else
    677     {
    678         cv::Mat v = test_mat[INPUT][0], M = test_mat[OUTPUT][0], v2 = test_mat[OUTPUT][2];
    679         cv::Mat M0 = M, v2_0 = v2;
    680         if( !calc_jacobians )
    681         {
    682             cv::Rodrigues(v, M);
    683             cv::Rodrigues(M, v2);
    684         }
    685         else
    686         {
    687             cv::Mat J1 = test_mat[OUTPUT][1], J2 = test_mat[OUTPUT][3];
    688             cv::Mat J1_0 = J1, J2_0 = J2;
    689             cv::Rodrigues(v, M, J1);
    690             cv::Rodrigues(M, v2, J2);
    691             if( J1.data != J1_0.data )
    692             {
    693                 if( J1.size() != J1_0.size() )
    694                     J1 = J1.t();
    695                 J1.convertTo(J1_0, J1_0.type());
    696             }
    697             if( J2.data != J2_0.data )
    698             {
    699                 if( J2.size() != J2_0.size() )
    700                     J2 = J2.t();
    701                 J2.convertTo(J2_0, J2_0.type());
    702             }
    703         }
    704         if( M.data != M0.data )
    705             M.reshape(M0.channels(), M0.rows).convertTo(M0, M0.type());
    706         if( v2.data != v2_0.data )
    707             v2.reshape(v2_0.channels(), v2_0.rows).convertTo(v2_0, v2_0.type());
    708     }
    709 }
    710 
    711 
    712 void CV_RodriguesTest::prepare_to_validation( int /*test_case_idx*/ )
    713 {
    714     const Mat& vec = test_mat[INPUT][0];
    715     Mat& m = test_mat[REF_OUTPUT][0];
    716     Mat& vec2 = test_mat[REF_OUTPUT][2];
    717     Mat* v2m_jac = 0, *m2v_jac = 0;
    718     double theta0, theta1;
    719 
    720     if( calc_jacobians )
    721     {
    722         v2m_jac = &test_mat[REF_OUTPUT][1];
    723         m2v_jac = &test_mat[REF_OUTPUT][3];
    724     }
    725 
    726 
    727     cvtest::Rodrigues( vec, m, v2m_jac );
    728     cvtest::Rodrigues( m, vec2, m2v_jac );
    729     cvtest::copy( vec, vec2 );
    730 
    731     theta0 = norm( vec2, CV_L2 );
    732     theta1 = fmod( theta0, CV_PI*2 );
    733 
    734     if( theta1 > CV_PI )
    735         theta1 = -(CV_PI*2 - theta1);
    736     vec2 *= theta1/(theta0 ? theta0 : 1);
    737 
    738     if( calc_jacobians )
    739     {
    740         //cvInvert( v2m_jac, m2v_jac, CV_SVD );
    741         double nrm = cvtest::norm(test_mat[REF_OUTPUT][3], CV_C);
    742         if( FLT_EPSILON < nrm && nrm < 1000 )
    743         {
    744             gemm( test_mat[OUTPUT][1], test_mat[OUTPUT][3],
    745                   1, Mat(), 0, test_mat[OUTPUT][4],
    746                   v2m_jac->rows == 3 ? 0 : CV_GEMM_A_T + CV_GEMM_B_T );
    747         }
    748         else
    749         {
    750             setIdentity(test_mat[OUTPUT][4], Scalar::all(1.));
    751             cvtest::copy( test_mat[REF_OUTPUT][2], test_mat[OUTPUT][2] );
    752         }
    753         setIdentity(test_mat[REF_OUTPUT][4], Scalar::all(1.));
    754     }
    755 }
    756 
    757 
    758 /********************************** fundamental matrix *********************************/
    759 
    760 class CV_FundamentalMatTest : public cvtest::ArrayTest
    761 {
    762 public:
    763     CV_FundamentalMatTest();
    764 
    765 protected:
    766     int read_params( CvFileStorage* fs );
    767     void fill_array( int test_case_idx, int i, int j, Mat& arr );
    768     int prepare_test_case( int test_case_idx );
    769     void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
    770     double get_success_error_level( int test_case_idx, int i, int j );
    771     void run_func();
    772     void prepare_to_validation( int );
    773 
    774     int method;
    775     int img_size;
    776     int cube_size;
    777     int dims;
    778     int f_result;
    779     double min_f, max_f;
    780     double sigma;
    781     bool test_cpp;
    782 };
    783 
    784 
    785 CV_FundamentalMatTest::CV_FundamentalMatTest()
    786 {
    787     // input arrays:
    788     //   0, 1 - arrays of 2d points that are passed to %func%.
    789     //          Can have different data type, layout, be stored in homogeneous coordinates or not.
    790     //   2 - array of 3d points that are projected to both view planes
    791     //   3 - [R|t] matrix for the second view plane (for the first one it is [I|0]
    792     //   4, 5 - intrinsic matrices
    793     test_array[INPUT].push_back(NULL);
    794     test_array[INPUT].push_back(NULL);
    795     test_array[INPUT].push_back(NULL);
    796     test_array[INPUT].push_back(NULL);
    797     test_array[INPUT].push_back(NULL);
    798     test_array[INPUT].push_back(NULL);
    799     test_array[TEMP].push_back(NULL);
    800     test_array[TEMP].push_back(NULL);
    801     test_array[OUTPUT].push_back(NULL);
    802     test_array[OUTPUT].push_back(NULL);
    803     test_array[REF_OUTPUT].push_back(NULL);
    804     test_array[REF_OUTPUT].push_back(NULL);
    805 
    806     element_wise_relative_error = false;
    807 
    808     method = 0;
    809     img_size = 10;
    810     cube_size = 10;
    811     dims = 0;
    812     min_f = 1;
    813     max_f = 3;
    814     sigma = 0;//0.1;
    815     f_result = 0;
    816 
    817     test_cpp = false;
    818 }
    819 
    820 
    821 int CV_FundamentalMatTest::read_params( CvFileStorage* fs )
    822 {
    823     int code = cvtest::ArrayTest::read_params( fs );
    824     return code;
    825 }
    826 
    827 
    828 void CV_FundamentalMatTest::get_test_array_types_and_sizes( int /*test_case_idx*/,
    829                                                 vector<vector<Size> >& sizes, vector<vector<int> >& types )
    830 {
    831     RNG& rng = ts->get_rng();
    832     int pt_depth = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;
    833     double pt_count_exp = cvtest::randReal(rng)*6 + 1;
    834     int pt_count = cvRound(exp(pt_count_exp));
    835 
    836     dims = cvtest::randInt(rng) % 2 + 2;
    837     method = 1 << (cvtest::randInt(rng) % 4);
    838 
    839     if( method == CV_FM_7POINT )
    840         pt_count = 7;
    841     else
    842     {
    843         pt_count = MAX( pt_count, 8 + (method == CV_FM_8POINT) );
    844         if( pt_count >= 8 && cvtest::randInt(rng) % 2 )
    845             method |= CV_FM_8POINT;
    846     }
    847 
    848     types[INPUT][0] = CV_MAKETYPE(pt_depth, 1);
    849 
    850     if( cvtest::randInt(rng) % 2 )
    851         sizes[INPUT][0] = cvSize(pt_count, dims);
    852     else
    853     {
    854         sizes[INPUT][0] = cvSize(dims, pt_count);
    855         if( cvtest::randInt(rng) % 2 )
    856         {
    857             types[INPUT][0] = CV_MAKETYPE(pt_depth, dims);
    858             if( cvtest::randInt(rng) % 2 )
    859                 sizes[INPUT][0] = cvSize(pt_count, 1);
    860             else
    861                 sizes[INPUT][0] = cvSize(1, pt_count);
    862         }
    863     }
    864 
    865     sizes[INPUT][1] = sizes[INPUT][0];
    866     types[INPUT][1] = types[INPUT][0];
    867 
    868     sizes[INPUT][2] = cvSize(pt_count, 1 );
    869     types[INPUT][2] = CV_64FC3;
    870 
    871     sizes[INPUT][3] = cvSize(4,3);
    872     types[INPUT][3] = CV_64FC1;
    873 
    874     sizes[INPUT][4] = sizes[INPUT][5] = cvSize(3,3);
    875     types[INPUT][4] = types[INPUT][5] = CV_MAKETYPE(CV_64F, 1);
    876 
    877     sizes[TEMP][0] = cvSize(3,3);
    878     types[TEMP][0] = CV_64FC1;
    879     sizes[TEMP][1] = cvSize(pt_count,1);
    880     types[TEMP][1] = CV_8UC1;
    881 
    882     sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(3,1);
    883     types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1;
    884     sizes[OUTPUT][1] = sizes[REF_OUTPUT][1] = cvSize(pt_count,1);
    885     types[OUTPUT][1] = types[REF_OUTPUT][1] = CV_8UC1;
    886 
    887     test_cpp = (cvtest::randInt(rng) & 256) == 0;
    888 }
    889 
    890 
    891 double CV_FundamentalMatTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
    892 {
    893     return 1e-2;
    894 }
    895 
    896 
    897 void CV_FundamentalMatTest::fill_array( int test_case_idx, int i, int j, Mat& arr )
    898 {
    899     double t[12]={0};
    900     RNG& rng = ts->get_rng();
    901 
    902     if( i != INPUT )
    903     {
    904         cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr );
    905         return;
    906     }
    907 
    908     switch( j )
    909     {
    910     case 0:
    911     case 1:
    912         return; // fill them later in prepare_test_case
    913     case 2:
    914         {
    915         double* p = arr.ptr<double>();
    916         for( i = 0; i < arr.cols*3; i += 3 )
    917         {
    918             p[i] = cvtest::randReal(rng)*cube_size;
    919             p[i+1] = cvtest::randReal(rng)*cube_size;
    920             p[i+2] = cvtest::randReal(rng)*cube_size + cube_size;
    921         }
    922         }
    923         break;
    924     case 3:
    925         {
    926         double r[3];
    927         Mat rot_vec( 3, 1, CV_64F, r );
    928         Mat rot_mat( 3, 3, CV_64F, t, 4*sizeof(t[0]) );
    929         r[0] = cvtest::randReal(rng)*CV_PI*2;
    930         r[1] = cvtest::randReal(rng)*CV_PI*2;
    931         r[2] = cvtest::randReal(rng)*CV_PI*2;
    932 
    933         cvtest::Rodrigues( rot_vec, rot_mat );
    934         t[3] = cvtest::randReal(rng)*cube_size;
    935         t[7] = cvtest::randReal(rng)*cube_size;
    936         t[11] = cvtest::randReal(rng)*cube_size;
    937         Mat( 3, 4, CV_64F, t ).convertTo(arr, arr.type());
    938         }
    939         break;
    940     case 4:
    941     case 5:
    942         t[0] = t[4] = cvtest::randReal(rng)*(max_f - min_f) + min_f;
    943         t[2] = (img_size*0.5 + cvtest::randReal(rng)*4. - 2.)*t[0];
    944         t[5] = (img_size*0.5 + cvtest::randReal(rng)*4. - 2.)*t[4];
    945         t[8] = 1.;
    946         Mat( 3, 3, CV_64F, t ).convertTo( arr, arr.type() );
    947         break;
    948     }
    949 }
    950 
    951 
    952 int CV_FundamentalMatTest::prepare_test_case( int test_case_idx )
    953 {
    954     int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
    955     if( code > 0 )
    956     {
    957         const Mat& _3d = test_mat[INPUT][2];
    958         RNG& rng = ts->get_rng();
    959         double Idata[] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0 };
    960         Mat I( 3, 4, CV_64F, Idata );
    961         int k;
    962 
    963         for( k = 0; k < 2; k++ )
    964         {
    965             const Mat& Rt = k == 0 ? I : test_mat[INPUT][3];
    966             const Mat& A = test_mat[INPUT][k == 0 ? 4 : 5];
    967             Mat& _2d = test_mat[INPUT][k];
    968 
    969             test_projectPoints( _3d, Rt, A, _2d, &rng, sigma );
    970         }
    971     }
    972 
    973     return code;
    974 }
    975 
    976 void CV_FundamentalMatTest::run_func()
    977 {
    978     // cvFindFundamentalMat calls cv::findFundamentalMat
    979     CvMat _input0 = test_mat[INPUT][0], _input1 = test_mat[INPUT][1];
    980     CvMat F = test_mat[TEMP][0], mask = test_mat[TEMP][1];
    981     f_result = cvFindFundamentalMat( &_input0, &_input1, &F, method, MAX(sigma*3, 0.01), 0, &mask );
    982 }
    983 
    984 
    985 void CV_FundamentalMatTest::prepare_to_validation( int test_case_idx )
    986 {
    987     const Mat& Rt = test_mat[INPUT][3];
    988     const Mat& A1 = test_mat[INPUT][4];
    989     const Mat& A2 = test_mat[INPUT][5];
    990     double f0[9], f[9];
    991     Mat F0(3, 3, CV_64FC1, f0), F(3, 3, CV_64F, f);
    992 
    993     Mat invA1, invA2, R=Rt.colRange(0, 3), T;
    994 
    995     cv::invert(A1, invA1, CV_SVD);
    996     cv::invert(A2, invA2, CV_SVD);
    997 
    998     double tx = Rt.at<double>(0, 3);
    999     double ty = Rt.at<double>(1, 3);
   1000     double tz = Rt.at<double>(2, 3);
   1001 
   1002     double _t_x[] = { 0, -tz, ty, tz, 0, -tx, -ty, tx, 0 };
   1003 
   1004     // F = (A2^-T)*[t]_x*R*(A1^-1)
   1005     cv::gemm( invA2, Mat( 3, 3, CV_64F, _t_x ), 1, Mat(), 0, T, CV_GEMM_A_T );
   1006     cv::gemm( R, invA1, 1, Mat(), 0, invA2 );
   1007     cv::gemm( T, invA2, 1, Mat(), 0, F0 );
   1008     F0 *= 1./f0[8];
   1009 
   1010     uchar* status = test_mat[TEMP][1].ptr();
   1011     double err_level = get_success_error_level( test_case_idx, OUTPUT, 1 );
   1012     uchar* mtfm1 = test_mat[REF_OUTPUT][1].ptr();
   1013     uchar* mtfm2 = test_mat[OUTPUT][1].ptr();
   1014     double* f_prop1 = test_mat[REF_OUTPUT][0].ptr<double>();
   1015     double* f_prop2 = test_mat[OUTPUT][0].ptr<double>();
   1016 
   1017     int i, pt_count = test_mat[INPUT][2].cols;
   1018     Mat p1( 1, pt_count, CV_64FC2 );
   1019     Mat p2( 1, pt_count, CV_64FC2 );
   1020 
   1021     test_convertHomogeneous( test_mat[INPUT][0], p1 );
   1022     test_convertHomogeneous( test_mat[INPUT][1], p2 );
   1023 
   1024     cvtest::convert(test_mat[TEMP][0], F, F.type());
   1025 
   1026     if( method <= CV_FM_8POINT )
   1027         memset( status, 1, pt_count );
   1028 
   1029     for( i = 0; i < pt_count; i++ )
   1030     {
   1031         double x1 = p1.at<Point2d>(i).x;
   1032         double y1 = p1.at<Point2d>(i).y;
   1033         double x2 = p2.at<Point2d>(i).x;
   1034         double y2 = p2.at<Point2d>(i).y;
   1035         double n1 = 1./sqrt(x1*x1 + y1*y1 + 1);
   1036         double n2 = 1./sqrt(x2*x2 + y2*y2 + 1);
   1037         double t0 = fabs(f0[0]*x2*x1 + f0[1]*x2*y1 + f0[2]*x2 +
   1038                    f0[3]*y2*x1 + f0[4]*y2*y1 + f0[5]*y2 +
   1039                    f0[6]*x1 + f0[7]*y1 + f0[8])*n1*n2;
   1040         double t = fabs(f[0]*x2*x1 + f[1]*x2*y1 + f[2]*x2 +
   1041                    f[3]*y2*x1 + f[4]*y2*y1 + f[5]*y2 +
   1042                    f[6]*x1 + f[7]*y1 + f[8])*n1*n2;
   1043         mtfm1[i] = 1;
   1044         mtfm2[i] = !status[i] || t0 > err_level || t < err_level;
   1045     }
   1046 
   1047     f_prop1[0] = 1;
   1048     f_prop1[1] = 1;
   1049     f_prop1[2] = 0;
   1050 
   1051     f_prop2[0] = f_result != 0;
   1052     f_prop2[1] = f[8];
   1053     f_prop2[2] = cv::determinant( F );
   1054 }
   1055 /******************************* find essential matrix ***********************************/
   1056 class CV_EssentialMatTest : public cvtest::ArrayTest
   1057 {
   1058 public:
   1059     CV_EssentialMatTest();
   1060 
   1061 protected:
   1062     int read_params( CvFileStorage* fs );
   1063     void fill_array( int test_case_idx, int i, int j, Mat& arr );
   1064     int prepare_test_case( int test_case_idx );
   1065     void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
   1066     double get_success_error_level( int test_case_idx, int i, int j );
   1067     void run_func();
   1068     void prepare_to_validation( int );
   1069 
   1070     double sampson_error(const double* f, double x1, double y1, double x2, double y2);
   1071 
   1072     int method;
   1073     int img_size;
   1074     int cube_size;
   1075     int dims;
   1076     double min_f, max_f;
   1077     double sigma;
   1078 };
   1079 
   1080 
   1081 CV_EssentialMatTest::CV_EssentialMatTest()
   1082 {
   1083     // input arrays:
   1084     //   0, 1 - arrays of 2d points that are passed to %func%.
   1085     //          Can have different data type, layout, be stored in homogeneous coordinates or not.
   1086     //   2 - array of 3d points that are projected to both view planes
   1087     //   3 - [R|t] matrix for the second view plane (for the first one it is [I|0]
   1088     //   4 - intrinsic matrix for both camera
   1089     test_array[INPUT].push_back(NULL);
   1090     test_array[INPUT].push_back(NULL);
   1091     test_array[INPUT].push_back(NULL);
   1092     test_array[INPUT].push_back(NULL);
   1093     test_array[INPUT].push_back(NULL);
   1094     test_array[TEMP].push_back(NULL);
   1095     test_array[TEMP].push_back(NULL);
   1096     test_array[TEMP].push_back(NULL);
   1097     test_array[TEMP].push_back(NULL);
   1098     test_array[TEMP].push_back(NULL);
   1099     test_array[OUTPUT].push_back(NULL); // Essential Matrix singularity
   1100     test_array[OUTPUT].push_back(NULL); // Inliers mask
   1101     test_array[OUTPUT].push_back(NULL); // Translation error
   1102     test_array[OUTPUT].push_back(NULL); // Positive depth count
   1103     test_array[REF_OUTPUT].push_back(NULL);
   1104     test_array[REF_OUTPUT].push_back(NULL);
   1105     test_array[REF_OUTPUT].push_back(NULL);
   1106     test_array[REF_OUTPUT].push_back(NULL);
   1107 
   1108     element_wise_relative_error = false;
   1109 
   1110     method = 0;
   1111     img_size = 10;
   1112     cube_size = 10;
   1113     dims = 0;
   1114     min_f = 1;
   1115     max_f = 3;
   1116     sigma = 0;
   1117 }
   1118 
   1119 
   1120 int CV_EssentialMatTest::read_params( CvFileStorage* fs )
   1121 {
   1122     int code = cvtest::ArrayTest::read_params( fs );
   1123     return code;
   1124 }
   1125 
   1126 
   1127 void CV_EssentialMatTest::get_test_array_types_and_sizes( int /*test_case_idx*/,
   1128                                                 vector<vector<Size> >& sizes, vector<vector<int> >& types )
   1129 {
   1130     RNG& rng = ts->get_rng();
   1131     int pt_depth = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;
   1132     double pt_count_exp = cvtest::randReal(rng)*6 + 1;
   1133     int pt_count = MAX(5, cvRound(exp(pt_count_exp)));
   1134 
   1135     dims = cvtest::randInt(rng) % 2 + 2;
   1136     dims = 2;
   1137     method = CV_LMEDS << (cvtest::randInt(rng) % 2);
   1138 
   1139     types[INPUT][0] = CV_MAKETYPE(pt_depth, 1);
   1140 
   1141     if( 0 && cvtest::randInt(rng) % 2 )
   1142         sizes[INPUT][0] = cvSize(pt_count, dims);
   1143     else
   1144     {
   1145         sizes[INPUT][0] = cvSize(dims, pt_count);
   1146         if( cvtest::randInt(rng) % 2 )
   1147         {
   1148             types[INPUT][0] = CV_MAKETYPE(pt_depth, dims);
   1149             if( cvtest::randInt(rng) % 2 )
   1150                 sizes[INPUT][0] = cvSize(pt_count, 1);
   1151             else
   1152                 sizes[INPUT][0] = cvSize(1, pt_count);
   1153         }
   1154     }
   1155 
   1156     sizes[INPUT][1] = sizes[INPUT][0];
   1157     types[INPUT][1] = types[INPUT][0];
   1158 
   1159     sizes[INPUT][2] = cvSize(pt_count, 1 );
   1160     types[INPUT][2] = CV_64FC3;
   1161 
   1162     sizes[INPUT][3] = cvSize(4,3);
   1163     types[INPUT][3] = CV_64FC1;
   1164 
   1165     sizes[INPUT][4] = cvSize(3,3);
   1166     types[INPUT][4] = CV_MAKETYPE(CV_64F, 1);
   1167 
   1168     sizes[TEMP][0] = cvSize(3,3);
   1169     types[TEMP][0] = CV_64FC1;
   1170     sizes[TEMP][1] = cvSize(pt_count,1);
   1171     types[TEMP][1] = CV_8UC1;
   1172     sizes[TEMP][2] = cvSize(3,3);
   1173     types[TEMP][2] = CV_64FC1;
   1174     sizes[TEMP][3] = cvSize(3, 1);
   1175     types[TEMP][3] = CV_64FC1;
   1176     sizes[TEMP][4] = cvSize(pt_count,1);
   1177     types[TEMP][4] = CV_8UC1;
   1178 
   1179     sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(3,1);
   1180     types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1;
   1181     sizes[OUTPUT][1] = sizes[REF_OUTPUT][1] = cvSize(pt_count,1);
   1182     types[OUTPUT][1] = types[REF_OUTPUT][1] = CV_8UC1;
   1183     sizes[OUTPUT][2] = sizes[REF_OUTPUT][2] = cvSize(1,1);
   1184     types[OUTPUT][2] = types[REF_OUTPUT][2] = CV_64FC1;
   1185     sizes[OUTPUT][3] = sizes[REF_OUTPUT][3] = cvSize(1,1);
   1186     types[OUTPUT][3] = types[REF_OUTPUT][3] = CV_8UC1;
   1187 
   1188 }
   1189 
   1190 
   1191 double CV_EssentialMatTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
   1192 {
   1193     return 1e-2;
   1194 }
   1195 
   1196 
   1197 void CV_EssentialMatTest::fill_array( int test_case_idx, int i, int j, Mat& arr )
   1198 {
   1199     double t[12]={0};
   1200     RNG& rng = ts->get_rng();
   1201 
   1202     if( i != INPUT )
   1203     {
   1204         cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr );
   1205         return;
   1206     }
   1207 
   1208     switch( j )
   1209     {
   1210     case 0:
   1211     case 1:
   1212         return; // fill them later in prepare_test_case
   1213     case 2:
   1214         {
   1215         double* p = arr.ptr<double>();
   1216         for( i = 0; i < arr.cols*3; i += 3 )
   1217         {
   1218             p[i] = cvtest::randReal(rng)*cube_size;
   1219             p[i+1] = cvtest::randReal(rng)*cube_size;
   1220             p[i+2] = cvtest::randReal(rng)*cube_size + cube_size;
   1221         }
   1222         }
   1223         break;
   1224     case 3:
   1225         {
   1226         double r[3];
   1227         Mat rot_vec( 3, 1, CV_64F, r );
   1228         Mat rot_mat( 3, 3, CV_64F, t, 4*sizeof(t[0]) );
   1229         r[0] = cvtest::randReal(rng)*CV_PI*2;
   1230         r[1] = cvtest::randReal(rng)*CV_PI*2;
   1231         r[2] = cvtest::randReal(rng)*CV_PI*2;
   1232 
   1233         cvtest::Rodrigues( rot_vec, rot_mat );
   1234         t[3] = cvtest::randReal(rng)*cube_size;
   1235         t[7] = cvtest::randReal(rng)*cube_size;
   1236         t[11] = cvtest::randReal(rng)*cube_size;
   1237         Mat( 3, 4, CV_64F, t ).convertTo(arr, arr.type());
   1238         }
   1239         break;
   1240     case 4:
   1241         t[0] = t[4] = cvtest::randReal(rng)*(max_f - min_f) + min_f;
   1242         t[2] = (img_size*0.5 + cvtest::randReal(rng)*4. - 2.)*t[0];
   1243         t[5] = (img_size*0.5 + cvtest::randReal(rng)*4. - 2.)*t[4];
   1244         t[8] = 1.;
   1245         Mat( 3, 3, CV_64F, t ).convertTo( arr, arr.type() );
   1246         break;
   1247     }
   1248 }
   1249 
   1250 
   1251 int CV_EssentialMatTest::prepare_test_case( int test_case_idx )
   1252 {
   1253     int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
   1254     if( code > 0 )
   1255     {
   1256         const Mat& _3d = test_mat[INPUT][2];
   1257         RNG& rng = ts->get_rng();
   1258         double Idata[] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0 };
   1259         Mat I( 3, 4, CV_64F, Idata );
   1260         int k;
   1261 
   1262         for( k = 0; k < 2; k++ )
   1263         {
   1264             const Mat& Rt = k == 0 ? I : test_mat[INPUT][3];
   1265             const Mat& A = test_mat[INPUT][4];
   1266             Mat& _2d = test_mat[INPUT][k];
   1267 
   1268             test_projectPoints( _3d, Rt, A, _2d, &rng, sigma );
   1269         }
   1270     }
   1271 
   1272     return code;
   1273 }
   1274 
   1275 
   1276 void CV_EssentialMatTest::run_func()
   1277 {
   1278     Mat _input0(test_mat[INPUT][0]), _input1(test_mat[INPUT][1]);
   1279     Mat K(test_mat[INPUT][4]);
   1280     double focal(K.at<double>(0, 0));
   1281     cv::Point2d pp(K.at<double>(0, 2), K.at<double>(1, 2));
   1282 
   1283     RNG& rng = ts->get_rng();
   1284     Mat E, mask1(test_mat[TEMP][1]);
   1285     E = cv::findEssentialMat( _input0, _input1, focal, pp, method, 0.99, MAX(sigma*3, 0.0001), mask1 );
   1286     if (E.rows > 3)
   1287     {
   1288         int count = E.rows / 3;
   1289         int row = (cvtest::randInt(rng) % count) * 3;
   1290         E = E.rowRange(row, row + 3) * 1.0;
   1291     }
   1292 
   1293     E.copyTo(test_mat[TEMP][0]);
   1294 
   1295     Mat R, t, mask2;
   1296     recoverPose( E, _input0, _input1, R, t, focal, pp, mask2 );
   1297     R.copyTo(test_mat[TEMP][2]);
   1298     t.copyTo(test_mat[TEMP][3]);
   1299     mask2.copyTo(test_mat[TEMP][4]);
   1300 }
   1301 
   1302 double CV_EssentialMatTest::sampson_error(const double * f, double x1, double y1, double x2, double y2)
   1303 {
   1304     double Fx1[3] = {
   1305         f[0] * x1 + f[1] * y1 + f[2],
   1306         f[3] * x1 + f[4] * y1 + f[5],
   1307         f[6] * x1 + f[7] * y1 + f[8]
   1308     };
   1309     double Ftx2[3] = {
   1310         f[0] * x2 + f[3] * y2 + f[6],
   1311         f[1] * x2 + f[4] * y2 + f[7],
   1312         f[2] * x2 + f[5] * y2 + f[8]
   1313     };
   1314     double x2tFx1 = Fx1[0] * x2 + Fx1[1] * y2 + Fx1[2];
   1315 
   1316     double error = x2tFx1 * x2tFx1 / (Fx1[0] * Fx1[0] + Fx1[1] * Fx1[1] + Ftx2[0] * Ftx2[0] + Ftx2[1] * Ftx2[1]);
   1317     error = sqrt(error);
   1318     return error;
   1319 
   1320 }
   1321 
   1322 void CV_EssentialMatTest::prepare_to_validation( int test_case_idx )
   1323 {
   1324     const Mat& Rt0 = test_mat[INPUT][3];
   1325     const Mat& A = test_mat[INPUT][4];
   1326     double f0[9], f[9], e[9];
   1327     Mat F0(3, 3, CV_64FC1, f0), F(3, 3, CV_64F, f);
   1328     Mat E(3, 3, CV_64F, e);
   1329 
   1330     Mat invA, R=Rt0.colRange(0, 3), T1, T2;
   1331 
   1332     cv::invert(A, invA, CV_SVD);
   1333 
   1334     double tx = Rt0.at<double>(0, 3);
   1335     double ty = Rt0.at<double>(1, 3);
   1336     double tz = Rt0.at<double>(2, 3);
   1337 
   1338     double _t_x[] = { 0, -tz, ty, tz, 0, -tx, -ty, tx, 0 };
   1339 
   1340     // F = (A2^-T)*[t]_x*R*(A1^-1)
   1341     cv::gemm( invA, Mat( 3, 3, CV_64F, _t_x ), 1, Mat(), 0, T1, CV_GEMM_A_T );
   1342     cv::gemm( R, invA, 1, Mat(), 0, T2 );
   1343     cv::gemm( T1, T2, 1, Mat(), 0, F0 );
   1344     F0 *= 1./f0[8];
   1345 
   1346     uchar* status = test_mat[TEMP][1].ptr();
   1347     double err_level = get_success_error_level( test_case_idx, OUTPUT, 1 );
   1348     uchar* mtfm1 = test_mat[REF_OUTPUT][1].ptr();
   1349     uchar* mtfm2 = test_mat[OUTPUT][1].ptr();
   1350     double* e_prop1 = test_mat[REF_OUTPUT][0].ptr<double>();
   1351     double* e_prop2 = test_mat[OUTPUT][0].ptr<double>();
   1352     Mat E_prop2 = Mat(3, 1, CV_64F, e_prop2);
   1353 
   1354     int i, pt_count = test_mat[INPUT][2].cols;
   1355     Mat p1( 1, pt_count, CV_64FC2 );
   1356     Mat p2( 1, pt_count, CV_64FC2 );
   1357 
   1358     test_convertHomogeneous( test_mat[INPUT][0], p1 );
   1359     test_convertHomogeneous( test_mat[INPUT][1], p2 );
   1360 
   1361     cvtest::convert(test_mat[TEMP][0], E, E.type());
   1362     cv::gemm( invA, E, 1, Mat(), 0, T1, CV_GEMM_A_T );
   1363     cv::gemm( T1, invA, 1, Mat(), 0, F );
   1364 
   1365     for( i = 0; i < pt_count; i++ )
   1366     {
   1367         double x1 = p1.at<Point2d>(i).x;
   1368         double y1 = p1.at<Point2d>(i).y;
   1369         double x2 = p2.at<Point2d>(i).x;
   1370         double y2 = p2.at<Point2d>(i).y;
   1371 //        double t0 = sampson_error(f0, x1, y1, x2, y2);
   1372 //        double t = sampson_error(f, x1, y1, x2, y2);
   1373         double n1 = 1./sqrt(x1*x1 + y1*y1 + 1);
   1374         double n2 = 1./sqrt(x2*x2 + y2*y2 + 1);
   1375         double t0 = fabs(f0[0]*x2*x1 + f0[1]*x2*y1 + f0[2]*x2 +
   1376                    f0[3]*y2*x1 + f0[4]*y2*y1 + f0[5]*y2 +
   1377                    f0[6]*x1 + f0[7]*y1 + f0[8])*n1*n2;
   1378         double t = fabs(f[0]*x2*x1 + f[1]*x2*y1 + f[2]*x2 +
   1379                    f[3]*y2*x1 + f[4]*y2*y1 + f[5]*y2 +
   1380                    f[6]*x1 + f[7]*y1 + f[8])*n1*n2;
   1381         mtfm1[i] = 1;
   1382         mtfm2[i] = !status[i] || t0 > err_level || t < err_level;
   1383     }
   1384 
   1385     e_prop1[0] = sqrt(0.5);
   1386     e_prop1[1] = sqrt(0.5);
   1387     e_prop1[2] = 0;
   1388 
   1389     e_prop2[0] = 0;
   1390     e_prop2[1] = 0;
   1391     e_prop2[2] = 0;
   1392     SVD::compute(E, E_prop2);
   1393 
   1394 
   1395 
   1396     double* pose_prop1 = test_mat[REF_OUTPUT][2].ptr<double>();
   1397     double* pose_prop2 = test_mat[OUTPUT][2].ptr<double>();
   1398     double terr1 = cvtest::norm(Rt0.col(3) / norm(Rt0.col(3)) + test_mat[TEMP][3], NORM_L2);
   1399     double terr2 = cvtest::norm(Rt0.col(3) / norm(Rt0.col(3)) - test_mat[TEMP][3], NORM_L2);
   1400     Mat rvec;
   1401     Rodrigues(Rt0.colRange(0, 3), rvec);
   1402     pose_prop1[0] = 0;
   1403     // No check for CV_LMeDS on translation. Since it
   1404     // involves with some degraded problem, when data is exact inliers.
   1405     pose_prop2[0] = method == CV_LMEDS || pt_count == 5 ? 0 : MIN(terr1, terr2);
   1406 
   1407 
   1408 //    int inliers_count = countNonZero(test_mat[TEMP][1]);
   1409 //    int good_count = countNonZero(test_mat[TEMP][4]);
   1410     test_mat[OUTPUT][3] = true; //good_count >= inliers_count / 2;
   1411     test_mat[REF_OUTPUT][3] = true;
   1412 
   1413 
   1414 }
   1415 
   1416 
   1417 /********************************** convert homogeneous *********************************/
   1418 
   1419 class CV_ConvertHomogeneousTest : public cvtest::ArrayTest
   1420 {
   1421 public:
   1422     CV_ConvertHomogeneousTest();
   1423 
   1424 protected:
   1425     int read_params( CvFileStorage* fs );
   1426     void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
   1427     void fill_array( int test_case_idx, int i, int j, Mat& arr );
   1428     double get_success_error_level( int test_case_idx, int i, int j );
   1429     void run_func();
   1430     void prepare_to_validation( int );
   1431 
   1432     int dims1, dims2;
   1433     int pt_count;
   1434 };
   1435 
   1436 
   1437 CV_ConvertHomogeneousTest::CV_ConvertHomogeneousTest()
   1438 {
   1439     test_array[INPUT].push_back(NULL);
   1440     test_array[OUTPUT].push_back(NULL);
   1441     test_array[REF_OUTPUT].push_back(NULL);
   1442     element_wise_relative_error = false;
   1443 
   1444     pt_count = dims1 = dims2 = 0;
   1445 }
   1446 
   1447 
   1448 int CV_ConvertHomogeneousTest::read_params( CvFileStorage* fs )
   1449 {
   1450     int code = cvtest::ArrayTest::read_params( fs );
   1451     return code;
   1452 }
   1453 
   1454 
   1455 void CV_ConvertHomogeneousTest::get_test_array_types_and_sizes( int /*test_case_idx*/,
   1456                                                 vector<vector<Size> >& sizes, vector<vector<int> >& types )
   1457 {
   1458     RNG& rng = ts->get_rng();
   1459     int pt_depth1 = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;
   1460     int pt_depth2 = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;
   1461     double pt_count_exp = cvtest::randReal(rng)*6 + 1;
   1462     int t;
   1463 
   1464     pt_count = cvRound(exp(pt_count_exp));
   1465     pt_count = MAX( pt_count, 5 );
   1466 
   1467     dims1 = 2 + (cvtest::randInt(rng) % 3);
   1468     dims2 = 2 + (cvtest::randInt(rng) % 3);
   1469 
   1470     if( dims1 == dims2 + 2 )
   1471         dims1--;
   1472     else if( dims1 == dims2 - 2 )
   1473         dims1++;
   1474 
   1475     if( cvtest::randInt(rng) % 2 )
   1476         CV_SWAP( dims1, dims2, t );
   1477 
   1478     types[INPUT][0] = CV_MAKETYPE(pt_depth1, 1);
   1479 
   1480     if( cvtest::randInt(rng) % 2 )
   1481         sizes[INPUT][0] = cvSize(pt_count, dims1);
   1482     else
   1483     {
   1484         sizes[INPUT][0] = cvSize(dims1, pt_count);
   1485         if( cvtest::randInt(rng) % 2 )
   1486         {
   1487             types[INPUT][0] = CV_MAKETYPE(pt_depth1, dims1);
   1488             if( cvtest::randInt(rng) % 2 )
   1489                 sizes[INPUT][0] = cvSize(pt_count, 1);
   1490             else
   1491                 sizes[INPUT][0] = cvSize(1, pt_count);
   1492         }
   1493     }
   1494 
   1495     types[OUTPUT][0] = CV_MAKETYPE(pt_depth2, 1);
   1496 
   1497     if( cvtest::randInt(rng) % 2 )
   1498         sizes[OUTPUT][0] = cvSize(pt_count, dims2);
   1499     else
   1500     {
   1501         sizes[OUTPUT][0] = cvSize(dims2, pt_count);
   1502         if( cvtest::randInt(rng) % 2 )
   1503         {
   1504             types[OUTPUT][0] = CV_MAKETYPE(pt_depth2, dims2);
   1505             if( cvtest::randInt(rng) % 2 )
   1506                 sizes[OUTPUT][0] = cvSize(pt_count, 1);
   1507             else
   1508                 sizes[OUTPUT][0] = cvSize(1, pt_count);
   1509         }
   1510     }
   1511 
   1512     types[REF_OUTPUT][0] = types[OUTPUT][0];
   1513     sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
   1514 }
   1515 
   1516 
   1517 double CV_ConvertHomogeneousTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
   1518 {
   1519     return 1e-5;
   1520 }
   1521 
   1522 
   1523 void CV_ConvertHomogeneousTest::fill_array( int /*test_case_idx*/, int /*i*/, int /*j*/, Mat& arr )
   1524 {
   1525     Mat temp( 1, pt_count, CV_MAKETYPE(CV_64FC1,dims1) );
   1526     RNG& rng = ts->get_rng();
   1527     CvScalar low = cvScalarAll(0), high = cvScalarAll(10);
   1528 
   1529     if( dims1 > dims2 )
   1530         low.val[dims1-1] = 1.;
   1531 
   1532     cvtest::randUni( rng, temp, low, high );
   1533     test_convertHomogeneous( temp, arr );
   1534 }
   1535 
   1536 
   1537 void CV_ConvertHomogeneousTest::run_func()
   1538 {
   1539     CvMat _input = test_mat[INPUT][0], _output = test_mat[OUTPUT][0];
   1540     cvConvertPointsHomogeneous( &_input, &_output );
   1541 }
   1542 
   1543 
   1544 void CV_ConvertHomogeneousTest::prepare_to_validation( int /*test_case_idx*/ )
   1545 {
   1546     test_convertHomogeneous( test_mat[INPUT][0], test_mat[REF_OUTPUT][0] );
   1547 }
   1548 
   1549 
   1550 /************************** compute corresponding epipolar lines ************************/
   1551 
   1552 class CV_ComputeEpilinesTest : public cvtest::ArrayTest
   1553 {
   1554 public:
   1555     CV_ComputeEpilinesTest();
   1556 
   1557 protected:
   1558     int read_params( CvFileStorage* fs );
   1559     void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
   1560     void fill_array( int test_case_idx, int i, int j, Mat& arr );
   1561     double get_success_error_level( int test_case_idx, int i, int j );
   1562     void run_func();
   1563     void prepare_to_validation( int );
   1564 
   1565     int which_image;
   1566     int dims;
   1567     int pt_count;
   1568 };
   1569 
   1570 
   1571 CV_ComputeEpilinesTest::CV_ComputeEpilinesTest()
   1572 {
   1573     test_array[INPUT].push_back(NULL);
   1574     test_array[INPUT].push_back(NULL);
   1575     test_array[OUTPUT].push_back(NULL);
   1576     test_array[REF_OUTPUT].push_back(NULL);
   1577     element_wise_relative_error = false;
   1578 
   1579     pt_count = dims = which_image = 0;
   1580 }
   1581 
   1582 
   1583 int CV_ComputeEpilinesTest::read_params( CvFileStorage* fs )
   1584 {
   1585     int code = cvtest::ArrayTest::read_params( fs );
   1586     return code;
   1587 }
   1588 
   1589 
   1590 void CV_ComputeEpilinesTest::get_test_array_types_and_sizes( int /*test_case_idx*/,
   1591                                                 vector<vector<Size> >& sizes, vector<vector<int> >& types )
   1592 {
   1593     RNG& rng = ts->get_rng();
   1594     int fm_depth = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;
   1595     int pt_depth = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;
   1596     int ln_depth = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;
   1597     double pt_count_exp = cvtest::randReal(rng)*6;
   1598 
   1599     which_image = 1 + (cvtest::randInt(rng) % 2);
   1600 
   1601     pt_count = cvRound(exp(pt_count_exp));
   1602     pt_count = MAX( pt_count, 1 );
   1603     bool few_points = pt_count < 5;
   1604 
   1605     dims = 2 + (cvtest::randInt(rng) % 2);
   1606 
   1607     types[INPUT][0] = CV_MAKETYPE(pt_depth, 1);
   1608 
   1609     if( cvtest::randInt(rng) % 2 && !few_points )
   1610         sizes[INPUT][0] = cvSize(pt_count, dims);
   1611     else
   1612     {
   1613         sizes[INPUT][0] = cvSize(dims, pt_count);
   1614         if( cvtest::randInt(rng) % 2 || few_points )
   1615         {
   1616             types[INPUT][0] = CV_MAKETYPE(pt_depth, dims);
   1617             if( cvtest::randInt(rng) % 2 )
   1618                 sizes[INPUT][0] = cvSize(pt_count, 1);
   1619             else
   1620                 sizes[INPUT][0] = cvSize(1, pt_count);
   1621         }
   1622     }
   1623 
   1624     types[INPUT][1] = CV_MAKETYPE(fm_depth, 1);
   1625     sizes[INPUT][1] = cvSize(3, 3);
   1626 
   1627     types[OUTPUT][0] = CV_MAKETYPE(ln_depth, 1);
   1628 
   1629     if( cvtest::randInt(rng) % 2 && !few_points )
   1630         sizes[OUTPUT][0] = cvSize(pt_count, 3);
   1631     else
   1632     {
   1633         sizes[OUTPUT][0] = cvSize(3, pt_count);
   1634         if( cvtest::randInt(rng) % 2 || few_points )
   1635         {
   1636             types[OUTPUT][0] = CV_MAKETYPE(ln_depth, 3);
   1637             if( cvtest::randInt(rng) % 2 )
   1638                 sizes[OUTPUT][0] = cvSize(pt_count, 1);
   1639             else
   1640                 sizes[OUTPUT][0] = cvSize(1, pt_count);
   1641         }
   1642     }
   1643 
   1644     types[REF_OUTPUT][0] = types[OUTPUT][0];
   1645     sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
   1646 }
   1647 
   1648 
   1649 double CV_ComputeEpilinesTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
   1650 {
   1651     return 1e-5;
   1652 }
   1653 
   1654 
   1655 void CV_ComputeEpilinesTest::fill_array( int test_case_idx, int i, int j, Mat& arr )
   1656 {
   1657     RNG& rng = ts->get_rng();
   1658 
   1659     if( i == INPUT && j == 0 )
   1660     {
   1661         Mat temp( 1, pt_count, CV_MAKETYPE(CV_64FC1,dims) );
   1662         cvtest::randUni( rng, temp, cvScalar(0,0,1), cvScalarAll(10) );
   1663         test_convertHomogeneous( temp, arr );
   1664     }
   1665     else if( i == INPUT && j == 1 )
   1666         cvtest::randUni( rng, arr, cvScalarAll(0), cvScalarAll(10) );
   1667     else
   1668         cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr );
   1669 }
   1670 
   1671 
   1672 void CV_ComputeEpilinesTest::run_func()
   1673 {
   1674     CvMat _points = test_mat[INPUT][0], _F = test_mat[INPUT][1], _lines = test_mat[OUTPUT][0];
   1675     cvComputeCorrespondEpilines( &_points, which_image, &_F, &_lines );
   1676 }
   1677 
   1678 
   1679 void CV_ComputeEpilinesTest::prepare_to_validation( int /*test_case_idx*/ )
   1680 {
   1681     Mat pt( 1, pt_count, CV_MAKETYPE(CV_64F, 3) );
   1682     Mat lines( 1, pt_count, CV_MAKETYPE(CV_64F, 3) );
   1683     double f[9];
   1684     Mat F( 3, 3, CV_64F, f );
   1685 
   1686     test_convertHomogeneous( test_mat[INPUT][0], pt );
   1687     test_mat[INPUT][1].convertTo(F, CV_64F);
   1688     if( which_image == 2 )
   1689         cv::transpose( F, F );
   1690 
   1691     for( int i = 0; i < pt_count; i++ )
   1692     {
   1693         double* p = pt.ptr<double>() + i*3;
   1694         double* l = lines.ptr<double>() + i*3;
   1695         double t0 = f[0]*p[0] + f[1]*p[1] + f[2]*p[2];
   1696         double t1 = f[3]*p[0] + f[4]*p[1] + f[5]*p[2];
   1697         double t2 = f[6]*p[0] + f[7]*p[1] + f[8]*p[2];
   1698         double d = sqrt(t0*t0 + t1*t1);
   1699         d = d ? 1./d : 1.;
   1700         l[0] = t0*d; l[1] = t1*d; l[2] = t2*d;
   1701     }
   1702 
   1703     test_convertHomogeneous( lines, test_mat[REF_OUTPUT][0] );
   1704 }
   1705 
   1706 TEST(Calib3d_Rodrigues, accuracy) { CV_RodriguesTest test; test.safe_run(); }
   1707 TEST(Calib3d_FindFundamentalMat, accuracy) { CV_FundamentalMatTest test; test.safe_run(); }
   1708 TEST(Calib3d_ConvertHomogeneoous, accuracy) { CV_ConvertHomogeneousTest test; test.safe_run(); }
   1709 TEST(Calib3d_ComputeEpilines, accuracy) { CV_ComputeEpilinesTest test; test.safe_run(); }
   1710 TEST(Calib3d_FindEssentialMat, accuracy) { CV_EssentialMatTest test; test.safe_run(); }
   1711 
   1712 TEST(Calib3d_FindFundamentalMat, correctMatches)
   1713 {
   1714     double fdata[] = {0, 0, 0, 0, 0, -1, 0, 1, 0};
   1715     double p1data[] = {200, 0, 1};
   1716     double p2data[] = {170, 0, 1};
   1717 
   1718     Mat F(3, 3, CV_64F, fdata);
   1719     Mat p1(1, 1, CV_64FC2, p1data);
   1720     Mat p2(1, 1, CV_64FC2, p2data);
   1721     Mat np1, np2;
   1722 
   1723     correctMatches(F, p1, p2, np1, np2);
   1724 
   1725     cout << np1 << endl;
   1726     cout << np2 << endl;
   1727 }
   1728 
   1729 /* End of file. */
   1730