test_histograms.cpp 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115
  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. const auto thresh = FLT_EPSILON*14*MAX(fabs(v0),0.17);
  896. if( cvIsNaN(v) || cvIsInf(v) )
  897. {
  898. ts->printf( cvtest::TS::LOG, "The comparison result using the method #%d (%s) is invalid (=%g)\n",
  899. i, method_name, v );
  900. code = cvtest::TS::FAIL_INVALID_OUTPUT;
  901. break;
  902. }
  903. else if( fabs(v0 - v) > thresh )
  904. {
  905. ts->printf( cvtest::TS::LOG, "The comparison result using the method #%d (%s)\n\tis inaccurate (=%g, should be =%g)\n",
  906. i, method_name, v, v0 );
  907. code = cvtest::TS::FAIL_BAD_ACCURACY;
  908. break;
  909. }
  910. }
  911. if( code < 0 )
  912. ts->set_failed_test_info( code );
  913. return code;
  914. }
  915. ////////////// cvCalcHist //////////////
  916. class CV_CalcHistTest : public CV_BaseHistTest
  917. {
  918. public:
  919. CV_CalcHistTest();
  920. ~CV_CalcHistTest();
  921. void clear();
  922. protected:
  923. int prepare_test_case( int test_case_idx );
  924. void run_func(void);
  925. int validate_test_results( int test_case_idx );
  926. vector<Mat> images;
  927. vector<int> channels;
  928. };
  929. CV_CalcHistTest::CV_CalcHistTest() : images(CV_MAX_DIM+1), channels(CV_MAX_DIM+1)
  930. {
  931. hist_count = 2;
  932. gen_random_hist = 0;
  933. init_ranges = 1;
  934. }
  935. CV_CalcHistTest::~CV_CalcHistTest()
  936. {
  937. clear();
  938. }
  939. void CV_CalcHistTest::clear()
  940. {
  941. CV_BaseHistTest::clear();
  942. }
  943. int CV_CalcHistTest::prepare_test_case( int test_case_idx )
  944. {
  945. int code = CV_BaseHistTest::prepare_test_case( test_case_idx );
  946. if( code > 0 )
  947. {
  948. RNG& rng = ts->get_rng();
  949. int i;
  950. for( i = 0; i <= CV_MAX_DIM; i++ )
  951. {
  952. if( i < cdims )
  953. {
  954. int nch = 1; //cvtest::randInt(rng) % 3 + 1;
  955. images[i] = Mat(img_size, CV_MAKETYPE(img_type, nch));
  956. channels[i] = cvtest::randInt(rng) % nch;
  957. cvtest::randUni( rng, images[i], Scalar::all(low), Scalar::all(high) );
  958. }
  959. else if( i == CV_MAX_DIM )
  960. {
  961. if( cvtest::randInt(rng) % 2 )
  962. {
  963. // create mask
  964. images[i] = Mat(img_size, CV_8U);
  965. // make ~25% pixels in the mask non-zero
  966. cvtest::randUni( rng, images[i], Scalar::all(-2), Scalar::all(2) );
  967. }
  968. else
  969. images[i] = Mat();
  970. }
  971. }
  972. }
  973. return code;
  974. }
  975. void CV_CalcHistTest::run_func(void)
  976. {
  977. int size[CV_MAX_DIM];
  978. int hdims = cvGetDims( hist[0]->bins, size);
  979. bool huniform = CV_IS_UNIFORM_HIST(hist[0]);
  980. const float* uranges[CV_MAX_DIM] = {0};
  981. const float** hranges = 0;
  982. if( hist[0]->type & CV_HIST_RANGES_FLAG )
  983. {
  984. hranges = (const float**)hist[0]->thresh2;
  985. if( huniform )
  986. {
  987. for(int i = 0; i < hdims; i++ )
  988. uranges[i] = &hist[0]->thresh[i][0];
  989. hranges = uranges;
  990. }
  991. }
  992. std::vector<cv::Mat> imagesv(cdims);
  993. std::copy(images.begin(), images.begin() + cdims, imagesv.begin());
  994. Mat mask = images[CV_MAX_DIM];
  995. if( !CV_IS_SPARSE_HIST(hist[0]) )
  996. {
  997. cv::Mat H = cv::cvarrToMat(hist[0]->bins);
  998. if(huniform)
  999. {
  1000. vector<int> emptyChannels;
  1001. vector<int> hSize(hdims);
  1002. for(int i = 0; i < hdims; i++)
  1003. hSize[i] = size[i];
  1004. vector<float> vranges;
  1005. if(hranges)
  1006. {
  1007. vranges.resize(hdims*2);
  1008. for(int i = 0; i < hdims; i++ )
  1009. {
  1010. vranges[i*2 ] = hist[0]->thresh[i][0];
  1011. vranges[i*2+1] = hist[0]->thresh[i][1];
  1012. }
  1013. }
  1014. cv::calcHist(imagesv, emptyChannels, mask, H, hSize, vranges);
  1015. }
  1016. else
  1017. {
  1018. cv::calcHist( &imagesv[0], (int)imagesv.size(), 0, mask,
  1019. H, cvGetDims(hist[0]->bins), H.size, hranges, huniform );
  1020. }
  1021. }
  1022. else
  1023. {
  1024. CvSparseMat* sparsemat = (CvSparseMat*)hist[0]->bins;
  1025. cvZero( hist[0]->bins );
  1026. cv::SparseMat sH;
  1027. sparsemat->copyToSparseMat(sH);
  1028. cv::calcHist( &imagesv[0], (int)imagesv.size(), 0, mask, sH, sH.dims(),
  1029. sH.dims() > 0 ? sH.hdr->size : 0, hranges, huniform, false);
  1030. cv::SparseMatConstIterator it = sH.begin();
  1031. int nz = (int)sH.nzcount();
  1032. for(int i = 0; i < nz; i++, ++it )
  1033. {
  1034. CV_Assert(it.ptr != NULL);
  1035. *(float*)cvPtrND(sparsemat, it.node()->idx, 0, -2) = *(const float*)it.ptr;
  1036. }
  1037. }
  1038. }
  1039. static void
  1040. cvTsCalcHist( const vector<Mat>& images, CvHistogram* hist, Mat mask, const vector<int>& channels )
  1041. {
  1042. int x, y, k;
  1043. union
  1044. {
  1045. const float* fl;
  1046. const uchar* ptr;
  1047. }
  1048. plane[CV_MAX_DIM];
  1049. int nch[CV_MAX_DIM];
  1050. int dims[CV_MAX_DIM];
  1051. int uniform = CV_IS_UNIFORM_HIST(hist);
  1052. int cdims = cvGetDims( hist->bins, dims );
  1053. cvZero( hist->bins );
  1054. Size img_size = images[0].size();
  1055. int img_depth = images[0].depth();
  1056. for( k = 0; k < cdims; k++ )
  1057. {
  1058. nch[k] = images[k].channels();
  1059. }
  1060. for( y = 0; y < img_size.height; y++ )
  1061. {
  1062. const uchar* mptr = mask.empty() ? 0 : mask.ptr<uchar>(y);
  1063. if( img_depth == CV_8U )
  1064. for( k = 0; k < cdims; k++ )
  1065. plane[k].ptr = images[k].ptr<uchar>(y) + channels[k];
  1066. else
  1067. for( k = 0; k < cdims; k++ )
  1068. plane[k].fl = images[k].ptr<float>(y) + channels[k];
  1069. for( x = 0; x < img_size.width; x++ )
  1070. {
  1071. float val[CV_MAX_DIM];
  1072. int idx[CV_MAX_DIM];
  1073. if( mptr && !mptr[x] )
  1074. continue;
  1075. if( img_depth == CV_8U )
  1076. for( k = 0; k < cdims; k++ )
  1077. val[k] = plane[k].ptr[x*nch[k]];
  1078. else
  1079. for( k = 0; k < cdims; k++ )
  1080. val[k] = plane[k].fl[x*nch[k]];
  1081. idx[cdims-1] = -1;
  1082. if( uniform )
  1083. {
  1084. for( k = 0; k < cdims; k++ )
  1085. {
  1086. double v = val[k], lo = hist->thresh[k][0], hi = hist->thresh[k][1];
  1087. if (v < lo || v >= hi)
  1088. break;
  1089. double idx_ = (v - lo)*dims[k]/(hi - lo);
  1090. idx[k] = cvFloor(idx_);
  1091. if (idx[k] < 0)
  1092. {
  1093. idx[k] = 0;
  1094. }
  1095. if (idx[k] >= dims[k])
  1096. {
  1097. idx[k] = dims[k] - 1;
  1098. }
  1099. }
  1100. }
  1101. else
  1102. {
  1103. for( k = 0; k < cdims; k++ )
  1104. {
  1105. float v = val[k];
  1106. float* t = hist->thresh2[k];
  1107. int j, n = dims[k];
  1108. for( j = 0; j <= n; j++ )
  1109. if( v < t[j] )
  1110. break;
  1111. if( j <= 0 || j > n )
  1112. break;
  1113. idx[k] = j-1;
  1114. }
  1115. }
  1116. if( k < cdims )
  1117. continue;
  1118. (*(float*)cvPtrND( hist->bins, idx ))++;
  1119. }
  1120. }
  1121. }
  1122. int CV_CalcHistTest::validate_test_results( int /*test_case_idx*/ )
  1123. {
  1124. int code = cvtest::TS::OK;
  1125. double diff;
  1126. cvTsCalcHist( images, hist[1], images[CV_MAX_DIM], channels );
  1127. diff = cvCompareHist( hist[0], hist[1], CV_COMP_CHISQR );
  1128. if( diff > DBL_EPSILON )
  1129. {
  1130. ts->printf( cvtest::TS::LOG, "The histogram does not match to the reference one\n" );
  1131. code = cvtest::TS::FAIL_BAD_ACCURACY;
  1132. }
  1133. if( code < 0 )
  1134. ts->set_failed_test_info( code );
  1135. return code;
  1136. }
  1137. CV_CalcHistTest hist_calc_test;
  1138. ////////////// cvCalcBackProject //////////////
  1139. class CV_CalcBackProjectTest : public CV_BaseHistTest
  1140. {
  1141. public:
  1142. CV_CalcBackProjectTest();
  1143. ~CV_CalcBackProjectTest();
  1144. void clear();
  1145. protected:
  1146. int prepare_test_case( int test_case_idx );
  1147. void run_func(void);
  1148. int validate_test_results( int test_case_idx );
  1149. vector<Mat> images;
  1150. vector<int> channels;
  1151. };
  1152. CV_CalcBackProjectTest::CV_CalcBackProjectTest() : images(CV_MAX_DIM+3), channels(CV_MAX_DIM+3)
  1153. {
  1154. hist_count = 1;
  1155. gen_random_hist = 0;
  1156. init_ranges = 1;
  1157. }
  1158. CV_CalcBackProjectTest::~CV_CalcBackProjectTest()
  1159. {
  1160. clear();
  1161. }
  1162. void CV_CalcBackProjectTest::clear()
  1163. {
  1164. CV_BaseHistTest::clear();
  1165. }
  1166. int CV_CalcBackProjectTest::prepare_test_case( int test_case_idx )
  1167. {
  1168. int code = CV_BaseHistTest::prepare_test_case( test_case_idx );
  1169. if( code > 0 )
  1170. {
  1171. RNG& rng = ts->get_rng();
  1172. int i, j, n, img_len = img_size.area();
  1173. for( i = 0; i < CV_MAX_DIM + 3; i++ )
  1174. {
  1175. if( i < cdims )
  1176. {
  1177. int nch = 1; //cvtest::randInt(rng) % 3 + 1;
  1178. images[i] = Mat(img_size, CV_MAKETYPE(img_type, nch));
  1179. channels[i] = cvtest::randInt(rng) % nch;
  1180. cvtest::randUni( rng, images[i], Scalar::all(low), Scalar::all(high) );
  1181. }
  1182. else if( i == CV_MAX_DIM )
  1183. {
  1184. if(cvtest::randInt(rng) % 2 )
  1185. {
  1186. // create mask
  1187. images[i] = Mat(img_size, CV_8U);
  1188. // make ~25% pixels in the mask non-zero
  1189. cvtest::randUni( rng, images[i], Scalar::all(-2), Scalar::all(2) );
  1190. }
  1191. else
  1192. {
  1193. images[i] = Mat();
  1194. }
  1195. }
  1196. else if( i > CV_MAX_DIM )
  1197. {
  1198. images[i] = Mat(img_size, images[0].type());
  1199. }
  1200. }
  1201. cvTsCalcHist( images, hist[0], images[CV_MAX_DIM], channels );
  1202. // now modify the images a bit to add some zeros go to the backprojection
  1203. n = cvtest::randInt(rng) % (img_len/20+1);
  1204. for( i = 0; i < cdims; i++ )
  1205. {
  1206. uchar* data = images[i].data;
  1207. for( j = 0; j < n; j++ )
  1208. {
  1209. int idx = cvtest::randInt(rng) % img_len;
  1210. double val = cvtest::randReal(rng)*(high - low) + low;
  1211. if( img_type == CV_8U )
  1212. ((uchar*)data)[idx] = (uchar)cvRound(val);
  1213. else
  1214. ((float*)data)[idx] = (float)val;
  1215. }
  1216. }
  1217. }
  1218. return code;
  1219. }
  1220. void CV_CalcBackProjectTest::run_func(void)
  1221. {
  1222. int size[CV_MAX_DIM];
  1223. int hdims = cvGetDims( hist[0]->bins, size );
  1224. bool huniform = CV_IS_UNIFORM_HIST(hist[0]);
  1225. const float* uranges[CV_MAX_DIM] = {0};
  1226. const float** hranges = 0;
  1227. if( hist[0]->type & CV_HIST_RANGES_FLAG )
  1228. {
  1229. hranges = (const float**)hist[0]->thresh2;
  1230. if( huniform )
  1231. {
  1232. for(int i = 0; i < hdims; i++ )
  1233. uranges[i] = &hist[0]->thresh[i][0];
  1234. hranges = uranges;
  1235. }
  1236. }
  1237. std::vector<cv::Mat> imagesv(hdims);
  1238. std::copy(images.begin(), images.begin() + hdims, imagesv.begin());
  1239. cv::Mat dst = images[CV_MAX_DIM+1];
  1240. CV_Assert( dst.size() == imagesv[0].size() && dst.depth() == imagesv[0].depth() );
  1241. if( !CV_IS_SPARSE_HIST(hist[0]) )
  1242. {
  1243. cv::Mat H = cv::cvarrToMat(hist[0]->bins);
  1244. if(huniform)
  1245. {
  1246. vector<int> emptyChannels;
  1247. vector<float> vranges;
  1248. if(hranges)
  1249. {
  1250. vranges.resize(hdims*2);
  1251. for(int i = 0; i < hdims; i++ )
  1252. {
  1253. vranges[i*2 ] = hist[0]->thresh[i][0];
  1254. vranges[i*2+1] = hist[0]->thresh[i][1];
  1255. }
  1256. }
  1257. cv::calcBackProject(imagesv, emptyChannels, H, dst, vranges, 1);
  1258. }
  1259. else
  1260. {
  1261. cv::calcBackProject( &imagesv[0], (int)imagesv.size(),
  1262. 0, H, dst, hranges, 1, false );
  1263. }
  1264. }
  1265. else
  1266. {
  1267. cv::SparseMat sH;
  1268. ((const CvSparseMat*)hist[0]->bins)->copyToSparseMat(sH);
  1269. cv::calcBackProject( &imagesv[0], (int)imagesv.size(),
  1270. 0, sH, dst, hranges, 1, huniform );
  1271. }
  1272. }
  1273. static void
  1274. cvTsCalcBackProject( const vector<Mat>& images, Mat dst, CvHistogram* hist, const vector<int>& channels )
  1275. {
  1276. int x, y, k, cdims;
  1277. union
  1278. {
  1279. const float* fl;
  1280. const uchar* ptr;
  1281. }
  1282. plane[CV_MAX_DIM];
  1283. int nch[CV_MAX_DIM];
  1284. int dims[CV_MAX_DIM];
  1285. int uniform = CV_IS_UNIFORM_HIST(hist);
  1286. Size img_size = images[0].size();
  1287. int img_depth = images[0].depth();
  1288. cdims = cvGetDims( hist->bins, dims );
  1289. for( k = 0; k < cdims; k++ )
  1290. nch[k] = images[k].channels();
  1291. for( y = 0; y < img_size.height; y++ )
  1292. {
  1293. if( img_depth == CV_8U )
  1294. for( k = 0; k < cdims; k++ )
  1295. plane[k].ptr = images[k].ptr<uchar>(y) + channels[k];
  1296. else
  1297. for( k = 0; k < cdims; k++ )
  1298. plane[k].fl = images[k].ptr<float>(y) + channels[k];
  1299. for( x = 0; x < img_size.width; x++ )
  1300. {
  1301. float val[CV_MAX_DIM];
  1302. float bin_val = 0;
  1303. int idx[CV_MAX_DIM];
  1304. if( img_depth == CV_8U )
  1305. for( k = 0; k < cdims; k++ )
  1306. val[k] = plane[k].ptr[x*nch[k]];
  1307. else
  1308. for( k = 0; k < cdims; k++ )
  1309. val[k] = plane[k].fl[x*nch[k]];
  1310. idx[cdims-1] = -1;
  1311. if( uniform )
  1312. {
  1313. for( k = 0; k < cdims; k++ )
  1314. {
  1315. double v = val[k], lo = hist->thresh[k][0], hi = hist->thresh[k][1];
  1316. idx[k] = cvFloor((v - lo)*dims[k]/(hi - lo));
  1317. if( idx[k] < 0 || idx[k] >= dims[k] )
  1318. break;
  1319. }
  1320. }
  1321. else
  1322. {
  1323. for( k = 0; k < cdims; k++ )
  1324. {
  1325. float v = val[k];
  1326. float* t = hist->thresh2[k];
  1327. int j, n = dims[k];
  1328. for( j = 0; j <= n; j++ )
  1329. if( v < t[j] )
  1330. break;
  1331. if( j <= 0 || j > n )
  1332. break;
  1333. idx[k] = j-1;
  1334. }
  1335. }
  1336. if( k == cdims )
  1337. bin_val = (float)cvGetRealND( hist->bins, idx );
  1338. if( img_depth == CV_8U )
  1339. {
  1340. int t = cvRound(bin_val);
  1341. dst.at<uchar>(y, x) = saturate_cast<uchar>(t);
  1342. }
  1343. else
  1344. dst.at<float>(y, x) = bin_val;
  1345. }
  1346. }
  1347. }
  1348. int CV_CalcBackProjectTest::validate_test_results( int /*test_case_idx*/ )
  1349. {
  1350. int code = cvtest::TS::OK;
  1351. cvTsCalcBackProject( images, images[CV_MAX_DIM+2], hist[0], channels );
  1352. Mat a = images[CV_MAX_DIM+1], b = images[CV_MAX_DIM+2];
  1353. double threshold = a.depth() == CV_8U ? 2 : FLT_EPSILON;
  1354. code = cvtest::cmpEps2( ts, a, b, threshold, true, "Back project image" );
  1355. if( code < 0 )
  1356. ts->set_failed_test_info( code );
  1357. return code;
  1358. }
  1359. ////////////// cvCalcBackProjectPatch //////////////
  1360. class CV_CalcBackProjectPatchTest : public CV_BaseHistTest
  1361. {
  1362. public:
  1363. CV_CalcBackProjectPatchTest();
  1364. ~CV_CalcBackProjectPatchTest();
  1365. void clear();
  1366. protected:
  1367. int prepare_test_case( int test_case_idx );
  1368. void run_func(void);
  1369. int validate_test_results( int test_case_idx );
  1370. vector<Mat> images;
  1371. vector<int> channels;
  1372. Size patch_size;
  1373. double factor;
  1374. int method;
  1375. };
  1376. CV_CalcBackProjectPatchTest::CV_CalcBackProjectPatchTest() :
  1377. images(CV_MAX_DIM+2), channels(CV_MAX_DIM+2)
  1378. {
  1379. hist_count = 1;
  1380. gen_random_hist = 0;
  1381. init_ranges = 1;
  1382. img_max_log_size = 6;
  1383. }
  1384. CV_CalcBackProjectPatchTest::~CV_CalcBackProjectPatchTest()
  1385. {
  1386. clear();
  1387. }
  1388. void CV_CalcBackProjectPatchTest::clear()
  1389. {
  1390. CV_BaseHistTest::clear();
  1391. }
  1392. int CV_CalcBackProjectPatchTest::prepare_test_case( int test_case_idx )
  1393. {
  1394. int code = CV_BaseHistTest::prepare_test_case( test_case_idx );
  1395. if( code > 0 )
  1396. {
  1397. RNG& rng = ts->get_rng();
  1398. int i, j, n, img_len = img_size.area();
  1399. patch_size.width = cvtest::randInt(rng) % img_size.width + 1;
  1400. patch_size.height = cvtest::randInt(rng) % img_size.height + 1;
  1401. patch_size.width = MIN( patch_size.width, 30 );
  1402. patch_size.height = MIN( patch_size.height, 30 );
  1403. factor = 1.;
  1404. method = cvtest::randInt(rng) % CV_CompareHistTest::MAX_METHOD;
  1405. for( i = 0; i < CV_MAX_DIM + 2; i++ )
  1406. {
  1407. if( i < cdims )
  1408. {
  1409. int nch = 1; //cvtest::randInt(rng) % 3 + 1;
  1410. images[i] = Mat(img_size, CV_MAKETYPE(img_type, nch));
  1411. channels[i] = cvtest::randInt(rng) % nch;
  1412. cvtest::randUni( rng, images[i], Scalar::all(low), Scalar::all(high) );
  1413. }
  1414. else if( i >= CV_MAX_DIM )
  1415. {
  1416. images[i] = Mat(img_size - patch_size + Size(1, 1), CV_32F);
  1417. }
  1418. }
  1419. cvTsCalcHist( images, hist[0], Mat(), channels );
  1420. cvNormalizeHist( hist[0], factor );
  1421. // now modify the images a bit
  1422. n = cvtest::randInt(rng) % (img_len/10+1);
  1423. for( i = 0; i < cdims; i++ )
  1424. {
  1425. uchar* data = images[i].data;
  1426. for( j = 0; j < n; j++ )
  1427. {
  1428. int idx = cvtest::randInt(rng) % img_len;
  1429. double val = cvtest::randReal(rng)*(high - low) + low;
  1430. if( img_type == CV_8U )
  1431. ((uchar*)data)[idx] = (uchar)cvRound(val);
  1432. else
  1433. ((float*)data)[idx] = (float)val;
  1434. }
  1435. }
  1436. }
  1437. return code;
  1438. }
  1439. void CV_CalcBackProjectPatchTest::run_func(void)
  1440. {
  1441. CvMat dst = cvMat(images[CV_MAX_DIM]);
  1442. vector<CvMat > img(cdims);
  1443. vector<CvMat*> pimg(cdims);
  1444. for(int i = 0; i < cdims; i++)
  1445. {
  1446. img[i] = cvMat(images[i]);
  1447. pimg[i] = &img[i];
  1448. }
  1449. cvCalcArrBackProjectPatch( (CvArr**)&pimg[0], &dst, cvSize(patch_size), hist[0], method, factor );
  1450. }
  1451. static void
  1452. cvTsCalcBackProjectPatch( const vector<Mat>& images, Mat dst, Size patch_size,
  1453. CvHistogram* hist, int method,
  1454. double factor, const vector<int>& channels )
  1455. {
  1456. CvHistogram* model = 0;
  1457. int x, y;
  1458. Size size = dst.size();
  1459. cvCopyHist( hist, &model );
  1460. cvNormalizeHist( hist, factor );
  1461. vector<Mat> img(images.size());
  1462. for( y = 0; y < size.height; y++ )
  1463. {
  1464. for( x = 0; x < size.width; x++ )
  1465. {
  1466. double result;
  1467. Rect roi(Point(x, y), patch_size);
  1468. for(size_t i = 0; i < img.size(); i++)
  1469. img[i] = images[i](roi);
  1470. cvTsCalcHist( img, model, Mat(), channels );
  1471. cvNormalizeHist( model, factor );
  1472. result = cvCompareHist( model, hist, method );
  1473. dst.at<float>(y, x) = (float)result;
  1474. }
  1475. }
  1476. cvReleaseHist( &model );
  1477. }
  1478. int CV_CalcBackProjectPatchTest::validate_test_results( int /*test_case_idx*/ )
  1479. {
  1480. int code = cvtest::TS::OK;
  1481. double err_level = 5e-3;
  1482. Mat dst = images[CV_MAX_DIM+1];
  1483. vector<Mat> imagesv(cdims);
  1484. for(int i = 0; i < cdims; i++)
  1485. imagesv[i] = images[i];
  1486. cvTsCalcBackProjectPatch( imagesv, dst, patch_size, hist[0],
  1487. method, factor, channels );
  1488. Mat a = images[CV_MAX_DIM], b = images[CV_MAX_DIM+1];
  1489. code = cvtest::cmpEps2( ts, a, b, err_level, true, "BackProjectPatch result" );
  1490. if( code < 0 )
  1491. ts->set_failed_test_info( code );
  1492. return code;
  1493. }
  1494. ////////////// cvCalcBayesianProb //////////////
  1495. class CV_BayesianProbTest : public CV_BaseHistTest
  1496. {
  1497. public:
  1498. enum { MAX_METHOD = 4 };
  1499. CV_BayesianProbTest();
  1500. protected:
  1501. int prepare_test_case( int test_case_idx );
  1502. void run_func(void);
  1503. int validate_test_results( int test_case_idx );
  1504. void init_hist( int test_case_idx, int i );
  1505. void get_hist_params( int test_case_idx );
  1506. };
  1507. CV_BayesianProbTest::CV_BayesianProbTest()
  1508. {
  1509. hist_count = CV_MAX_DIM;
  1510. gen_random_hist = 1;
  1511. }
  1512. void CV_BayesianProbTest::get_hist_params( int test_case_idx )
  1513. {
  1514. CV_BaseHistTest::get_hist_params( test_case_idx );
  1515. hist_type = CV_HIST_ARRAY;
  1516. }
  1517. void CV_BayesianProbTest::init_hist( int test_case_idx, int hist_i )
  1518. {
  1519. if( hist_i < hist_count/2 )
  1520. CV_BaseHistTest::init_hist( test_case_idx, hist_i );
  1521. }
  1522. int CV_BayesianProbTest::prepare_test_case( int test_case_idx )
  1523. {
  1524. RNG& rng = ts->get_rng();
  1525. hist_count = (cvtest::randInt(rng) % (MAX_HIST/2-1) + 2)*2;
  1526. hist_count = MIN( hist_count, MAX_HIST );
  1527. int code = CV_BaseHistTest::prepare_test_case( test_case_idx );
  1528. return code;
  1529. }
  1530. void CV_BayesianProbTest::run_func(void)
  1531. {
  1532. cvCalcBayesianProb( &hist[0], hist_count/2, &hist[hist_count/2] );
  1533. }
  1534. int CV_BayesianProbTest::validate_test_results( int /*test_case_idx*/ )
  1535. {
  1536. int code = cvtest::TS::OK;
  1537. int i, j, n = hist_count/2;
  1538. double s[CV_MAX_DIM];
  1539. const double err_level = 1e-5;
  1540. for( i = 0; i < total_size; i++ )
  1541. {
  1542. double sum = 0;
  1543. for( j = 0; j < n; j++ )
  1544. {
  1545. double v = hist[j]->mat.data.fl[i];
  1546. sum += v;
  1547. s[j] = v;
  1548. }
  1549. sum = sum > DBL_EPSILON ? 1./sum : 0;
  1550. for( j = 0; j < n; j++ )
  1551. {
  1552. double v0 = s[j]*sum;
  1553. double v = hist[j+n]->mat.data.fl[i];
  1554. if( cvIsNaN(v) || cvIsInf(v) )
  1555. {
  1556. ts->printf( cvtest::TS::LOG,
  1557. "The element #%d in the destination histogram #%d is invalid (=%g)\n",
  1558. i, j, v );
  1559. code = cvtest::TS::FAIL_INVALID_OUTPUT;
  1560. break;
  1561. }
  1562. else if( fabs(v0 - v) > err_level*fabs(v0) )
  1563. {
  1564. ts->printf( cvtest::TS::LOG,
  1565. "The element #%d in the destination histogram #%d is inaccurate (=%g, should be =%g)\n",
  1566. i, j, v, v0 );
  1567. code = cvtest::TS::FAIL_BAD_ACCURACY;
  1568. break;
  1569. }
  1570. }
  1571. if( j < n )
  1572. break;
  1573. }
  1574. if( code < 0 )
  1575. ts->set_failed_test_info( code );
  1576. return code;
  1577. }
  1578. //////////////////////////////////////////////////////////////////////////////////////////////////////
  1579. TEST(Imgproc_Hist_Calc, accuracy) { CV_CalcHistTest test; test.safe_run(); }
  1580. TEST(Imgproc_Hist_Query, accuracy) { CV_QueryHistTest test; test.safe_run(); }
  1581. TEST(Imgproc_Hist_Compare, accuracy) { CV_CompareHistTest test; test.safe_run(); }
  1582. TEST(Imgproc_Hist_Threshold, accuracy) { CV_ThreshHistTest test; test.safe_run(); }
  1583. TEST(Imgproc_Hist_Normalize, accuracy) { CV_NormHistTest test; test.safe_run(); }
  1584. TEST(Imgproc_Hist_MinMaxVal, accuracy) { CV_MinMaxHistTest test; test.safe_run(); }
  1585. TEST(Imgproc_Hist_CalcBackProject, accuracy) { CV_CalcBackProjectTest test; test.safe_run(); }
  1586. TEST(Imgproc_Hist_CalcBackProjectPatch, accuracy) { CV_CalcBackProjectPatchTest test; test.safe_run(); }
  1587. TEST(Imgproc_Hist_BayesianProb, accuracy) { CV_BayesianProbTest test; test.safe_run(); }
  1588. TEST(Imgproc_Hist_Calc, calcHist_regression_11544)
  1589. {
  1590. cv::Mat1w m = cv::Mat1w::zeros(10, 10);
  1591. int n_images = 1;
  1592. int channels[] = { 0 };
  1593. cv::Mat mask;
  1594. cv::MatND hist1, hist2;
  1595. cv::MatND hist1_opt, hist2_opt;
  1596. int dims = 1;
  1597. int hist_size[] = { 1000 };
  1598. float range1[] = { 0, 900 };
  1599. float range2[] = { 0, 1000 };
  1600. const float* ranges1[] = { range1 };
  1601. const float* ranges2[] = { range2 };
  1602. setUseOptimized(false);
  1603. cv::calcHist(&m, n_images, channels, mask, hist1, dims, hist_size, ranges1);
  1604. cv::calcHist(&m, n_images, channels, mask, hist2, dims, hist_size, ranges2);
  1605. setUseOptimized(true);
  1606. cv::calcHist(&m, n_images, channels, mask, hist1_opt, dims, hist_size, ranges1);
  1607. cv::calcHist(&m, n_images, channels, mask, hist2_opt, dims, hist_size, ranges2);
  1608. for(int i = 0; i < 1000; i++)
  1609. {
  1610. EXPECT_EQ(hist1.at<float>(i, 0), hist1_opt.at<float>(i, 0)) << i;
  1611. EXPECT_EQ(hist2.at<float>(i, 0), hist2_opt.at<float>(i, 0)) << i;
  1612. }
  1613. }
  1614. TEST(Imgproc_Hist_Calc, badarg)
  1615. {
  1616. const int channels[] = {0};
  1617. float range1[] = {0, 10};
  1618. float range2[] = {10, 20};
  1619. const float * ranges[] = {range1, range2};
  1620. Mat img = cv::Mat::zeros(10, 10, CV_8UC1);
  1621. Mat imgInt = cv::Mat::zeros(10, 10, CV_32SC1);
  1622. Mat hist;
  1623. const int hist_size[] = { 100, 100 };
  1624. // base run
  1625. EXPECT_NO_THROW(cv::calcHist(&img, 1, channels, noArray(), hist, 1, hist_size, ranges, true));
  1626. // bad parameters
  1627. EXPECT_THROW(cv::calcHist(NULL, 1, channels, noArray(), hist, 1, hist_size, ranges, true), cv::Exception);
  1628. EXPECT_THROW(cv::calcHist(&img, 0, channels, noArray(), hist, 1, hist_size, ranges, true), cv::Exception);
  1629. EXPECT_THROW(cv::calcHist(&img, 1, NULL, noArray(), hist, 2, hist_size, ranges, true), cv::Exception);
  1630. EXPECT_THROW(cv::calcHist(&img, 1, channels, noArray(), noArray(), 1, hist_size, ranges, true), cv::Exception);
  1631. EXPECT_THROW(cv::calcHist(&img, 1, channels, noArray(), hist, -1, hist_size, ranges, true), cv::Exception);
  1632. EXPECT_THROW(cv::calcHist(&img, 1, channels, noArray(), hist, 1, NULL, ranges, true), cv::Exception);
  1633. EXPECT_THROW(cv::calcHist(&imgInt, 1, channels, noArray(), hist, 1, hist_size, NULL, true), cv::Exception);
  1634. // special case
  1635. EXPECT_NO_THROW(cv::calcHist(&img, 1, channels, noArray(), hist, 1, hist_size, NULL, true));
  1636. Mat backProj;
  1637. // base run
  1638. EXPECT_NO_THROW(cv::calcBackProject(&img, 1, channels, hist, backProj, ranges, 1, true));
  1639. // bad parameters
  1640. EXPECT_THROW(cv::calcBackProject(NULL, 1, channels, hist, backProj, ranges, 1, true), cv::Exception);
  1641. EXPECT_THROW(cv::calcBackProject(&img, 0, channels, hist, backProj, ranges, 1, true), cv::Exception);
  1642. EXPECT_THROW(cv::calcBackProject(&img, 1, channels, noArray(), backProj, ranges, 1, true), cv::Exception);
  1643. EXPECT_THROW(cv::calcBackProject(&img, 1, channels, hist, noArray(), ranges, 1, true), cv::Exception);
  1644. EXPECT_THROW(cv::calcBackProject(&imgInt, 1, channels, hist, backProj, NULL, 1, true), cv::Exception);
  1645. // special case
  1646. EXPECT_NO_THROW(cv::calcBackProject(&img, 1, channels, hist, backProj, NULL, 1, true));
  1647. }
  1648. TEST(Imgproc_Hist_Calc, IPP_ranges_with_equal_exponent_21595)
  1649. {
  1650. const int channels[] = { 0 };
  1651. float range1[] = { -0.5f, 1.5f };
  1652. const float* ranges[] = { range1 };
  1653. const int hist_size[] = { 2 };
  1654. uint8_t m[1][6] = { { 0, 1, 0, 1 , 1, 1 } };
  1655. cv::Mat images_u = Mat(1, 6, CV_8UC1, m);
  1656. cv::Mat histogram_u;
  1657. cv::calcHist(&images_u, 1, channels, noArray(), histogram_u, 1, hist_size, ranges);
  1658. ASSERT_EQ(histogram_u.at<float>(0), 2.f) << "0 not counts correctly, res: " << histogram_u.at<float>(0);
  1659. ASSERT_EQ(histogram_u.at<float>(1), 4.f) << "1 not counts correctly, res: " << histogram_u.at<float>(0);
  1660. }
  1661. TEST(Imgproc_Hist_Calc, IPP_ranges_with_nonequal_exponent_21595)
  1662. {
  1663. const int channels[] = { 0 };
  1664. float range1[] = { -1.3f, 1.5f };
  1665. const float* ranges[] = { range1 };
  1666. const int hist_size[] = { 3 };
  1667. uint8_t m[1][6] = { { 0, 1, 0, 1 , 1, 1 } };
  1668. cv::Mat images_u = Mat(1, 6, CV_8UC1, m);
  1669. cv::Mat histogram_u;
  1670. cv::calcHist(&images_u, 1, channels, noArray(), histogram_u, 1, hist_size, ranges);
  1671. ASSERT_EQ(histogram_u.at<float>(0), 0.f) << "not equal to zero, res: " << histogram_u.at<float>(0);
  1672. ASSERT_EQ(histogram_u.at<float>(1), 2.f) << "0 not counts correctly, res: " << histogram_u.at<float>(1);
  1673. ASSERT_EQ(histogram_u.at<float>(2), 4.f) << "1 not counts correctly, res: " << histogram_u.at<float>(2);
  1674. }
  1675. ////////////////////////////////////////// equalizeHist() /////////////////////////////////////////
  1676. void equalizeHistReference(const Mat& src, Mat& dst)
  1677. {
  1678. std::vector<int> hist(256, 0);
  1679. for (int y = 0; y < src.rows; y++)
  1680. {
  1681. const uchar* srow = src.ptr(y);
  1682. for (int x = 0; x < src.cols; x++)
  1683. {
  1684. hist[srow[x]]++;
  1685. }
  1686. }
  1687. int first = 0;
  1688. while (!hist[first]) ++first;
  1689. int total = (int)src.total();
  1690. if (hist[first] == total)
  1691. {
  1692. dst.setTo(first);
  1693. return;
  1694. }
  1695. std::vector<uchar> lut(256);
  1696. lut[first] = 0;
  1697. float scale = (255.f)/(total - hist[first]);
  1698. int sum = 0;
  1699. for (int i = first + 1; i < 256; ++i)
  1700. {
  1701. sum += hist[i];
  1702. lut[i] = saturate_cast<uchar>(sum * scale);
  1703. }
  1704. cv::LUT(src, lut, dst);
  1705. }
  1706. typedef ::testing::TestWithParam<std::tuple<cv::Size, int>> Imgproc_Equalize_Hist;
  1707. TEST_P(Imgproc_Equalize_Hist, accuracy)
  1708. {
  1709. auto p = GetParam();
  1710. cv::Size size = std::get<0>(p);
  1711. int idx = std::get<1>(p);
  1712. RNG &rng = cvtest::TS::ptr()->get_rng();
  1713. rng.state += idx;
  1714. cv::Mat src(size, CV_8U);
  1715. cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));
  1716. cv::Mat dst, gold;
  1717. equalizeHistReference(src, gold);
  1718. cv::equalizeHist(src, dst);
  1719. ASSERT_EQ(CV_8UC1, dst.type());
  1720. ASSERT_EQ(gold.size(), dst.size());
  1721. EXPECT_MAT_NEAR(dst, gold, 1);
  1722. EXPECT_MAT_N_DIFF(dst, gold, 0.05 * size.area()); // The 5% range could be accomodated to HAL
  1723. }
  1724. INSTANTIATE_TEST_CASE_P(Imgproc_Hist, Imgproc_Equalize_Hist, ::testing::Combine(
  1725. ::testing::Values(cv::Size(123, 321), cv::Size(256, 256), cv::Size(1024, 768)),
  1726. ::testing::Range(0, 10)));
  1727. // See https://github.com/opencv/opencv/issues/24757
  1728. TEST(Imgproc_Hist_Compare, intersect_regression_24757)
  1729. {
  1730. cv::Mat src1 = cv::Mat::zeros(128,1, CV_32FC1);
  1731. cv::Mat src2 = cv::Mat(128,1, CV_32FC1, cv::Scalar(std::numeric_limits<double>::max()));
  1732. // Ideal result Wrong result
  1733. src1.at<float>(32 * 0,0) = +1.0f; // work = +1.0 +1.0
  1734. src1.at<float>(32 * 1,0) = +55555555.5f; // work = +55555556.5 +55555555.5
  1735. src1.at<float>(32 * 2,0) = -55555555.5f; // work = +1.0 0.0
  1736. src1.at<float>(32 * 3,0) = -1.0f; // work = 0.0 -1.0
  1737. EXPECT_DOUBLE_EQ(compareHist(src1, src2, cv::HISTCMP_INTERSECT), 0.0);
  1738. }
  1739. }} // namespace
  1740. /* End Of File */