Path: blob/master/modules/calib3d/test/test_fundam.cpp
16337 views
/*M///////////////////////////////////////////////////////////////////////////////////////1//2// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.3//4// By downloading, copying, installing or using the software you agree to this license.5// If you do not agree to this license, do not download, install,6// copy or use the software.7//8//9// Intel License Agreement10// For Open Source Computer Vision Library11//12// Copyright (C) 2000, Intel Corporation, all rights reserved.13// Third party copyrights are property of their respective owners.14//15// Redistribution and use in source and binary forms, with or without modification,16// are permitted provided that the following conditions are met:17//18// * Redistribution's of source code must retain the above copyright notice,19// this list of conditions and the following disclaimer.20//21// * Redistribution's in binary form must reproduce the above copyright notice,22// this list of conditions and the following disclaimer in the documentation23// and/or other materials provided with the distribution.24//25// * The name of Intel Corporation may not be used to endorse or promote products26// derived from this software without specific prior written permission.27//28// This software is provided by the copyright holders and contributors "as is" and29// any express or implied warranties, including, but not limited to, the implied30// warranties of merchantability and fitness for a particular purpose are disclaimed.31// In no event shall the Intel Corporation or contributors be liable for any direct,32// indirect, incidental, special, exemplary, or consequential damages33// (including, but not limited to, procurement of substitute goods or services;34// loss of use, data, or profits; or business interruption) however caused35// and on any theory of liability, whether in contract, strict liability,36// or tort (including negligence or otherwise) arising in any way out of37// the use of this software, even if advised of the possibility of such damage.38//39//M*/4041#include "test_precomp.hpp"42#include "opencv2/calib3d/calib3d_c.h"4344namespace cvtest {4546static int cvTsRodrigues( const CvMat* src, CvMat* dst, CvMat* jacobian )47{48int depth;49int i;50float Jf[27];51double J[27];52CvMat _Jf, matJ = cvMat( 3, 9, CV_64F, J );5354depth = CV_MAT_DEPTH(src->type);5556if( jacobian )57{58assert( (jacobian->rows == 9 && jacobian->cols == 3) ||59(jacobian->rows == 3 && jacobian->cols == 9) );60}6162if( src->cols == 1 || src->rows == 1 )63{64double r[3], theta;65CvMat _r = cvMat( src->rows, src->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(src->type)), r);6667assert( dst->rows == 3 && dst->cols == 3 );6869cvConvert( src, &_r );7071theta = sqrt(r[0]*r[0] + r[1]*r[1] + r[2]*r[2]);72if( theta < DBL_EPSILON )73{74cvSetIdentity( dst );7576if( jacobian )77{78memset( J, 0, sizeof(J) );79J[5] = J[15] = J[19] = 1;80J[7] = J[11] = J[21] = -1;81}82}83else84{85// omega = r/theta (~[w1, w2, w3])86double itheta = 1./theta;87double w1 = r[0]*itheta, w2 = r[1]*itheta, w3 = r[2]*itheta;88double alpha = cos(theta);89double beta = sin(theta);90double gamma = 1 - alpha;91double omegav[] =92{930, -w3, w2,94w3, 0, -w1,95-w2, w1, 096};97double A[] =98{99w1*w1, w1*w2, w1*w3,100w2*w1, w2*w2, w2*w3,101w3*w1, w3*w2, w3*w3102};103double R[9];104CvMat _omegav = cvMat(3, 3, CV_64F, omegav);105CvMat matA = cvMat(3, 3, CV_64F, A);106CvMat matR = cvMat(3, 3, CV_64F, R);107108cvSetIdentity( &matR, cvRealScalar(alpha) );109cvScaleAdd( &_omegav, cvRealScalar(beta), &matR, &matR );110cvScaleAdd( &matA, cvRealScalar(gamma), &matR, &matR );111cvConvert( &matR, dst );112113if( jacobian )114{115// m3 = [r, theta]116double dm3din[] =117{1181, 0, 0,1190, 1, 0,1200, 0, 1,121w1, w2, w3122};123// m2 = [omega, theta]124double dm2dm3[] =125{126itheta, 0, 0, -w1*itheta,1270, itheta, 0, -w2*itheta,1280, 0, itheta, -w3*itheta,1290, 0, 0, 1130};131double t0[9*4];132double dm1dm2[21*4];133double dRdm1[9*21];134CvMat _dm3din = cvMat( 4, 3, CV_64FC1, dm3din );135CvMat _dm2dm3 = cvMat( 4, 4, CV_64FC1, dm2dm3 );136CvMat _dm1dm2 = cvMat( 21, 4, CV_64FC1, dm1dm2 );137CvMat _dRdm1 = cvMat( 9, 21, CV_64FC1, dRdm1 );138CvMat _dRdm1_part;139CvMat _t0 = cvMat( 9, 4, CV_64FC1, t0 );140CvMat _t1 = cvMat( 9, 4, CV_64FC1, dRdm1 );141142// m1 = [alpha, beta, gamma, omegav; A]143memset( dm1dm2, 0, sizeof(dm1dm2) );144dm1dm2[3] = -beta;145dm1dm2[7] = alpha;146dm1dm2[11] = beta;147148// dm1dm2(4:12,1:3) = [0 0 0 0 0 1 0 -1 0;149// 0 0 -1 0 0 0 1 0 0;150// 0 1 0 -1 0 0 0 0 0]'151// -------------------152// 0 0 0 0 0 0 0 0 0153dm1dm2[12 + 6] = dm1dm2[12 + 20] = dm1dm2[12 + 25] = 1;154dm1dm2[12 + 9] = dm1dm2[12 + 14] = dm1dm2[12 + 28] = -1;155156double dm1dw[] =157{1582*w1, w2, w3, w2, 0, 0, w3, 0, 0,1590, w1, 0, w1, 2*w2, w3, 0, w3, 0,1600, 0, w1, 0, 0, w2, w1, w2, 2*w3161};162163CvMat _dm1dw = cvMat( 3, 9, CV_64FC1, dm1dw );164CvMat _dm1dm2_part;165166cvGetSubRect( &_dm1dm2, &_dm1dm2_part, cvRect(0,12,3,9) );167cvTranspose( &_dm1dw, &_dm1dm2_part );168169memset( dRdm1, 0, sizeof(dRdm1) );170dRdm1[0*21] = dRdm1[4*21] = dRdm1[8*21] = 1;171172cvGetCol( &_dRdm1, &_dRdm1_part, 1 );173cvTranspose( &_omegav, &_omegav );174cvReshape( &_omegav, &_omegav, 1, 1 );175cvTranspose( &_omegav, &_dRdm1_part );176177cvGetCol( &_dRdm1, &_dRdm1_part, 2 );178cvReshape( &matA, &matA, 1, 1 );179cvTranspose( &matA, &_dRdm1_part );180181cvGetSubRect( &_dRdm1, &_dRdm1_part, cvRect(3,0,9,9) );182cvSetIdentity( &_dRdm1_part, cvScalarAll(beta) );183184cvGetSubRect( &_dRdm1, &_dRdm1_part, cvRect(12,0,9,9) );185cvSetIdentity( &_dRdm1_part, cvScalarAll(gamma) );186187matJ = cvMat( 9, 3, CV_64FC1, J );188189cvMatMul( &_dRdm1, &_dm1dm2, &_t0 );190cvMatMul( &_t0, &_dm2dm3, &_t1 );191cvMatMul( &_t1, &_dm3din, &matJ );192193_t0 = cvMat( 3, 9, CV_64FC1, t0 );194cvTranspose( &matJ, &_t0 );195196for( i = 0; i < 3; i++ )197{198_t1 = cvMat( 3, 3, CV_64FC1, t0 + i*9 );199cvTranspose( &_t1, &_t1 );200}201202cvTranspose( &_t0, &matJ );203}204}205}206else if( src->cols == 3 && src->rows == 3 )207{208double R[9], A[9], I[9], r[3], W[3], U[9], V[9];209double tr, alpha, beta, theta;210CvMat matR = cvMat( 3, 3, CV_64F, R );211CvMat matA = cvMat( 3, 3, CV_64F, A );212CvMat matI = cvMat( 3, 3, CV_64F, I );213CvMat _r = cvMat( dst->rows, dst->cols, CV_MAKETYPE(CV_64F, CV_MAT_CN(dst->type)), r );214CvMat matW = cvMat( 1, 3, CV_64F, W );215CvMat matU = cvMat( 3, 3, CV_64F, U );216CvMat matV = cvMat( 3, 3, CV_64F, V );217218cvConvert( src, &matR );219cvSVD( &matR, &matW, &matU, &matV, CV_SVD_MODIFY_A + CV_SVD_U_T + CV_SVD_V_T );220cvGEMM( &matU, &matV, 1, 0, 0, &matR, CV_GEMM_A_T );221222cvMulTransposed( &matR, &matA, 0 );223cvSetIdentity( &matI );224225if( cvNorm( &matA, &matI, CV_C ) > 1e-3 ||226fabs( cvDet(&matR) - 1 ) > 1e-3 )227return 0;228229tr = (cvTrace(&matR).val[0] - 1.)*0.5;230tr = tr > 1. ? 1. : tr < -1. ? -1. : tr;231theta = acos(tr);232alpha = cos(theta);233beta = sin(theta);234235if( beta >= 1e-5 )236{237double dtheta_dtr = -1./sqrt(1 - tr*tr);238double vth = 1/(2*beta);239240// om1 = [R(3,2) - R(2,3), R(1,3) - R(3,1), R(2,1) - R(1,2)]'241double om1[] = { R[7] - R[5], R[2] - R[6], R[3] - R[1] };242// om = om1*vth243// r = om*theta244double d3 = vth*theta;245246r[0] = om1[0]*d3; r[1] = om1[1]*d3; r[2] = om1[2]*d3;247cvConvert( &_r, dst );248249if( jacobian )250{251// var1 = [vth;theta]252// var = [om1;var1] = [om1;vth;theta]253double dvth_dtheta = -vth*alpha/beta;254double d1 = 0.5*dvth_dtheta*dtheta_dtr;255double d2 = 0.5*dtheta_dtr;256// dvar1/dR = dvar1/dtheta*dtheta/dR = [dvth/dtheta; 1] * dtheta/dtr * dtr/dR257double dvardR[5*9] =258{2590, 0, 0, 0, 0, 1, 0, -1, 0,2600, 0, -1, 0, 0, 0, 1, 0, 0,2610, 1, 0, -1, 0, 0, 0, 0, 0,262d1, 0, 0, 0, d1, 0, 0, 0, d1,263d2, 0, 0, 0, d2, 0, 0, 0, d2264};265// var2 = [om;theta]266double dvar2dvar[] =267{268vth, 0, 0, om1[0], 0,2690, vth, 0, om1[1], 0,2700, 0, vth, om1[2], 0,2710, 0, 0, 0, 1272};273double domegadvar2[] =274{275theta, 0, 0, om1[0]*vth,2760, theta, 0, om1[1]*vth,2770, 0, theta, om1[2]*vth278};279280CvMat _dvardR = cvMat( 5, 9, CV_64FC1, dvardR );281CvMat _dvar2dvar = cvMat( 4, 5, CV_64FC1, dvar2dvar );282CvMat _domegadvar2 = cvMat( 3, 4, CV_64FC1, domegadvar2 );283double t0[3*5];284CvMat _t0 = cvMat( 3, 5, CV_64FC1, t0 );285286cvMatMul( &_domegadvar2, &_dvar2dvar, &_t0 );287cvMatMul( &_t0, &_dvardR, &matJ );288}289}290else if( tr > 0 )291{292cvZero( dst );293if( jacobian )294{295memset( J, 0, sizeof(J) );296J[5] = J[15] = J[19] = 0.5;297J[7] = J[11] = J[21] = -0.5;298}299}300else301{302r[0] = theta*sqrt((R[0] + 1)*0.5);303r[1] = theta*sqrt((R[4] + 1)*0.5)*(R[1] >= 0 ? 1 : -1);304r[2] = theta*sqrt((R[8] + 1)*0.5)*(R[2] >= 0 ? 1 : -1);305cvConvert( &_r, dst );306307if( jacobian )308memset( J, 0, sizeof(J) );309}310311if( jacobian )312{313for( i = 0; i < 3; i++ )314{315CvMat t = cvMat( 3, 3, CV_64F, J + i*9 );316cvTranspose( &t, &t );317}318}319}320else321{322assert(0);323return 0;324}325326if( jacobian )327{328if( depth == CV_32F )329{330if( jacobian->rows == matJ.rows )331cvConvert( &matJ, jacobian );332else333{334_Jf = cvMat( matJ.rows, matJ.cols, CV_32FC1, Jf );335cvConvert( &matJ, &_Jf );336cvTranspose( &_Jf, jacobian );337}338}339else if( jacobian->rows == matJ.rows )340cvCopy( &matJ, jacobian );341else342cvTranspose( &matJ, jacobian );343}344345return 1;346}347348349/*extern*/ void Rodrigues(const Mat& src, Mat& dst, Mat* jac)350{351CV_Assert(src.data != dst.data && "Inplace is not supported");352CV_Assert(!dst.empty() && "'dst' must be allocated");353CvMat _src = cvMat(src), _dst = cvMat(dst), _jac;354if( jac )355_jac = cvMat(*jac);356cvTsRodrigues(&_src, &_dst, jac ? &_jac : 0);357}358359} // namespace360namespace opencv_test {361362static void test_convertHomogeneous( const Mat& _src, Mat& _dst )363{364Mat src = _src, dst = _dst;365int i, count, sdims, ddims;366int sstep1, sstep2, dstep1, dstep2;367368if( src.depth() != CV_64F )369_src.convertTo(src, CV_64F);370371if( dst.depth() != CV_64F )372dst.create(dst.size(), CV_MAKETYPE(CV_64F, _dst.channels()));373374if( src.rows > src.cols )375{376count = src.rows;377sdims = src.channels()*src.cols;378sstep1 = (int)(src.step/sizeof(double));379sstep2 = 1;380}381else382{383count = src.cols;384sdims = src.channels()*src.rows;385if( src.rows == 1 )386{387sstep1 = sdims;388sstep2 = 1;389}390else391{392sstep1 = 1;393sstep2 = (int)(src.step/sizeof(double));394}395}396397if( dst.rows > dst.cols )398{399CV_Assert( count == dst.rows );400ddims = dst.channels()*dst.cols;401dstep1 = (int)(dst.step/sizeof(double));402dstep2 = 1;403}404else405{406assert( count == dst.cols );407ddims = dst.channels()*dst.rows;408if( dst.rows == 1 )409{410dstep1 = ddims;411dstep2 = 1;412}413else414{415dstep1 = 1;416dstep2 = (int)(dst.step/sizeof(double));417}418}419420double* s = src.ptr<double>();421double* d = dst.ptr<double>();422423if( sdims <= ddims )424{425int wstep = dstep2*(ddims - 1);426427for( i = 0; i < count; i++, s += sstep1, d += dstep1 )428{429double x = s[0];430double y = s[sstep2];431432d[wstep] = 1;433d[0] = x;434d[dstep2] = y;435436if( sdims >= 3 )437{438d[dstep2*2] = s[sstep2*2];439if( sdims == 4 )440d[dstep2*3] = s[sstep2*3];441}442}443}444else445{446int wstep = sstep2*(sdims - 1);447448for( i = 0; i < count; i++, s += sstep1, d += dstep1 )449{450double w = s[wstep];451double x = s[0];452double y = s[sstep2];453454w = w ? 1./w : 1;455456d[0] = x*w;457d[dstep2] = y*w;458459if( ddims == 3 )460d[dstep2*2] = s[sstep2*2]*w;461}462}463464if( dst.data != _dst.data )465dst.convertTo(_dst, _dst.depth());466}467468namespace {469470void471test_projectPoints( const Mat& _3d, const Mat& Rt, const Mat& A, Mat& _2d, RNG* rng, double sigma )472{473CV_Assert( _3d.isContinuous() );474475double p[12];476Mat P( 3, 4, CV_64F, p );477gemm(A, Rt, 1, Mat(), 0, P);478479int i, count = _3d.cols;480481Mat noise;482if( rng )483{484if( sigma == 0 )485rng = 0;486else487{488noise.create( 1, _3d.cols, CV_64FC2 );489rng->fill(noise, RNG::NORMAL, Scalar::all(0), Scalar::all(sigma) );490}491}492493Mat temp( 1, count, CV_64FC3 );494495for( i = 0; i < count; i++ )496{497const double* M = _3d.ptr<double>() + i*3;498double* m = temp.ptr<double>() + i*3;499double X = M[0], Y = M[1], Z = M[2];500double u = p[0]*X + p[1]*Y + p[2]*Z + p[3];501double v = p[4]*X + p[5]*Y + p[6]*Z + p[7];502double s = p[8]*X + p[9]*Y + p[10]*Z + p[11];503504if( !noise.empty() )505{506u += noise.at<Point2d>(i).x*s;507v += noise.at<Point2d>(i).y*s;508}509510m[0] = u;511m[1] = v;512m[2] = s;513}514515test_convertHomogeneous( temp, _2d );516}517518519/********************************** Rodrigues transform ********************************/520521class CV_RodriguesTest : public cvtest::ArrayTest522{523public:524CV_RodriguesTest();525526protected:527int read_params( CvFileStorage* fs );528void fill_array( int test_case_idx, int i, int j, Mat& arr );529int prepare_test_case( int test_case_idx );530void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );531double get_success_error_level( int test_case_idx, int i, int j );532void run_func();533void prepare_to_validation( int );534535bool calc_jacobians;536bool test_cpp;537};538539540CV_RodriguesTest::CV_RodriguesTest()541{542test_array[INPUT].push_back(NULL); // rotation vector543test_array[OUTPUT].push_back(NULL); // rotation matrix544test_array[OUTPUT].push_back(NULL); // jacobian (J)545test_array[OUTPUT].push_back(NULL); // rotation vector (backward transform result)546test_array[OUTPUT].push_back(NULL); // inverse transform jacobian (J1)547test_array[OUTPUT].push_back(NULL); // J*J1 (or J1*J) == I(3x3)548test_array[REF_OUTPUT].push_back(NULL);549test_array[REF_OUTPUT].push_back(NULL);550test_array[REF_OUTPUT].push_back(NULL);551test_array[REF_OUTPUT].push_back(NULL);552test_array[REF_OUTPUT].push_back(NULL);553554element_wise_relative_error = false;555calc_jacobians = false;556557test_cpp = false;558}559560561int CV_RodriguesTest::read_params( CvFileStorage* fs )562{563int code = cvtest::ArrayTest::read_params( fs );564return code;565}566567568void CV_RodriguesTest::get_test_array_types_and_sizes(569int /*test_case_idx*/, vector<vector<Size> >& sizes, vector<vector<int> >& types )570{571RNG& rng = ts->get_rng();572int depth = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;573int i, code;574575code = cvtest::randInt(rng) % 3;576types[INPUT][0] = CV_MAKETYPE(depth, 1);577578if( code == 0 )579{580sizes[INPUT][0] = cvSize(1,1);581types[INPUT][0] = CV_MAKETYPE(depth, 3);582}583else if( code == 1 )584sizes[INPUT][0] = cvSize(3,1);585else586sizes[INPUT][0] = cvSize(1,3);587588sizes[OUTPUT][0] = cvSize(3, 3);589types[OUTPUT][0] = CV_MAKETYPE(depth, 1);590591types[OUTPUT][1] = CV_MAKETYPE(depth, 1);592593if( cvtest::randInt(rng) % 2 )594sizes[OUTPUT][1] = cvSize(3,9);595else596sizes[OUTPUT][1] = cvSize(9,3);597598types[OUTPUT][2] = types[INPUT][0];599sizes[OUTPUT][2] = sizes[INPUT][0];600601types[OUTPUT][3] = types[OUTPUT][1];602sizes[OUTPUT][3] = cvSize(sizes[OUTPUT][1].height, sizes[OUTPUT][1].width);603604types[OUTPUT][4] = types[OUTPUT][1];605sizes[OUTPUT][4] = cvSize(3,3);606607calc_jacobians = cvtest::randInt(rng) % 3 != 0;608if( !calc_jacobians )609sizes[OUTPUT][1] = sizes[OUTPUT][3] = sizes[OUTPUT][4] = cvSize(0,0);610611for( i = 0; i < 5; i++ )612{613types[REF_OUTPUT][i] = types[OUTPUT][i];614sizes[REF_OUTPUT][i] = sizes[OUTPUT][i];615}616test_cpp = (cvtest::randInt(rng) & 256) == 0;617}618619620double CV_RodriguesTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int j )621{622return j == 4 ? 1e-2 : 1e-2;623}624625626void CV_RodriguesTest::fill_array( int test_case_idx, int i, int j, Mat& arr )627{628if( i == INPUT && j == 0 )629{630double r[3], theta0, theta1, f;631Mat _r( arr.rows, arr.cols, CV_MAKETYPE(CV_64F,arr.channels()), r );632RNG& rng = ts->get_rng();633634r[0] = cvtest::randReal(rng)*CV_PI*2;635r[1] = cvtest::randReal(rng)*CV_PI*2;636r[2] = cvtest::randReal(rng)*CV_PI*2;637638theta0 = sqrt(r[0]*r[0] + r[1]*r[1] + r[2]*r[2]);639theta1 = fmod(theta0, CV_PI*2);640641if( theta1 > CV_PI )642theta1 = -(CV_PI*2 - theta1);643644f = theta1/(theta0 ? theta0 : 1);645r[0] *= f;646r[1] *= f;647r[2] *= f;648649cvtest::convert( _r, arr, arr.type() );650}651else652cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr );653}654655656int CV_RodriguesTest::prepare_test_case( int test_case_idx )657{658int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );659return code;660}661662663void CV_RodriguesTest::run_func()664{665CvMat v2m_jac, m2v_jac;666667if( calc_jacobians )668{669v2m_jac = cvMat(test_mat[OUTPUT][1]);670m2v_jac = cvMat(test_mat[OUTPUT][3]);671}672673if( !test_cpp )674{675CvMat _input = cvMat(test_mat[INPUT][0]), _output = cvMat(test_mat[OUTPUT][0]), _output2 = cvMat(test_mat[OUTPUT][2]);676cvRodrigues2( &_input, &_output, calc_jacobians ? &v2m_jac : 0 );677cvRodrigues2( &_output, &_output2, calc_jacobians ? &m2v_jac : 0 );678}679else680{681cv::Mat v = test_mat[INPUT][0], M = test_mat[OUTPUT][0], v2 = test_mat[OUTPUT][2];682cv::Mat M0 = M, v2_0 = v2;683if( !calc_jacobians )684{685cv::Rodrigues(v, M);686cv::Rodrigues(M, v2);687}688else689{690cv::Mat J1 = test_mat[OUTPUT][1], J2 = test_mat[OUTPUT][3];691cv::Mat J1_0 = J1, J2_0 = J2;692cv::Rodrigues(v, M, J1);693cv::Rodrigues(M, v2, J2);694if( J1.data != J1_0.data )695{696if( J1.size() != J1_0.size() )697J1 = J1.t();698J1.convertTo(J1_0, J1_0.type());699}700if( J2.data != J2_0.data )701{702if( J2.size() != J2_0.size() )703J2 = J2.t();704J2.convertTo(J2_0, J2_0.type());705}706}707if( M.data != M0.data )708M.reshape(M0.channels(), M0.rows).convertTo(M0, M0.type());709if( v2.data != v2_0.data )710v2.reshape(v2_0.channels(), v2_0.rows).convertTo(v2_0, v2_0.type());711}712}713714715void CV_RodriguesTest::prepare_to_validation( int /*test_case_idx*/ )716{717const Mat& vec = test_mat[INPUT][0];718Mat& m = test_mat[REF_OUTPUT][0];719Mat& vec2 = test_mat[REF_OUTPUT][2];720Mat* v2m_jac = 0, *m2v_jac = 0;721double theta0, theta1;722723if( calc_jacobians )724{725v2m_jac = &test_mat[REF_OUTPUT][1];726m2v_jac = &test_mat[REF_OUTPUT][3];727}728729730cvtest::Rodrigues( vec, m, v2m_jac );731cvtest::Rodrigues( m, vec2, m2v_jac );732cvtest::copy( vec, vec2 );733734theta0 = cvtest::norm( vec2, CV_L2 );735theta1 = fmod( theta0, CV_PI*2 );736737if( theta1 > CV_PI )738theta1 = -(CV_PI*2 - theta1);739vec2 *= theta1/(theta0 ? theta0 : 1);740741if( calc_jacobians )742{743//cvInvert( v2m_jac, m2v_jac, CV_SVD );744double nrm = cvtest::norm(test_mat[REF_OUTPUT][3], CV_C);745if( FLT_EPSILON < nrm && nrm < 1000 )746{747gemm( test_mat[OUTPUT][1], test_mat[OUTPUT][3],7481, Mat(), 0, test_mat[OUTPUT][4],749v2m_jac->rows == 3 ? 0 : CV_GEMM_A_T + CV_GEMM_B_T );750}751else752{753setIdentity(test_mat[OUTPUT][4], Scalar::all(1.));754cvtest::copy( test_mat[REF_OUTPUT][2], test_mat[OUTPUT][2] );755}756setIdentity(test_mat[REF_OUTPUT][4], Scalar::all(1.));757}758}759760761/********************************** fundamental matrix *********************************/762763class CV_FundamentalMatTest : public cvtest::ArrayTest764{765public:766CV_FundamentalMatTest();767768protected:769int read_params( CvFileStorage* fs );770void fill_array( int test_case_idx, int i, int j, Mat& arr );771int prepare_test_case( int test_case_idx );772void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );773double get_success_error_level( int test_case_idx, int i, int j );774void run_func();775void prepare_to_validation( int );776777int method;778int img_size;779int cube_size;780int dims;781int f_result;782double min_f, max_f;783double sigma;784bool test_cpp;785};786787788CV_FundamentalMatTest::CV_FundamentalMatTest()789{790// input arrays:791// 0, 1 - arrays of 2d points that are passed to %func%.792// Can have different data type, layout, be stored in homogeneous coordinates or not.793// 2 - array of 3d points that are projected to both view planes794// 3 - [R|t] matrix for the second view plane (for the first one it is [I|0]795// 4, 5 - intrinsic matrices796test_array[INPUT].push_back(NULL);797test_array[INPUT].push_back(NULL);798test_array[INPUT].push_back(NULL);799test_array[INPUT].push_back(NULL);800test_array[INPUT].push_back(NULL);801test_array[INPUT].push_back(NULL);802test_array[TEMP].push_back(NULL);803test_array[TEMP].push_back(NULL);804test_array[OUTPUT].push_back(NULL);805test_array[OUTPUT].push_back(NULL);806test_array[REF_OUTPUT].push_back(NULL);807test_array[REF_OUTPUT].push_back(NULL);808809element_wise_relative_error = false;810811method = 0;812img_size = 10;813cube_size = 10;814dims = 0;815min_f = 1;816max_f = 3;817sigma = 0;//0.1;818f_result = 0;819820test_cpp = false;821}822823824int CV_FundamentalMatTest::read_params( CvFileStorage* fs )825{826int code = cvtest::ArrayTest::read_params( fs );827return code;828}829830831void CV_FundamentalMatTest::get_test_array_types_and_sizes( int /*test_case_idx*/,832vector<vector<Size> >& sizes, vector<vector<int> >& types )833{834RNG& rng = ts->get_rng();835int pt_depth = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;836double pt_count_exp = cvtest::randReal(rng)*6 + 1;837int pt_count = cvRound(exp(pt_count_exp));838839dims = cvtest::randInt(rng) % 2 + 2;840method = 1 << (cvtest::randInt(rng) % 4);841842if( method == CV_FM_7POINT )843pt_count = 7;844else845{846pt_count = MAX( pt_count, 8 + (method == CV_FM_8POINT) );847if( pt_count >= 8 && cvtest::randInt(rng) % 2 )848method |= CV_FM_8POINT;849}850851types[INPUT][0] = CV_MAKETYPE(pt_depth, 1);852853if( cvtest::randInt(rng) % 2 )854sizes[INPUT][0] = cvSize(pt_count, dims);855else856{857sizes[INPUT][0] = cvSize(dims, pt_count);858if( cvtest::randInt(rng) % 2 )859{860types[INPUT][0] = CV_MAKETYPE(pt_depth, dims);861if( cvtest::randInt(rng) % 2 )862sizes[INPUT][0] = cvSize(pt_count, 1);863else864sizes[INPUT][0] = cvSize(1, pt_count);865}866}867868sizes[INPUT][1] = sizes[INPUT][0];869types[INPUT][1] = types[INPUT][0];870871sizes[INPUT][2] = cvSize(pt_count, 1 );872types[INPUT][2] = CV_64FC3;873874sizes[INPUT][3] = cvSize(4,3);875types[INPUT][3] = CV_64FC1;876877sizes[INPUT][4] = sizes[INPUT][5] = cvSize(3,3);878types[INPUT][4] = types[INPUT][5] = CV_MAKETYPE(CV_64F, 1);879880sizes[TEMP][0] = cvSize(3,3);881types[TEMP][0] = CV_64FC1;882sizes[TEMP][1] = cvSize(pt_count,1);883types[TEMP][1] = CV_8UC1;884885sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(3,1);886types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1;887sizes[OUTPUT][1] = sizes[REF_OUTPUT][1] = cvSize(pt_count,1);888types[OUTPUT][1] = types[REF_OUTPUT][1] = CV_8UC1;889890test_cpp = (cvtest::randInt(rng) & 256) == 0;891}892893894double CV_FundamentalMatTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )895{896return 1e-2;897}898899900void CV_FundamentalMatTest::fill_array( int test_case_idx, int i, int j, Mat& arr )901{902double t[12]={0};903RNG& rng = ts->get_rng();904905if( i != INPUT )906{907cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr );908return;909}910911switch( j )912{913case 0:914case 1:915return; // fill them later in prepare_test_case916case 2:917{918double* p = arr.ptr<double>();919for( i = 0; i < arr.cols*3; i += 3 )920{921p[i] = cvtest::randReal(rng)*cube_size;922p[i+1] = cvtest::randReal(rng)*cube_size;923p[i+2] = cvtest::randReal(rng)*cube_size + cube_size;924}925}926break;927case 3:928{929double r[3];930Mat rot_vec( 3, 1, CV_64F, r );931Mat rot_mat( 3, 3, CV_64F, t, 4*sizeof(t[0]) );932r[0] = cvtest::randReal(rng)*CV_PI*2;933r[1] = cvtest::randReal(rng)*CV_PI*2;934r[2] = cvtest::randReal(rng)*CV_PI*2;935936cvtest::Rodrigues( rot_vec, rot_mat );937t[3] = cvtest::randReal(rng)*cube_size;938t[7] = cvtest::randReal(rng)*cube_size;939t[11] = cvtest::randReal(rng)*cube_size;940Mat( 3, 4, CV_64F, t ).convertTo(arr, arr.type());941}942break;943case 4:944case 5:945t[0] = t[4] = cvtest::randReal(rng)*(max_f - min_f) + min_f;946t[2] = (img_size*0.5 + cvtest::randReal(rng)*4. - 2.)*t[0];947t[5] = (img_size*0.5 + cvtest::randReal(rng)*4. - 2.)*t[4];948t[8] = 1.;949Mat( 3, 3, CV_64F, t ).convertTo( arr, arr.type() );950break;951}952}953954955int CV_FundamentalMatTest::prepare_test_case( int test_case_idx )956{957int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );958if( code > 0 )959{960const Mat& _3d = test_mat[INPUT][2];961RNG& rng = ts->get_rng();962double Idata[] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0 };963Mat I( 3, 4, CV_64F, Idata );964int k;965966for( k = 0; k < 2; k++ )967{968const Mat& Rt = k == 0 ? I : test_mat[INPUT][3];969const Mat& A = test_mat[INPUT][k == 0 ? 4 : 5];970Mat& _2d = test_mat[INPUT][k];971972test_projectPoints( _3d, Rt, A, _2d, &rng, sigma );973}974}975976return code;977}978979void CV_FundamentalMatTest::run_func()980{981// cvFindFundamentalMat calls cv::findFundamentalMat982CvMat _input0 = cvMat(test_mat[INPUT][0]), _input1 = cvMat(test_mat[INPUT][1]);983CvMat F = cvMat(test_mat[TEMP][0]), mask = cvMat(test_mat[TEMP][1]);984f_result = cvFindFundamentalMat( &_input0, &_input1, &F, method, MAX(sigma*3, 0.01), 0, &mask );985}986987988void CV_FundamentalMatTest::prepare_to_validation( int test_case_idx )989{990const Mat& Rt = test_mat[INPUT][3];991const Mat& A1 = test_mat[INPUT][4];992const Mat& A2 = test_mat[INPUT][5];993double f0[9], f[9];994Mat F0(3, 3, CV_64FC1, f0), F(3, 3, CV_64F, f);995996Mat invA1, invA2, R=Rt.colRange(0, 3), T;997998cv::invert(A1, invA1, CV_SVD);999cv::invert(A2, invA2, CV_SVD);10001001double tx = Rt.at<double>(0, 3);1002double ty = Rt.at<double>(1, 3);1003double tz = Rt.at<double>(2, 3);10041005double _t_x[] = { 0, -tz, ty, tz, 0, -tx, -ty, tx, 0 };10061007// F = (A2^-T)*[t]_x*R*(A1^-1)1008cv::gemm( invA2, Mat( 3, 3, CV_64F, _t_x ), 1, Mat(), 0, T, CV_GEMM_A_T );1009cv::gemm( R, invA1, 1, Mat(), 0, invA2 );1010cv::gemm( T, invA2, 1, Mat(), 0, F0 );1011F0 *= 1./f0[8];10121013uchar* status = test_mat[TEMP][1].ptr();1014double err_level = get_success_error_level( test_case_idx, OUTPUT, 1 );1015uchar* mtfm1 = test_mat[REF_OUTPUT][1].ptr();1016uchar* mtfm2 = test_mat[OUTPUT][1].ptr();1017double* f_prop1 = test_mat[REF_OUTPUT][0].ptr<double>();1018double* f_prop2 = test_mat[OUTPUT][0].ptr<double>();10191020int i, pt_count = test_mat[INPUT][2].cols;1021Mat p1( 1, pt_count, CV_64FC2 );1022Mat p2( 1, pt_count, CV_64FC2 );10231024test_convertHomogeneous( test_mat[INPUT][0], p1 );1025test_convertHomogeneous( test_mat[INPUT][1], p2 );10261027cvtest::convert(test_mat[TEMP][0], F, F.type());10281029if( method <= CV_FM_8POINT )1030memset( status, 1, pt_count );10311032for( i = 0; i < pt_count; i++ )1033{1034double x1 = p1.at<Point2d>(i).x;1035double y1 = p1.at<Point2d>(i).y;1036double x2 = p2.at<Point2d>(i).x;1037double y2 = p2.at<Point2d>(i).y;1038double n1 = 1./sqrt(x1*x1 + y1*y1 + 1);1039double n2 = 1./sqrt(x2*x2 + y2*y2 + 1);1040double t0 = fabs(f0[0]*x2*x1 + f0[1]*x2*y1 + f0[2]*x2 +1041f0[3]*y2*x1 + f0[4]*y2*y1 + f0[5]*y2 +1042f0[6]*x1 + f0[7]*y1 + f0[8])*n1*n2;1043double t = fabs(f[0]*x2*x1 + f[1]*x2*y1 + f[2]*x2 +1044f[3]*y2*x1 + f[4]*y2*y1 + f[5]*y2 +1045f[6]*x1 + f[7]*y1 + f[8])*n1*n2;1046mtfm1[i] = 1;1047mtfm2[i] = !status[i] || t0 > err_level || t < err_level;1048}10491050f_prop1[0] = 1;1051f_prop1[1] = 1;1052f_prop1[2] = 0;10531054f_prop2[0] = f_result != 0;1055f_prop2[1] = f[8];1056f_prop2[2] = cv::determinant( F );1057}1058/******************************* find essential matrix ***********************************/1059class CV_EssentialMatTest : public cvtest::ArrayTest1060{1061public:1062CV_EssentialMatTest();10631064protected:1065int read_params( CvFileStorage* fs );1066void fill_array( int test_case_idx, int i, int j, Mat& arr );1067int prepare_test_case( int test_case_idx );1068void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );1069double get_success_error_level( int test_case_idx, int i, int j );1070void run_func();1071void prepare_to_validation( int );10721073#if 01074double sampson_error(const double* f, double x1, double y1, double x2, double y2);1075#endif10761077int method;1078int img_size;1079int cube_size;1080int dims;1081double min_f, max_f;1082double sigma;1083};108410851086CV_EssentialMatTest::CV_EssentialMatTest()1087{1088// input arrays:1089// 0, 1 - arrays of 2d points that are passed to %func%.1090// Can have different data type, layout, be stored in homogeneous coordinates or not.1091// 2 - array of 3d points that are projected to both view planes1092// 3 - [R|t] matrix for the second view plane (for the first one it is [I|0]1093// 4 - intrinsic matrix for both camera1094test_array[INPUT].push_back(NULL);1095test_array[INPUT].push_back(NULL);1096test_array[INPUT].push_back(NULL);1097test_array[INPUT].push_back(NULL);1098test_array[INPUT].push_back(NULL);1099test_array[TEMP].push_back(NULL);1100test_array[TEMP].push_back(NULL);1101test_array[TEMP].push_back(NULL);1102test_array[TEMP].push_back(NULL);1103test_array[TEMP].push_back(NULL);1104test_array[OUTPUT].push_back(NULL); // Essential Matrix singularity1105test_array[OUTPUT].push_back(NULL); // Inliers mask1106test_array[OUTPUT].push_back(NULL); // Translation error1107test_array[OUTPUT].push_back(NULL); // Positive depth count1108test_array[REF_OUTPUT].push_back(NULL);1109test_array[REF_OUTPUT].push_back(NULL);1110test_array[REF_OUTPUT].push_back(NULL);1111test_array[REF_OUTPUT].push_back(NULL);11121113element_wise_relative_error = false;11141115method = 0;1116img_size = 10;1117cube_size = 10;1118dims = 0;1119min_f = 1;1120max_f = 3;1121sigma = 0;1122}112311241125int CV_EssentialMatTest::read_params( CvFileStorage* fs )1126{1127int code = cvtest::ArrayTest::read_params( fs );1128return code;1129}113011311132void CV_EssentialMatTest::get_test_array_types_and_sizes( int /*test_case_idx*/,1133vector<vector<Size> >& sizes, vector<vector<int> >& types )1134{1135RNG& rng = ts->get_rng();1136int pt_depth = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;1137double pt_count_exp = cvtest::randReal(rng)*6 + 1;1138int pt_count = MAX(5, cvRound(exp(pt_count_exp)));11391140dims = cvtest::randInt(rng) % 2 + 2;1141dims = 2;1142method = CV_LMEDS << (cvtest::randInt(rng) % 2);11431144types[INPUT][0] = CV_MAKETYPE(pt_depth, 1);11451146if( 0 && cvtest::randInt(rng) % 2 )1147sizes[INPUT][0] = cvSize(pt_count, dims);1148else1149{1150sizes[INPUT][0] = cvSize(dims, pt_count);1151if( cvtest::randInt(rng) % 2 )1152{1153types[INPUT][0] = CV_MAKETYPE(pt_depth, dims);1154if( cvtest::randInt(rng) % 2 )1155sizes[INPUT][0] = cvSize(pt_count, 1);1156else1157sizes[INPUT][0] = cvSize(1, pt_count);1158}1159}11601161sizes[INPUT][1] = sizes[INPUT][0];1162types[INPUT][1] = types[INPUT][0];11631164sizes[INPUT][2] = cvSize(pt_count, 1 );1165types[INPUT][2] = CV_64FC3;11661167sizes[INPUT][3] = cvSize(4,3);1168types[INPUT][3] = CV_64FC1;11691170sizes[INPUT][4] = cvSize(3,3);1171types[INPUT][4] = CV_MAKETYPE(CV_64F, 1);11721173sizes[TEMP][0] = cvSize(3,3);1174types[TEMP][0] = CV_64FC1;1175sizes[TEMP][1] = cvSize(pt_count,1);1176types[TEMP][1] = CV_8UC1;1177sizes[TEMP][2] = cvSize(3,3);1178types[TEMP][2] = CV_64FC1;1179sizes[TEMP][3] = cvSize(3, 1);1180types[TEMP][3] = CV_64FC1;1181sizes[TEMP][4] = cvSize(pt_count,1);1182types[TEMP][4] = CV_8UC1;11831184sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(3,1);1185types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1;1186sizes[OUTPUT][1] = sizes[REF_OUTPUT][1] = cvSize(pt_count,1);1187types[OUTPUT][1] = types[REF_OUTPUT][1] = CV_8UC1;1188sizes[OUTPUT][2] = sizes[REF_OUTPUT][2] = cvSize(1,1);1189types[OUTPUT][2] = types[REF_OUTPUT][2] = CV_64FC1;1190sizes[OUTPUT][3] = sizes[REF_OUTPUT][3] = cvSize(1,1);1191types[OUTPUT][3] = types[REF_OUTPUT][3] = CV_8UC1;11921193}119411951196double CV_EssentialMatTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )1197{1198return 1e-2;1199}120012011202void CV_EssentialMatTest::fill_array( int test_case_idx, int i, int j, Mat& arr )1203{1204double t[12]={0};1205RNG& rng = ts->get_rng();12061207if( i != INPUT )1208{1209cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr );1210return;1211}12121213switch( j )1214{1215case 0:1216case 1:1217return; // fill them later in prepare_test_case1218case 2:1219{1220double* p = arr.ptr<double>();1221for( i = 0; i < arr.cols*3; i += 3 )1222{1223p[i] = cvtest::randReal(rng)*cube_size;1224p[i+1] = cvtest::randReal(rng)*cube_size;1225p[i+2] = cvtest::randReal(rng)*cube_size + cube_size;1226}1227}1228break;1229case 3:1230{1231double r[3];1232Mat rot_vec( 3, 1, CV_64F, r );1233Mat rot_mat( 3, 3, CV_64F, t, 4*sizeof(t[0]) );1234r[0] = cvtest::randReal(rng)*CV_PI*2;1235r[1] = cvtest::randReal(rng)*CV_PI*2;1236r[2] = cvtest::randReal(rng)*CV_PI*2;12371238cvtest::Rodrigues( rot_vec, rot_mat );1239t[3] = cvtest::randReal(rng)*cube_size;1240t[7] = cvtest::randReal(rng)*cube_size;1241t[11] = cvtest::randReal(rng)*cube_size;1242Mat( 3, 4, CV_64F, t ).convertTo(arr, arr.type());1243}1244break;1245case 4:1246t[0] = t[4] = cvtest::randReal(rng)*(max_f - min_f) + min_f;1247t[2] = (img_size*0.5 + cvtest::randReal(rng)*4. - 2.)*t[0];1248t[5] = (img_size*0.5 + cvtest::randReal(rng)*4. - 2.)*t[4];1249t[8] = 1.;1250Mat( 3, 3, CV_64F, t ).convertTo( arr, arr.type() );1251break;1252}1253}125412551256int CV_EssentialMatTest::prepare_test_case( int test_case_idx )1257{1258int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );1259if( code > 0 )1260{1261const Mat& _3d = test_mat[INPUT][2];1262RNG& rng = ts->get_rng();1263double Idata[] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0 };1264Mat I( 3, 4, CV_64F, Idata );1265int k;12661267for( k = 0; k < 2; k++ )1268{1269const Mat& Rt = k == 0 ? I : test_mat[INPUT][3];1270const Mat& A = test_mat[INPUT][4];1271Mat& _2d = test_mat[INPUT][k];12721273test_projectPoints( _3d, Rt, A, _2d, &rng, sigma );1274}1275}12761277return code;1278}127912801281void CV_EssentialMatTest::run_func()1282{1283Mat _input0(test_mat[INPUT][0]), _input1(test_mat[INPUT][1]);1284Mat K(test_mat[INPUT][4]);1285double focal(K.at<double>(0, 0));1286cv::Point2d pp(K.at<double>(0, 2), K.at<double>(1, 2));12871288RNG& rng = ts->get_rng();1289Mat E, mask1(test_mat[TEMP][1]);1290E = cv::findEssentialMat( _input0, _input1, focal, pp, method, 0.99, MAX(sigma*3, 0.0001), mask1 );1291if (E.rows > 3)1292{1293int count = E.rows / 3;1294int row = (cvtest::randInt(rng) % count) * 3;1295E = E.rowRange(row, row + 3) * 1.0;1296}12971298E.copyTo(test_mat[TEMP][0]);12991300Mat R, t, mask2;1301recoverPose( E, _input0, _input1, R, t, focal, pp, mask2 );1302R.copyTo(test_mat[TEMP][2]);1303t.copyTo(test_mat[TEMP][3]);1304mask2.copyTo(test_mat[TEMP][4]);1305}13061307#if 01308double CV_EssentialMatTest::sampson_error(const double * f, double x1, double y1, double x2, double y2)1309{1310double Fx1[3] = {1311f[0] * x1 + f[1] * y1 + f[2],1312f[3] * x1 + f[4] * y1 + f[5],1313f[6] * x1 + f[7] * y1 + f[8]1314};1315double Ftx2[3] = {1316f[0] * x2 + f[3] * y2 + f[6],1317f[1] * x2 + f[4] * y2 + f[7],1318f[2] * x2 + f[5] * y2 + f[8]1319};1320double x2tFx1 = Fx1[0] * x2 + Fx1[1] * y2 + Fx1[2];13211322double error = x2tFx1 * x2tFx1 / (Fx1[0] * Fx1[0] + Fx1[1] * Fx1[1] + Ftx2[0] * Ftx2[0] + Ftx2[1] * Ftx2[1]);1323error = sqrt(error);1324return error;1325}1326#endif13271328void CV_EssentialMatTest::prepare_to_validation( int test_case_idx )1329{1330const Mat& Rt0 = test_mat[INPUT][3];1331const Mat& A = test_mat[INPUT][4];1332double f0[9], f[9], e[9];1333Mat F0(3, 3, CV_64FC1, f0), F(3, 3, CV_64F, f);1334Mat E(3, 3, CV_64F, e);13351336Mat invA, R=Rt0.colRange(0, 3), T1, T2;13371338cv::invert(A, invA, CV_SVD);13391340double tx = Rt0.at<double>(0, 3);1341double ty = Rt0.at<double>(1, 3);1342double tz = Rt0.at<double>(2, 3);13431344double _t_x[] = { 0, -tz, ty, tz, 0, -tx, -ty, tx, 0 };13451346// F = (A2^-T)*[t]_x*R*(A1^-1)1347cv::gemm( invA, Mat( 3, 3, CV_64F, _t_x ), 1, Mat(), 0, T1, CV_GEMM_A_T );1348cv::gemm( R, invA, 1, Mat(), 0, T2 );1349cv::gemm( T1, T2, 1, Mat(), 0, F0 );1350F0 *= 1./f0[8];13511352uchar* status = test_mat[TEMP][1].ptr();1353double err_level = get_success_error_level( test_case_idx, OUTPUT, 1 );1354uchar* mtfm1 = test_mat[REF_OUTPUT][1].ptr();1355uchar* mtfm2 = test_mat[OUTPUT][1].ptr();1356double* e_prop1 = test_mat[REF_OUTPUT][0].ptr<double>();1357double* e_prop2 = test_mat[OUTPUT][0].ptr<double>();1358Mat E_prop2 = Mat(3, 1, CV_64F, e_prop2);13591360int i, pt_count = test_mat[INPUT][2].cols;1361Mat p1( 1, pt_count, CV_64FC2 );1362Mat p2( 1, pt_count, CV_64FC2 );13631364test_convertHomogeneous( test_mat[INPUT][0], p1 );1365test_convertHomogeneous( test_mat[INPUT][1], p2 );13661367cvtest::convert(test_mat[TEMP][0], E, E.type());1368cv::gemm( invA, E, 1, Mat(), 0, T1, CV_GEMM_A_T );1369cv::gemm( T1, invA, 1, Mat(), 0, F );13701371for( i = 0; i < pt_count; i++ )1372{1373double x1 = p1.at<Point2d>(i).x;1374double y1 = p1.at<Point2d>(i).y;1375double x2 = p2.at<Point2d>(i).x;1376double y2 = p2.at<Point2d>(i).y;1377// double t0 = sampson_error(f0, x1, y1, x2, y2);1378// double t = sampson_error(f, x1, y1, x2, y2);1379double n1 = 1./sqrt(x1*x1 + y1*y1 + 1);1380double n2 = 1./sqrt(x2*x2 + y2*y2 + 1);1381double t0 = fabs(f0[0]*x2*x1 + f0[1]*x2*y1 + f0[2]*x2 +1382f0[3]*y2*x1 + f0[4]*y2*y1 + f0[5]*y2 +1383f0[6]*x1 + f0[7]*y1 + f0[8])*n1*n2;1384double t = fabs(f[0]*x2*x1 + f[1]*x2*y1 + f[2]*x2 +1385f[3]*y2*x1 + f[4]*y2*y1 + f[5]*y2 +1386f[6]*x1 + f[7]*y1 + f[8])*n1*n2;1387mtfm1[i] = 1;1388mtfm2[i] = !status[i] || t0 > err_level || t < err_level;1389}13901391e_prop1[0] = sqrt(0.5);1392e_prop1[1] = sqrt(0.5);1393e_prop1[2] = 0;13941395e_prop2[0] = 0;1396e_prop2[1] = 0;1397e_prop2[2] = 0;1398SVD::compute(E, E_prop2);1399140014011402double* pose_prop1 = test_mat[REF_OUTPUT][2].ptr<double>();1403double* pose_prop2 = test_mat[OUTPUT][2].ptr<double>();1404double terr1 = cvtest::norm(Rt0.col(3) / cvtest::norm(Rt0.col(3), NORM_L2) + test_mat[TEMP][3], NORM_L2);1405double terr2 = cvtest::norm(Rt0.col(3) / cvtest::norm(Rt0.col(3), NORM_L2) - test_mat[TEMP][3], NORM_L2);1406Mat rvec(3, 1, CV_32F);1407cvtest::Rodrigues(Rt0.colRange(0, 3), rvec);1408pose_prop1[0] = 0;1409// No check for CV_LMeDS on translation. Since it1410// involves with some degraded problem, when data is exact inliers.1411pose_prop2[0] = method == CV_LMEDS || pt_count == 5 ? 0 : MIN(terr1, terr2);141214131414// int inliers_count = countNonZero(test_mat[TEMP][1]);1415// int good_count = countNonZero(test_mat[TEMP][4]);1416test_mat[OUTPUT][3] = true; //good_count >= inliers_count / 2;1417test_mat[REF_OUTPUT][3] = true;141814191420}142114221423/********************************** convert homogeneous *********************************/14241425class CV_ConvertHomogeneousTest : public cvtest::ArrayTest1426{1427public:1428CV_ConvertHomogeneousTest();14291430protected:1431int read_params( CvFileStorage* fs );1432void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );1433void fill_array( int test_case_idx, int i, int j, Mat& arr );1434double get_success_error_level( int test_case_idx, int i, int j );1435void run_func();1436void prepare_to_validation( int );14371438int dims1, dims2;1439int pt_count;1440};144114421443CV_ConvertHomogeneousTest::CV_ConvertHomogeneousTest()1444{1445test_array[INPUT].push_back(NULL);1446test_array[OUTPUT].push_back(NULL);1447test_array[REF_OUTPUT].push_back(NULL);1448element_wise_relative_error = false;14491450pt_count = dims1 = dims2 = 0;1451}145214531454int CV_ConvertHomogeneousTest::read_params( CvFileStorage* fs )1455{1456int code = cvtest::ArrayTest::read_params( fs );1457return code;1458}145914601461void CV_ConvertHomogeneousTest::get_test_array_types_and_sizes( int /*test_case_idx*/,1462vector<vector<Size> >& sizes, vector<vector<int> >& types )1463{1464RNG& rng = ts->get_rng();1465int pt_depth1 = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;1466int pt_depth2 = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;1467double pt_count_exp = cvtest::randReal(rng)*6 + 1;1468int t;14691470pt_count = cvRound(exp(pt_count_exp));1471pt_count = MAX( pt_count, 5 );14721473dims1 = 2 + (cvtest::randInt(rng) % 3);1474dims2 = 2 + (cvtest::randInt(rng) % 3);14751476if( dims1 == dims2 + 2 )1477dims1--;1478else if( dims1 == dims2 - 2 )1479dims1++;14801481if( cvtest::randInt(rng) % 2 )1482CV_SWAP( dims1, dims2, t );14831484types[INPUT][0] = CV_MAKETYPE(pt_depth1, 1);14851486if( cvtest::randInt(rng) % 2 )1487sizes[INPUT][0] = cvSize(pt_count, dims1);1488else1489{1490sizes[INPUT][0] = cvSize(dims1, pt_count);1491if( cvtest::randInt(rng) % 2 )1492{1493types[INPUT][0] = CV_MAKETYPE(pt_depth1, dims1);1494if( cvtest::randInt(rng) % 2 )1495sizes[INPUT][0] = cvSize(pt_count, 1);1496else1497sizes[INPUT][0] = cvSize(1, pt_count);1498}1499}15001501types[OUTPUT][0] = CV_MAKETYPE(pt_depth2, 1);15021503if( cvtest::randInt(rng) % 2 )1504sizes[OUTPUT][0] = cvSize(pt_count, dims2);1505else1506{1507sizes[OUTPUT][0] = cvSize(dims2, pt_count);1508if( cvtest::randInt(rng) % 2 )1509{1510types[OUTPUT][0] = CV_MAKETYPE(pt_depth2, dims2);1511if( cvtest::randInt(rng) % 2 )1512sizes[OUTPUT][0] = cvSize(pt_count, 1);1513else1514sizes[OUTPUT][0] = cvSize(1, pt_count);1515}1516}15171518types[REF_OUTPUT][0] = types[OUTPUT][0];1519sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];1520}152115221523double CV_ConvertHomogeneousTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )1524{1525return 1e-5;1526}152715281529void CV_ConvertHomogeneousTest::fill_array( int /*test_case_idx*/, int /*i*/, int /*j*/, Mat& arr )1530{1531Mat temp( 1, pt_count, CV_MAKETYPE(CV_64FC1,dims1) );1532RNG& rng = ts->get_rng();1533CvScalar low = cvScalarAll(0), high = cvScalarAll(10);15341535if( dims1 > dims2 )1536low.val[dims1-1] = 1.;15371538cvtest::randUni( rng, temp, low, high );1539test_convertHomogeneous( temp, arr );1540}154115421543void CV_ConvertHomogeneousTest::run_func()1544{1545CvMat _input = cvMat(test_mat[INPUT][0]), _output = cvMat(test_mat[OUTPUT][0]);1546cvConvertPointsHomogeneous( &_input, &_output );1547}154815491550void CV_ConvertHomogeneousTest::prepare_to_validation( int /*test_case_idx*/ )1551{1552test_convertHomogeneous( test_mat[INPUT][0], test_mat[REF_OUTPUT][0] );1553}155415551556/************************** compute corresponding epipolar lines ************************/15571558class CV_ComputeEpilinesTest : public cvtest::ArrayTest1559{1560public:1561CV_ComputeEpilinesTest();15621563protected:1564int read_params( CvFileStorage* fs );1565void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );1566void fill_array( int test_case_idx, int i, int j, Mat& arr );1567double get_success_error_level( int test_case_idx, int i, int j );1568void run_func();1569void prepare_to_validation( int );15701571int which_image;1572int dims;1573int pt_count;1574};157515761577CV_ComputeEpilinesTest::CV_ComputeEpilinesTest()1578{1579test_array[INPUT].push_back(NULL);1580test_array[INPUT].push_back(NULL);1581test_array[OUTPUT].push_back(NULL);1582test_array[REF_OUTPUT].push_back(NULL);1583element_wise_relative_error = false;15841585pt_count = dims = which_image = 0;1586}158715881589int CV_ComputeEpilinesTest::read_params( CvFileStorage* fs )1590{1591int code = cvtest::ArrayTest::read_params( fs );1592return code;1593}159415951596void CV_ComputeEpilinesTest::get_test_array_types_and_sizes( int /*test_case_idx*/,1597vector<vector<Size> >& sizes, vector<vector<int> >& types )1598{1599RNG& rng = ts->get_rng();1600int fm_depth = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;1601int pt_depth = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;1602int ln_depth = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;1603double pt_count_exp = cvtest::randReal(rng)*6;16041605which_image = 1 + (cvtest::randInt(rng) % 2);16061607pt_count = cvRound(exp(pt_count_exp));1608pt_count = MAX( pt_count, 1 );1609bool few_points = pt_count < 5;16101611dims = 2 + (cvtest::randInt(rng) % 2);16121613types[INPUT][0] = CV_MAKETYPE(pt_depth, 1);16141615if( cvtest::randInt(rng) % 2 && !few_points )1616sizes[INPUT][0] = cvSize(pt_count, dims);1617else1618{1619sizes[INPUT][0] = cvSize(dims, pt_count);1620if( cvtest::randInt(rng) % 2 || few_points )1621{1622types[INPUT][0] = CV_MAKETYPE(pt_depth, dims);1623if( cvtest::randInt(rng) % 2 )1624sizes[INPUT][0] = cvSize(pt_count, 1);1625else1626sizes[INPUT][0] = cvSize(1, pt_count);1627}1628}16291630types[INPUT][1] = CV_MAKETYPE(fm_depth, 1);1631sizes[INPUT][1] = cvSize(3, 3);16321633types[OUTPUT][0] = CV_MAKETYPE(ln_depth, 1);16341635if( cvtest::randInt(rng) % 2 && !few_points )1636sizes[OUTPUT][0] = cvSize(pt_count, 3);1637else1638{1639sizes[OUTPUT][0] = cvSize(3, pt_count);1640if( cvtest::randInt(rng) % 2 || few_points )1641{1642types[OUTPUT][0] = CV_MAKETYPE(ln_depth, 3);1643if( cvtest::randInt(rng) % 2 )1644sizes[OUTPUT][0] = cvSize(pt_count, 1);1645else1646sizes[OUTPUT][0] = cvSize(1, pt_count);1647}1648}16491650types[REF_OUTPUT][0] = types[OUTPUT][0];1651sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];1652}165316541655double CV_ComputeEpilinesTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )1656{1657return 1e-5;1658}165916601661void CV_ComputeEpilinesTest::fill_array( int test_case_idx, int i, int j, Mat& arr )1662{1663RNG& rng = ts->get_rng();16641665if( i == INPUT && j == 0 )1666{1667Mat temp( 1, pt_count, CV_MAKETYPE(CV_64FC1,dims) );1668cvtest::randUni( rng, temp, cvScalar(0,0,1), cvScalarAll(10) );1669test_convertHomogeneous( temp, arr );1670}1671else if( i == INPUT && j == 1 )1672cvtest::randUni( rng, arr, cvScalarAll(0), cvScalarAll(10) );1673else1674cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr );1675}167616771678void CV_ComputeEpilinesTest::run_func()1679{1680CvMat _points = cvMat(test_mat[INPUT][0]), _F = cvMat(test_mat[INPUT][1]), _lines = cvMat(test_mat[OUTPUT][0]);1681cvComputeCorrespondEpilines( &_points, which_image, &_F, &_lines );1682}168316841685void CV_ComputeEpilinesTest::prepare_to_validation( int /*test_case_idx*/ )1686{1687Mat pt( 1, pt_count, CV_MAKETYPE(CV_64F, 3) );1688Mat lines( 1, pt_count, CV_MAKETYPE(CV_64F, 3) );1689double f[9];1690Mat F( 3, 3, CV_64F, f );16911692test_convertHomogeneous( test_mat[INPUT][0], pt );1693test_mat[INPUT][1].convertTo(F, CV_64F);1694if( which_image == 2 )1695cv::transpose( F, F );16961697for( int i = 0; i < pt_count; i++ )1698{1699double* p = pt.ptr<double>() + i*3;1700double* l = lines.ptr<double>() + i*3;1701double t0 = f[0]*p[0] + f[1]*p[1] + f[2]*p[2];1702double t1 = f[3]*p[0] + f[4]*p[1] + f[5]*p[2];1703double t2 = f[6]*p[0] + f[7]*p[1] + f[8]*p[2];1704double d = sqrt(t0*t0 + t1*t1);1705d = d ? 1./d : 1.;1706l[0] = t0*d; l[1] = t1*d; l[2] = t2*d;1707}17081709test_convertHomogeneous( lines, test_mat[REF_OUTPUT][0] );1710}17111712TEST(Calib3d_Rodrigues, accuracy) { CV_RodriguesTest test; test.safe_run(); }1713TEST(Calib3d_FindFundamentalMat, accuracy) { CV_FundamentalMatTest test; test.safe_run(); }1714TEST(Calib3d_ConvertHomogeneoous, accuracy) { CV_ConvertHomogeneousTest test; test.safe_run(); }1715TEST(Calib3d_ComputeEpilines, accuracy) { CV_ComputeEpilinesTest test; test.safe_run(); }1716TEST(Calib3d_FindEssentialMat, accuracy) { CV_EssentialMatTest test; test.safe_run(); }17171718TEST(Calib3d_FindFundamentalMat, correctMatches)1719{1720double fdata[] = {0, 0, 0, 0, 0, -1, 0, 1, 0};1721double p1data[] = {200, 0, 1};1722double p2data[] = {170, 0, 1};17231724Mat F(3, 3, CV_64F, fdata);1725Mat p1(1, 1, CV_64FC2, p1data);1726Mat p2(1, 1, CV_64FC2, p2data);1727Mat np1, np2;17281729correctMatches(F, p1, p2, np1, np2);17301731cout << np1 << endl;1732cout << np2 << endl;1733}17341735}} // namespace1736/* End of file. */173717381739