Path: blob/master/modules/imgproc/test/test_histograms.cpp
16354 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_BaseHistTest : public cvtest::BaseTest46{47public:48enum { MAX_HIST = 12 };4950CV_BaseHistTest();51~CV_BaseHistTest();52void clear();5354protected:55int read_params( CvFileStorage* fs );56void run_func(void);57int prepare_test_case( int test_case_idx );58int validate_test_results( int test_case_idx );59virtual void init_hist( int test_case_idx, int i );6061virtual void get_hist_params( int test_case_idx );62virtual float** get_hist_ranges( int test_case_idx );6364int max_log_size;65int max_cdims;66int cdims;67int dims[CV_MAX_DIM];68int total_size;69int hist_type;70int hist_count;71int uniform;72int gen_random_hist;73double gen_hist_max_val, gen_hist_sparse_nz_ratio;7475int init_ranges;76int img_type;77int img_max_log_size;78double low, high, range_delta;79Size img_size;8081vector<CvHistogram*> hist;82vector<float> _ranges;83vector<float*> ranges;84bool test_cpp;85};868788CV_BaseHistTest::CV_BaseHistTest()89{90test_case_count = 100;91max_log_size = 20;92img_max_log_size = 8;93max_cdims = 6;94hist_count = 1;95init_ranges = 0;96gen_random_hist = 0;97gen_hist_max_val = 100;9899test_cpp = false;100}101102103CV_BaseHistTest::~CV_BaseHistTest()104{105clear();106}107108109void CV_BaseHistTest::clear()110{111cvtest::BaseTest::clear();112for( size_t i = 0; i < hist.size(); i++ )113cvReleaseHist( &hist[i] );114}115116117int CV_BaseHistTest::read_params( CvFileStorage* fs )118{119int code = cvtest::BaseTest::read_params( fs );120if( code < 0 )121return code;122123test_case_count = cvReadInt( find_param( fs, "struct_count" ), test_case_count );124max_log_size = cvReadInt( find_param( fs, "max_log_size" ), max_log_size );125max_log_size = cvtest::clipInt( max_log_size, 1, 20 );126img_max_log_size = cvReadInt( find_param( fs, "max_log_array_size" ), img_max_log_size );127img_max_log_size = cvtest::clipInt( img_max_log_size, 1, 9 );128129max_cdims = cvReadInt( find_param( fs, "max_cdims" ), max_cdims );130max_cdims = cvtest::clipInt( max_cdims, 1, 6 );131132return 0;133}134135136void CV_BaseHistTest::get_hist_params( int /*test_case_idx*/ )137{138RNG& rng = ts->get_rng();139int i, max_dim_size, max_ni_dim_size = 31;140double hist_size;141142cdims = cvtest::randInt(rng) % max_cdims + 1;143hist_size = exp(cvtest::randReal(rng)*max_log_size*CV_LOG2);144max_dim_size = cvRound(pow(hist_size,1./cdims));145total_size = 1;146uniform = cvtest::randInt(rng) % 2;147hist_type = cvtest::randInt(rng) % 2 ? CV_HIST_SPARSE : CV_HIST_ARRAY;148149for( i = 0; i < cdims; i++ )150{151dims[i] = cvtest::randInt(rng) % (max_dim_size + 2) + 2;152if( !uniform )153dims[i] = MIN(dims[i], max_ni_dim_size);154total_size *= dims[i];155}156157img_type = cvtest::randInt(rng) % 2 ? CV_32F : CV_8U;158img_size.width = cvRound( exp(cvtest::randReal(rng) * img_max_log_size * CV_LOG2) );159img_size.height = cvRound( exp(cvtest::randReal(rng) * img_max_log_size * CV_LOG2) );160161if( img_type < CV_32F )162{163low = cvtest::getMinVal(img_type);164high = cvtest::getMaxVal(img_type);165}166else167{168high = 1000;169low = -high;170}171172range_delta = (cvtest::randInt(rng) % 2)*(high-low)*0.05;173}174175176float** CV_BaseHistTest::get_hist_ranges( int /*test_case_idx*/ )177{178double _low = low + range_delta, _high = high - range_delta;179180if( !init_ranges )181return 0;182183ranges.resize(cdims);184185if( uniform )186{187_ranges.resize(cdims*2);188for( int i = 0; i < cdims; i++ )189{190_ranges[i*2] = (float)_low;191_ranges[i*2+1] = (float)_high;192ranges[i] = &_ranges[i*2];193}194}195else196{197int i, dims_sum = 0, ofs = 0;198for( i = 0; i < cdims; i++ )199dims_sum += dims[i] + 1;200_ranges.resize(dims_sum);201202for( i = 0; i < cdims; i++ )203{204int j, n = dims[i];205// generate logarithmic scale206double delta, q, val;207for( j = 0; j < 10; j++ )208{209q = 1. + (j+1)*0.1;210if( (pow(q,(double)n)-1)/(q-1.) >= _high-_low )211break;212}213214if( j == 0 )215{216delta = (_high-_low)/n;217q = 1.;218}219else220{221q = 1 + j*0.1;222delta = cvFloor((_high-_low)*(q-1)/(pow(q,(double)n) - 1));223delta = MAX(delta, 1.);224}225val = _low;226227for( j = 0; j <= n; j++ )228{229_ranges[j+ofs] = (float)MIN(val,_high);230val += delta;231delta *= q;232}233ranges[i] = &_ranges[ofs];234ofs += n + 1;235}236}237238return &ranges[0];239}240241242void CV_BaseHistTest::init_hist( int /*test_case_idx*/, int hist_i )243{244if( gen_random_hist )245{246RNG& rng = ts->get_rng();247248if( hist_type == CV_HIST_ARRAY )249{250Mat h = cvarrToMat(hist[hist_i]->bins);251cvtest::randUni(rng, h, Scalar::all(0), Scalar::all(gen_hist_max_val) );252}253else254{255CvArr* arr = hist[hist_i]->bins;256int i, j, totalSize = 1, nz_count;257int idx[CV_MAX_DIM];258for( i = 0; i < cdims; i++ )259totalSize *= dims[i];260261nz_count = cvtest::randInt(rng) % MAX( totalSize/4, 100 );262nz_count = MIN( nz_count, totalSize );263264// a zero number of non-zero elements should be allowed265for( i = 0; i < nz_count; i++ )266{267for( j = 0; j < cdims; j++ )268idx[j] = cvtest::randInt(rng) % dims[j];269cvSetRealND(arr, idx, cvtest::randReal(rng)*gen_hist_max_val);270}271}272}273}274275276int CV_BaseHistTest::prepare_test_case( int test_case_idx )277{278int i;279float** r;280281clear();282283cvtest::BaseTest::prepare_test_case( test_case_idx );284get_hist_params( test_case_idx );285r = get_hist_ranges( test_case_idx );286hist.resize(hist_count);287288for( i = 0; i < hist_count; i++ )289{290hist[i] = cvCreateHist( cdims, dims, hist_type, r, uniform );291init_hist( test_case_idx, i );292}293test_cpp = (cvtest::randInt(ts->get_rng()) % 2) != 0;294295return 1;296}297298299void CV_BaseHistTest::run_func(void)300{301}302303304int CV_BaseHistTest::validate_test_results( int /*test_case_idx*/ )305{306return 0;307}308309310////////////// testing operation for reading/writing individual histogram bins //////////////311312class CV_QueryHistTest : public CV_BaseHistTest313{314public:315CV_QueryHistTest();316~CV_QueryHistTest();317void clear();318319protected:320void run_func(void);321int prepare_test_case( int test_case_idx );322int validate_test_results( int test_case_idx );323void init_hist( int test_case_idx, int i );324325Mat indices;326Mat values;327Mat values0;328};329330331CV_QueryHistTest::CV_QueryHistTest()332{333hist_count = 1;334}335336337CV_QueryHistTest::~CV_QueryHistTest()338{339clear();340}341342343void CV_QueryHistTest::clear()344{345CV_BaseHistTest::clear();346}347348349void CV_QueryHistTest::init_hist( int /*test_case_idx*/, int i )350{351if( hist_type == CV_HIST_ARRAY )352cvZero( hist[i]->bins );353}354355356int CV_QueryHistTest::prepare_test_case( int test_case_idx )357{358int code = CV_BaseHistTest::prepare_test_case( test_case_idx );359360if( code > 0 )361{362int i, j, iters;363float default_value = 0.f;364RNG& rng = ts->get_rng();365int* idx;366367iters = (cvtest::randInt(rng) % MAX(total_size/10,100)) + 1;368iters = MIN( iters, total_size*9/10 + 1 );369370indices = Mat(1, iters*cdims, CV_32S);371values = Mat(1, iters, CV_32F );372values0 = Mat( 1, iters, CV_32F );373idx = indices.ptr<int>();374375//printf( "total_size = %d, cdims = %d, iters = %d\n", total_size, cdims, iters );376377Mat bit_mask(1, (total_size + 7)/8, CV_8U, Scalar(0));378379#define GET_BIT(n) (bit_mask.data[(n)/8] & (1 << ((n)&7)))380#define SET_BIT(n) bit_mask.data[(n)/8] |= (1 << ((n)&7))381382// set random histogram bins' values to the linear indices of the bins383for( i = 0; i < iters; i++ )384{385int lin_idx = 0;386for( j = 0; j < cdims; j++ )387{388int t = cvtest::randInt(rng) % dims[j];389idx[i*cdims + j] = t;390lin_idx = lin_idx*dims[j] + t;391}392393if( cvtest::randInt(rng) % 8 || GET_BIT(lin_idx) )394{395values0.at<float>(i) = (float)(lin_idx+1);396SET_BIT(lin_idx);397}398else399// some histogram bins will not be initialized intentionally,400// they should be equal to the default value401values0.at<float>(i) = default_value;402}403404// do the second pass to make values0 consistent with bit_mask405for( i = 0; i < iters; i++ )406{407int lin_idx = 0;408for( j = 0; j < cdims; j++ )409lin_idx = lin_idx*dims[j] + idx[i*cdims + j];410411if( GET_BIT(lin_idx) )412values0.at<float>(i) = (float)(lin_idx+1);413}414}415416return code;417}418419420void CV_QueryHistTest::run_func(void)421{422int i, iters = values.cols;423CvArr* h = hist[0]->bins;424const int* idx = indices.ptr<int>();425float* val = values.ptr<float>();426float default_value = 0.f;427428// stage 1: write bins429if( cdims == 1 )430for( i = 0; i < iters; i++ )431{432float v0 = values0.at<float>(i);433if( fabs(v0 - default_value) < FLT_EPSILON )434continue;435if( !(i % 2) )436{437if( !(i % 4) )438cvSetReal1D( h, idx[i], v0 );439else440*(float*)cvPtr1D( h, idx[i] ) = v0;441}442else443cvSetRealND( h, idx+i, v0 );444}445else if( cdims == 2 )446for( i = 0; i < iters; i++ )447{448float v0 = values0.at<float>(i);449if( fabs(v0 - default_value) < FLT_EPSILON )450continue;451if( !(i % 2) )452{453if( !(i % 4) )454cvSetReal2D( h, idx[i*2], idx[i*2+1], v0 );455else456*(float*)cvPtr2D( h, idx[i*2], idx[i*2+1] ) = v0;457}458else459cvSetRealND( h, idx+i*2, v0 );460}461else if( cdims == 3 )462for( i = 0; i < iters; i++ )463{464float v0 = values0.at<float>(i);465if( fabs(v0 - default_value) < FLT_EPSILON )466continue;467if( !(i % 2) )468{469if( !(i % 4) )470cvSetReal3D( h, idx[i*3], idx[i*3+1], idx[i*3+2], v0 );471else472*(float*)cvPtr3D( h, idx[i*3], idx[i*3+1], idx[i*3+2] ) = v0;473}474else475cvSetRealND( h, idx+i*3, v0 );476}477else478for( i = 0; i < iters; i++ )479{480float v0 = values0.at<float>(i);481if( fabs(v0 - default_value) < FLT_EPSILON )482continue;483if( !(i % 2) )484cvSetRealND( h, idx+i*cdims, v0 );485else486*(float*)cvPtrND( h, idx+i*cdims ) = v0;487}488489// stage 2: read bins490if( cdims == 1 )491for( i = 0; i < iters; i++ )492{493if( !(i % 2) )494val[i] = *(float*)cvPtr1D( h, idx[i] );495else496val[i] = (float)cvGetReal1D( h, idx[i] );497}498else if( cdims == 2 )499for( i = 0; i < iters; i++ )500{501if( !(i % 2) )502val[i] = *(float*)cvPtr2D( h, idx[i*2], idx[i*2+1] );503else504val[i] = (float)cvGetReal2D( h, idx[i*2], idx[i*2+1] );505}506else if( cdims == 3 )507for( i = 0; i < iters; i++ )508{509if( !(i % 2) )510val[i] = *(float*)cvPtr3D( h, idx[i*3], idx[i*3+1], idx[i*3+2] );511else512val[i] = (float)cvGetReal3D( h, idx[i*3], idx[i*3+1], idx[i*3+2] );513}514else515for( i = 0; i < iters; i++ )516{517if( !(i % 2) )518val[i] = *(float*)cvPtrND( h, idx+i*cdims );519else520val[i] = (float)cvGetRealND( h, idx+i*cdims );521}522}523524525int CV_QueryHistTest::validate_test_results( int /*test_case_idx*/ )526{527int code = cvtest::TS::OK;528int i, j, iters = values.cols;529530for( i = 0; i < iters; i++ )531{532float v = values.at<float>(i), v0 = values0.at<float>(i);533534if( cvIsNaN(v) || cvIsInf(v) )535{536ts->printf( cvtest::TS::LOG, "The bin #%d has invalid value\n", i );537code = cvtest::TS::FAIL_INVALID_OUTPUT;538}539else if( fabs(v - v0) > FLT_EPSILON )540{541ts->printf( cvtest::TS::LOG, "The bin #%d = %g, while it should be %g\n", i, v, v0 );542code = cvtest::TS::FAIL_BAD_ACCURACY;543}544545if( code < 0 )546{547ts->printf( cvtest::TS::LOG, "The bin index = (" );548for( j = 0; j < cdims; j++ )549ts->printf( cvtest::TS::LOG, "%d%s", indices.at<int>(i*cdims + j),550j < cdims-1 ? ", " : ")\n" );551break;552}553}554555if( code < 0 )556ts->set_failed_test_info( code );557return code;558}559560561////////////// cvGetMinMaxHistValue //////////////562563class CV_MinMaxHistTest : public CV_BaseHistTest564{565public:566CV_MinMaxHistTest();567568protected:569void run_func(void);570void init_hist(int, int);571int validate_test_results( int test_case_idx );572int min_idx[CV_MAX_DIM], max_idx[CV_MAX_DIM];573float min_val, max_val;574int min_idx0[CV_MAX_DIM], max_idx0[CV_MAX_DIM];575float min_val0, max_val0;576};577578579580CV_MinMaxHistTest::CV_MinMaxHistTest()581{582hist_count = 1;583gen_random_hist = 1;584}585586587void CV_MinMaxHistTest::init_hist(int test_case_idx, int hist_i)588{589int i, eq = 1;590RNG& rng = ts->get_rng();591CV_BaseHistTest::init_hist( test_case_idx, hist_i );592593for(;;)594{595for( i = 0; i < cdims; i++ )596{597min_idx0[i] = cvtest::randInt(rng) % dims[i];598max_idx0[i] = cvtest::randInt(rng) % dims[i];599eq &= min_idx0[i] == max_idx0[i];600}601if( !eq || total_size == 1 )602break;603}604605min_val0 = (float)(-cvtest::randReal(rng)*10 - FLT_EPSILON);606max_val0 = (float)(cvtest::randReal(rng)*10 + FLT_EPSILON + gen_hist_max_val);607608if( total_size == 1 )609min_val0 = max_val0;610611cvSetRealND( hist[0]->bins, min_idx0, min_val0 );612cvSetRealND( hist[0]->bins, max_idx0, max_val0 );613}614615616void CV_MinMaxHistTest::run_func(void)617{618if( hist_type != CV_HIST_ARRAY && test_cpp )619{620cv::SparseMat h;621((CvSparseMat*)hist[0]->bins)->copyToSparseMat(h);622double _min_val = 0, _max_val = 0;623cv::minMaxLoc(h, &_min_val, &_max_val, min_idx, max_idx );624min_val = (float)_min_val;625max_val = (float)_max_val;626}627else628cvGetMinMaxHistValue( hist[0], &min_val, &max_val, min_idx, max_idx );629}630631632int CV_MinMaxHistTest::validate_test_results( int /*test_case_idx*/ )633{634int code = cvtest::TS::OK;635636if( cvIsNaN(min_val) || cvIsInf(min_val) ||637cvIsNaN(max_val) || cvIsInf(max_val) )638{639ts->printf( cvtest::TS::LOG,640"The extrema histogram bin values are invalid (min = %g, max = %g)\n", min_val, max_val );641code = cvtest::TS::FAIL_INVALID_OUTPUT;642}643else if( fabs(min_val - min_val0) > FLT_EPSILON ||644fabs(max_val - max_val0) > FLT_EPSILON )645{646ts->printf( cvtest::TS::LOG,647"The extrema histogram bin values are incorrect: (min = %g, should be = %g), (max = %g, should be = %g)\n",648min_val, min_val0, max_val, max_val0 );649code = cvtest::TS::FAIL_BAD_ACCURACY;650}651else652{653int i;654for( i = 0; i < cdims; i++ )655{656if( min_idx[i] != min_idx0[i] || max_idx[i] != max_idx0[i] )657{658ts->printf( cvtest::TS::LOG,659"The %d-th coordinates of extrema histogram bin values are incorrect: "660"(min = %d, should be = %d), (max = %d, should be = %d)\n",661i, min_idx[i], min_idx0[i], max_idx[i], max_idx0[i] );662code = cvtest::TS::FAIL_BAD_ACCURACY;663}664}665}666667if( code < 0 )668ts->set_failed_test_info( code );669return code;670}671672673////////////// cvNormalizeHist //////////////674675class CV_NormHistTest : public CV_BaseHistTest676{677public:678CV_NormHistTest();679680protected:681int prepare_test_case( int test_case_idx );682void run_func(void);683int validate_test_results( int test_case_idx );684double factor;685};686687688689CV_NormHistTest::CV_NormHistTest()690{691hist_count = 1;692gen_random_hist = 1;693factor = 0;694}695696697int CV_NormHistTest::prepare_test_case( int test_case_idx )698{699int code = CV_BaseHistTest::prepare_test_case( test_case_idx );700701if( code > 0 )702{703RNG& rng = ts->get_rng();704factor = cvtest::randReal(rng)*10 + 0.1;705if( hist_type == CV_HIST_SPARSE &&706((CvSparseMat*)hist[0]->bins)->heap->active_count == 0 )707factor = 0;708}709710return code;711}712713714void CV_NormHistTest::run_func(void)715{716if( hist_type != CV_HIST_ARRAY && test_cpp )717{718cv::SparseMat h;719((CvSparseMat*)hist[0]->bins)->copyToSparseMat(h);720cv::normalize(h, h, factor, CV_L1);721cvReleaseSparseMat((CvSparseMat**)&hist[0]->bins);722hist[0]->bins = cvCreateSparseMat(h);723}724else725cvNormalizeHist( hist[0], factor );726}727728729int CV_NormHistTest::validate_test_results( int /*test_case_idx*/ )730{731int code = cvtest::TS::OK;732double sum = 0;733734if( hist_type == CV_HIST_ARRAY )735{736int i;737const float* ptr = (float*)cvPtr1D( hist[0]->bins, 0 );738739for( i = 0; i < total_size; i++ )740sum += ptr[i];741}742else743{744CvSparseMat* sparse = (CvSparseMat*)hist[0]->bins;745CvSparseMatIterator iterator;746CvSparseNode *node;747748for( node = cvInitSparseMatIterator( sparse, &iterator );749node != 0; node = cvGetNextSparseNode( &iterator ))750{751sum += *(float*)CV_NODE_VAL(sparse,node);752}753}754755if( cvIsNaN(sum) || cvIsInf(sum) )756{757ts->printf( cvtest::TS::LOG,758"The normalized histogram has invalid sum =%g\n", sum );759code = cvtest::TS::FAIL_INVALID_OUTPUT;760}761else if( fabs(sum - factor) > FLT_EPSILON*10*fabs(factor) )762{763ts->printf( cvtest::TS::LOG,764"The normalized histogram has incorrect sum =%g, while it should be =%g\n", sum, factor );765code = cvtest::TS::FAIL_BAD_ACCURACY;766}767768if( code < 0 )769ts->set_failed_test_info( code );770return code;771}772773774////////////// cvThreshHist //////////////775776class CV_ThreshHistTest : public CV_BaseHistTest777{778public:779CV_ThreshHistTest();780~CV_ThreshHistTest();781void clear();782783protected:784int prepare_test_case( int test_case_idx );785void run_func(void);786int validate_test_results( int test_case_idx );787Mat indices;788Mat values;789int orig_nz_count;790791double threshold;792};793794795796CV_ThreshHistTest::CV_ThreshHistTest() : threshold(0)797{798hist_count = 1;799gen_random_hist = 1;800}801802803CV_ThreshHistTest::~CV_ThreshHistTest()804{805clear();806}807808809void CV_ThreshHistTest::clear()810{811CV_BaseHistTest::clear();812}813814815int CV_ThreshHistTest::prepare_test_case( int test_case_idx )816{817int code = CV_BaseHistTest::prepare_test_case( test_case_idx );818819if( code > 0 )820{821RNG& rng = ts->get_rng();822threshold = cvtest::randReal(rng)*gen_hist_max_val;823824if( hist_type == CV_HIST_ARRAY )825{826orig_nz_count = total_size;827828values = Mat( 1, total_size, CV_32F );829indices = Mat();830memcpy( values.ptr<float>(), cvPtr1D( hist[0]->bins, 0 ), total_size*sizeof(float) );831}832else833{834CvSparseMat* sparse = (CvSparseMat*)hist[0]->bins;835CvSparseMatIterator iterator;836CvSparseNode* node;837int i, k;838839orig_nz_count = sparse->heap->active_count;840841values = Mat( 1, orig_nz_count+1, CV_32F );842indices = Mat( 1, (orig_nz_count+1)*cdims, CV_32S );843844for( node = cvInitSparseMatIterator( sparse, &iterator ), i = 0;845node != 0; node = cvGetNextSparseNode( &iterator ), i++ )846{847const int* idx = CV_NODE_IDX(sparse,node);848849OPENCV_ASSERT( i < orig_nz_count, "CV_ThreshHistTest::prepare_test_case", "Buffer overflow" );850851values.at<float>(i) = *(float*)CV_NODE_VAL(sparse,node);852for( k = 0; k < cdims; k++ )853indices.at<int>(i*cdims + k) = idx[k];854}855856OPENCV_ASSERT( i == orig_nz_count, "Unmatched buffer size",857"CV_ThreshHistTest::prepare_test_case" );858}859}860861return code;862}863864865void CV_ThreshHistTest::run_func(void)866{867cvThreshHist( hist[0], threshold );868}869870871int CV_ThreshHistTest::validate_test_results( int /*test_case_idx*/ )872{873int code = cvtest::TS::OK;874int i;875float* ptr0 = values.ptr<float>();876float* ptr = 0;877CvSparseMat* sparse = 0;878879if( hist_type == CV_HIST_ARRAY )880ptr = (float*)cvPtr1D( hist[0]->bins, 0 );881else882sparse = (CvSparseMat*)hist[0]->bins;883884if( code > 0 )885{886for( i = 0; i < orig_nz_count; i++ )887{888float v0 = ptr0[i], v;889890if( hist_type == CV_HIST_ARRAY )891v = ptr[i];892else893{894v = (float)cvGetRealND( sparse, indices.ptr<int>() + i*cdims );895cvClearND( sparse, indices.ptr<int>() + i*cdims );896}897898if( v0 <= threshold ) v0 = 0.f;899if( cvIsNaN(v) || cvIsInf(v) )900{901ts->printf( cvtest::TS::LOG, "The %d-th bin is invalid (=%g)\n", i, v );902code = cvtest::TS::FAIL_INVALID_OUTPUT;903break;904}905else if( fabs(v0 - v) > FLT_EPSILON*10*fabs(v0) )906{907ts->printf( cvtest::TS::LOG, "The %d-th bin is incorrect (=%g, should be =%g)\n", i, v, v0 );908code = cvtest::TS::FAIL_BAD_ACCURACY;909break;910}911}912}913914if( code > 0 && hist_type == CV_HIST_SPARSE )915{916if( sparse->heap->active_count > 0 )917{918ts->printf( cvtest::TS::LOG,919"There some extra histogram bins in the sparse histogram after the thresholding\n" );920code = cvtest::TS::FAIL_INVALID_OUTPUT;921}922}923924if( code < 0 )925ts->set_failed_test_info( code );926return code;927}928929930////////////// cvCompareHist //////////////931932class CV_CompareHistTest : public CV_BaseHistTest933{934public:935enum { MAX_METHOD = 6 };936937CV_CompareHistTest();938protected:939int prepare_test_case( int test_case_idx );940void run_func(void);941int validate_test_results( int test_case_idx );942double result[MAX_METHOD+1];943};944945946947CV_CompareHistTest::CV_CompareHistTest()948{949hist_count = 2;950gen_random_hist = 1;951}952953954int CV_CompareHistTest::prepare_test_case( int test_case_idx )955{956int code = CV_BaseHistTest::prepare_test_case( test_case_idx );957958return code;959}960961962void CV_CompareHistTest::run_func(void)963{964int k;965if( hist_type != CV_HIST_ARRAY && test_cpp )966{967cv::SparseMat h0, h1;968((CvSparseMat*)hist[0]->bins)->copyToSparseMat(h0);969((CvSparseMat*)hist[1]->bins)->copyToSparseMat(h1);970for( k = 0; k < MAX_METHOD; k++ )971result[k] = cv::compareHist(h0, h1, k);972}973else974for( k = 0; k < MAX_METHOD; k++ )975result[k] = cvCompareHist( hist[0], hist[1], k );976}977978979int CV_CompareHistTest::validate_test_results( int /*test_case_idx*/ )980{981int code = cvtest::TS::OK;982int i;983double result0[MAX_METHOD+1];984double s0 = 0, s1 = 0, sq0 = 0, sq1 = 0, t;985986for( i = 0; i < MAX_METHOD; i++ )987result0[i] = 0;988989if( hist_type == CV_HIST_ARRAY )990{991float* ptr0 = (float*)cvPtr1D( hist[0]->bins, 0 );992float* ptr1 = (float*)cvPtr1D( hist[1]->bins, 0 );993994for( i = 0; i < total_size; i++ )995{996double v0 = ptr0[i], v1 = ptr1[i];997result0[CV_COMP_CORREL] += v0*v1;998result0[CV_COMP_INTERSECT] += MIN(v0,v1);999if( fabs(v0) > DBL_EPSILON )1000result0[CV_COMP_CHISQR] += (v0 - v1)*(v0 - v1)/v0;1001if( fabs(v0 + v1) > DBL_EPSILON )1002result0[CV_COMP_CHISQR_ALT] += (v0 - v1)*(v0 - v1)/(v0 + v1);1003s0 += v0;1004s1 += v1;1005sq0 += v0*v0;1006sq1 += v1*v1;1007result0[CV_COMP_BHATTACHARYYA] += sqrt(v0*v1);1008{1009if( fabs(v0) <= DBL_EPSILON )1010continue;1011if( fabs(v1) <= DBL_EPSILON )1012v1 = 1e-10;1013result0[CV_COMP_KL_DIV] += v0 * std::log( v0 / v1 );1014}1015}1016}1017else1018{1019CvSparseMat* sparse0 = (CvSparseMat*)hist[0]->bins;1020CvSparseMat* sparse1 = (CvSparseMat*)hist[1]->bins;1021CvSparseMatIterator iterator;1022CvSparseNode* node;10231024for( node = cvInitSparseMatIterator( sparse0, &iterator );1025node != 0; node = cvGetNextSparseNode( &iterator ) )1026{1027const int* idx = CV_NODE_IDX(sparse0, node);1028double v0 = *(float*)CV_NODE_VAL(sparse0, node);1029double v1 = (float)cvGetRealND(sparse1, idx);10301031result0[CV_COMP_CORREL] += v0*v1;1032result0[CV_COMP_INTERSECT] += MIN(v0,v1);1033if( fabs(v0) > DBL_EPSILON )1034result0[CV_COMP_CHISQR] += (v0 - v1)*(v0 - v1)/v0;1035if( fabs(v0 + v1) > DBL_EPSILON )1036result0[CV_COMP_CHISQR_ALT] += (v0 - v1)*(v0 - v1)/(v0 + v1);1037s0 += v0;1038sq0 += v0*v0;1039result0[CV_COMP_BHATTACHARYYA] += sqrt(v0*v1);1040{1041if (v0 <= DBL_EPSILON)1042continue;1043if (!v1)1044v1 = 1e-10;1045result0[CV_COMP_KL_DIV] += v0 * std::log( v0 / v1 );1046}1047}10481049for( node = cvInitSparseMatIterator( sparse1, &iterator );1050node != 0; node = cvGetNextSparseNode( &iterator ) )1051{1052double v1 = *(float*)CV_NODE_VAL(sparse1, node);1053s1 += v1;1054sq1 += v1*v1;1055}1056}10571058result0[CV_COMP_CHISQR_ALT] *= 2;10591060t = (sq0 - s0*s0/total_size)*(sq1 - s1*s1/total_size);1061result0[CV_COMP_CORREL] = fabs(t) > DBL_EPSILON ?1062(result0[CV_COMP_CORREL] - s0*s1/total_size)/sqrt(t) : 1;10631064s1 *= s0;1065s0 = result0[CV_COMP_BHATTACHARYYA];1066s0 = 1. - s0*(s1 > FLT_EPSILON ? 1./sqrt(s1) : 1.);1067result0[CV_COMP_BHATTACHARYYA] = sqrt(MAX(s0,0.));10681069for( i = 0; i < MAX_METHOD; i++ )1070{1071double v = result[i], v0 = result0[i];1072const char* method_name =1073i == CV_COMP_CHISQR ? "Chi-Square" :1074i == CV_COMP_CHISQR_ALT ? "Alternative Chi-Square" :1075i == CV_COMP_CORREL ? "Correlation" :1076i == CV_COMP_INTERSECT ? "Intersection" :1077i == CV_COMP_BHATTACHARYYA ? "Bhattacharyya" :1078i == CV_COMP_KL_DIV ? "Kullback-Leibler" : "Unknown";10791080if( cvIsNaN(v) || cvIsInf(v) )1081{1082ts->printf( cvtest::TS::LOG, "The comparison result using the method #%d (%s) is invalid (=%g)\n",1083i, method_name, v );1084code = cvtest::TS::FAIL_INVALID_OUTPUT;1085break;1086}1087else if( fabs(v0 - v) > FLT_EPSILON*14*MAX(fabs(v0),0.1) )1088{1089ts->printf( cvtest::TS::LOG, "The comparison result using the method #%d (%s)\n\tis inaccurate (=%g, should be =%g)\n",1090i, method_name, v, v0 );1091code = cvtest::TS::FAIL_BAD_ACCURACY;1092break;1093}1094}10951096if( code < 0 )1097ts->set_failed_test_info( code );1098return code;1099}110011011102////////////// cvCalcHist //////////////11031104class CV_CalcHistTest : public CV_BaseHistTest1105{1106public:1107CV_CalcHistTest();1108~CV_CalcHistTest();1109void clear();11101111protected:1112int prepare_test_case( int test_case_idx );1113void run_func(void);1114int validate_test_results( int test_case_idx );1115vector<Mat> images;1116vector<int> channels;1117};1118111911201121CV_CalcHistTest::CV_CalcHistTest() : images(CV_MAX_DIM+1), channels(CV_MAX_DIM+1)1122{1123hist_count = 2;1124gen_random_hist = 0;1125init_ranges = 1;1126}112711281129CV_CalcHistTest::~CV_CalcHistTest()1130{1131clear();1132}113311341135void CV_CalcHistTest::clear()1136{1137CV_BaseHistTest::clear();1138}113911401141int CV_CalcHistTest::prepare_test_case( int test_case_idx )1142{1143int code = CV_BaseHistTest::prepare_test_case( test_case_idx );11441145if( code > 0 )1146{1147RNG& rng = ts->get_rng();1148int i;11491150for( i = 0; i <= CV_MAX_DIM; i++ )1151{1152if( i < cdims )1153{1154int nch = 1; //cvtest::randInt(rng) % 3 + 1;1155images[i] = Mat(img_size, CV_MAKETYPE(img_type, nch));1156channels[i] = cvtest::randInt(rng) % nch;1157cvtest::randUni( rng, images[i], Scalar::all(low), Scalar::all(high) );1158}1159else if( i == CV_MAX_DIM )1160{1161if( cvtest::randInt(rng) % 2 )1162{1163// create mask1164images[i] = Mat(img_size, CV_8U);11651166// make ~25% pixels in the mask non-zero1167cvtest::randUni( rng, images[i], Scalar::all(-2), Scalar::all(2) );1168}1169else1170images[i] = Mat();1171}1172}1173}11741175return code;1176}117711781179void CV_CalcHistTest::run_func(void)1180{1181int size[CV_MAX_DIM];1182int hdims = cvGetDims( hist[0]->bins, size);1183bool huniform = CV_IS_UNIFORM_HIST(hist[0]);11841185const float* uranges[CV_MAX_DIM] = {0};1186const float** hranges = 0;11871188if( hist[0]->type & CV_HIST_RANGES_FLAG )1189{1190hranges = (const float**)hist[0]->thresh2;1191if( huniform )1192{1193for(int i = 0; i < hdims; i++ )1194uranges[i] = &hist[0]->thresh[i][0];1195hranges = uranges;1196}1197}11981199std::vector<cv::Mat> imagesv(cdims);1200copy(images.begin(), images.begin() + cdims, imagesv.begin());12011202Mat mask = images[CV_MAX_DIM];1203if( !CV_IS_SPARSE_HIST(hist[0]) )1204{1205cv::Mat H = cv::cvarrToMat(hist[0]->bins);1206if(huniform)1207{1208vector<int> emptyChannels;1209vector<int> hSize(hdims);1210for(int i = 0; i < hdims; i++)1211hSize[i] = size[i];1212vector<float> vranges;1213if(hranges)1214{1215vranges.resize(hdims*2);1216for(int i = 0; i < hdims; i++ )1217{1218vranges[i*2 ] = hist[0]->thresh[i][0];1219vranges[i*2+1] = hist[0]->thresh[i][1];1220}1221}1222cv::calcHist(imagesv, emptyChannels, mask, H, hSize, vranges);1223}1224else1225{1226cv::calcHist( &imagesv[0], (int)imagesv.size(), 0, mask,1227H, cvGetDims(hist[0]->bins), H.size, hranges, huniform );1228}1229}1230else1231{1232CvSparseMat* sparsemat = (CvSparseMat*)hist[0]->bins;12331234cvZero( hist[0]->bins );12351236cv::SparseMat sH;1237sparsemat->copyToSparseMat(sH);12381239cv::calcHist( &imagesv[0], (int)imagesv.size(), 0, mask, sH, sH.dims(),1240sH.dims() > 0 ? sH.hdr->size : 0, hranges, huniform, false);12411242cv::SparseMatConstIterator it = sH.begin();1243int nz = (int)sH.nzcount();1244for(int i = 0; i < nz; i++, ++it )1245{1246CV_Assert(it.ptr != NULL);1247*(float*)cvPtrND(sparsemat, it.node()->idx, 0, -2) = *(const float*)it.ptr;1248}1249}1250}125112521253static void1254cvTsCalcHist( const vector<Mat>& images, CvHistogram* hist, Mat mask, const vector<int>& channels )1255{1256int x, y, k;1257union1258{1259const float* fl;1260const uchar* ptr;1261}1262plane[CV_MAX_DIM];1263int nch[CV_MAX_DIM];1264int dims[CV_MAX_DIM];1265int uniform = CV_IS_UNIFORM_HIST(hist);12661267int cdims = cvGetDims( hist->bins, dims );1268cvZero( hist->bins );12691270Size img_size = images[0].size();1271int img_depth = images[0].depth();1272for( k = 0; k < cdims; k++ )1273{1274nch[k] = images[k].channels();1275}12761277for( y = 0; y < img_size.height; y++ )1278{1279const uchar* mptr = mask.empty() ? 0 : mask.ptr<uchar>(y);12801281if( img_depth == CV_8U )1282for( k = 0; k < cdims; k++ )1283plane[k].ptr = images[k].ptr<uchar>(y) + channels[k];1284else1285for( k = 0; k < cdims; k++ )1286plane[k].fl = images[k].ptr<float>(y) + channels[k];12871288for( x = 0; x < img_size.width; x++ )1289{1290float val[CV_MAX_DIM];1291int idx[CV_MAX_DIM];12921293if( mptr && !mptr[x] )1294continue;1295if( img_depth == CV_8U )1296for( k = 0; k < cdims; k++ )1297val[k] = plane[k].ptr[x*nch[k]];1298else1299for( k = 0; k < cdims; k++ )1300val[k] = plane[k].fl[x*nch[k]];13011302idx[cdims-1] = -1;13031304if( uniform )1305{1306for( k = 0; k < cdims; k++ )1307{1308double v = val[k], lo = hist->thresh[k][0], hi = hist->thresh[k][1];1309idx[k] = cvFloor((v - lo)*dims[k]/(hi - lo));1310if( idx[k] < 0 || idx[k] >= dims[k] )1311break;1312}1313}1314else1315{1316for( k = 0; k < cdims; k++ )1317{1318float v = val[k];1319float* t = hist->thresh2[k];1320int j, n = dims[k];13211322for( j = 0; j <= n; j++ )1323if( v < t[j] )1324break;1325if( j <= 0 || j > n )1326break;1327idx[k] = j-1;1328}1329}13301331if( k < cdims )1332continue;13331334(*(float*)cvPtrND( hist->bins, idx ))++;1335}1336}1337}133813391340int CV_CalcHistTest::validate_test_results( int /*test_case_idx*/ )1341{1342int code = cvtest::TS::OK;1343double diff;1344cvTsCalcHist( images, hist[1], images[CV_MAX_DIM], channels );1345diff = cvCompareHist( hist[0], hist[1], CV_COMP_CHISQR );1346if( diff > DBL_EPSILON )1347{1348ts->printf( cvtest::TS::LOG, "The histogram does not match to the reference one\n" );1349code = cvtest::TS::FAIL_BAD_ACCURACY;13501351}13521353if( code < 0 )1354ts->set_failed_test_info( code );1355return code;1356}135713581359CV_CalcHistTest hist_calc_test;1360136113621363////////////// cvCalcBackProject //////////////13641365class CV_CalcBackProjectTest : public CV_BaseHistTest1366{1367public:1368CV_CalcBackProjectTest();1369~CV_CalcBackProjectTest();1370void clear();13711372protected:1373int prepare_test_case( int test_case_idx );1374void run_func(void);1375int validate_test_results( int test_case_idx );1376vector<Mat> images;1377vector<int> channels;1378};1379138013811382CV_CalcBackProjectTest::CV_CalcBackProjectTest() : images(CV_MAX_DIM+3), channels(CV_MAX_DIM+3)1383{1384hist_count = 1;1385gen_random_hist = 0;1386init_ranges = 1;1387}138813891390CV_CalcBackProjectTest::~CV_CalcBackProjectTest()1391{1392clear();1393}139413951396void CV_CalcBackProjectTest::clear()1397{1398CV_BaseHistTest::clear();1399}140014011402int CV_CalcBackProjectTest::prepare_test_case( int test_case_idx )1403{1404int code = CV_BaseHistTest::prepare_test_case( test_case_idx );14051406if( code > 0 )1407{1408RNG& rng = ts->get_rng();1409int i, j, n, img_len = img_size.area();14101411for( i = 0; i < CV_MAX_DIM + 3; i++ )1412{1413if( i < cdims )1414{1415int nch = 1; //cvtest::randInt(rng) % 3 + 1;1416images[i] = Mat(img_size, CV_MAKETYPE(img_type, nch));1417channels[i] = cvtest::randInt(rng) % nch;14181419cvtest::randUni( rng, images[i], Scalar::all(low), Scalar::all(high) );1420}1421else if( i == CV_MAX_DIM )1422{1423if(cvtest::randInt(rng) % 2 )1424{1425// create mask1426images[i] = Mat(img_size, CV_8U);1427// make ~25% pixels in the mask non-zero1428cvtest::randUni( rng, images[i], Scalar::all(-2), Scalar::all(2) );1429}1430else1431{1432images[i] = Mat();1433}1434}1435else if( i > CV_MAX_DIM )1436{1437images[i] = Mat(img_size, images[0].type());1438}1439}14401441cvTsCalcHist( images, hist[0], images[CV_MAX_DIM], channels );14421443// now modify the images a bit to add some zeros go to the backprojection1444n = cvtest::randInt(rng) % (img_len/20+1);1445for( i = 0; i < cdims; i++ )1446{1447uchar* data = images[i].data;1448for( j = 0; j < n; j++ )1449{1450int idx = cvtest::randInt(rng) % img_len;1451double val = cvtest::randReal(rng)*(high - low) + low;14521453if( img_type == CV_8U )1454((uchar*)data)[idx] = (uchar)cvRound(val);1455else1456((float*)data)[idx] = (float)val;1457}1458}1459}14601461return code;1462}146314641465void CV_CalcBackProjectTest::run_func(void)1466{1467int size[CV_MAX_DIM];1468int hdims = cvGetDims( hist[0]->bins, size );14691470bool huniform = CV_IS_UNIFORM_HIST(hist[0]);1471const float* uranges[CV_MAX_DIM] = {0};1472const float** hranges = 0;14731474if( hist[0]->type & CV_HIST_RANGES_FLAG )1475{1476hranges = (const float**)hist[0]->thresh2;1477if( huniform )1478{1479for(int i = 0; i < hdims; i++ )1480uranges[i] = &hist[0]->thresh[i][0];1481hranges = uranges;1482}1483}14841485std::vector<cv::Mat> imagesv(hdims);1486copy(images.begin(), images.begin() + hdims, imagesv.begin());14871488cv::Mat dst = images[CV_MAX_DIM+1];14891490CV_Assert( dst.size() == imagesv[0].size() && dst.depth() == imagesv[0].depth() );14911492if( !CV_IS_SPARSE_HIST(hist[0]) )1493{1494cv::Mat H = cv::cvarrToMat(hist[0]->bins);1495if(huniform)1496{1497vector<int> emptyChannels;1498vector<float> vranges;1499if(hranges)1500{1501vranges.resize(hdims*2);1502for(int i = 0; i < hdims; i++ )1503{1504vranges[i*2 ] = hist[0]->thresh[i][0];1505vranges[i*2+1] = hist[0]->thresh[i][1];1506}1507}1508cv::calcBackProject(imagesv, emptyChannels, H, dst, vranges, 1);1509}1510else1511{1512cv::calcBackProject( &imagesv[0], (int)imagesv.size(),15130, H, dst, hranges, 1, false );1514}1515}1516else1517{1518cv::SparseMat sH;1519((const CvSparseMat*)hist[0]->bins)->copyToSparseMat(sH);1520cv::calcBackProject( &imagesv[0], (int)imagesv.size(),15210, sH, dst, hranges, 1, huniform );1522}1523}152415251526static void1527cvTsCalcBackProject( const vector<Mat>& images, Mat dst, CvHistogram* hist, const vector<int>& channels )1528{1529int x, y, k, cdims;1530union1531{1532const float* fl;1533const uchar* ptr;1534}1535plane[CV_MAX_DIM];1536int nch[CV_MAX_DIM];1537int dims[CV_MAX_DIM];1538int uniform = CV_IS_UNIFORM_HIST(hist);1539Size img_size = images[0].size();1540int img_depth = images[0].depth();15411542cdims = cvGetDims( hist->bins, dims );15431544for( k = 0; k < cdims; k++ )1545nch[k] = images[k].channels();15461547for( y = 0; y < img_size.height; y++ )1548{1549if( img_depth == CV_8U )1550for( k = 0; k < cdims; k++ )1551plane[k].ptr = images[k].ptr<uchar>(y) + channels[k];1552else1553for( k = 0; k < cdims; k++ )1554plane[k].fl = images[k].ptr<float>(y) + channels[k];15551556for( x = 0; x < img_size.width; x++ )1557{1558float val[CV_MAX_DIM];1559float bin_val = 0;1560int idx[CV_MAX_DIM];15611562if( img_depth == CV_8U )1563for( k = 0; k < cdims; k++ )1564val[k] = plane[k].ptr[x*nch[k]];1565else1566for( k = 0; k < cdims; k++ )1567val[k] = plane[k].fl[x*nch[k]];1568idx[cdims-1] = -1;15691570if( uniform )1571{1572for( k = 0; k < cdims; k++ )1573{1574double v = val[k], lo = hist->thresh[k][0], hi = hist->thresh[k][1];1575idx[k] = cvFloor((v - lo)*dims[k]/(hi - lo));1576if( idx[k] < 0 || idx[k] >= dims[k] )1577break;1578}1579}1580else1581{1582for( k = 0; k < cdims; k++ )1583{1584float v = val[k];1585float* t = hist->thresh2[k];1586int j, n = dims[k];15871588for( j = 0; j <= n; j++ )1589if( v < t[j] )1590break;1591if( j <= 0 || j > n )1592break;1593idx[k] = j-1;1594}1595}15961597if( k == cdims )1598bin_val = (float)cvGetRealND( hist->bins, idx );15991600if( img_depth == CV_8U )1601{1602int t = cvRound(bin_val);1603dst.at<uchar>(y, x) = saturate_cast<uchar>(t);1604}1605else1606dst.at<float>(y, x) = bin_val;1607}1608}1609}161016111612int CV_CalcBackProjectTest::validate_test_results( int /*test_case_idx*/ )1613{1614int code = cvtest::TS::OK;16151616cvTsCalcBackProject( images, images[CV_MAX_DIM+2], hist[0], channels );1617Mat a = images[CV_MAX_DIM+1], b = images[CV_MAX_DIM+2];1618double threshold = a.depth() == CV_8U ? 2 : FLT_EPSILON;1619code = cvtest::cmpEps2( ts, a, b, threshold, true, "Back project image" );16201621if( code < 0 )1622ts->set_failed_test_info( code );16231624return code;1625}162616271628////////////// cvCalcBackProjectPatch //////////////16291630class CV_CalcBackProjectPatchTest : public CV_BaseHistTest1631{1632public:1633CV_CalcBackProjectPatchTest();1634~CV_CalcBackProjectPatchTest();1635void clear();16361637protected:1638int prepare_test_case( int test_case_idx );1639void run_func(void);1640int validate_test_results( int test_case_idx );1641vector<Mat> images;1642vector<int> channels;16431644Size patch_size;1645double factor;1646int method;1647};164816491650CV_CalcBackProjectPatchTest::CV_CalcBackProjectPatchTest() :1651images(CV_MAX_DIM+2), channels(CV_MAX_DIM+2)1652{1653hist_count = 1;1654gen_random_hist = 0;1655init_ranges = 1;1656img_max_log_size = 6;1657}165816591660CV_CalcBackProjectPatchTest::~CV_CalcBackProjectPatchTest()1661{1662clear();1663}166416651666void CV_CalcBackProjectPatchTest::clear()1667{1668CV_BaseHistTest::clear();1669}167016711672int CV_CalcBackProjectPatchTest::prepare_test_case( int test_case_idx )1673{1674int code = CV_BaseHistTest::prepare_test_case( test_case_idx );16751676if( code > 0 )1677{1678RNG& rng = ts->get_rng();1679int i, j, n, img_len = img_size.area();16801681patch_size.width = cvtest::randInt(rng) % img_size.width + 1;1682patch_size.height = cvtest::randInt(rng) % img_size.height + 1;1683patch_size.width = MIN( patch_size.width, 30 );1684patch_size.height = MIN( patch_size.height, 30 );16851686factor = 1.;1687method = cvtest::randInt(rng) % CV_CompareHistTest::MAX_METHOD;16881689for( i = 0; i < CV_MAX_DIM + 2; i++ )1690{1691if( i < cdims )1692{1693int nch = 1; //cvtest::randInt(rng) % 3 + 1;1694images[i] = Mat(img_size, CV_MAKETYPE(img_type, nch));1695channels[i] = cvtest::randInt(rng) % nch;1696cvtest::randUni( rng, images[i], Scalar::all(low), Scalar::all(high) );1697}1698else if( i >= CV_MAX_DIM )1699{1700images[i] = Mat(img_size - patch_size + Size(1, 1), CV_32F);1701}1702}17031704cvTsCalcHist( images, hist[0], Mat(), channels );1705cvNormalizeHist( hist[0], factor );17061707// now modify the images a bit1708n = cvtest::randInt(rng) % (img_len/10+1);1709for( i = 0; i < cdims; i++ )1710{1711uchar* data = images[i].data;1712for( j = 0; j < n; j++ )1713{1714int idx = cvtest::randInt(rng) % img_len;1715double val = cvtest::randReal(rng)*(high - low) + low;17161717if( img_type == CV_8U )1718((uchar*)data)[idx] = (uchar)cvRound(val);1719else1720((float*)data)[idx] = (float)val;1721}1722}1723}17241725return code;1726}172717281729void CV_CalcBackProjectPatchTest::run_func(void)1730{1731CvMat dst = cvMat(images[CV_MAX_DIM]);1732vector<CvMat > img(cdims);1733vector<CvMat*> pimg(cdims);1734for(int i = 0; i < cdims; i++)1735{1736img[i] = cvMat(images[i]);1737pimg[i] = &img[i];1738}1739cvCalcArrBackProjectPatch( (CvArr**)&pimg[0], &dst, cvSize(patch_size), hist[0], method, factor );1740}174117421743static void1744cvTsCalcBackProjectPatch( const vector<Mat>& images, Mat dst, Size patch_size,1745CvHistogram* hist, int method,1746double factor, const vector<int>& channels )1747{1748CvHistogram* model = 0;17491750int x, y;1751Size size = dst.size();17521753cvCopyHist( hist, &model );1754cvNormalizeHist( hist, factor );17551756vector<Mat> img(images.size());1757for( y = 0; y < size.height; y++ )1758{1759for( x = 0; x < size.width; x++ )1760{1761double result;17621763Rect roi(Point(x, y), patch_size);1764for(size_t i = 0; i < img.size(); i++)1765img[i] = images[i](roi);17661767cvTsCalcHist( img, model, Mat(), channels );1768cvNormalizeHist( model, factor );1769result = cvCompareHist( model, hist, method );1770dst.at<float>(y, x) = (float)result;1771}1772}17731774cvReleaseHist( &model );1775}177617771778int CV_CalcBackProjectPatchTest::validate_test_results( int /*test_case_idx*/ )1779{1780int code = cvtest::TS::OK;1781double err_level = 5e-3;17821783Mat dst = images[CV_MAX_DIM+1];1784vector<Mat> imagesv(cdims);1785for(int i = 0; i < cdims; i++)1786imagesv[i] = images[i];1787cvTsCalcBackProjectPatch( imagesv, dst, patch_size, hist[0],1788method, factor, channels );17891790Mat a = images[CV_MAX_DIM], b = images[CV_MAX_DIM+1];1791code = cvtest::cmpEps2( ts, a, b, err_level, true, "BackProjectPatch result" );17921793if( code < 0 )1794ts->set_failed_test_info( code );17951796return code;1797}179817991800////////////// cvCalcBayesianProb //////////////18011802class CV_BayesianProbTest : public CV_BaseHistTest1803{1804public:1805enum { MAX_METHOD = 4 };18061807CV_BayesianProbTest();1808protected:1809int prepare_test_case( int test_case_idx );1810void run_func(void);1811int validate_test_results( int test_case_idx );1812void init_hist( int test_case_idx, int i );1813void get_hist_params( int test_case_idx );1814};1815181618171818CV_BayesianProbTest::CV_BayesianProbTest()1819{1820hist_count = CV_MAX_DIM;1821gen_random_hist = 1;1822}182318241825void CV_BayesianProbTest::get_hist_params( int test_case_idx )1826{1827CV_BaseHistTest::get_hist_params( test_case_idx );1828hist_type = CV_HIST_ARRAY;1829}183018311832void CV_BayesianProbTest::init_hist( int test_case_idx, int hist_i )1833{1834if( hist_i < hist_count/2 )1835CV_BaseHistTest::init_hist( test_case_idx, hist_i );1836}183718381839int CV_BayesianProbTest::prepare_test_case( int test_case_idx )1840{1841RNG& rng = ts->get_rng();18421843hist_count = (cvtest::randInt(rng) % (MAX_HIST/2-1) + 2)*2;1844hist_count = MIN( hist_count, MAX_HIST );1845int code = CV_BaseHistTest::prepare_test_case( test_case_idx );18461847return code;1848}184918501851void CV_BayesianProbTest::run_func(void)1852{1853cvCalcBayesianProb( &hist[0], hist_count/2, &hist[hist_count/2] );1854}185518561857int CV_BayesianProbTest::validate_test_results( int /*test_case_idx*/ )1858{1859int code = cvtest::TS::OK;1860int i, j, n = hist_count/2;1861double s[CV_MAX_DIM];1862const double err_level = 1e-5;18631864for( i = 0; i < total_size; i++ )1865{1866double sum = 0;1867for( j = 0; j < n; j++ )1868{1869double v = hist[j]->mat.data.fl[i];1870sum += v;1871s[j] = v;1872}1873sum = sum > DBL_EPSILON ? 1./sum : 0;18741875for( j = 0; j < n; j++ )1876{1877double v0 = s[j]*sum;1878double v = hist[j+n]->mat.data.fl[i];18791880if( cvIsNaN(v) || cvIsInf(v) )1881{1882ts->printf( cvtest::TS::LOG,1883"The element #%d in the destination histogram #%d is invalid (=%g)\n",1884i, j, v );1885code = cvtest::TS::FAIL_INVALID_OUTPUT;1886break;1887}1888else if( fabs(v0 - v) > err_level*fabs(v0) )1889{1890ts->printf( cvtest::TS::LOG,1891"The element #%d in the destination histogram #%d is inaccurate (=%g, should be =%g)\n",1892i, j, v, v0 );1893code = cvtest::TS::FAIL_BAD_ACCURACY;1894break;1895}1896}1897if( j < n )1898break;1899}19001901if( code < 0 )1902ts->set_failed_test_info( code );1903return code;1904}19051906//////////////////////////////////////////////////////////////////////////////////////////////////////19071908TEST(Imgproc_Hist_Calc, accuracy) { CV_CalcHistTest test; test.safe_run(); }1909TEST(Imgproc_Hist_Query, accuracy) { CV_QueryHistTest test; test.safe_run(); }19101911TEST(Imgproc_Hist_Compare, accuracy) { CV_CompareHistTest test; test.safe_run(); }1912TEST(Imgproc_Hist_Threshold, accuracy) { CV_ThreshHistTest test; test.safe_run(); }1913TEST(Imgproc_Hist_Normalize, accuracy) { CV_NormHistTest test; test.safe_run(); }1914TEST(Imgproc_Hist_MinMaxVal, accuracy) { CV_MinMaxHistTest test; test.safe_run(); }19151916TEST(Imgproc_Hist_CalcBackProject, accuracy) { CV_CalcBackProjectTest test; test.safe_run(); }1917TEST(Imgproc_Hist_CalcBackProjectPatch, accuracy) { CV_CalcBackProjectPatchTest test; test.safe_run(); }1918TEST(Imgproc_Hist_BayesianProb, accuracy) { CV_BayesianProbTest test; test.safe_run(); }19191920TEST(Imgproc_Hist_Calc, calcHist_regression_11544)1921{1922cv::Mat1w m = cv::Mat1w::zeros(10, 10);1923int n_images = 1;1924int channels[] = { 0 };1925cv::Mat mask;1926cv::MatND hist1, hist2;1927cv::MatND hist1_opt, hist2_opt;1928int dims = 1;1929int hist_size[] = { 1000 };1930float range1[] = { 0, 900 };1931float range2[] = { 0, 1000 };1932const float* ranges1[] = { range1 };1933const float* ranges2[] = { range2 };19341935setUseOptimized(false);1936cv::calcHist(&m, n_images, channels, mask, hist1, dims, hist_size, ranges1);1937cv::calcHist(&m, n_images, channels, mask, hist2, dims, hist_size, ranges2);19381939setUseOptimized(true);1940cv::calcHist(&m, n_images, channels, mask, hist1_opt, dims, hist_size, ranges1);1941cv::calcHist(&m, n_images, channels, mask, hist2_opt, dims, hist_size, ranges2);19421943for(int i = 0; i < 1000; i++)1944{1945EXPECT_EQ(hist1.at<float>(i, 0), hist1_opt.at<float>(i, 0)) << i;1946EXPECT_EQ(hist2.at<float>(i, 0), hist2_opt.at<float>(i, 0)) << i;1947}1948}19491950}} // namespace1951/* End Of File */195219531954