old_ml_inner_functions.cpp 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684
  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. //
  12. // Copyright (C) 2000, Intel Corporation, all rights reserved.
  13. // Third party copyrights are property of their respective owners.
  14. //
  15. // Redistribution and use in source and binary forms, with or without modification,
  16. // are permitted provided that the following conditions are met:
  17. //
  18. // * Redistribution's of source code must retain the above copyright notice,
  19. // this list of conditions and the following disclaimer.
  20. //
  21. // * Redistribution's in binary form must reproduce the above copyright notice,
  22. // this list of conditions and the following disclaimer in the documentation
  23. // and/or other materials provided with the distribution.
  24. //
  25. // * The name of Intel Corporation may not be used to endorse or promote products
  26. // derived from this software without specific prior written permission.
  27. //
  28. // This software is provided by the copyright holders and contributors "as is" and
  29. // any express or implied warranties, including, but not limited to, the implied
  30. // warranties of merchantability and fitness for a particular purpose are disclaimed.
  31. // In no event shall the Intel Corporation or contributors be liable for any direct,
  32. // indirect, incidental, special, exemplary, or consequential damages
  33. // (including, but not limited to, procurement of substitute goods or services;
  34. // loss of use, data, or profits; or business interruption) however caused
  35. // and on any theory of liability, whether in contract, strict liability,
  36. // or tort (including negligence or otherwise) arising in any way out of
  37. // the use of this software, even if advised of the possibility of such damage.
  38. //
  39. //M*/
  40. #include "old_ml_precomp.hpp"
  41. CvStatModel::CvStatModel()
  42. {
  43. default_model_name = "my_stat_model";
  44. }
  45. CvStatModel::~CvStatModel()
  46. {
  47. clear();
  48. }
  49. void CvStatModel::clear()
  50. {
  51. }
  52. void CvStatModel::save( const char* filename, const char* name ) const
  53. {
  54. cv::FileStorage fs;
  55. CV_FUNCNAME( "CvStatModel::save" );
  56. __BEGIN__;
  57. if( !fs.open( filename, cv::FileStorage::WRITE ))
  58. CV_ERROR( CV_StsError, "Could not open the file storage. Check the path and permissions" );
  59. write( fs, name ? name : default_model_name );
  60. __END__;
  61. }
  62. void CvStatModel::load( const char* filename, const char* name )
  63. {
  64. cv::FileStorage fs;
  65. CV_FUNCNAME( "CvStatModel::load" );
  66. __BEGIN__;
  67. cv::FileNode model_node;
  68. if( !fs.open(filename, cv::FileStorage::READ) )
  69. CV_ERROR( CV_StsError, "Could not open the file storage. Check the path and permissions" );
  70. if( name )
  71. model_node = fs[ name ];
  72. else
  73. {
  74. auto root = fs.root();
  75. if ( root.size() > 0 )
  76. model_node = fs[0];
  77. }
  78. read( model_node );
  79. __END__;
  80. }
  81. void CvStatModel::write( cv::FileStorage&, const char* ) const
  82. {
  83. OPENCV_ERROR( CV_StsNotImplemented, "CvStatModel::write", "" );
  84. }
  85. void CvStatModel::read( const cv::FileNode& )
  86. {
  87. OPENCV_ERROR( CV_StsNotImplemented, "CvStatModel::read", "" );
  88. }
  89. CvMat* icvGenerateRandomClusterCenters ( int seed, const CvMat* data,
  90. int num_of_clusters, CvMat* _centers )
  91. {
  92. CvMat* centers = _centers;
  93. CV_FUNCNAME("icvGenerateRandomClusterCenters");
  94. __BEGIN__;
  95. CvRNG rng;
  96. CvMat data_comp, centers_comp;
  97. CvPoint minLoc, maxLoc; // Not used, just for function "cvMinMaxLoc"
  98. double minVal, maxVal;
  99. int i;
  100. int dim = data ? data->cols : 0;
  101. if( ICV_IS_MAT_OF_TYPE(data, CV_32FC1) )
  102. {
  103. if( _centers && !ICV_IS_MAT_OF_TYPE (_centers, CV_32FC1) )
  104. {
  105. CV_ERROR(CV_StsBadArg,"");
  106. }
  107. else if( !_centers )
  108. CV_CALL(centers = cvCreateMat (num_of_clusters, dim, CV_32FC1));
  109. }
  110. else if( ICV_IS_MAT_OF_TYPE(data, CV_64FC1) )
  111. {
  112. if( _centers && !ICV_IS_MAT_OF_TYPE (_centers, CV_64FC1) )
  113. {
  114. CV_ERROR(CV_StsBadArg,"");
  115. }
  116. else if( !_centers )
  117. CV_CALL(centers = cvCreateMat (num_of_clusters, dim, CV_64FC1));
  118. }
  119. else
  120. CV_ERROR (CV_StsBadArg,"");
  121. if( num_of_clusters < 1 )
  122. CV_ERROR (CV_StsBadArg,"");
  123. rng = cvRNG(seed);
  124. for (i = 0; i < dim; i++)
  125. {
  126. CV_CALL(cvGetCol (data, &data_comp, i));
  127. CV_CALL(cvMinMaxLoc (&data_comp, &minVal, &maxVal, &minLoc, &maxLoc));
  128. CV_CALL(cvGetCol (centers, &centers_comp, i));
  129. CV_CALL(cvRandArr (&rng, &centers_comp, CV_RAND_UNI, cvScalarAll(minVal), cvScalarAll(maxVal)));
  130. }
  131. __END__;
  132. if( (cvGetErrStatus () < 0) || (centers != _centers) )
  133. cvReleaseMat (&centers);
  134. return _centers ? _centers : centers;
  135. } // end of icvGenerateRandomClusterCenters
  136. static int CV_CDECL
  137. icvCmpIntegers( const void* a, const void* b )
  138. {
  139. return *(const int*)a - *(const int*)b;
  140. }
  141. static int CV_CDECL
  142. icvCmpIntegersPtr( const void* _a, const void* _b )
  143. {
  144. int a = **(const int**)_a;
  145. int b = **(const int**)_b;
  146. return (a < b ? -1 : 0)|(a > b);
  147. }
  148. static int icvCmpSparseVecElems( const void* a, const void* b )
  149. {
  150. return ((CvSparseVecElem32f*)a)->idx - ((CvSparseVecElem32f*)b)->idx;
  151. }
  152. CvMat*
  153. cvPreprocessIndexArray( const CvMat* idx_arr, int data_arr_size, bool check_for_duplicates )
  154. {
  155. CvMat* idx = 0;
  156. CV_FUNCNAME( "cvPreprocessIndexArray" );
  157. __BEGIN__;
  158. int i, idx_total, idx_selected = 0, step, type, prev = INT_MIN, is_sorted = 1;
  159. uchar* srcb = 0;
  160. int* srci = 0;
  161. int* dsti;
  162. if( !CV_IS_MAT(idx_arr) )
  163. CV_ERROR( CV_StsBadArg, "Invalid index array" );
  164. if( idx_arr->rows != 1 && idx_arr->cols != 1 )
  165. CV_ERROR( CV_StsBadSize, "the index array must be 1-dimensional" );
  166. idx_total = idx_arr->rows + idx_arr->cols - 1;
  167. srcb = idx_arr->data.ptr;
  168. srci = idx_arr->data.i;
  169. type = CV_MAT_TYPE(idx_arr->type);
  170. step = CV_IS_MAT_CONT(idx_arr->type) ? 1 : idx_arr->step/CV_ELEM_SIZE(type);
  171. switch( type )
  172. {
  173. case CV_8UC1:
  174. case CV_8SC1:
  175. // idx_arr is array of 1's and 0's -
  176. // i.e. it is a mask of the selected components
  177. if( idx_total != data_arr_size )
  178. CV_ERROR( CV_StsUnmatchedSizes,
  179. "Component mask should contain as many elements as the total number of input variables" );
  180. for( i = 0; i < idx_total; i++ )
  181. idx_selected += srcb[i*step] != 0;
  182. if( idx_selected == 0 )
  183. CV_ERROR( CV_StsOutOfRange, "No components/input_variables is selected!" );
  184. break;
  185. case CV_32SC1:
  186. // idx_arr is array of integer indices of selected components
  187. if( idx_total > data_arr_size )
  188. CV_ERROR( CV_StsOutOfRange,
  189. "index array may not contain more elements than the total number of input variables" );
  190. idx_selected = idx_total;
  191. // check if sorted already
  192. for( i = 0; i < idx_total; i++ )
  193. {
  194. int val = srci[i*step];
  195. if( val >= prev )
  196. {
  197. is_sorted = 0;
  198. break;
  199. }
  200. prev = val;
  201. }
  202. break;
  203. default:
  204. CV_ERROR( CV_StsUnsupportedFormat, "Unsupported index array data type "
  205. "(it should be 8uC1, 8sC1 or 32sC1)" );
  206. }
  207. CV_CALL( idx = cvCreateMat( 1, idx_selected, CV_32SC1 ));
  208. dsti = idx->data.i;
  209. if( type < CV_32SC1 )
  210. {
  211. for( i = 0; i < idx_total; i++ )
  212. if( srcb[i*step] )
  213. *dsti++ = i;
  214. }
  215. else
  216. {
  217. for( i = 0; i < idx_total; i++ )
  218. dsti[i] = srci[i*step];
  219. if( !is_sorted )
  220. qsort( dsti, idx_total, sizeof(dsti[0]), icvCmpIntegers );
  221. if( dsti[0] < 0 || dsti[idx_total-1] >= data_arr_size )
  222. CV_ERROR( CV_StsOutOfRange, "the index array elements are out of range" );
  223. if( check_for_duplicates )
  224. {
  225. for( i = 1; i < idx_total; i++ )
  226. if( dsti[i] <= dsti[i-1] )
  227. CV_ERROR( CV_StsBadArg, "There are duplicated index array elements" );
  228. }
  229. }
  230. __END__;
  231. if( cvGetErrStatus() < 0 )
  232. cvReleaseMat( &idx );
  233. return idx;
  234. }
  235. CvMat*
  236. cvPreprocessVarType( const CvMat* var_type, const CvMat* var_idx,
  237. int var_count, int* response_type )
  238. {
  239. CvMat* out_var_type = 0;
  240. CV_FUNCNAME( "cvPreprocessVarType" );
  241. if( response_type )
  242. *response_type = -1;
  243. __BEGIN__;
  244. int i, tm_size, tm_step;
  245. //int* map = 0;
  246. const uchar* src;
  247. uchar* dst;
  248. if( !CV_IS_MAT(var_type) )
  249. CV_ERROR( var_type ? CV_StsBadArg : CV_StsNullPtr, "Invalid or absent var_type array" );
  250. if( var_type->rows != 1 && var_type->cols != 1 )
  251. CV_ERROR( CV_StsBadSize, "var_type array must be 1-dimensional" );
  252. if( !CV_IS_MASK_ARR(var_type))
  253. CV_ERROR( CV_StsUnsupportedFormat, "type mask must be 8uC1 or 8sC1 array" );
  254. tm_size = var_type->rows + var_type->cols - 1;
  255. tm_step = var_type->rows == 1 ? 1 : var_type->step/CV_ELEM_SIZE(var_type->type);
  256. if( /*tm_size != var_count &&*/ tm_size != var_count + 1 )
  257. CV_ERROR( CV_StsBadArg,
  258. "type mask must be of <input var count> + 1 size" );
  259. if( response_type && tm_size > var_count )
  260. *response_type = var_type->data.ptr[var_count*tm_step] != 0;
  261. if( var_idx )
  262. {
  263. if( !CV_IS_MAT(var_idx) || CV_MAT_TYPE(var_idx->type) != CV_32SC1 ||
  264. (var_idx->rows != 1 && var_idx->cols != 1) || !CV_IS_MAT_CONT(var_idx->type) )
  265. CV_ERROR( CV_StsBadArg, "var index array should be continuous 1-dimensional integer vector" );
  266. if( var_idx->rows + var_idx->cols - 1 > var_count )
  267. CV_ERROR( CV_StsBadSize, "var index array is too large" );
  268. //map = var_idx->data.i;
  269. var_count = var_idx->rows + var_idx->cols - 1;
  270. }
  271. CV_CALL( out_var_type = cvCreateMat( 1, var_count, CV_8UC1 ));
  272. src = var_type->data.ptr;
  273. dst = out_var_type->data.ptr;
  274. for( i = 0; i < var_count; i++ )
  275. {
  276. //int idx = map ? map[i] : i;
  277. assert( (unsigned)/*idx*/i < (unsigned)tm_size );
  278. dst[i] = (uchar)(src[/*idx*/i*tm_step] != 0);
  279. }
  280. __END__;
  281. return out_var_type;
  282. }
  283. CvMat*
  284. cvPreprocessOrderedResponses( const CvMat* responses, const CvMat* sample_idx, int sample_all )
  285. {
  286. CvMat* out_responses = 0;
  287. CV_FUNCNAME( "cvPreprocessOrderedResponses" );
  288. __BEGIN__;
  289. int i, r_type, r_step;
  290. const int* map = 0;
  291. float* dst;
  292. int sample_count = sample_all;
  293. if( !CV_IS_MAT(responses) )
  294. CV_ERROR( CV_StsBadArg, "Invalid response array" );
  295. if( responses->rows != 1 && responses->cols != 1 )
  296. CV_ERROR( CV_StsBadSize, "Response array must be 1-dimensional" );
  297. if( responses->rows + responses->cols - 1 != sample_count )
  298. CV_ERROR( CV_StsUnmatchedSizes,
  299. "Response array must contain as many elements as the total number of samples" );
  300. r_type = CV_MAT_TYPE(responses->type);
  301. if( r_type != CV_32FC1 && r_type != CV_32SC1 )
  302. CV_ERROR( CV_StsUnsupportedFormat, "Unsupported response type" );
  303. r_step = responses->step ? responses->step / CV_ELEM_SIZE(responses->type) : 1;
  304. if( r_type == CV_32FC1 && CV_IS_MAT_CONT(responses->type) && !sample_idx )
  305. {
  306. out_responses = cvCloneMat( responses );
  307. EXIT;
  308. }
  309. if( sample_idx )
  310. {
  311. if( !CV_IS_MAT(sample_idx) || CV_MAT_TYPE(sample_idx->type) != CV_32SC1 ||
  312. (sample_idx->rows != 1 && sample_idx->cols != 1) || !CV_IS_MAT_CONT(sample_idx->type) )
  313. CV_ERROR( CV_StsBadArg, "sample index array should be continuous 1-dimensional integer vector" );
  314. if( sample_idx->rows + sample_idx->cols - 1 > sample_count )
  315. CV_ERROR( CV_StsBadSize, "sample index array is too large" );
  316. map = sample_idx->data.i;
  317. sample_count = sample_idx->rows + sample_idx->cols - 1;
  318. }
  319. CV_CALL( out_responses = cvCreateMat( 1, sample_count, CV_32FC1 ));
  320. dst = out_responses->data.fl;
  321. if( r_type == CV_32FC1 )
  322. {
  323. const float* src = responses->data.fl;
  324. for( i = 0; i < sample_count; i++ )
  325. {
  326. int idx = map ? map[i] : i;
  327. assert( (unsigned)idx < (unsigned)sample_all );
  328. dst[i] = src[idx*r_step];
  329. }
  330. }
  331. else
  332. {
  333. const int* src = responses->data.i;
  334. for( i = 0; i < sample_count; i++ )
  335. {
  336. int idx = map ? map[i] : i;
  337. assert( (unsigned)idx < (unsigned)sample_all );
  338. dst[i] = (float)src[idx*r_step];
  339. }
  340. }
  341. __END__;
  342. return out_responses;
  343. }
  344. CvMat*
  345. cvPreprocessCategoricalResponses( const CvMat* responses,
  346. const CvMat* sample_idx, int sample_all,
  347. CvMat** out_response_map, CvMat** class_counts )
  348. {
  349. CvMat* out_responses = 0;
  350. int** response_ptr = 0;
  351. CV_FUNCNAME( "cvPreprocessCategoricalResponses" );
  352. if( out_response_map )
  353. *out_response_map = 0;
  354. if( class_counts )
  355. *class_counts = 0;
  356. __BEGIN__;
  357. int i, r_type, r_step;
  358. int cls_count = 1, prev_cls, prev_i;
  359. const int* map = 0;
  360. const int* srci;
  361. const float* srcfl;
  362. int* dst;
  363. int* cls_map;
  364. int* cls_counts = 0;
  365. int sample_count = sample_all;
  366. if( !CV_IS_MAT(responses) )
  367. CV_ERROR( CV_StsBadArg, "Invalid response array" );
  368. if( responses->rows != 1 && responses->cols != 1 )
  369. CV_ERROR( CV_StsBadSize, "Response array must be 1-dimensional" );
  370. if( responses->rows + responses->cols - 1 != sample_count )
  371. CV_ERROR( CV_StsUnmatchedSizes,
  372. "Response array must contain as many elements as the total number of samples" );
  373. r_type = CV_MAT_TYPE(responses->type);
  374. if( r_type != CV_32FC1 && r_type != CV_32SC1 )
  375. CV_ERROR( CV_StsUnsupportedFormat, "Unsupported response type" );
  376. r_step = responses->rows == 1 ? 1 : responses->step / CV_ELEM_SIZE(responses->type);
  377. if( sample_idx )
  378. {
  379. if( !CV_IS_MAT(sample_idx) || CV_MAT_TYPE(sample_idx->type) != CV_32SC1 ||
  380. (sample_idx->rows != 1 && sample_idx->cols != 1) || !CV_IS_MAT_CONT(sample_idx->type) )
  381. CV_ERROR( CV_StsBadArg, "sample index array should be continuous 1-dimensional integer vector" );
  382. if( sample_idx->rows + sample_idx->cols - 1 > sample_count )
  383. CV_ERROR( CV_StsBadSize, "sample index array is too large" );
  384. map = sample_idx->data.i;
  385. sample_count = sample_idx->rows + sample_idx->cols - 1;
  386. }
  387. CV_CALL( out_responses = cvCreateMat( 1, sample_count, CV_32SC1 ));
  388. if( !out_response_map )
  389. CV_ERROR( CV_StsNullPtr, "out_response_map pointer is NULL" );
  390. CV_CALL( response_ptr = (int**)cvAlloc( sample_count*sizeof(response_ptr[0])));
  391. srci = responses->data.i;
  392. srcfl = responses->data.fl;
  393. dst = out_responses->data.i;
  394. for( i = 0; i < sample_count; i++ )
  395. {
  396. int idx = map ? map[i] : i;
  397. assert( (unsigned)idx < (unsigned)sample_all );
  398. if( r_type == CV_32SC1 )
  399. dst[i] = srci[idx*r_step];
  400. else
  401. {
  402. float rf = srcfl[idx*r_step];
  403. int ri = cvRound(rf);
  404. if( ri != rf )
  405. {
  406. char buf[100];
  407. snprintf( buf, sizeof(buf), "response #%d is not integral", idx );
  408. CV_ERROR( CV_StsBadArg, buf );
  409. }
  410. dst[i] = ri;
  411. }
  412. response_ptr[i] = dst + i;
  413. }
  414. qsort( response_ptr, sample_count, sizeof(int*), icvCmpIntegersPtr );
  415. // count the classes
  416. for( i = 1; i < sample_count; i++ )
  417. cls_count += *response_ptr[i] != *response_ptr[i-1];
  418. if( cls_count < 2 )
  419. CV_ERROR( CV_StsBadArg, "There is only a single class" );
  420. CV_CALL( *out_response_map = cvCreateMat( 1, cls_count, CV_32SC1 ));
  421. if( class_counts )
  422. {
  423. CV_CALL( *class_counts = cvCreateMat( 1, cls_count, CV_32SC1 ));
  424. cls_counts = (*class_counts)->data.i;
  425. }
  426. // compact the class indices and build the map
  427. prev_cls = ~*response_ptr[0];
  428. cls_count = -1;
  429. cls_map = (*out_response_map)->data.i;
  430. for( i = 0, prev_i = -1; i < sample_count; i++ )
  431. {
  432. int cur_cls = *response_ptr[i];
  433. if( cur_cls != prev_cls )
  434. {
  435. if( cls_counts && cls_count >= 0 )
  436. cls_counts[cls_count] = i - prev_i;
  437. cls_map[++cls_count] = prev_cls = cur_cls;
  438. prev_i = i;
  439. }
  440. *response_ptr[i] = cls_count;
  441. }
  442. if( cls_counts )
  443. cls_counts[cls_count] = i - prev_i;
  444. __END__;
  445. cvFree( &response_ptr );
  446. return out_responses;
  447. }
  448. const float**
  449. cvGetTrainSamples( const CvMat* train_data, int tflag,
  450. const CvMat* var_idx, const CvMat* sample_idx,
  451. int* _var_count, int* _sample_count,
  452. bool always_copy_data )
  453. {
  454. float** samples = 0;
  455. CV_FUNCNAME( "cvGetTrainSamples" );
  456. __BEGIN__;
  457. int i, j, var_count, sample_count, s_step, v_step;
  458. bool copy_data;
  459. const float* data;
  460. const int *s_idx, *v_idx;
  461. if( !CV_IS_MAT(train_data) )
  462. CV_ERROR( CV_StsBadArg, "Invalid or NULL training data matrix" );
  463. var_count = var_idx ? var_idx->cols + var_idx->rows - 1 :
  464. tflag == CV_ROW_SAMPLE ? train_data->cols : train_data->rows;
  465. sample_count = sample_idx ? sample_idx->cols + sample_idx->rows - 1 :
  466. tflag == CV_ROW_SAMPLE ? train_data->rows : train_data->cols;
  467. if( _var_count )
  468. *_var_count = var_count;
  469. if( _sample_count )
  470. *_sample_count = sample_count;
  471. copy_data = tflag != CV_ROW_SAMPLE || var_idx || always_copy_data;
  472. CV_CALL( samples = (float**)cvAlloc(sample_count*sizeof(samples[0]) +
  473. (copy_data ? 1 : 0)*var_count*sample_count*sizeof(samples[0][0])) );
  474. data = train_data->data.fl;
  475. s_step = train_data->step / sizeof(samples[0][0]);
  476. v_step = 1;
  477. s_idx = sample_idx ? sample_idx->data.i : 0;
  478. v_idx = var_idx ? var_idx->data.i : 0;
  479. if( !copy_data )
  480. {
  481. for( i = 0; i < sample_count; i++ )
  482. samples[i] = (float*)(data + (s_idx ? s_idx[i] : i)*s_step);
  483. }
  484. else
  485. {
  486. samples[0] = (float*)(samples + sample_count);
  487. if( tflag != CV_ROW_SAMPLE )
  488. CV_SWAP( s_step, v_step, i );
  489. for( i = 0; i < sample_count; i++ )
  490. {
  491. float* dst = samples[i] = samples[0] + i*var_count;
  492. const float* src = data + (s_idx ? s_idx[i] : i)*s_step;
  493. if( !v_idx )
  494. for( j = 0; j < var_count; j++ )
  495. dst[j] = src[j*v_step];
  496. else
  497. for( j = 0; j < var_count; j++ )
  498. dst[j] = src[v_idx[j]*v_step];
  499. }
  500. }
  501. __END__;
  502. return (const float**)samples;
  503. }
  504. void
  505. cvCheckTrainData( const CvMat* train_data, int tflag,
  506. const CvMat* missing_mask,
  507. int* var_all, int* sample_all )
  508. {
  509. CV_FUNCNAME( "cvCheckTrainData" );
  510. if( var_all )
  511. *var_all = 0;
  512. if( sample_all )
  513. *sample_all = 0;
  514. __BEGIN__;
  515. // check parameter types and sizes
  516. if( !CV_IS_MAT(train_data) || CV_MAT_TYPE(train_data->type) != CV_32FC1 )
  517. CV_ERROR( CV_StsBadArg, "train data must be floating-point matrix" );
  518. if( missing_mask )
  519. {
  520. if( !CV_IS_MAT(missing_mask) || !CV_IS_MASK_ARR(missing_mask) ||
  521. !CV_ARE_SIZES_EQ(train_data, missing_mask) )
  522. CV_ERROR( CV_StsBadArg,
  523. "missing value mask must be 8-bit matrix of the same size as training data" );
  524. }
  525. if( tflag != CV_ROW_SAMPLE && tflag != CV_COL_SAMPLE )
  526. CV_ERROR( CV_StsBadArg,
  527. "Unknown training data layout (must be CV_ROW_SAMPLE or CV_COL_SAMPLE)" );
  528. if( var_all )
  529. *var_all = tflag == CV_ROW_SAMPLE ? train_data->cols : train_data->rows;
  530. if( sample_all )
  531. *sample_all = tflag == CV_ROW_SAMPLE ? train_data->rows : train_data->cols;
  532. __END__;
  533. }
  534. int
  535. cvPrepareTrainData( const char* /*funcname*/,
  536. const CvMat* train_data, int tflag,
  537. const CvMat* responses, int response_type,
  538. const CvMat* var_idx,
  539. const CvMat* sample_idx,
  540. bool always_copy_data,
  541. const float*** out_train_samples,
  542. int* _sample_count,
  543. int* _var_count,
  544. int* _var_all,
  545. CvMat** out_responses,
  546. CvMat** out_response_map,
  547. CvMat** out_var_idx,
  548. CvMat** out_sample_idx )
  549. {
  550. int ok = 0;
  551. CvMat* _var_idx = 0;
  552. CvMat* _sample_idx = 0;
  553. CvMat* _responses = 0;
  554. int sample_all = 0, sample_count = 0, var_all = 0, var_count = 0;
  555. CV_FUNCNAME( "cvPrepareTrainData" );
  556. // step 0. clear all the output pointers to ensure we do not try
  557. // to call free() with uninitialized pointers
  558. if( out_responses )
  559. *out_responses = 0;
  560. if( out_response_map )
  561. *out_response_map = 0;
  562. if( out_var_idx )
  563. *out_var_idx = 0;
  564. if( out_sample_idx )
  565. *out_sample_idx = 0;
  566. if( out_train_samples )
  567. *out_train_samples = 0;
  568. if( _sample_count )
  569. *_sample_count = 0;
  570. if( _var_count )
  571. *_var_count = 0;
  572. if( _var_all )
  573. *_var_all = 0;
  574. __BEGIN__;
  575. if( !out_train_samples )
  576. CV_ERROR( CV_StsBadArg, "output pointer to train samples is NULL" );
  577. CV_CALL( cvCheckTrainData( train_data, tflag, 0, &var_all, &sample_all ));
  578. if( sample_idx )
  579. CV_CALL( _sample_idx = cvPreprocessIndexArray( sample_idx, sample_all ));
  580. if( var_idx )
  581. CV_CALL( _var_idx = cvPreprocessIndexArray( var_idx, var_all ));
  582. if( responses )
  583. {
  584. if( !out_responses )
  585. CV_ERROR( CV_StsNullPtr, "output response pointer is NULL" );
  586. if( response_type == CV_VAR_NUMERICAL )
  587. {
  588. CV_CALL( _responses = cvPreprocessOrderedResponses( responses,
  589. _sample_idx, sample_all ));
  590. }
  591. else
  592. {
  593. CV_CALL( _responses = cvPreprocessCategoricalResponses( responses,
  594. _sample_idx, sample_all, out_response_map, 0 ));
  595. }
  596. }
  597. CV_CALL( *out_train_samples =
  598. cvGetTrainSamples( train_data, tflag, _var_idx, _sample_idx,
  599. &var_count, &sample_count, always_copy_data ));
  600. ok = 1;
  601. __END__;
  602. if( ok )
  603. {
  604. if( out_responses )
  605. *out_responses = _responses, _responses = 0;
  606. if( out_var_idx )
  607. *out_var_idx = _var_idx, _var_idx = 0;
  608. if( out_sample_idx )
  609. *out_sample_idx = _sample_idx, _sample_idx = 0;
  610. if( _sample_count )
  611. *_sample_count = sample_count;
  612. if( _var_count )
  613. *_var_count = var_count;
  614. if( _var_all )
  615. *_var_all = var_all;
  616. }
  617. else
  618. {
  619. if( out_response_map )
  620. cvReleaseMat( out_response_map );
  621. cvFree( out_train_samples );
  622. }
  623. if( _responses != responses )
  624. cvReleaseMat( &_responses );
  625. cvReleaseMat( &_var_idx );
  626. cvReleaseMat( &_sample_idx );
  627. return ok;
  628. }
  629. typedef struct CvSampleResponsePair
  630. {
  631. const float* sample;
  632. const uchar* mask;
  633. int response;
  634. int index;
  635. }
  636. CvSampleResponsePair;
  637. static int
  638. CV_CDECL icvCmpSampleResponsePairs( const void* a, const void* b )
  639. {
  640. int ra = ((const CvSampleResponsePair*)a)->response;
  641. int rb = ((const CvSampleResponsePair*)b)->response;
  642. int ia = ((const CvSampleResponsePair*)a)->index;
  643. int ib = ((const CvSampleResponsePair*)b)->index;
  644. return ra < rb ? -1 : ra > rb ? 1 : ia - ib;
  645. //return (ra > rb ? -1 : 0)|(ra < rb);
  646. }
  647. void
  648. cvSortSamplesByClasses( const float** samples, const CvMat* classes,
  649. int* class_ranges, const uchar** mask )
  650. {
  651. CvSampleResponsePair* pairs = 0;
  652. CV_FUNCNAME( "cvSortSamplesByClasses" );
  653. __BEGIN__;
  654. int i, k = 0, sample_count;
  655. if( !samples || !classes || !class_ranges )
  656. CV_ERROR( CV_StsNullPtr, "INTERNAL ERROR: some of the args are NULL pointers" );
  657. if( classes->rows != 1 || CV_MAT_TYPE(classes->type) != CV_32SC1 )
  658. CV_ERROR( CV_StsBadArg, "classes array must be a single row of integers" );
  659. sample_count = classes->cols;
  660. CV_CALL( pairs = (CvSampleResponsePair*)cvAlloc( (sample_count+1)*sizeof(pairs[0])));
  661. for( i = 0; i < sample_count; i++ )
  662. {
  663. pairs[i].sample = samples[i];
  664. pairs[i].mask = (mask) ? (mask[i]) : 0;
  665. pairs[i].response = classes->data.i[i];
  666. pairs[i].index = i;
  667. assert( classes->data.i[i] >= 0 );
  668. }
  669. qsort( pairs, sample_count, sizeof(pairs[0]), icvCmpSampleResponsePairs );
  670. pairs[sample_count].response = -1;
  671. class_ranges[0] = 0;
  672. for( i = 0; i < sample_count; i++ )
  673. {
  674. samples[i] = pairs[i].sample;
  675. if (mask)
  676. mask[i] = pairs[i].mask;
  677. classes->data.i[i] = pairs[i].response;
  678. if( pairs[i].response != pairs[i+1].response )
  679. class_ranges[++k] = i+1;
  680. }
  681. __END__;
  682. cvFree( &pairs );
  683. }
  684. void
  685. cvPreparePredictData( const CvArr* _sample, int dims_all,
  686. const CvMat* comp_idx, int class_count,
  687. const CvMat* prob, float** _row_sample,
  688. int as_sparse )
  689. {
  690. float* row_sample = 0;
  691. int* inverse_comp_idx = 0;
  692. CV_FUNCNAME( "cvPreparePredictData" );
  693. __BEGIN__;
  694. const CvMat* sample = (const CvMat*)_sample;
  695. float* sample_data;
  696. int sample_step;
  697. int is_sparse = CV_IS_SPARSE_MAT(sample);
  698. int d, sizes[CV_MAX_DIM];
  699. int i, dims_selected;
  700. int vec_size;
  701. if( !is_sparse && !CV_IS_MAT(sample) )
  702. CV_ERROR( !sample ? CV_StsNullPtr : CV_StsBadArg, "The sample is not a valid vector" );
  703. if( cvGetElemType( sample ) != CV_32FC1 )
  704. CV_ERROR( CV_StsUnsupportedFormat, "Input sample must have 32fC1 type" );
  705. CV_CALL( d = cvGetDims( sample, sizes ));
  706. if( !((is_sparse && d == 1) || (!is_sparse && d == 2 && (sample->rows == 1 || sample->cols == 1))) )
  707. CV_ERROR( CV_StsBadSize, "Input sample must be 1-dimensional vector" );
  708. if( d == 1 )
  709. sizes[1] = 1;
  710. if( sizes[0] + sizes[1] - 1 != dims_all )
  711. CV_ERROR( CV_StsUnmatchedSizes,
  712. "The sample size is different from what has been used for training" );
  713. if( !_row_sample )
  714. CV_ERROR( CV_StsNullPtr, "INTERNAL ERROR: The row_sample pointer is NULL" );
  715. if( comp_idx && (!CV_IS_MAT(comp_idx) || comp_idx->rows != 1 ||
  716. CV_MAT_TYPE(comp_idx->type) != CV_32SC1) )
  717. CV_ERROR( CV_StsBadArg, "INTERNAL ERROR: invalid comp_idx" );
  718. dims_selected = comp_idx ? comp_idx->cols : dims_all;
  719. if( prob )
  720. {
  721. if( !CV_IS_MAT(prob) )
  722. CV_ERROR( CV_StsBadArg, "The output matrix of probabilities is invalid" );
  723. if( (prob->rows != 1 && prob->cols != 1) ||
  724. (CV_MAT_TYPE(prob->type) != CV_32FC1 &&
  725. CV_MAT_TYPE(prob->type) != CV_64FC1) )
  726. CV_ERROR( CV_StsBadSize,
  727. "The matrix of probabilities must be 1-dimensional vector of 32fC1 type" );
  728. if( prob->rows + prob->cols - 1 != class_count )
  729. CV_ERROR( CV_StsUnmatchedSizes,
  730. "The vector of probabilities must contain as many elements as "
  731. "the number of classes in the training set" );
  732. }
  733. vec_size = !as_sparse ? dims_selected*sizeof(row_sample[0]) :
  734. (dims_selected + 1)*sizeof(CvSparseVecElem32f);
  735. if( CV_IS_MAT(sample) )
  736. {
  737. sample_data = sample->data.fl;
  738. sample_step = CV_IS_MAT_CONT(sample->type) ? 1 : sample->step/sizeof(row_sample[0]);
  739. if( !comp_idx && CV_IS_MAT_CONT(sample->type) && !as_sparse )
  740. *_row_sample = sample_data;
  741. else
  742. {
  743. CV_CALL( row_sample = (float*)cvAlloc( vec_size ));
  744. if( !comp_idx )
  745. for( i = 0; i < dims_selected; i++ )
  746. row_sample[i] = sample_data[sample_step*i];
  747. else
  748. {
  749. int* comp = comp_idx->data.i;
  750. for( i = 0; i < dims_selected; i++ )
  751. row_sample[i] = sample_data[sample_step*comp[i]];
  752. }
  753. *_row_sample = row_sample;
  754. }
  755. if( as_sparse )
  756. {
  757. const float* src = (const float*)row_sample;
  758. CvSparseVecElem32f* dst = (CvSparseVecElem32f*)row_sample;
  759. dst[dims_selected].idx = -1;
  760. for( i = dims_selected - 1; i >= 0; i-- )
  761. {
  762. dst[i].idx = i;
  763. dst[i].val = src[i];
  764. }
  765. }
  766. }
  767. else
  768. {
  769. CvSparseNode* node;
  770. CvSparseMatIterator mat_iterator;
  771. const CvSparseMat* sparse = (const CvSparseMat*)sample;
  772. assert( is_sparse );
  773. node = cvInitSparseMatIterator( sparse, &mat_iterator );
  774. CV_CALL( row_sample = (float*)cvAlloc( vec_size ));
  775. if( comp_idx )
  776. {
  777. CV_CALL( inverse_comp_idx = (int*)cvAlloc( dims_all*sizeof(int) ));
  778. memset( inverse_comp_idx, -1, dims_all*sizeof(int) );
  779. for( i = 0; i < dims_selected; i++ )
  780. inverse_comp_idx[comp_idx->data.i[i]] = i;
  781. }
  782. if( !as_sparse )
  783. {
  784. memset( row_sample, 0, vec_size );
  785. for( ; node != 0; node = cvGetNextSparseNode(&mat_iterator) )
  786. {
  787. int idx = *CV_NODE_IDX( sparse, node );
  788. if( inverse_comp_idx )
  789. {
  790. idx = inverse_comp_idx[idx];
  791. if( idx < 0 )
  792. continue;
  793. }
  794. row_sample[idx] = *(float*)CV_NODE_VAL( sparse, node );
  795. }
  796. }
  797. else
  798. {
  799. CvSparseVecElem32f* ptr = (CvSparseVecElem32f*)row_sample;
  800. for( ; node != 0; node = cvGetNextSparseNode(&mat_iterator) )
  801. {
  802. int idx = *CV_NODE_IDX( sparse, node );
  803. if( inverse_comp_idx )
  804. {
  805. idx = inverse_comp_idx[idx];
  806. if( idx < 0 )
  807. continue;
  808. }
  809. ptr->idx = idx;
  810. ptr->val = *(float*)CV_NODE_VAL( sparse, node );
  811. ptr++;
  812. }
  813. qsort( row_sample, ptr - (CvSparseVecElem32f*)row_sample,
  814. sizeof(ptr[0]), icvCmpSparseVecElems );
  815. ptr->idx = -1;
  816. }
  817. *_row_sample = row_sample;
  818. }
  819. __END__;
  820. if( inverse_comp_idx )
  821. cvFree( &inverse_comp_idx );
  822. if( cvGetErrStatus() < 0 && _row_sample )
  823. {
  824. cvFree( &row_sample );
  825. *_row_sample = 0;
  826. }
  827. }
  828. static void
  829. icvConvertDataToSparse( const uchar* src, int src_step, int src_type,
  830. uchar* dst, int dst_step, int dst_type,
  831. CvSize size, int* idx )
  832. {
  833. CV_FUNCNAME( "icvConvertDataToSparse" );
  834. __BEGIN__;
  835. int i, j;
  836. src_type = CV_MAT_TYPE(src_type);
  837. dst_type = CV_MAT_TYPE(dst_type);
  838. if( CV_MAT_CN(src_type) != 1 || CV_MAT_CN(dst_type) != 1 )
  839. CV_ERROR( CV_StsUnsupportedFormat, "The function supports only single-channel arrays" );
  840. if( src_step == 0 )
  841. src_step = CV_ELEM_SIZE(src_type);
  842. if( dst_step == 0 )
  843. dst_step = CV_ELEM_SIZE(dst_type);
  844. // if there is no "idx" and if both arrays are continuous,
  845. // do the whole processing (copying or conversion) in a single loop
  846. if( !idx && CV_ELEM_SIZE(src_type)*size.width == src_step &&
  847. CV_ELEM_SIZE(dst_type)*size.width == dst_step )
  848. {
  849. size.width *= size.height;
  850. size.height = 1;
  851. }
  852. if( src_type == dst_type )
  853. {
  854. int full_width = CV_ELEM_SIZE(dst_type)*size.width;
  855. if( full_width == sizeof(int) ) // another common case: copy int's or float's
  856. for( i = 0; i < size.height; i++, src += src_step )
  857. *(int*)(dst + dst_step*(idx ? idx[i] : i)) = *(int*)src;
  858. else
  859. for( i = 0; i < size.height; i++, src += src_step )
  860. memcpy( dst + dst_step*(idx ? idx[i] : i), src, full_width );
  861. }
  862. else if( src_type == CV_32SC1 && (dst_type == CV_32FC1 || dst_type == CV_64FC1) )
  863. for( i = 0; i < size.height; i++, src += src_step )
  864. {
  865. uchar* _dst = dst + dst_step*(idx ? idx[i] : i);
  866. if( dst_type == CV_32FC1 )
  867. for( j = 0; j < size.width; j++ )
  868. ((float*)_dst)[j] = (float)((int*)src)[j];
  869. else
  870. for( j = 0; j < size.width; j++ )
  871. ((double*)_dst)[j] = ((int*)src)[j];
  872. }
  873. else if( (src_type == CV_32FC1 || src_type == CV_64FC1) && dst_type == CV_32SC1 )
  874. for( i = 0; i < size.height; i++, src += src_step )
  875. {
  876. uchar* _dst = dst + dst_step*(idx ? idx[i] : i);
  877. if( src_type == CV_32FC1 )
  878. for( j = 0; j < size.width; j++ )
  879. ((int*)_dst)[j] = cvRound(((float*)src)[j]);
  880. else
  881. for( j = 0; j < size.width; j++ )
  882. ((int*)_dst)[j] = cvRound(((double*)src)[j]);
  883. }
  884. else if( (src_type == CV_32FC1 && dst_type == CV_64FC1) ||
  885. (src_type == CV_64FC1 && dst_type == CV_32FC1) )
  886. for( i = 0; i < size.height; i++, src += src_step )
  887. {
  888. uchar* _dst = dst + dst_step*(idx ? idx[i] : i);
  889. if( src_type == CV_32FC1 )
  890. for( j = 0; j < size.width; j++ )
  891. ((double*)_dst)[j] = ((float*)src)[j];
  892. else
  893. for( j = 0; j < size.width; j++ )
  894. ((float*)_dst)[j] = (float)((double*)src)[j];
  895. }
  896. else
  897. CV_ERROR( CV_StsUnsupportedFormat, "Unsupported combination of input and output vectors" );
  898. __END__;
  899. }
  900. void
  901. cvWritebackLabels( const CvMat* labels, CvMat* dst_labels,
  902. const CvMat* centers, CvMat* dst_centers,
  903. const CvMat* probs, CvMat* dst_probs,
  904. const CvMat* sample_idx, int samples_all,
  905. const CvMat* comp_idx, int dims_all )
  906. {
  907. CV_FUNCNAME( "cvWritebackLabels" );
  908. __BEGIN__;
  909. int samples_selected = samples_all, dims_selected = dims_all;
  910. if( dst_labels && !CV_IS_MAT(dst_labels) )
  911. CV_ERROR( CV_StsBadArg, "Array of output labels is not a valid matrix" );
  912. if( dst_centers )
  913. if( !ICV_IS_MAT_OF_TYPE(dst_centers, CV_32FC1) &&
  914. !ICV_IS_MAT_OF_TYPE(dst_centers, CV_64FC1) )
  915. CV_ERROR( CV_StsBadArg, "Array of cluster centers is not a valid matrix" );
  916. if( dst_probs && !CV_IS_MAT(dst_probs) )
  917. CV_ERROR( CV_StsBadArg, "Probability matrix is not valid" );
  918. if( sample_idx )
  919. {
  920. CV_ASSERT( sample_idx->rows == 1 && CV_MAT_TYPE(sample_idx->type) == CV_32SC1 );
  921. samples_selected = sample_idx->cols;
  922. }
  923. if( comp_idx )
  924. {
  925. CV_ASSERT( comp_idx->rows == 1 && CV_MAT_TYPE(comp_idx->type) == CV_32SC1 );
  926. dims_selected = comp_idx->cols;
  927. }
  928. if( dst_labels && (!labels || labels->data.ptr != dst_labels->data.ptr) )
  929. {
  930. if( !labels )
  931. CV_ERROR( CV_StsNullPtr, "NULL labels" );
  932. CV_ASSERT( labels->rows == 1 );
  933. if( dst_labels->rows != 1 && dst_labels->cols != 1 )
  934. CV_ERROR( CV_StsBadSize, "Array of output labels should be 1d vector" );
  935. if( dst_labels->rows + dst_labels->cols - 1 != samples_all )
  936. CV_ERROR( CV_StsUnmatchedSizes,
  937. "Size of vector of output labels is not equal to the total number of input samples" );
  938. CV_ASSERT( labels->cols == samples_selected );
  939. CV_CALL( icvConvertDataToSparse( labels->data.ptr, labels->step, labels->type,
  940. dst_labels->data.ptr, dst_labels->step, dst_labels->type,
  941. cvSize( 1, samples_selected ), sample_idx ? sample_idx->data.i : 0 ));
  942. }
  943. if( dst_centers && (!centers || centers->data.ptr != dst_centers->data.ptr) )
  944. {
  945. int i;
  946. if( !centers )
  947. CV_ERROR( CV_StsNullPtr, "NULL centers" );
  948. if( centers->rows != dst_centers->rows )
  949. CV_ERROR( CV_StsUnmatchedSizes, "Invalid number of rows in matrix of output centers" );
  950. if( dst_centers->cols != dims_all )
  951. CV_ERROR( CV_StsUnmatchedSizes,
  952. "Number of columns in matrix of output centers is "
  953. "not equal to the total number of components in the input samples" );
  954. CV_ASSERT( centers->cols == dims_selected );
  955. for( i = 0; i < centers->rows; i++ )
  956. CV_CALL( icvConvertDataToSparse( centers->data.ptr + i*centers->step, 0, centers->type,
  957. dst_centers->data.ptr + i*dst_centers->step, 0, dst_centers->type,
  958. cvSize( 1, dims_selected ), comp_idx ? comp_idx->data.i : 0 ));
  959. }
  960. if( dst_probs && (!probs || probs->data.ptr != dst_probs->data.ptr) )
  961. {
  962. if( !probs )
  963. CV_ERROR( CV_StsNullPtr, "NULL probs" );
  964. if( probs->cols != dst_probs->cols )
  965. CV_ERROR( CV_StsUnmatchedSizes, "Invalid number of columns in output probability matrix" );
  966. if( dst_probs->rows != samples_all )
  967. CV_ERROR( CV_StsUnmatchedSizes,
  968. "Number of rows in output probability matrix is "
  969. "not equal to the total number of input samples" );
  970. CV_ASSERT( probs->rows == samples_selected );
  971. CV_CALL( icvConvertDataToSparse( probs->data.ptr, probs->step, probs->type,
  972. dst_probs->data.ptr, dst_probs->step, dst_probs->type,
  973. cvSize( probs->cols, samples_selected ),
  974. sample_idx ? sample_idx->data.i : 0 ));
  975. }
  976. __END__;
  977. }
  978. #if 0
  979. CV_IMPL void
  980. cvStatModelMultiPredict( const CvStatModel* stat_model,
  981. const CvArr* predict_input,
  982. int flags, CvMat* predict_output,
  983. CvMat* probs, const CvMat* sample_idx )
  984. {
  985. CvMemStorage* storage = 0;
  986. CvMat* sample_idx_buffer = 0;
  987. CvSparseMat** sparse_rows = 0;
  988. int samples_selected = 0;
  989. CV_FUNCNAME( "cvStatModelMultiPredict" );
  990. __BEGIN__;
  991. int i;
  992. int predict_output_step = 1, sample_idx_step = 1;
  993. int type;
  994. int d, sizes[CV_MAX_DIM];
  995. int tflag = flags == CV_COL_SAMPLE;
  996. int samples_all, dims_all;
  997. int is_sparse = CV_IS_SPARSE_MAT(predict_input);
  998. CvMat predict_input_part;
  999. CvArr* sample = &predict_input_part;
  1000. CvMat probs_part;
  1001. CvMat* probs1 = probs ? &probs_part : 0;
  1002. if( !CV_IS_STAT_MODEL(stat_model) )
  1003. CV_ERROR( !stat_model ? CV_StsNullPtr : CV_StsBadArg, "Invalid statistical model" );
  1004. if( !stat_model->predict )
  1005. CV_ERROR( CV_StsNotImplemented, "There is no \"predict\" method" );
  1006. if( !predict_input || !predict_output )
  1007. CV_ERROR( CV_StsNullPtr, "NULL input or output matrices" );
  1008. if( !is_sparse && !CV_IS_MAT(predict_input) )
  1009. CV_ERROR( CV_StsBadArg, "predict_input should be a matrix or a sparse matrix" );
  1010. if( !CV_IS_MAT(predict_output) )
  1011. CV_ERROR( CV_StsBadArg, "predict_output should be a matrix" );
  1012. type = cvGetElemType( predict_input );
  1013. if( type != CV_32FC1 ||
  1014. (CV_MAT_TYPE(predict_output->type) != CV_32FC1 &&
  1015. CV_MAT_TYPE(predict_output->type) != CV_32SC1 ))
  1016. CV_ERROR( CV_StsUnsupportedFormat, "The input or output matrix has unsupported format" );
  1017. CV_CALL( d = cvGetDims( predict_input, sizes ));
  1018. if( d > 2 )
  1019. CV_ERROR( CV_StsBadSize, "The input matrix should be 1- or 2-dimensional" );
  1020. if( !tflag )
  1021. {
  1022. samples_all = samples_selected = sizes[0];
  1023. dims_all = sizes[1];
  1024. }
  1025. else
  1026. {
  1027. samples_all = samples_selected = sizes[1];
  1028. dims_all = sizes[0];
  1029. }
  1030. if( sample_idx )
  1031. {
  1032. if( !CV_IS_MAT(sample_idx) )
  1033. CV_ERROR( CV_StsBadArg, "Invalid sample_idx matrix" );
  1034. if( sample_idx->cols != 1 && sample_idx->rows != 1 )
  1035. CV_ERROR( CV_StsBadSize, "sample_idx must be 1-dimensional matrix" );
  1036. samples_selected = sample_idx->rows + sample_idx->cols - 1;
  1037. if( CV_MAT_TYPE(sample_idx->type) == CV_32SC1 )
  1038. {
  1039. if( samples_selected > samples_all )
  1040. CV_ERROR( CV_StsBadSize, "sample_idx is too large vector" );
  1041. }
  1042. else if( samples_selected != samples_all )
  1043. CV_ERROR( CV_StsUnmatchedSizes, "sample_idx has incorrect size" );
  1044. sample_idx_step = sample_idx->step ?
  1045. sample_idx->step / CV_ELEM_SIZE(sample_idx->type) : 1;
  1046. }
  1047. if( predict_output->rows != 1 && predict_output->cols != 1 )
  1048. CV_ERROR( CV_StsBadSize, "predict_output should be a 1-dimensional matrix" );
  1049. if( predict_output->rows + predict_output->cols - 1 != samples_all )
  1050. CV_ERROR( CV_StsUnmatchedSizes, "predict_output and predict_input have uncoordinated sizes" );
  1051. predict_output_step = predict_output->step ?
  1052. predict_output->step / CV_ELEM_SIZE(predict_output->type) : 1;
  1053. if( probs )
  1054. {
  1055. if( !CV_IS_MAT(probs) )
  1056. CV_ERROR( CV_StsBadArg, "Invalid matrix of probabilities" );
  1057. if( probs->rows != samples_all )
  1058. CV_ERROR( CV_StsUnmatchedSizes,
  1059. "matrix of probabilities must have as many rows as the total number of samples" );
  1060. if( CV_MAT_TYPE(probs->type) != CV_32FC1 )
  1061. CV_ERROR( CV_StsUnsupportedFormat, "matrix of probabilities must have 32fC1 type" );
  1062. }
  1063. if( is_sparse )
  1064. {
  1065. CvSparseNode* node;
  1066. CvSparseMatIterator mat_iterator;
  1067. CvSparseMat* sparse = (CvSparseMat*)predict_input;
  1068. if( sample_idx && CV_MAT_TYPE(sample_idx->type) == CV_32SC1 )
  1069. {
  1070. CV_CALL( sample_idx_buffer = cvCreateMat( 1, samples_all, CV_8UC1 ));
  1071. cvZero( sample_idx_buffer );
  1072. for( i = 0; i < samples_selected; i++ )
  1073. sample_idx_buffer->data.ptr[sample_idx->data.i[i*sample_idx_step]] = 1;
  1074. samples_selected = samples_all;
  1075. sample_idx = sample_idx_buffer;
  1076. sample_idx_step = 1;
  1077. }
  1078. CV_CALL( sparse_rows = (CvSparseMat**)cvAlloc( samples_selected*sizeof(sparse_rows[0])));
  1079. for( i = 0; i < samples_selected; i++ )
  1080. {
  1081. if( sample_idx && sample_idx->data.ptr[i*sample_idx_step] == 0 )
  1082. continue;
  1083. CV_CALL( sparse_rows[i] = cvCreateSparseMat( 1, &dims_all, type ));
  1084. if( !storage )
  1085. storage = sparse_rows[i]->heap->storage;
  1086. else
  1087. {
  1088. // hack: to decrease memory footprint, make all the sparse matrices
  1089. // reside in the same storage
  1090. int elem_size = sparse_rows[i]->heap->elem_size;
  1091. cvReleaseMemStorage( &sparse_rows[i]->heap->storage );
  1092. sparse_rows[i]->heap = cvCreateSet( 0, sizeof(CvSet), elem_size, storage );
  1093. }
  1094. }
  1095. // put each row (or column) of predict_input into separate sparse matrix.
  1096. node = cvInitSparseMatIterator( sparse, &mat_iterator );
  1097. for( ; node != 0; node = cvGetNextSparseNode( &mat_iterator ))
  1098. {
  1099. int* idx = CV_NODE_IDX( sparse, node );
  1100. int idx0 = idx[tflag ^ 1];
  1101. int idx1 = idx[tflag];
  1102. if( sample_idx && sample_idx->data.ptr[idx0*sample_idx_step] == 0 )
  1103. continue;
  1104. assert( sparse_rows[idx0] != 0 );
  1105. *(float*)cvPtrND( sparse, &idx1, 0, 1, 0 ) = *(float*)CV_NODE_VAL( sparse, node );
  1106. }
  1107. }
  1108. for( i = 0; i < samples_selected; i++ )
  1109. {
  1110. int idx = i;
  1111. float response;
  1112. if( sample_idx )
  1113. {
  1114. if( CV_MAT_TYPE(sample_idx->type) == CV_32SC1 )
  1115. {
  1116. idx = sample_idx->data.i[i*sample_idx_step];
  1117. if( (unsigned)idx >= (unsigned)samples_all )
  1118. CV_ERROR( CV_StsOutOfRange, "Some of sample_idx elements are out of range" );
  1119. }
  1120. else if( CV_MAT_TYPE(sample_idx->type) == CV_8UC1 &&
  1121. sample_idx->data.ptr[i*sample_idx_step] == 0 )
  1122. continue;
  1123. }
  1124. if( !is_sparse )
  1125. {
  1126. if( !tflag )
  1127. cvGetRow( predict_input, &predict_input_part, idx );
  1128. else
  1129. {
  1130. cvGetCol( predict_input, &predict_input_part, idx );
  1131. }
  1132. }
  1133. else
  1134. sample = sparse_rows[idx];
  1135. if( probs )
  1136. cvGetRow( probs, probs1, idx );
  1137. CV_CALL( response = stat_model->predict( stat_model, (CvMat*)sample, probs1 ));
  1138. if( CV_MAT_TYPE(predict_output->type) == CV_32FC1 )
  1139. predict_output->data.fl[idx*predict_output_step] = response;
  1140. else
  1141. {
  1142. CV_ASSERT( cvRound(response) == response );
  1143. predict_output->data.i[idx*predict_output_step] = cvRound(response);
  1144. }
  1145. }
  1146. __END__;
  1147. if( sparse_rows )
  1148. {
  1149. int i;
  1150. for( i = 0; i < samples_selected; i++ )
  1151. if( sparse_rows[i] )
  1152. {
  1153. sparse_rows[i]->heap->storage = 0;
  1154. cvReleaseSparseMat( &sparse_rows[i] );
  1155. }
  1156. cvFree( &sparse_rows );
  1157. }
  1158. cvReleaseMat( &sample_idx_buffer );
  1159. cvReleaseMemStorage( &storage );
  1160. }
  1161. #endif
  1162. // By P. Yarykin - begin -
  1163. void cvCombineResponseMaps (CvMat* _responses,
  1164. const CvMat* old_response_map,
  1165. CvMat* new_response_map,
  1166. CvMat** out_response_map)
  1167. {
  1168. int** old_data = NULL;
  1169. int** new_data = NULL;
  1170. CV_FUNCNAME ("cvCombineResponseMaps");
  1171. __BEGIN__
  1172. int i,j;
  1173. int old_n, new_n, out_n;
  1174. int samples, free_response;
  1175. int* first;
  1176. int* responses;
  1177. int* out_data;
  1178. if( out_response_map )
  1179. *out_response_map = 0;
  1180. // Check input data.
  1181. if ((!ICV_IS_MAT_OF_TYPE (_responses, CV_32SC1)) ||
  1182. (!ICV_IS_MAT_OF_TYPE (old_response_map, CV_32SC1)) ||
  1183. (!ICV_IS_MAT_OF_TYPE (new_response_map, CV_32SC1)))
  1184. {
  1185. CV_ERROR (CV_StsBadArg, "Some of input arguments is not the CvMat")
  1186. }
  1187. // Prepare sorted responses.
  1188. first = new_response_map->data.i;
  1189. new_n = new_response_map->cols;
  1190. CV_CALL (new_data = (int**)cvAlloc (new_n * sizeof (new_data[0])));
  1191. for (i = 0; i < new_n; i++)
  1192. new_data[i] = first + i;
  1193. qsort (new_data, new_n, sizeof(int*), icvCmpIntegersPtr);
  1194. first = old_response_map->data.i;
  1195. old_n = old_response_map->cols;
  1196. CV_CALL (old_data = (int**)cvAlloc (old_n * sizeof (old_data[0])));
  1197. for (i = 0; i < old_n; i++)
  1198. old_data[i] = first + i;
  1199. qsort (old_data, old_n, sizeof(int*), icvCmpIntegersPtr);
  1200. // Count the number of different responses.
  1201. for (i = 0, j = 0, out_n = 0; i < old_n && j < new_n; out_n++)
  1202. {
  1203. if (*old_data[i] == *new_data[j])
  1204. {
  1205. i++;
  1206. j++;
  1207. }
  1208. else if (*old_data[i] < *new_data[j])
  1209. i++;
  1210. else
  1211. j++;
  1212. }
  1213. out_n += old_n - i + new_n - j;
  1214. // Create and fill the result response maps.
  1215. CV_CALL (*out_response_map = cvCreateMat (1, out_n, CV_32SC1));
  1216. out_data = (*out_response_map)->data.i;
  1217. memcpy (out_data, first, old_n * sizeof (int));
  1218. free_response = old_n;
  1219. for (i = 0, j = 0; i < old_n && j < new_n; )
  1220. {
  1221. if (*old_data[i] == *new_data[j])
  1222. {
  1223. *new_data[j] = (int)(old_data[i] - first);
  1224. i++;
  1225. j++;
  1226. }
  1227. else if (*old_data[i] < *new_data[j])
  1228. i++;
  1229. else
  1230. {
  1231. out_data[free_response] = *new_data[j];
  1232. *new_data[j] = free_response++;
  1233. j++;
  1234. }
  1235. }
  1236. for (; j < new_n; j++)
  1237. {
  1238. out_data[free_response] = *new_data[j];
  1239. *new_data[j] = free_response++;
  1240. }
  1241. CV_ASSERT (free_response == out_n);
  1242. // Change <responses> according to out response map.
  1243. samples = _responses->cols + _responses->rows - 1;
  1244. responses = _responses->data.i;
  1245. first = new_response_map->data.i;
  1246. for (i = 0; i < samples; i++)
  1247. {
  1248. responses[i] = first[responses[i]];
  1249. }
  1250. __END__
  1251. cvFree(&old_data);
  1252. cvFree(&new_data);
  1253. }
  1254. static int icvGetNumberOfCluster( double* prob_vector, int num_of_clusters, float r,
  1255. float outlier_thresh, int normalize_probs )
  1256. {
  1257. int max_prob_loc = 0;
  1258. CV_FUNCNAME("icvGetNumberOfCluster");
  1259. __BEGIN__;
  1260. double prob, maxprob, sum;
  1261. int i;
  1262. CV_ASSERT(prob_vector);
  1263. CV_ASSERT(num_of_clusters >= 0);
  1264. maxprob = prob_vector[0];
  1265. max_prob_loc = 0;
  1266. sum = maxprob;
  1267. for( i = 1; i < num_of_clusters; i++ )
  1268. {
  1269. prob = prob_vector[i];
  1270. sum += prob;
  1271. if( prob > maxprob )
  1272. {
  1273. max_prob_loc = i;
  1274. maxprob = prob;
  1275. }
  1276. }
  1277. if( normalize_probs && fabs(sum - 1.) > FLT_EPSILON )
  1278. {
  1279. for( i = 0; i < num_of_clusters; i++ )
  1280. prob_vector[i] /= sum;
  1281. }
  1282. if( fabs(r - 1.) > FLT_EPSILON && fabs(sum - 1.) < outlier_thresh )
  1283. max_prob_loc = -1;
  1284. __END__;
  1285. return max_prob_loc;
  1286. } // End of icvGetNumberOfCluster
  1287. void icvFindClusterLabels( const CvMat* probs, float outlier_thresh, float r,
  1288. const CvMat* labels )
  1289. {
  1290. CvMat* counts = 0;
  1291. CV_FUNCNAME("icvFindClusterLabels");
  1292. __BEGIN__;
  1293. int nclusters, nsamples;
  1294. int i, j;
  1295. double* probs_data;
  1296. CV_ASSERT( ICV_IS_MAT_OF_TYPE(probs, CV_64FC1) );
  1297. CV_ASSERT( ICV_IS_MAT_OF_TYPE(labels, CV_32SC1) );
  1298. nclusters = probs->cols;
  1299. nsamples = probs->rows;
  1300. CV_ASSERT( nsamples == labels->cols );
  1301. CV_CALL( counts = cvCreateMat( 1, nclusters + 1, CV_32SC1 ) );
  1302. CV_CALL( cvSetZero( counts ));
  1303. for( i = 0; i < nsamples; i++ )
  1304. {
  1305. labels->data.i[i] = icvGetNumberOfCluster( probs->data.db + i*probs->cols,
  1306. nclusters, r, outlier_thresh, 1 );
  1307. counts->data.i[labels->data.i[i] + 1]++;
  1308. }
  1309. CV_ASSERT((int)cvSum(counts).val[0] == nsamples);
  1310. // Filling empty clusters with the vector, that has the maximal probability
  1311. for( j = 0; j < nclusters; j++ ) // outliers are ignored
  1312. {
  1313. int maxprob_loc = -1;
  1314. double maxprob = 0;
  1315. if( counts->data.i[j+1] ) // j-th class is not empty
  1316. continue;
  1317. // look for the presentative, which is not lonely in it's cluster
  1318. // and that has a maximal probability among all these vectors
  1319. probs_data = probs->data.db;
  1320. for( i = 0; i < nsamples; i++, probs_data++ )
  1321. {
  1322. int label = labels->data.i[i];
  1323. double prob;
  1324. if( counts->data.i[label+1] == 0 ||
  1325. (counts->data.i[label+1] <= 1 && label != -1) )
  1326. continue;
  1327. prob = *probs_data;
  1328. if( prob >= maxprob )
  1329. {
  1330. maxprob = prob;
  1331. maxprob_loc = i;
  1332. }
  1333. }
  1334. // maxprob_loc == 0 <=> number of vectors less then number of clusters
  1335. CV_ASSERT( maxprob_loc >= 0 );
  1336. counts->data.i[labels->data.i[maxprob_loc] + 1]--;
  1337. labels->data.i[maxprob_loc] = j;
  1338. counts->data.i[j + 1]++;
  1339. }
  1340. __END__;
  1341. cvReleaseMat( &counts );
  1342. } // End of icvFindClusterLabels
  1343. /* End of file */