test_histograms.cpp 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998
  1. /*M///////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
  4. //
  5. // By downloading, copying, installing or using the software you agree to this license.
  6. // If you do not agree to this license, do not download, install,
  7. // copy or use the software.
  8. //
  9. //
  10. // Intel License Agreement
  11. // For Open Source Computer Vision Library
  12. //
  13. // Copyright (C) 2000, Intel Corporation, all rights reserved.
  14. // Third party copyrights are property of their respective owners.
  15. //
  16. // Redistribution and use in source and binary forms, with or without modification,
  17. // are permitted provided that the following conditions are met:
  18. //
  19. // * Redistribution's of source code must retain the above copyright notice,
  20. // this list of conditions and the following disclaimer.
  21. //
  22. // * Redistribution's in binary form must reproduce the above copyright notice,
  23. // this list of conditions and the following disclaimer in the documentation
  24. // and/or other materials provided with the distribution.
  25. //
  26. // * The name of Intel Corporation may not be used to endorse or promote products
  27. // derived from this software without specific prior written permission.
  28. //
  29. // This software is provided by the copyright holders and contributors "as is" and
  30. // any express or implied warranties, including, but not limited to, the implied
  31. // warranties of merchantability and fitness for a particular purpose are disclaimed.
  32. // In no event shall the Intel Corporation or contributors be liable for any direct,
  33. // indirect, incidental, special, exemplary, or consequential damages
  34. // (including, but not limited to, procurement of substitute goods or services;
  35. // loss of use, data, or profits; or business interruption) however caused
  36. // and on any theory of liability, whether in contract, strict liability,
  37. // or tort (including negligence or otherwise) arising in any way out of
  38. // the use of this software, even if advised of the possibility of such damage.
  39. //
  40. //M*/
  41. #include "test_precomp.hpp"
  42. namespace opencv_test { namespace {
  43. class CV_BaseHistTest : public cvtest::BaseTest
  44. {
  45. public:
  46. enum { MAX_HIST = 12 };
  47. CV_BaseHistTest();
  48. ~CV_BaseHistTest();
  49. void clear();
  50. protected:
  51. int read_params( const cv::FileStorage& fs );
  52. void run_func(void);
  53. int prepare_test_case( int test_case_idx );
  54. int validate_test_results( int test_case_idx );
  55. virtual void init_hist( int test_case_idx, int i );
  56. virtual void get_hist_params( int test_case_idx );
  57. virtual float** get_hist_ranges( int test_case_idx );
  58. int max_log_size;
  59. int max_cdims;
  60. int cdims;
  61. int dims[CV_MAX_DIM];
  62. int total_size;
  63. int hist_type;
  64. int hist_count;
  65. int uniform;
  66. int gen_random_hist;
  67. double gen_hist_max_val, gen_hist_sparse_nz_ratio;
  68. int init_ranges;
  69. int img_type;
  70. int img_max_log_size;
  71. double low, high, range_delta;
  72. Size img_size;
  73. vector<CvHistogram*> hist;
  74. vector<float> _ranges;
  75. vector<float*> ranges;
  76. bool test_cpp;
  77. };
  78. CV_BaseHistTest::CV_BaseHistTest()
  79. {
  80. test_case_count = 100;
  81. max_log_size = 20;
  82. img_max_log_size = 8;
  83. max_cdims = 6;
  84. hist_count = 1;
  85. init_ranges = 0;
  86. gen_random_hist = 0;
  87. gen_hist_max_val = 100;
  88. test_cpp = false;
  89. }
  90. CV_BaseHistTest::~CV_BaseHistTest()
  91. {
  92. clear();
  93. }
  94. void CV_BaseHistTest::clear()
  95. {
  96. cvtest::BaseTest::clear();
  97. for( size_t i = 0; i < hist.size(); i++ )
  98. cvReleaseHist( &hist[i] );
  99. }
  100. int CV_BaseHistTest::read_params( const cv::FileStorage& fs )
  101. {
  102. int code = cvtest::BaseTest::read_params( fs );
  103. if( code < 0 )
  104. return code;
  105. read( find_param( fs, "struct_count" ), test_case_count, test_case_count );
  106. read( find_param( fs, "max_log_size" ), max_log_size, max_log_size );
  107. max_log_size = cvtest::clipInt( max_log_size, 1, 20 );
  108. read( find_param( fs, "max_log_array_size" ), img_max_log_size, img_max_log_size );
  109. img_max_log_size = cvtest::clipInt( img_max_log_size, 1, 9 );
  110. read( find_param( fs, "max_cdims" ), max_cdims, max_cdims );
  111. max_cdims = cvtest::clipInt( max_cdims, 1, 6 );
  112. return 0;
  113. }
  114. void CV_BaseHistTest::get_hist_params( int /*test_case_idx*/ )
  115. {
  116. RNG& rng = ts->get_rng();
  117. int i, max_dim_size, max_ni_dim_size = 31;
  118. double hist_size;
  119. cdims = cvtest::randInt(rng) % max_cdims + 1;
  120. hist_size = exp(cvtest::randReal(rng)*max_log_size*CV_LOG2);
  121. max_dim_size = cvRound(pow(hist_size,1./cdims));
  122. total_size = 1;
  123. uniform = cvtest::randInt(rng) % 2;
  124. hist_type = cvtest::randInt(rng) % 2 ? CV_HIST_SPARSE : CV_HIST_ARRAY;
  125. for( i = 0; i < cdims; i++ )
  126. {
  127. dims[i] = cvtest::randInt(rng) % (max_dim_size + 2) + 2;
  128. if( !uniform )
  129. dims[i] = MIN(dims[i], max_ni_dim_size);
  130. total_size *= dims[i];
  131. }
  132. img_type = cvtest::randInt(rng) % 2 ? CV_32F : CV_8U;
  133. img_size.width = cvRound( exp(cvtest::randReal(rng) * img_max_log_size * CV_LOG2) );
  134. img_size.height = cvRound( exp(cvtest::randReal(rng) * img_max_log_size * CV_LOG2) );
  135. if( img_type < CV_32F )
  136. {
  137. low = cvtest::getMinVal(img_type);
  138. high = cvtest::getMaxVal(img_type);
  139. }
  140. else
  141. {
  142. high = 1000;
  143. low = -high;
  144. }
  145. range_delta = (cvtest::randInt(rng) % 2)*(high-low)*0.05;
  146. }
  147. float** CV_BaseHistTest::get_hist_ranges( int /*test_case_idx*/ )
  148. {
  149. double _low = low + range_delta, _high = high - range_delta;
  150. if( !init_ranges )
  151. return 0;
  152. ranges.resize(cdims);
  153. if( uniform )
  154. {
  155. _ranges.resize(cdims*2);
  156. for( int i = 0; i < cdims; i++ )
  157. {
  158. _ranges[i*2] = (float)_low;
  159. _ranges[i*2+1] = (float)_high;
  160. ranges[i] = &_ranges[i*2];
  161. }
  162. }
  163. else
  164. {
  165. int i, dims_sum = 0, ofs = 0;
  166. for( i = 0; i < cdims; i++ )
  167. dims_sum += dims[i] + 1;
  168. _ranges.resize(dims_sum);
  169. for( i = 0; i < cdims; i++ )
  170. {
  171. int j, n = dims[i];
  172. // generate logarithmic scale
  173. double delta, q, val;
  174. for( j = 0; j < 10; j++ )
  175. {
  176. q = 1. + (j+1)*0.1;
  177. if( (pow(q,(double)n)-1)/(q-1.) >= _high-_low )
  178. break;
  179. }
  180. if( j == 0 )
  181. {
  182. delta = (_high-_low)/n;
  183. q = 1.;
  184. }
  185. else
  186. {
  187. q = 1 + j*0.1;
  188. delta = cvFloor((_high-_low)*(q-1)/(pow(q,(double)n) - 1));
  189. delta = MAX(delta, 1.);
  190. }
  191. val = _low;
  192. for( j = 0; j <= n; j++ )
  193. {
  194. _ranges[j+ofs] = (float)MIN(val,_high);
  195. val += delta;
  196. delta *= q;
  197. }
  198. ranges[i] = &_ranges[ofs];
  199. ofs += n + 1;
  200. }
  201. }
  202. return &ranges[0];
  203. }
  204. void CV_BaseHistTest::init_hist( int /*test_case_idx*/, int hist_i )
  205. {
  206. if( gen_random_hist )
  207. {
  208. RNG& rng = ts->get_rng();
  209. if( hist_type == CV_HIST_ARRAY )
  210. {
  211. Mat h = cvarrToMat(hist[hist_i]->bins);
  212. cvtest::randUni(rng, h, Scalar::all(0), Scalar::all(gen_hist_max_val) );
  213. }
  214. else
  215. {
  216. CvArr* arr = hist[hist_i]->bins;
  217. int i, j, totalSize = 1, nz_count;
  218. int idx[CV_MAX_DIM];
  219. for( i = 0; i < cdims; i++ )
  220. totalSize *= dims[i];
  221. nz_count = cvtest::randInt(rng) % MAX( totalSize/4, 100 );
  222. nz_count = MIN( nz_count, totalSize );
  223. // a zero number of non-zero elements should be allowed
  224. for( i = 0; i < nz_count; i++ )
  225. {
  226. for( j = 0; j < cdims; j++ )
  227. idx[j] = cvtest::randInt(rng) % dims[j];
  228. cvSetRealND(arr, idx, cvtest::randReal(rng)*gen_hist_max_val);
  229. }
  230. }
  231. }
  232. }
  233. int CV_BaseHistTest::prepare_test_case( int test_case_idx )
  234. {
  235. int i;
  236. float** r;
  237. clear();
  238. cvtest::BaseTest::prepare_test_case( test_case_idx );
  239. get_hist_params( test_case_idx );
  240. r = get_hist_ranges( test_case_idx );
  241. hist.resize(hist_count);
  242. for( i = 0; i < hist_count; i++ )
  243. {
  244. hist[i] = cvCreateHist( cdims, dims, hist_type, r, uniform );
  245. init_hist( test_case_idx, i );
  246. }
  247. test_cpp = (cvtest::randInt(ts->get_rng()) % 2) != 0;
  248. return 1;
  249. }
  250. void CV_BaseHistTest::run_func(void)
  251. {
  252. }
  253. int CV_BaseHistTest::validate_test_results( int /*test_case_idx*/ )
  254. {
  255. return 0;
  256. }
  257. ////////////// testing operation for reading/writing individual histogram bins //////////////
  258. class CV_QueryHistTest : public CV_BaseHistTest
  259. {
  260. public:
  261. CV_QueryHistTest();
  262. ~CV_QueryHistTest();
  263. void clear();
  264. protected:
  265. void run_func(void);
  266. int prepare_test_case( int test_case_idx );
  267. int validate_test_results( int test_case_idx );
  268. void init_hist( int test_case_idx, int i );
  269. Mat indices;
  270. Mat values;
  271. Mat values0;
  272. };
  273. CV_QueryHistTest::CV_QueryHistTest()
  274. {
  275. hist_count = 1;
  276. }
  277. CV_QueryHistTest::~CV_QueryHistTest()
  278. {
  279. clear();
  280. }
  281. void CV_QueryHistTest::clear()
  282. {
  283. CV_BaseHistTest::clear();
  284. }
  285. void CV_QueryHistTest::init_hist( int /*test_case_idx*/, int i )
  286. {
  287. if( hist_type == CV_HIST_ARRAY )
  288. cvZero( hist[i]->bins );
  289. }
  290. int CV_QueryHistTest::prepare_test_case( int test_case_idx )
  291. {
  292. int code = CV_BaseHistTest::prepare_test_case( test_case_idx );
  293. if( code > 0 )
  294. {
  295. int i, j, iters;
  296. float default_value = 0.f;
  297. RNG& rng = ts->get_rng();
  298. int* idx;
  299. iters = (cvtest::randInt(rng) % MAX(total_size/10,100)) + 1;
  300. iters = MIN( iters, total_size*9/10 + 1 );
  301. indices = Mat(1, iters*cdims, CV_32S);
  302. values = Mat(1, iters, CV_32F );
  303. values0 = Mat( 1, iters, CV_32F );
  304. idx = indices.ptr<int>();
  305. //printf( "total_size = %d, cdims = %d, iters = %d\n", total_size, cdims, iters );
  306. Mat bit_mask(1, (total_size + 7)/8, CV_8U, Scalar(0));
  307. #define GET_BIT(n) (bit_mask.data[(n)/8] & (1 << ((n)&7)))
  308. #define SET_BIT(n) bit_mask.data[(n)/8] |= (1 << ((n)&7))
  309. // set random histogram bins' values to the linear indices of the bins
  310. for( i = 0; i < iters; i++ )
  311. {
  312. int lin_idx = 0;
  313. for( j = 0; j < cdims; j++ )
  314. {
  315. int t = cvtest::randInt(rng) % dims[j];
  316. idx[i*cdims + j] = t;
  317. lin_idx = lin_idx*dims[j] + t;
  318. }
  319. if( cvtest::randInt(rng) % 8 || GET_BIT(lin_idx) )
  320. {
  321. values0.at<float>(i) = (float)(lin_idx+1);
  322. SET_BIT(lin_idx);
  323. }
  324. else
  325. // some histogram bins will not be initialized intentionally,
  326. // they should be equal to the default value
  327. values0.at<float>(i) = default_value;
  328. }
  329. // do the second pass to make values0 consistent with bit_mask
  330. for( i = 0; i < iters; i++ )
  331. {
  332. int lin_idx = 0;
  333. for( j = 0; j < cdims; j++ )
  334. lin_idx = lin_idx*dims[j] + idx[i*cdims + j];
  335. if( GET_BIT(lin_idx) )
  336. values0.at<float>(i) = (float)(lin_idx+1);
  337. }
  338. }
  339. return code;
  340. }
  341. void CV_QueryHistTest::run_func(void)
  342. {
  343. int i, iters = values.cols;
  344. CvArr* h = hist[0]->bins;
  345. const int* idx = indices.ptr<int>();
  346. float* val = values.ptr<float>();
  347. float default_value = 0.f;
  348. // stage 1: write bins
  349. if( cdims == 1 )
  350. for( i = 0; i < iters; i++ )
  351. {
  352. float v0 = values0.at<float>(i);
  353. if( fabs(v0 - default_value) < FLT_EPSILON )
  354. continue;
  355. if( !(i % 2) )
  356. {
  357. if( !(i % 4) )
  358. cvSetReal1D( h, idx[i], v0 );
  359. else
  360. *(float*)cvPtr1D( h, idx[i] ) = v0;
  361. }
  362. else
  363. cvSetRealND( h, idx+i, v0 );
  364. }
  365. else if( cdims == 2 )
  366. for( i = 0; i < iters; i++ )
  367. {
  368. float v0 = values0.at<float>(i);
  369. if( fabs(v0 - default_value) < FLT_EPSILON )
  370. continue;
  371. if( !(i % 2) )
  372. {
  373. if( !(i % 4) )
  374. cvSetReal2D( h, idx[i*2], idx[i*2+1], v0 );
  375. else
  376. *(float*)cvPtr2D( h, idx[i*2], idx[i*2+1] ) = v0;
  377. }
  378. else
  379. cvSetRealND( h, idx+i*2, v0 );
  380. }
  381. else if( cdims == 3 )
  382. for( i = 0; i < iters; i++ )
  383. {
  384. float v0 = values0.at<float>(i);
  385. if( fabs(v0 - default_value) < FLT_EPSILON )
  386. continue;
  387. if( !(i % 2) )
  388. {
  389. if( !(i % 4) )
  390. cvSetReal3D( h, idx[i*3], idx[i*3+1], idx[i*3+2], v0 );
  391. else
  392. *(float*)cvPtr3D( h, idx[i*3], idx[i*3+1], idx[i*3+2] ) = v0;
  393. }
  394. else
  395. cvSetRealND( h, idx+i*3, v0 );
  396. }
  397. else
  398. for( i = 0; i < iters; i++ )
  399. {
  400. float v0 = values0.at<float>(i);
  401. if( fabs(v0 - default_value) < FLT_EPSILON )
  402. continue;
  403. if( !(i % 2) )
  404. cvSetRealND( h, idx+i*cdims, v0 );
  405. else
  406. *(float*)cvPtrND( h, idx+i*cdims ) = v0;
  407. }
  408. // stage 2: read bins
  409. if( cdims == 1 )
  410. for( i = 0; i < iters; i++ )
  411. {
  412. if( !(i % 2) )
  413. val[i] = *(float*)cvPtr1D( h, idx[i] );
  414. else
  415. val[i] = (float)cvGetReal1D( h, idx[i] );
  416. }
  417. else if( cdims == 2 )
  418. for( i = 0; i < iters; i++ )
  419. {
  420. if( !(i % 2) )
  421. val[i] = *(float*)cvPtr2D( h, idx[i*2], idx[i*2+1] );
  422. else
  423. val[i] = (float)cvGetReal2D( h, idx[i*2], idx[i*2+1] );
  424. }
  425. else if( cdims == 3 )
  426. for( i = 0; i < iters; i++ )
  427. {
  428. if( !(i % 2) )
  429. val[i] = *(float*)cvPtr3D( h, idx[i*3], idx[i*3+1], idx[i*3+2] );
  430. else
  431. val[i] = (float)cvGetReal3D( h, idx[i*3], idx[i*3+1], idx[i*3+2] );
  432. }
  433. else
  434. for( i = 0; i < iters; i++ )
  435. {
  436. if( !(i % 2) )
  437. val[i] = *(float*)cvPtrND( h, idx+i*cdims );
  438. else
  439. val[i] = (float)cvGetRealND( h, idx+i*cdims );
  440. }
  441. }
  442. int CV_QueryHistTest::validate_test_results( int /*test_case_idx*/ )
  443. {
  444. int code = cvtest::TS::OK;
  445. int i, j, iters = values.cols;
  446. for( i = 0; i < iters; i++ )
  447. {
  448. float v = values.at<float>(i), v0 = values0.at<float>(i);
  449. if( cvIsNaN(v) || cvIsInf(v) )
  450. {
  451. ts->printf( cvtest::TS::LOG, "The bin #%d has invalid value\n", i );
  452. code = cvtest::TS::FAIL_INVALID_OUTPUT;
  453. }
  454. else if( fabs(v - v0) > FLT_EPSILON )
  455. {
  456. ts->printf( cvtest::TS::LOG, "The bin #%d = %g, while it should be %g\n", i, v, v0 );
  457. code = cvtest::TS::FAIL_BAD_ACCURACY;
  458. }
  459. if( code < 0 )
  460. {
  461. ts->printf( cvtest::TS::LOG, "The bin index = (" );
  462. for( j = 0; j < cdims; j++ )
  463. ts->printf( cvtest::TS::LOG, "%d%s", indices.at<int>(i*cdims + j),
  464. j < cdims-1 ? ", " : ")\n" );
  465. break;
  466. }
  467. }
  468. if( code < 0 )
  469. ts->set_failed_test_info( code );
  470. return code;
  471. }
  472. ////////////// cvGetMinMaxHistValue //////////////
  473. class CV_MinMaxHistTest : public CV_BaseHistTest
  474. {
  475. public:
  476. CV_MinMaxHistTest();
  477. protected:
  478. void run_func(void);
  479. void init_hist(int, int);
  480. int validate_test_results( int test_case_idx );
  481. int min_idx[CV_MAX_DIM], max_idx[CV_MAX_DIM];
  482. float min_val, max_val;
  483. int min_idx0[CV_MAX_DIM], max_idx0[CV_MAX_DIM];
  484. float min_val0, max_val0;
  485. };
  486. CV_MinMaxHistTest::CV_MinMaxHistTest()
  487. {
  488. hist_count = 1;
  489. gen_random_hist = 1;
  490. }
  491. void CV_MinMaxHistTest::init_hist(int test_case_idx, int hist_i)
  492. {
  493. int i, eq = 1;
  494. RNG& rng = ts->get_rng();
  495. CV_BaseHistTest::init_hist( test_case_idx, hist_i );
  496. for(;;)
  497. {
  498. for( i = 0; i < cdims; i++ )
  499. {
  500. min_idx0[i] = cvtest::randInt(rng) % dims[i];
  501. max_idx0[i] = cvtest::randInt(rng) % dims[i];
  502. eq &= min_idx0[i] == max_idx0[i];
  503. }
  504. if( !eq || total_size == 1 )
  505. break;
  506. }
  507. min_val0 = (float)(-cvtest::randReal(rng)*10 - FLT_EPSILON);
  508. max_val0 = (float)(cvtest::randReal(rng)*10 + FLT_EPSILON + gen_hist_max_val);
  509. if( total_size == 1 )
  510. min_val0 = max_val0;
  511. cvSetRealND( hist[0]->bins, min_idx0, min_val0 );
  512. cvSetRealND( hist[0]->bins, max_idx0, max_val0 );
  513. }
  514. void CV_MinMaxHistTest::run_func(void)
  515. {
  516. if( hist_type != CV_HIST_ARRAY && test_cpp )
  517. {
  518. cv::SparseMat h;
  519. ((CvSparseMat*)hist[0]->bins)->copyToSparseMat(h);
  520. double _min_val = 0, _max_val = 0;
  521. cv::minMaxLoc(h, &_min_val, &_max_val, min_idx, max_idx );
  522. min_val = (float)_min_val;
  523. max_val = (float)_max_val;
  524. }
  525. else
  526. cvGetMinMaxHistValue( hist[0], &min_val, &max_val, min_idx, max_idx );
  527. }
  528. int CV_MinMaxHistTest::validate_test_results( int /*test_case_idx*/ )
  529. {
  530. int code = cvtest::TS::OK;
  531. if( cvIsNaN(min_val) || cvIsInf(min_val) ||
  532. cvIsNaN(max_val) || cvIsInf(max_val) )
  533. {
  534. ts->printf( cvtest::TS::LOG,
  535. "The extrema histogram bin values are invalid (min = %g, max = %g)\n", min_val, max_val );
  536. code = cvtest::TS::FAIL_INVALID_OUTPUT;
  537. }
  538. else if( fabs(min_val - min_val0) > FLT_EPSILON ||
  539. fabs(max_val - max_val0) > FLT_EPSILON )
  540. {
  541. ts->printf( cvtest::TS::LOG,
  542. "The extrema histogram bin values are incorrect: (min = %g, should be = %g), (max = %g, should be = %g)\n",
  543. min_val, min_val0, max_val, max_val0 );
  544. code = cvtest::TS::FAIL_BAD_ACCURACY;
  545. }
  546. else
  547. {
  548. int i;
  549. for( i = 0; i < cdims; i++ )
  550. {
  551. if( min_idx[i] != min_idx0[i] || max_idx[i] != max_idx0[i] )
  552. {
  553. ts->printf( cvtest::TS::LOG,
  554. "The %d-th coordinates of extrema histogram bin values are incorrect: "
  555. "(min = %d, should be = %d), (max = %d, should be = %d)\n",
  556. i, min_idx[i], min_idx0[i], max_idx[i], max_idx0[i] );
  557. code = cvtest::TS::FAIL_BAD_ACCURACY;
  558. }
  559. }
  560. }
  561. if( code < 0 )
  562. ts->set_failed_test_info( code );
  563. return code;
  564. }
  565. ////////////// cvNormalizeHist //////////////
  566. class CV_NormHistTest : public CV_BaseHistTest
  567. {
  568. public:
  569. CV_NormHistTest();
  570. protected:
  571. int prepare_test_case( int test_case_idx );
  572. void run_func(void);
  573. int validate_test_results( int test_case_idx );
  574. double factor;
  575. };
  576. CV_NormHistTest::CV_NormHistTest()
  577. {
  578. hist_count = 1;
  579. gen_random_hist = 1;
  580. factor = 0;
  581. }
  582. int CV_NormHistTest::prepare_test_case( int test_case_idx )
  583. {
  584. int code = CV_BaseHistTest::prepare_test_case( test_case_idx );
  585. if( code > 0 )
  586. {
  587. RNG& rng = ts->get_rng();
  588. factor = cvtest::randReal(rng)*10 + 0.1;
  589. if( hist_type == CV_HIST_SPARSE &&
  590. ((CvSparseMat*)hist[0]->bins)->heap->active_count == 0 )
  591. factor = 0;
  592. }
  593. return code;
  594. }
  595. void CV_NormHistTest::run_func(void)
  596. {
  597. if( hist_type != CV_HIST_ARRAY && test_cpp )
  598. {
  599. cv::SparseMat h;
  600. ((CvSparseMat*)hist[0]->bins)->copyToSparseMat(h);
  601. cv::normalize(h, h, factor, CV_L1);
  602. cvReleaseSparseMat((CvSparseMat**)&hist[0]->bins);
  603. hist[0]->bins = cvCreateSparseMat(h);
  604. }
  605. else
  606. cvNormalizeHist( hist[0], factor );
  607. }
  608. int CV_NormHistTest::validate_test_results( int /*test_case_idx*/ )
  609. {
  610. int code = cvtest::TS::OK;
  611. double sum = 0;
  612. if( hist_type == CV_HIST_ARRAY )
  613. {
  614. int i;
  615. const float* ptr = (float*)cvPtr1D( hist[0]->bins, 0 );
  616. for( i = 0; i < total_size; i++ )
  617. sum += ptr[i];
  618. }
  619. else
  620. {
  621. CvSparseMat* sparse = (CvSparseMat*)hist[0]->bins;
  622. CvSparseMatIterator iterator;
  623. CvSparseNode *node;
  624. for( node = cvInitSparseMatIterator( sparse, &iterator );
  625. node != 0; node = cvGetNextSparseNode( &iterator ))
  626. {
  627. sum += *(float*)CV_NODE_VAL(sparse,node);
  628. }
  629. }
  630. if( cvIsNaN(sum) || cvIsInf(sum) )
  631. {
  632. ts->printf( cvtest::TS::LOG,
  633. "The normalized histogram has invalid sum =%g\n", sum );
  634. code = cvtest::TS::FAIL_INVALID_OUTPUT;
  635. }
  636. else if( fabs(sum - factor) > FLT_EPSILON*10*fabs(factor) )
  637. {
  638. ts->printf( cvtest::TS::LOG,
  639. "The normalized histogram has incorrect sum =%g, while it should be =%g\n", sum, factor );
  640. code = cvtest::TS::FAIL_BAD_ACCURACY;
  641. }
  642. if( code < 0 )
  643. ts->set_failed_test_info( code );
  644. return code;
  645. }
  646. ////////////// cvThreshHist //////////////
  647. class CV_ThreshHistTest : public CV_BaseHistTest
  648. {
  649. public:
  650. CV_ThreshHistTest();
  651. ~CV_ThreshHistTest();
  652. void clear();
  653. protected:
  654. int prepare_test_case( int test_case_idx );
  655. void run_func(void);
  656. int validate_test_results( int test_case_idx );
  657. Mat indices;
  658. Mat values;
  659. int orig_nz_count;
  660. double threshold;
  661. };
  662. CV_ThreshHistTest::CV_ThreshHistTest() : threshold(0)
  663. {
  664. hist_count = 1;
  665. gen_random_hist = 1;
  666. }
  667. CV_ThreshHistTest::~CV_ThreshHistTest()
  668. {
  669. clear();
  670. }
  671. void CV_ThreshHistTest::clear()
  672. {
  673. CV_BaseHistTest::clear();
  674. }
  675. int CV_ThreshHistTest::prepare_test_case( int test_case_idx )
  676. {
  677. int code = CV_BaseHistTest::prepare_test_case( test_case_idx );
  678. if( code > 0 )
  679. {
  680. RNG& rng = ts->get_rng();
  681. threshold = cvtest::randReal(rng)*gen_hist_max_val;
  682. if( hist_type == CV_HIST_ARRAY )
  683. {
  684. orig_nz_count = total_size;
  685. values = Mat( 1, total_size, CV_32F );
  686. indices = Mat();
  687. memcpy( values.ptr<float>(), cvPtr1D( hist[0]->bins, 0 ), total_size*sizeof(float) );
  688. }
  689. else
  690. {
  691. CvSparseMat* sparse = (CvSparseMat*)hist[0]->bins;
  692. CvSparseMatIterator iterator;
  693. CvSparseNode* node;
  694. int i, k;
  695. orig_nz_count = sparse->heap->active_count;
  696. values = Mat( 1, orig_nz_count+1, CV_32F );
  697. indices = Mat( 1, (orig_nz_count+1)*cdims, CV_32S );
  698. for( node = cvInitSparseMatIterator( sparse, &iterator ), i = 0;
  699. node != 0; node = cvGetNextSparseNode( &iterator ), i++ )
  700. {
  701. const int* idx = CV_NODE_IDX(sparse,node);
  702. OPENCV_ASSERT( i < orig_nz_count, "CV_ThreshHistTest::prepare_test_case", "Buffer overflow" );
  703. values.at<float>(i) = *(float*)CV_NODE_VAL(sparse,node);
  704. for( k = 0; k < cdims; k++ )
  705. indices.at<int>(i*cdims + k) = idx[k];
  706. }
  707. OPENCV_ASSERT( i == orig_nz_count, "Unmatched buffer size",
  708. "CV_ThreshHistTest::prepare_test_case" );
  709. }
  710. }
  711. return code;
  712. }
  713. void CV_ThreshHistTest::run_func(void)
  714. {
  715. cvThreshHist( hist[0], threshold );
  716. }
  717. int CV_ThreshHistTest::validate_test_results( int /*test_case_idx*/ )
  718. {
  719. int code = cvtest::TS::OK;
  720. int i;
  721. float* ptr0 = values.ptr<float>();
  722. float* ptr = 0;
  723. CvSparseMat* sparse = 0;
  724. if( hist_type == CV_HIST_ARRAY )
  725. ptr = (float*)cvPtr1D( hist[0]->bins, 0 );
  726. else
  727. sparse = (CvSparseMat*)hist[0]->bins;
  728. if( code > 0 )
  729. {
  730. for( i = 0; i < orig_nz_count; i++ )
  731. {
  732. float v0 = ptr0[i], v;
  733. if( hist_type == CV_HIST_ARRAY )
  734. v = ptr[i];
  735. else
  736. {
  737. v = (float)cvGetRealND( sparse, indices.ptr<int>() + i*cdims );
  738. cvClearND( sparse, indices.ptr<int>() + i*cdims );
  739. }
  740. if( v0 <= threshold ) v0 = 0.f;
  741. if( cvIsNaN(v) || cvIsInf(v) )
  742. {
  743. ts->printf( cvtest::TS::LOG, "The %d-th bin is invalid (=%g)\n", i, v );
  744. code = cvtest::TS::FAIL_INVALID_OUTPUT;
  745. break;
  746. }
  747. else if( fabs(v0 - v) > FLT_EPSILON*10*fabs(v0) )
  748. {
  749. ts->printf( cvtest::TS::LOG, "The %d-th bin is incorrect (=%g, should be =%g)\n", i, v, v0 );
  750. code = cvtest::TS::FAIL_BAD_ACCURACY;
  751. break;
  752. }
  753. }
  754. }
  755. if( code > 0 && hist_type == CV_HIST_SPARSE )
  756. {
  757. if( sparse->heap->active_count > 0 )
  758. {
  759. ts->printf( cvtest::TS::LOG,
  760. "There some extra histogram bins in the sparse histogram after the thresholding\n" );
  761. code = cvtest::TS::FAIL_INVALID_OUTPUT;
  762. }
  763. }
  764. if( code < 0 )
  765. ts->set_failed_test_info( code );
  766. return code;
  767. }
  768. ////////////// cvCompareHist //////////////
  769. class CV_CompareHistTest : public CV_BaseHistTest
  770. {
  771. public:
  772. enum { MAX_METHOD = 6 };
  773. CV_CompareHistTest();
  774. protected:
  775. int prepare_test_case( int test_case_idx );
  776. void run_func(void);
  777. int validate_test_results( int test_case_idx );
  778. double result[MAX_METHOD+1];
  779. };
  780. CV_CompareHistTest::CV_CompareHistTest()
  781. {
  782. hist_count = 2;
  783. gen_random_hist = 1;
  784. }
  785. int CV_CompareHistTest::prepare_test_case( int test_case_idx )
  786. {
  787. int code = CV_BaseHistTest::prepare_test_case( test_case_idx );
  788. return code;
  789. }
  790. void CV_CompareHistTest::run_func(void)
  791. {
  792. int k;
  793. if( hist_type != CV_HIST_ARRAY && test_cpp )
  794. {
  795. cv::SparseMat h0, h1;
  796. ((CvSparseMat*)hist[0]->bins)->copyToSparseMat(h0);
  797. ((CvSparseMat*)hist[1]->bins)->copyToSparseMat(h1);
  798. for( k = 0; k < MAX_METHOD; k++ )
  799. result[k] = cv::compareHist(h0, h1, k);
  800. }
  801. else
  802. for( k = 0; k < MAX_METHOD; k++ )
  803. result[k] = cvCompareHist( hist[0], hist[1], k );
  804. }
  805. int CV_CompareHistTest::validate_test_results( int /*test_case_idx*/ )
  806. {
  807. int code = cvtest::TS::OK;
  808. int i;
  809. double result0[MAX_METHOD+1];
  810. double s0 = 0, s1 = 0, sq0 = 0, sq1 = 0, t;
  811. for( i = 0; i < MAX_METHOD; i++ )
  812. result0[i] = 0;
  813. if( hist_type == CV_HIST_ARRAY )
  814. {
  815. float* ptr0 = (float*)cvPtr1D( hist[0]->bins, 0 );
  816. float* ptr1 = (float*)cvPtr1D( hist[1]->bins, 0 );
  817. for( i = 0; i < total_size; i++ )
  818. {
  819. double v0 = ptr0[i], v1 = ptr1[i];
  820. result0[CV_COMP_CORREL] += v0*v1;
  821. result0[CV_COMP_INTERSECT] += MIN(v0,v1);
  822. if( fabs(v0) > DBL_EPSILON )
  823. result0[CV_COMP_CHISQR] += (v0 - v1)*(v0 - v1)/v0;
  824. if( fabs(v0 + v1) > DBL_EPSILON )
  825. result0[CV_COMP_CHISQR_ALT] += (v0 - v1)*(v0 - v1)/(v0 + v1);
  826. s0 += v0;
  827. s1 += v1;
  828. sq0 += v0*v0;
  829. sq1 += v1*v1;
  830. result0[CV_COMP_BHATTACHARYYA] += sqrt(v0*v1);
  831. {
  832. if( fabs(v0) <= DBL_EPSILON )
  833. continue;
  834. if( fabs(v1) <= DBL_EPSILON )
  835. v1 = 1e-10;
  836. result0[CV_COMP_KL_DIV] += v0 * std::log( v0 / v1 );
  837. }
  838. }
  839. }
  840. else
  841. {
  842. CvSparseMat* sparse0 = (CvSparseMat*)hist[0]->bins;
  843. CvSparseMat* sparse1 = (CvSparseMat*)hist[1]->bins;
  844. CvSparseMatIterator iterator;
  845. CvSparseNode* node;
  846. for( node = cvInitSparseMatIterator( sparse0, &iterator );
  847. node != 0; node = cvGetNextSparseNode( &iterator ) )
  848. {
  849. const int* idx = CV_NODE_IDX(sparse0, node);
  850. double v0 = *(float*)CV_NODE_VAL(sparse0, node);
  851. double v1 = (float)cvGetRealND(sparse1, idx);
  852. result0[CV_COMP_CORREL] += v0*v1;
  853. result0[CV_COMP_INTERSECT] += MIN(v0,v1);
  854. if( fabs(v0) > DBL_EPSILON )
  855. result0[CV_COMP_CHISQR] += (v0 - v1)*(v0 - v1)/v0;
  856. if( fabs(v0 + v1) > DBL_EPSILON )
  857. result0[CV_COMP_CHISQR_ALT] += (v0 - v1)*(v0 - v1)/(v0 + v1);
  858. s0 += v0;
  859. sq0 += v0*v0;
  860. result0[CV_COMP_BHATTACHARYYA] += sqrt(v0*v1);
  861. {
  862. if (v0 <= DBL_EPSILON)
  863. continue;
  864. if (!v1)
  865. v1 = 1e-10;
  866. result0[CV_COMP_KL_DIV] += v0 * std::log( v0 / v1 );
  867. }
  868. }
  869. for( node = cvInitSparseMatIterator( sparse1, &iterator );
  870. node != 0; node = cvGetNextSparseNode( &iterator ) )
  871. {
  872. double v1 = *(float*)CV_NODE_VAL(sparse1, node);
  873. s1 += v1;
  874. sq1 += v1*v1;
  875. }
  876. }
  877. result0[CV_COMP_CHISQR_ALT] *= 2;
  878. t = (sq0 - s0*s0/total_size)*(sq1 - s1*s1/total_size);
  879. result0[CV_COMP_CORREL] = fabs(t) > DBL_EPSILON ?
  880. (result0[CV_COMP_CORREL] - s0*s1/total_size)/sqrt(t) : 1;
  881. s1 *= s0;
  882. s0 = result0[CV_COMP_BHATTACHARYYA];
  883. s0 = 1. - s0*(s1 > FLT_EPSILON ? 1./sqrt(s1) : 1.);
  884. result0[CV_COMP_BHATTACHARYYA] = sqrt(MAX(s0,0.));
  885. for( i = 0; i < MAX_METHOD; i++ )
  886. {
  887. double v = result[i], v0 = result0[i];
  888. const char* method_name =
  889. i == CV_COMP_CHISQR ? "Chi-Square" :
  890. i == CV_COMP_CHISQR_ALT ? "Alternative Chi-Square" :
  891. i == CV_COMP_CORREL ? "Correlation" :
  892. i == CV_COMP_INTERSECT ? "Intersection" :
  893. i == CV_COMP_BHATTACHARYYA ? "Bhattacharyya" :
  894. i == CV_COMP_KL_DIV ? "Kullback-Leibler" : "Unknown";
  895. if( cvIsNaN(v) || cvIsInf(v) )
  896. {
  897. ts->printf( cvtest::TS::LOG, "The comparison result using the method #%d (%s) is invalid (=%g)\n",
  898. i, method_name, v );
  899. code = cvtest::TS::FAIL_INVALID_OUTPUT;
  900. break;
  901. }
  902. else if( fabs(v0 - v) > FLT_EPSILON*14*MAX(fabs(v0),0.1) )
  903. {
  904. ts->printf( cvtest::TS::LOG, "The comparison result using the method #%d (%s)\n\tis inaccurate (=%g, should be =%g)\n",
  905. i, method_name, v, v0 );
  906. code = cvtest::TS::FAIL_BAD_ACCURACY;
  907. break;
  908. }
  909. }
  910. if( code < 0 )
  911. ts->set_failed_test_info( code );
  912. return code;
  913. }
  914. ////////////// cvCalcHist //////////////
  915. class CV_CalcHistTest : public CV_BaseHistTest
  916. {
  917. public:
  918. CV_CalcHistTest();
  919. ~CV_CalcHistTest();
  920. void clear();
  921. protected:
  922. int prepare_test_case( int test_case_idx );
  923. void run_func(void);
  924. int validate_test_results( int test_case_idx );
  925. vector<Mat> images;
  926. vector<int> channels;
  927. };
  928. CV_CalcHistTest::CV_CalcHistTest() : images(CV_MAX_DIM+1), channels(CV_MAX_DIM+1)
  929. {
  930. hist_count = 2;
  931. gen_random_hist = 0;
  932. init_ranges = 1;
  933. }
  934. CV_CalcHistTest::~CV_CalcHistTest()
  935. {
  936. clear();
  937. }
  938. void CV_CalcHistTest::clear()
  939. {
  940. CV_BaseHistTest::clear();
  941. }
  942. int CV_CalcHistTest::prepare_test_case( int test_case_idx )
  943. {
  944. int code = CV_BaseHistTest::prepare_test_case( test_case_idx );
  945. if( code > 0 )
  946. {
  947. RNG& rng = ts->get_rng();
  948. int i;
  949. for( i = 0; i <= CV_MAX_DIM; i++ )
  950. {
  951. if( i < cdims )
  952. {
  953. int nch = 1; //cvtest::randInt(rng) % 3 + 1;
  954. images[i] = Mat(img_size, CV_MAKETYPE(img_type, nch));
  955. channels[i] = cvtest::randInt(rng) % nch;
  956. cvtest::randUni( rng, images[i], Scalar::all(low), Scalar::all(high) );
  957. }
  958. else if( i == CV_MAX_DIM )
  959. {
  960. if( cvtest::randInt(rng) % 2 )
  961. {
  962. // create mask
  963. images[i] = Mat(img_size, CV_8U);
  964. // make ~25% pixels in the mask non-zero
  965. cvtest::randUni( rng, images[i], Scalar::all(-2), Scalar::all(2) );
  966. }
  967. else
  968. images[i] = Mat();
  969. }
  970. }
  971. }
  972. return code;
  973. }
  974. void CV_CalcHistTest::run_func(void)
  975. {
  976. int size[CV_MAX_DIM];
  977. int hdims = cvGetDims( hist[0]->bins, size);
  978. bool huniform = CV_IS_UNIFORM_HIST(hist[0]);
  979. const float* uranges[CV_MAX_DIM] = {0};
  980. const float** hranges = 0;
  981. if( hist[0]->type & CV_HIST_RANGES_FLAG )
  982. {
  983. hranges = (const float**)hist[0]->thresh2;
  984. if( huniform )
  985. {
  986. for(int i = 0; i < hdims; i++ )
  987. uranges[i] = &hist[0]->thresh[i][0];
  988. hranges = uranges;
  989. }
  990. }
  991. std::vector<cv::Mat> imagesv(cdims);
  992. copy(images.begin(), images.begin() + cdims, imagesv.begin());
  993. Mat mask = images[CV_MAX_DIM];
  994. if( !CV_IS_SPARSE_HIST(hist[0]) )
  995. {
  996. cv::Mat H = cv::cvarrToMat(hist[0]->bins);
  997. if(huniform)
  998. {
  999. vector<int> emptyChannels;
  1000. vector<int> hSize(hdims);
  1001. for(int i = 0; i < hdims; i++)
  1002. hSize[i] = size[i];
  1003. vector<float> vranges;
  1004. if(hranges)
  1005. {
  1006. vranges.resize(hdims*2);
  1007. for(int i = 0; i < hdims; i++ )
  1008. {
  1009. vranges[i*2 ] = hist[0]->thresh[i][0];
  1010. vranges[i*2+1] = hist[0]->thresh[i][1];
  1011. }
  1012. }
  1013. cv::calcHist(imagesv, emptyChannels, mask, H, hSize, vranges);
  1014. }
  1015. else
  1016. {
  1017. cv::calcHist( &imagesv[0], (int)imagesv.size(), 0, mask,
  1018. H, cvGetDims(hist[0]->bins), H.size, hranges, huniform );
  1019. }
  1020. }
  1021. else
  1022. {
  1023. CvSparseMat* sparsemat = (CvSparseMat*)hist[0]->bins;
  1024. cvZero( hist[0]->bins );
  1025. cv::SparseMat sH;
  1026. sparsemat->copyToSparseMat(sH);
  1027. cv::calcHist( &imagesv[0], (int)imagesv.size(), 0, mask, sH, sH.dims(),
  1028. sH.dims() > 0 ? sH.hdr->size : 0, hranges, huniform, false);
  1029. cv::SparseMatConstIterator it = sH.begin();
  1030. int nz = (int)sH.nzcount();
  1031. for(int i = 0; i < nz; i++, ++it )
  1032. {
  1033. CV_Assert(it.ptr != NULL);
  1034. *(float*)cvPtrND(sparsemat, it.node()->idx, 0, -2) = *(const float*)it.ptr;
  1035. }
  1036. }
  1037. }
  1038. static void
  1039. cvTsCalcHist( const vector<Mat>& images, CvHistogram* hist, Mat mask, const vector<int>& channels )
  1040. {
  1041. int x, y, k;
  1042. union
  1043. {
  1044. const float* fl;
  1045. const uchar* ptr;
  1046. }
  1047. plane[CV_MAX_DIM];
  1048. int nch[CV_MAX_DIM];
  1049. int dims[CV_MAX_DIM];
  1050. int uniform = CV_IS_UNIFORM_HIST(hist);
  1051. int cdims = cvGetDims( hist->bins, dims );
  1052. cvZero( hist->bins );
  1053. Size img_size = images[0].size();
  1054. int img_depth = images[0].depth();
  1055. for( k = 0; k < cdims; k++ )
  1056. {
  1057. nch[k] = images[k].channels();
  1058. }
  1059. for( y = 0; y < img_size.height; y++ )
  1060. {
  1061. const uchar* mptr = mask.empty() ? 0 : mask.ptr<uchar>(y);
  1062. if( img_depth == CV_8U )
  1063. for( k = 0; k < cdims; k++ )
  1064. plane[k].ptr = images[k].ptr<uchar>(y) + channels[k];
  1065. else
  1066. for( k = 0; k < cdims; k++ )
  1067. plane[k].fl = images[k].ptr<float>(y) + channels[k];
  1068. for( x = 0; x < img_size.width; x++ )
  1069. {
  1070. float val[CV_MAX_DIM];
  1071. int idx[CV_MAX_DIM];
  1072. if( mptr && !mptr[x] )
  1073. continue;
  1074. if( img_depth == CV_8U )
  1075. for( k = 0; k < cdims; k++ )
  1076. val[k] = plane[k].ptr[x*nch[k]];
  1077. else
  1078. for( k = 0; k < cdims; k++ )
  1079. val[k] = plane[k].fl[x*nch[k]];
  1080. idx[cdims-1] = -1;
  1081. if( uniform )
  1082. {
  1083. for( k = 0; k < cdims; k++ )
  1084. {
  1085. double v = val[k], lo = hist->thresh[k][0], hi = hist->thresh[k][1];
  1086. if (v < lo || v >= hi)
  1087. break;
  1088. double idx_ = (v - lo)*dims[k]/(hi - lo);
  1089. idx[k] = cvFloor(idx_);
  1090. if (idx[k] < 0)
  1091. {
  1092. idx[k] = 0;
  1093. }
  1094. if (idx[k] >= dims[k])
  1095. {
  1096. idx[k] = dims[k] - 1;
  1097. }
  1098. }
  1099. }
  1100. else
  1101. {
  1102. for( k = 0; k < cdims; k++ )
  1103. {
  1104. float v = val[k];
  1105. float* t = hist->thresh2[k];
  1106. int j, n = dims[k];
  1107. for( j = 0; j <= n; j++ )
  1108. if( v < t[j] )
  1109. break;
  1110. if( j <= 0 || j > n )
  1111. break;
  1112. idx[k] = j-1;
  1113. }
  1114. }
  1115. if( k < cdims )
  1116. continue;
  1117. (*(float*)cvPtrND( hist->bins, idx ))++;
  1118. }
  1119. }
  1120. }
  1121. int CV_CalcHistTest::validate_test_results( int /*test_case_idx*/ )
  1122. {
  1123. int code = cvtest::TS::OK;
  1124. double diff;
  1125. cvTsCalcHist( images, hist[1], images[CV_MAX_DIM], channels );
  1126. diff = cvCompareHist( hist[0], hist[1], CV_COMP_CHISQR );
  1127. if( diff > DBL_EPSILON )
  1128. {
  1129. ts->printf( cvtest::TS::LOG, "The histogram does not match to the reference one\n" );
  1130. code = cvtest::TS::FAIL_BAD_ACCURACY;
  1131. }
  1132. if( code < 0 )
  1133. ts->set_failed_test_info( code );
  1134. return code;
  1135. }
  1136. CV_CalcHistTest hist_calc_test;
  1137. ////////////// cvCalcBackProject //////////////
  1138. class CV_CalcBackProjectTest : public CV_BaseHistTest
  1139. {
  1140. public:
  1141. CV_CalcBackProjectTest();
  1142. ~CV_CalcBackProjectTest();
  1143. void clear();
  1144. protected:
  1145. int prepare_test_case( int test_case_idx );
  1146. void run_func(void);
  1147. int validate_test_results( int test_case_idx );
  1148. vector<Mat> images;
  1149. vector<int> channels;
  1150. };
  1151. CV_CalcBackProjectTest::CV_CalcBackProjectTest() : images(CV_MAX_DIM+3), channels(CV_MAX_DIM+3)
  1152. {
  1153. hist_count = 1;
  1154. gen_random_hist = 0;
  1155. init_ranges = 1;
  1156. }
  1157. CV_CalcBackProjectTest::~CV_CalcBackProjectTest()
  1158. {
  1159. clear();
  1160. }
  1161. void CV_CalcBackProjectTest::clear()
  1162. {
  1163. CV_BaseHistTest::clear();
  1164. }
  1165. int CV_CalcBackProjectTest::prepare_test_case( int test_case_idx )
  1166. {
  1167. int code = CV_BaseHistTest::prepare_test_case( test_case_idx );
  1168. if( code > 0 )
  1169. {
  1170. RNG& rng = ts->get_rng();
  1171. int i, j, n, img_len = img_size.area();
  1172. for( i = 0; i < CV_MAX_DIM + 3; i++ )
  1173. {
  1174. if( i < cdims )
  1175. {
  1176. int nch = 1; //cvtest::randInt(rng) % 3 + 1;
  1177. images[i] = Mat(img_size, CV_MAKETYPE(img_type, nch));
  1178. channels[i] = cvtest::randInt(rng) % nch;
  1179. cvtest::randUni( rng, images[i], Scalar::all(low), Scalar::all(high) );
  1180. }
  1181. else if( i == CV_MAX_DIM )
  1182. {
  1183. if(cvtest::randInt(rng) % 2 )
  1184. {
  1185. // create mask
  1186. images[i] = Mat(img_size, CV_8U);
  1187. // make ~25% pixels in the mask non-zero
  1188. cvtest::randUni( rng, images[i], Scalar::all(-2), Scalar::all(2) );
  1189. }
  1190. else
  1191. {
  1192. images[i] = Mat();
  1193. }
  1194. }
  1195. else if( i > CV_MAX_DIM )
  1196. {
  1197. images[i] = Mat(img_size, images[0].type());
  1198. }
  1199. }
  1200. cvTsCalcHist( images, hist[0], images[CV_MAX_DIM], channels );
  1201. // now modify the images a bit to add some zeros go to the backprojection
  1202. n = cvtest::randInt(rng) % (img_len/20+1);
  1203. for( i = 0; i < cdims; i++ )
  1204. {
  1205. uchar* data = images[i].data;
  1206. for( j = 0; j < n; j++ )
  1207. {
  1208. int idx = cvtest::randInt(rng) % img_len;
  1209. double val = cvtest::randReal(rng)*(high - low) + low;
  1210. if( img_type == CV_8U )
  1211. ((uchar*)data)[idx] = (uchar)cvRound(val);
  1212. else
  1213. ((float*)data)[idx] = (float)val;
  1214. }
  1215. }
  1216. }
  1217. return code;
  1218. }
  1219. void CV_CalcBackProjectTest::run_func(void)
  1220. {
  1221. int size[CV_MAX_DIM];
  1222. int hdims = cvGetDims( hist[0]->bins, size );
  1223. bool huniform = CV_IS_UNIFORM_HIST(hist[0]);
  1224. const float* uranges[CV_MAX_DIM] = {0};
  1225. const float** hranges = 0;
  1226. if( hist[0]->type & CV_HIST_RANGES_FLAG )
  1227. {
  1228. hranges = (const float**)hist[0]->thresh2;
  1229. if( huniform )
  1230. {
  1231. for(int i = 0; i < hdims; i++ )
  1232. uranges[i] = &hist[0]->thresh[i][0];
  1233. hranges = uranges;
  1234. }
  1235. }
  1236. std::vector<cv::Mat> imagesv(hdims);
  1237. copy(images.begin(), images.begin() + hdims, imagesv.begin());
  1238. cv::Mat dst = images[CV_MAX_DIM+1];
  1239. CV_Assert( dst.size() == imagesv[0].size() && dst.depth() == imagesv[0].depth() );
  1240. if( !CV_IS_SPARSE_HIST(hist[0]) )
  1241. {
  1242. cv::Mat H = cv::cvarrToMat(hist[0]->bins);
  1243. if(huniform)
  1244. {
  1245. vector<int> emptyChannels;
  1246. vector<float> vranges;
  1247. if(hranges)
  1248. {
  1249. vranges.resize(hdims*2);
  1250. for(int i = 0; i < hdims; i++ )
  1251. {
  1252. vranges[i*2 ] = hist[0]->thresh[i][0];
  1253. vranges[i*2+1] = hist[0]->thresh[i][1];
  1254. }
  1255. }
  1256. cv::calcBackProject(imagesv, emptyChannels, H, dst, vranges, 1);
  1257. }
  1258. else
  1259. {
  1260. cv::calcBackProject( &imagesv[0], (int)imagesv.size(),
  1261. 0, H, dst, hranges, 1, false );
  1262. }
  1263. }
  1264. else
  1265. {
  1266. cv::SparseMat sH;
  1267. ((const CvSparseMat*)hist[0]->bins)->copyToSparseMat(sH);
  1268. cv::calcBackProject( &imagesv[0], (int)imagesv.size(),
  1269. 0, sH, dst, hranges, 1, huniform );
  1270. }
  1271. }
  1272. static void
  1273. cvTsCalcBackProject( const vector<Mat>& images, Mat dst, CvHistogram* hist, const vector<int>& channels )
  1274. {
  1275. int x, y, k, cdims;
  1276. union
  1277. {
  1278. const float* fl;
  1279. const uchar* ptr;
  1280. }
  1281. plane[CV_MAX_DIM];
  1282. int nch[CV_MAX_DIM];
  1283. int dims[CV_MAX_DIM];
  1284. int uniform = CV_IS_UNIFORM_HIST(hist);
  1285. Size img_size = images[0].size();
  1286. int img_depth = images[0].depth();
  1287. cdims = cvGetDims( hist->bins, dims );
  1288. for( k = 0; k < cdims; k++ )
  1289. nch[k] = images[k].channels();
  1290. for( y = 0; y < img_size.height; y++ )
  1291. {
  1292. if( img_depth == CV_8U )
  1293. for( k = 0; k < cdims; k++ )
  1294. plane[k].ptr = images[k].ptr<uchar>(y) + channels[k];
  1295. else
  1296. for( k = 0; k < cdims; k++ )
  1297. plane[k].fl = images[k].ptr<float>(y) + channels[k];
  1298. for( x = 0; x < img_size.width; x++ )
  1299. {
  1300. float val[CV_MAX_DIM];
  1301. float bin_val = 0;
  1302. int idx[CV_MAX_DIM];
  1303. if( img_depth == CV_8U )
  1304. for( k = 0; k < cdims; k++ )
  1305. val[k] = plane[k].ptr[x*nch[k]];
  1306. else
  1307. for( k = 0; k < cdims; k++ )
  1308. val[k] = plane[k].fl[x*nch[k]];
  1309. idx[cdims-1] = -1;
  1310. if( uniform )
  1311. {
  1312. for( k = 0; k < cdims; k++ )
  1313. {
  1314. double v = val[k], lo = hist->thresh[k][0], hi = hist->thresh[k][1];
  1315. idx[k] = cvFloor((v - lo)*dims[k]/(hi - lo));
  1316. if( idx[k] < 0 || idx[k] >= dims[k] )
  1317. break;
  1318. }
  1319. }
  1320. else
  1321. {
  1322. for( k = 0; k < cdims; k++ )
  1323. {
  1324. float v = val[k];
  1325. float* t = hist->thresh2[k];
  1326. int j, n = dims[k];
  1327. for( j = 0; j <= n; j++ )
  1328. if( v < t[j] )
  1329. break;
  1330. if( j <= 0 || j > n )
  1331. break;
  1332. idx[k] = j-1;
  1333. }
  1334. }
  1335. if( k == cdims )
  1336. bin_val = (float)cvGetRealND( hist->bins, idx );
  1337. if( img_depth == CV_8U )
  1338. {
  1339. int t = cvRound(bin_val);
  1340. dst.at<uchar>(y, x) = saturate_cast<uchar>(t);
  1341. }
  1342. else
  1343. dst.at<float>(y, x) = bin_val;
  1344. }
  1345. }
  1346. }
  1347. int CV_CalcBackProjectTest::validate_test_results( int /*test_case_idx*/ )
  1348. {
  1349. int code = cvtest::TS::OK;
  1350. cvTsCalcBackProject( images, images[CV_MAX_DIM+2], hist[0], channels );
  1351. Mat a = images[CV_MAX_DIM+1], b = images[CV_MAX_DIM+2];
  1352. double threshold = a.depth() == CV_8U ? 2 : FLT_EPSILON;
  1353. code = cvtest::cmpEps2( ts, a, b, threshold, true, "Back project image" );
  1354. if( code < 0 )
  1355. ts->set_failed_test_info( code );
  1356. return code;
  1357. }
  1358. ////////////// cvCalcBackProjectPatch //////////////
  1359. class CV_CalcBackProjectPatchTest : public CV_BaseHistTest
  1360. {
  1361. public:
  1362. CV_CalcBackProjectPatchTest();
  1363. ~CV_CalcBackProjectPatchTest();
  1364. void clear();
  1365. protected:
  1366. int prepare_test_case( int test_case_idx );
  1367. void run_func(void);
  1368. int validate_test_results( int test_case_idx );
  1369. vector<Mat> images;
  1370. vector<int> channels;
  1371. Size patch_size;
  1372. double factor;
  1373. int method;
  1374. };
  1375. CV_CalcBackProjectPatchTest::CV_CalcBackProjectPatchTest() :
  1376. images(CV_MAX_DIM+2), channels(CV_MAX_DIM+2)
  1377. {
  1378. hist_count = 1;
  1379. gen_random_hist = 0;
  1380. init_ranges = 1;
  1381. img_max_log_size = 6;
  1382. }
  1383. CV_CalcBackProjectPatchTest::~CV_CalcBackProjectPatchTest()
  1384. {
  1385. clear();
  1386. }
  1387. void CV_CalcBackProjectPatchTest::clear()
  1388. {
  1389. CV_BaseHistTest::clear();
  1390. }
  1391. int CV_CalcBackProjectPatchTest::prepare_test_case( int test_case_idx )
  1392. {
  1393. int code = CV_BaseHistTest::prepare_test_case( test_case_idx );
  1394. if( code > 0 )
  1395. {
  1396. RNG& rng = ts->get_rng();
  1397. int i, j, n, img_len = img_size.area();
  1398. patch_size.width = cvtest::randInt(rng) % img_size.width + 1;
  1399. patch_size.height = cvtest::randInt(rng) % img_size.height + 1;
  1400. patch_size.width = MIN( patch_size.width, 30 );
  1401. patch_size.height = MIN( patch_size.height, 30 );
  1402. factor = 1.;
  1403. method = cvtest::randInt(rng) % CV_CompareHistTest::MAX_METHOD;
  1404. for( i = 0; i < CV_MAX_DIM + 2; i++ )
  1405. {
  1406. if( i < cdims )
  1407. {
  1408. int nch = 1; //cvtest::randInt(rng) % 3 + 1;
  1409. images[i] = Mat(img_size, CV_MAKETYPE(img_type, nch));
  1410. channels[i] = cvtest::randInt(rng) % nch;
  1411. cvtest::randUni( rng, images[i], Scalar::all(low), Scalar::all(high) );
  1412. }
  1413. else if( i >= CV_MAX_DIM )
  1414. {
  1415. images[i] = Mat(img_size - patch_size + Size(1, 1), CV_32F);
  1416. }
  1417. }
  1418. cvTsCalcHist( images, hist[0], Mat(), channels );
  1419. cvNormalizeHist( hist[0], factor );
  1420. // now modify the images a bit
  1421. n = cvtest::randInt(rng) % (img_len/10+1);
  1422. for( i = 0; i < cdims; i++ )
  1423. {
  1424. uchar* data = images[i].data;
  1425. for( j = 0; j < n; j++ )
  1426. {
  1427. int idx = cvtest::randInt(rng) % img_len;
  1428. double val = cvtest::randReal(rng)*(high - low) + low;
  1429. if( img_type == CV_8U )
  1430. ((uchar*)data)[idx] = (uchar)cvRound(val);
  1431. else
  1432. ((float*)data)[idx] = (float)val;
  1433. }
  1434. }
  1435. }
  1436. return code;
  1437. }
  1438. void CV_CalcBackProjectPatchTest::run_func(void)
  1439. {
  1440. CvMat dst = cvMat(images[CV_MAX_DIM]);
  1441. vector<CvMat > img(cdims);
  1442. vector<CvMat*> pimg(cdims);
  1443. for(int i = 0; i < cdims; i++)
  1444. {
  1445. img[i] = cvMat(images[i]);
  1446. pimg[i] = &img[i];
  1447. }
  1448. cvCalcArrBackProjectPatch( (CvArr**)&pimg[0], &dst, cvSize(patch_size), hist[0], method, factor );
  1449. }
  1450. static void
  1451. cvTsCalcBackProjectPatch( const vector<Mat>& images, Mat dst, Size patch_size,
  1452. CvHistogram* hist, int method,
  1453. double factor, const vector<int>& channels )
  1454. {
  1455. CvHistogram* model = 0;
  1456. int x, y;
  1457. Size size = dst.size();
  1458. cvCopyHist( hist, &model );
  1459. cvNormalizeHist( hist, factor );
  1460. vector<Mat> img(images.size());
  1461. for( y = 0; y < size.height; y++ )
  1462. {
  1463. for( x = 0; x < size.width; x++ )
  1464. {
  1465. double result;
  1466. Rect roi(Point(x, y), patch_size);
  1467. for(size_t i = 0; i < img.size(); i++)
  1468. img[i] = images[i](roi);
  1469. cvTsCalcHist( img, model, Mat(), channels );
  1470. cvNormalizeHist( model, factor );
  1471. result = cvCompareHist( model, hist, method );
  1472. dst.at<float>(y, x) = (float)result;
  1473. }
  1474. }
  1475. cvReleaseHist( &model );
  1476. }
  1477. int CV_CalcBackProjectPatchTest::validate_test_results( int /*test_case_idx*/ )
  1478. {
  1479. int code = cvtest::TS::OK;
  1480. double err_level = 5e-3;
  1481. Mat dst = images[CV_MAX_DIM+1];
  1482. vector<Mat> imagesv(cdims);
  1483. for(int i = 0; i < cdims; i++)
  1484. imagesv[i] = images[i];
  1485. cvTsCalcBackProjectPatch( imagesv, dst, patch_size, hist[0],
  1486. method, factor, channels );
  1487. Mat a = images[CV_MAX_DIM], b = images[CV_MAX_DIM+1];
  1488. code = cvtest::cmpEps2( ts, a, b, err_level, true, "BackProjectPatch result" );
  1489. if( code < 0 )
  1490. ts->set_failed_test_info( code );
  1491. return code;
  1492. }
  1493. ////////////// cvCalcBayesianProb //////////////
  1494. class CV_BayesianProbTest : public CV_BaseHistTest
  1495. {
  1496. public:
  1497. enum { MAX_METHOD = 4 };
  1498. CV_BayesianProbTest();
  1499. protected:
  1500. int prepare_test_case( int test_case_idx );
  1501. void run_func(void);
  1502. int validate_test_results( int test_case_idx );
  1503. void init_hist( int test_case_idx, int i );
  1504. void get_hist_params( int test_case_idx );
  1505. };
  1506. CV_BayesianProbTest::CV_BayesianProbTest()
  1507. {
  1508. hist_count = CV_MAX_DIM;
  1509. gen_random_hist = 1;
  1510. }
  1511. void CV_BayesianProbTest::get_hist_params( int test_case_idx )
  1512. {
  1513. CV_BaseHistTest::get_hist_params( test_case_idx );
  1514. hist_type = CV_HIST_ARRAY;
  1515. }
  1516. void CV_BayesianProbTest::init_hist( int test_case_idx, int hist_i )
  1517. {
  1518. if( hist_i < hist_count/2 )
  1519. CV_BaseHistTest::init_hist( test_case_idx, hist_i );
  1520. }
  1521. int CV_BayesianProbTest::prepare_test_case( int test_case_idx )
  1522. {
  1523. RNG& rng = ts->get_rng();
  1524. hist_count = (cvtest::randInt(rng) % (MAX_HIST/2-1) + 2)*2;
  1525. hist_count = MIN( hist_count, MAX_HIST );
  1526. int code = CV_BaseHistTest::prepare_test_case( test_case_idx );
  1527. return code;
  1528. }
  1529. void CV_BayesianProbTest::run_func(void)
  1530. {
  1531. cvCalcBayesianProb( &hist[0], hist_count/2, &hist[hist_count/2] );
  1532. }
  1533. int CV_BayesianProbTest::validate_test_results( int /*test_case_idx*/ )
  1534. {
  1535. int code = cvtest::TS::OK;
  1536. int i, j, n = hist_count/2;
  1537. double s[CV_MAX_DIM];
  1538. const double err_level = 1e-5;
  1539. for( i = 0; i < total_size; i++ )
  1540. {
  1541. double sum = 0;
  1542. for( j = 0; j < n; j++ )
  1543. {
  1544. double v = hist[j]->mat.data.fl[i];
  1545. sum += v;
  1546. s[j] = v;
  1547. }
  1548. sum = sum > DBL_EPSILON ? 1./sum : 0;
  1549. for( j = 0; j < n; j++ )
  1550. {
  1551. double v0 = s[j]*sum;
  1552. double v = hist[j+n]->mat.data.fl[i];
  1553. if( cvIsNaN(v) || cvIsInf(v) )
  1554. {
  1555. ts->printf( cvtest::TS::LOG,
  1556. "The element #%d in the destination histogram #%d is invalid (=%g)\n",
  1557. i, j, v );
  1558. code = cvtest::TS::FAIL_INVALID_OUTPUT;
  1559. break;
  1560. }
  1561. else if( fabs(v0 - v) > err_level*fabs(v0) )
  1562. {
  1563. ts->printf( cvtest::TS::LOG,
  1564. "The element #%d in the destination histogram #%d is inaccurate (=%g, should be =%g)\n",
  1565. i, j, v, v0 );
  1566. code = cvtest::TS::FAIL_BAD_ACCURACY;
  1567. break;
  1568. }
  1569. }
  1570. if( j < n )
  1571. break;
  1572. }
  1573. if( code < 0 )
  1574. ts->set_failed_test_info( code );
  1575. return code;
  1576. }
  1577. //////////////////////////////////////////////////////////////////////////////////////////////////////
  1578. TEST(Imgproc_Hist_Calc, accuracy) { CV_CalcHistTest test; test.safe_run(); }
  1579. TEST(Imgproc_Hist_Query, accuracy) { CV_QueryHistTest test; test.safe_run(); }
  1580. TEST(Imgproc_Hist_Compare, accuracy) { CV_CompareHistTest test; test.safe_run(); }
  1581. TEST(Imgproc_Hist_Threshold, accuracy) { CV_ThreshHistTest test; test.safe_run(); }
  1582. TEST(Imgproc_Hist_Normalize, accuracy) { CV_NormHistTest test; test.safe_run(); }
  1583. TEST(Imgproc_Hist_MinMaxVal, accuracy) { CV_MinMaxHistTest test; test.safe_run(); }
  1584. TEST(Imgproc_Hist_CalcBackProject, accuracy) { CV_CalcBackProjectTest test; test.safe_run(); }
  1585. TEST(Imgproc_Hist_CalcBackProjectPatch, accuracy) { CV_CalcBackProjectPatchTest test; test.safe_run(); }
  1586. TEST(Imgproc_Hist_BayesianProb, accuracy) { CV_BayesianProbTest test; test.safe_run(); }
  1587. TEST(Imgproc_Hist_Calc, calcHist_regression_11544)
  1588. {
  1589. cv::Mat1w m = cv::Mat1w::zeros(10, 10);
  1590. int n_images = 1;
  1591. int channels[] = { 0 };
  1592. cv::Mat mask;
  1593. cv::MatND hist1, hist2;
  1594. cv::MatND hist1_opt, hist2_opt;
  1595. int dims = 1;
  1596. int hist_size[] = { 1000 };
  1597. float range1[] = { 0, 900 };
  1598. float range2[] = { 0, 1000 };
  1599. const float* ranges1[] = { range1 };
  1600. const float* ranges2[] = { range2 };
  1601. setUseOptimized(false);
  1602. cv::calcHist(&m, n_images, channels, mask, hist1, dims, hist_size, ranges1);
  1603. cv::calcHist(&m, n_images, channels, mask, hist2, dims, hist_size, ranges2);
  1604. setUseOptimized(true);
  1605. cv::calcHist(&m, n_images, channels, mask, hist1_opt, dims, hist_size, ranges1);
  1606. cv::calcHist(&m, n_images, channels, mask, hist2_opt, dims, hist_size, ranges2);
  1607. for(int i = 0; i < 1000; i++)
  1608. {
  1609. EXPECT_EQ(hist1.at<float>(i, 0), hist1_opt.at<float>(i, 0)) << i;
  1610. EXPECT_EQ(hist2.at<float>(i, 0), hist2_opt.at<float>(i, 0)) << i;
  1611. }
  1612. }
  1613. TEST(Imgproc_Hist_Calc, badarg)
  1614. {
  1615. const int channels[] = {0};
  1616. float range1[] = {0, 10};
  1617. float range2[] = {10, 20};
  1618. const float * ranges[] = {range1, range2};
  1619. Mat img = cv::Mat::zeros(10, 10, CV_8UC1);
  1620. Mat imgInt = cv::Mat::zeros(10, 10, CV_32SC1);
  1621. Mat hist;
  1622. const int hist_size[] = { 100, 100 };
  1623. // base run
  1624. EXPECT_NO_THROW(cv::calcHist(&img, 1, channels, noArray(), hist, 1, hist_size, ranges, true));
  1625. // bad parameters
  1626. EXPECT_THROW(cv::calcHist(NULL, 1, channels, noArray(), hist, 1, hist_size, ranges, true), cv::Exception);
  1627. EXPECT_THROW(cv::calcHist(&img, 0, channels, noArray(), hist, 1, hist_size, ranges, true), cv::Exception);
  1628. EXPECT_THROW(cv::calcHist(&img, 1, NULL, noArray(), hist, 2, hist_size, ranges, true), cv::Exception);
  1629. EXPECT_THROW(cv::calcHist(&img, 1, channels, noArray(), noArray(), 1, hist_size, ranges, true), cv::Exception);
  1630. EXPECT_THROW(cv::calcHist(&img, 1, channels, noArray(), hist, -1, hist_size, ranges, true), cv::Exception);
  1631. EXPECT_THROW(cv::calcHist(&img, 1, channels, noArray(), hist, 1, NULL, ranges, true), cv::Exception);
  1632. EXPECT_THROW(cv::calcHist(&imgInt, 1, channels, noArray(), hist, 1, hist_size, NULL, true), cv::Exception);
  1633. // special case
  1634. EXPECT_NO_THROW(cv::calcHist(&img, 1, channels, noArray(), hist, 1, hist_size, NULL, true));
  1635. Mat backProj;
  1636. // base run
  1637. EXPECT_NO_THROW(cv::calcBackProject(&img, 1, channels, hist, backProj, ranges, 1, true));
  1638. // bad parameters
  1639. EXPECT_THROW(cv::calcBackProject(NULL, 1, channels, hist, backProj, ranges, 1, true), cv::Exception);
  1640. EXPECT_THROW(cv::calcBackProject(&img, 0, channels, hist, backProj, ranges, 1, true), cv::Exception);
  1641. EXPECT_THROW(cv::calcBackProject(&img, 1, channels, noArray(), backProj, ranges, 1, true), cv::Exception);
  1642. EXPECT_THROW(cv::calcBackProject(&img, 1, channels, hist, noArray(), ranges, 1, true), cv::Exception);
  1643. EXPECT_THROW(cv::calcBackProject(&imgInt, 1, channels, hist, backProj, NULL, 1, true), cv::Exception);
  1644. // special case
  1645. EXPECT_NO_THROW(cv::calcBackProject(&img, 1, channels, hist, backProj, NULL, 1, true));
  1646. }
  1647. }} // namespace
  1648. /* End Of File */