Path: blob/master/modules/imgproc/test/test_templmatch.cpp
16344 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"4243namespace opencv_test { namespace {4445class CV_TemplMatchTest : public cvtest::ArrayTest46{47public:48CV_TemplMatchTest();4950protected:51int read_params( CvFileStorage* fs );52void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );53void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );54double get_success_error_level( int test_case_idx, int i, int j );55void run_func();56void prepare_to_validation( int );5758int max_template_size;59int method;60bool test_cpp;61};626364CV_TemplMatchTest::CV_TemplMatchTest()65{66test_array[INPUT].push_back(NULL);67test_array[INPUT].push_back(NULL);68test_array[OUTPUT].push_back(NULL);69test_array[REF_OUTPUT].push_back(NULL);70element_wise_relative_error = false;71max_template_size = 100;72method = 0;73test_cpp = false;74}757677int CV_TemplMatchTest::read_params( CvFileStorage* fs )78{79int code = cvtest::ArrayTest::read_params( fs );80if( code < 0 )81return code;8283max_template_size = cvReadInt( find_param( fs, "max_template_size" ), max_template_size );84max_template_size = cvtest::clipInt( max_template_size, 1, 100 );8586return code;87}888990void CV_TemplMatchTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )91{92cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high );93int depth = CV_MAT_DEPTH(type);94if( depth == CV_32F )95{96low = Scalar::all(-10.);97high = Scalar::all(10.);98}99}100101102void CV_TemplMatchTest::get_test_array_types_and_sizes( int test_case_idx,103vector<vector<Size> >& sizes, vector<vector<int> >& types )104{105RNG& rng = ts->get_rng();106int depth = cvtest::randInt(rng) % 2, cn = cvtest::randInt(rng) & 1 ? 3 : 1;107cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );108depth = depth == 0 ? CV_8U : CV_32F;109110types[INPUT][0] = types[INPUT][1] = CV_MAKETYPE(depth,cn);111types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_32FC1;112113sizes[INPUT][1].width = cvtest::randInt(rng)%MIN(sizes[INPUT][1].width,max_template_size) + 1;114sizes[INPUT][1].height = cvtest::randInt(rng)%MIN(sizes[INPUT][1].height,max_template_size) + 1;115sizes[OUTPUT][0].width = sizes[INPUT][0].width - sizes[INPUT][1].width + 1;116sizes[OUTPUT][0].height = sizes[INPUT][0].height - sizes[INPUT][1].height + 1;117sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];118119method = cvtest::randInt(rng)%6;120test_cpp = (cvtest::randInt(rng) & 256) == 0;121}122123124double CV_TemplMatchTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )125{126if( test_mat[INPUT][1].depth() == CV_8U ||127(method >= CV_TM_CCOEFF && test_mat[INPUT][1].cols*test_mat[INPUT][1].rows <= 2) )128return 1e-2;129else130return 1e-3;131}132133134void CV_TemplMatchTest::run_func()135{136if(!test_cpp)137cvMatchTemplate( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0], method );138else139{140cv::Mat _out = cv::cvarrToMat(test_array[OUTPUT][0]);141cv::matchTemplate(cv::cvarrToMat(test_array[INPUT][0]), cv::cvarrToMat(test_array[INPUT][1]), _out, method);142}143}144145146static void cvTsMatchTemplate( const CvMat* img, const CvMat* templ, CvMat* result, int method )147{148int i, j, k, l;149int depth = CV_MAT_DEPTH(img->type), cn = CV_MAT_CN(img->type);150int width_n = templ->cols*cn, height = templ->rows;151int a_step = img->step / CV_ELEM_SIZE(img->type & CV_MAT_DEPTH_MASK);152int b_step = templ->step / CV_ELEM_SIZE(templ->type & CV_MAT_DEPTH_MASK);153CvScalar b_mean = CV_STRUCT_INITIALIZER, b_sdv = CV_STRUCT_INITIALIZER;154double b_denom = 1., b_sum2 = 0;155int area = templ->rows*templ->cols;156157cvAvgSdv(templ, &b_mean, &b_sdv);158159for( i = 0; i < cn; i++ )160b_sum2 += (b_sdv.val[i]*b_sdv.val[i] + b_mean.val[i]*b_mean.val[i])*area;161162if( b_sdv.val[0]*b_sdv.val[0] + b_sdv.val[1]*b_sdv.val[1] +163b_sdv.val[2]*b_sdv.val[2] + b_sdv.val[3]*b_sdv.val[3] < DBL_EPSILON &&164method == CV_TM_CCOEFF_NORMED )165{166cvSet( result, cvScalarAll(1.) );167return;168}169170if( method & 1 )171{172b_denom = 0;173if( method != CV_TM_CCOEFF_NORMED )174{175b_denom = b_sum2;176}177else178{179for( i = 0; i < cn; i++ )180b_denom += b_sdv.val[i]*b_sdv.val[i]*area;181}182b_denom = sqrt(b_denom);183if( b_denom == 0 )184b_denom = 1.;185}186187assert( CV_TM_SQDIFF <= method && method <= CV_TM_CCOEFF_NORMED );188189for( i = 0; i < result->rows; i++ )190{191for( j = 0; j < result->cols; j++ )192{193Scalar a_sum(0), a_sum2(0);194Scalar ccorr(0);195double value = 0.;196197if( depth == CV_8U )198{199const uchar* a = img->data.ptr + i*img->step + j*cn;200const uchar* b = templ->data.ptr;201202if( cn == 1 || method < CV_TM_CCOEFF )203{204for( k = 0; k < height; k++, a += a_step, b += b_step )205for( l = 0; l < width_n; l++ )206{207ccorr.val[0] += a[l]*b[l];208a_sum.val[0] += a[l];209a_sum2.val[0] += a[l]*a[l];210}211}212else213{214for( k = 0; k < height; k++, a += a_step, b += b_step )215for( l = 0; l < width_n; l += 3 )216{217ccorr.val[0] += a[l]*b[l];218ccorr.val[1] += a[l+1]*b[l+1];219ccorr.val[2] += a[l+2]*b[l+2];220a_sum.val[0] += a[l];221a_sum.val[1] += a[l+1];222a_sum.val[2] += a[l+2];223a_sum2.val[0] += a[l]*a[l];224a_sum2.val[1] += a[l+1]*a[l+1];225a_sum2.val[2] += a[l+2]*a[l+2];226}227}228}229else230{231const float* a = (const float*)(img->data.ptr + i*img->step) + j*cn;232const float* b = (const float*)templ->data.ptr;233234if( cn == 1 || method < CV_TM_CCOEFF )235{236for( k = 0; k < height; k++, a += a_step, b += b_step )237for( l = 0; l < width_n; l++ )238{239ccorr.val[0] += a[l]*b[l];240a_sum.val[0] += a[l];241a_sum2.val[0] += a[l]*a[l];242}243}244else245{246for( k = 0; k < height; k++, a += a_step, b += b_step )247for( l = 0; l < width_n; l += 3 )248{249ccorr.val[0] += a[l]*b[l];250ccorr.val[1] += a[l+1]*b[l+1];251ccorr.val[2] += a[l+2]*b[l+2];252a_sum.val[0] += a[l];253a_sum.val[1] += a[l+1];254a_sum.val[2] += a[l+2];255a_sum2.val[0] += a[l]*a[l];256a_sum2.val[1] += a[l+1]*a[l+1];257a_sum2.val[2] += a[l+2]*a[l+2];258}259}260}261262switch( method )263{264case CV_TM_CCORR:265case CV_TM_CCORR_NORMED:266value = ccorr.val[0];267break;268case CV_TM_SQDIFF:269case CV_TM_SQDIFF_NORMED:270value = (a_sum2.val[0] + b_sum2 - 2*ccorr.val[0]);271break;272default:273value = (ccorr.val[0] - a_sum.val[0]*b_mean.val[0]+274ccorr.val[1] - a_sum.val[1]*b_mean.val[1]+275ccorr.val[2] - a_sum.val[2]*b_mean.val[2]);276}277278if( method & 1 )279{280double denom;281282// calc denominator283if( method != CV_TM_CCOEFF_NORMED )284{285denom = a_sum2.val[0] + a_sum2.val[1] + a_sum2.val[2];286}287else288{289denom = a_sum2.val[0] - (a_sum.val[0]*a_sum.val[0])/area;290denom += a_sum2.val[1] - (a_sum.val[1]*a_sum.val[1])/area;291denom += a_sum2.val[2] - (a_sum.val[2]*a_sum.val[2])/area;292}293denom = sqrt(MAX(denom,0))*b_denom;294if( fabs(value) < denom )295value /= denom;296else if( fabs(value) < denom*1.125 )297value = value > 0 ? 1 : -1;298else299value = method != CV_TM_SQDIFF_NORMED ? 0 : 1;300}301302((float*)(result->data.ptr + result->step*i))[j] = (float)value;303}304}305}306307308void CV_TemplMatchTest::prepare_to_validation( int /*test_case_idx*/ )309{310CvMat _input = cvMat(test_mat[INPUT][0]), _templ = cvMat(test_mat[INPUT][1]);311CvMat _output = cvMat(test_mat[REF_OUTPUT][0]);312cvTsMatchTemplate( &_input, &_templ, &_output, method );313314//if( ts->get_current_test_info()->test_case_idx == 0 )315/*{316CvFileStorage* fs = cvOpenFileStorage( "_match_template.yml", 0, CV_STORAGE_WRITE );317cvWrite( fs, "image", &test_mat[INPUT][0] );318cvWrite( fs, "template", &test_mat[INPUT][1] );319cvWrite( fs, "ref", &test_mat[REF_OUTPUT][0] );320cvWrite( fs, "opencv", &test_mat[OUTPUT][0] );321cvWriteInt( fs, "method", method );322cvReleaseFileStorage( &fs );323}*/324325if( method >= CV_TM_CCOEFF )326{327// avoid numerical stability problems in singular cases (when the results are near to 0)328const double delta = 10.;329test_mat[REF_OUTPUT][0] += Scalar::all(delta);330test_mat[OUTPUT][0] += Scalar::all(delta);331}332}333334TEST(Imgproc_MatchTemplate, accuracy) { CV_TemplMatchTest test; test.safe_run(); }335336}} // namespace337338339