Path: blob/master/apps/traincascade/old_ml_inner_functions.cpp
16337 views
/*M///////////////////////////////////////////////////////////////////////////////////////1//2// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.3//4// By downloading, copying, installing or using the software you agree to this license.5// If you do not agree to this license, do not download, install,6// copy or use the software.7//8//9// Intel License Agreement10//11// Copyright (C) 2000, Intel Corporation, all rights reserved.12// Third party copyrights are property of their respective owners.13//14// Redistribution and use in source and binary forms, with or without modification,15// are permitted provided that the following conditions are met:16//17// * Redistribution's of source code must retain the above copyright notice,18// this list of conditions and the following disclaimer.19//20// * Redistribution's in binary form must reproduce the above copyright notice,21// this list of conditions and the following disclaimer in the documentation22// and/or other materials provided with the distribution.23//24// * The name of Intel Corporation may not be used to endorse or promote products25// derived from this software without specific prior written permission.26//27// This software is provided by the copyright holders and contributors "as is" and28// any express or implied warranties, including, but not limited to, the implied29// warranties of merchantability and fitness for a particular purpose are disclaimed.30// In no event shall the Intel Corporation or contributors be liable for any direct,31// indirect, incidental, special, exemplary, or consequential damages32// (including, but not limited to, procurement of substitute goods or services;33// loss of use, data, or profits; or business interruption) however caused34// and on any theory of liability, whether in contract, strict liability,35// or tort (including negligence or otherwise) arising in any way out of36// the use of this software, even if advised of the possibility of such damage.37//38//M*/3940#include "old_ml_precomp.hpp"414243CvStatModel::CvStatModel()44{45default_model_name = "my_stat_model";46}474849CvStatModel::~CvStatModel()50{51clear();52}535455void CvStatModel::clear()56{57}585960void CvStatModel::save( const char* filename, const char* name ) const61{62CvFileStorage* fs = 0;6364CV_FUNCNAME( "CvStatModel::save" );6566__BEGIN__;6768CV_CALL( fs = cvOpenFileStorage( filename, 0, CV_STORAGE_WRITE ));69if( !fs )70CV_ERROR( CV_StsError, "Could not open the file storage. Check the path and permissions" );7172write( fs, name ? name : default_model_name );7374__END__;7576cvReleaseFileStorage( &fs );77}787980void CvStatModel::load( const char* filename, const char* name )81{82CvFileStorage* fs = 0;8384CV_FUNCNAME( "CvAlgorithm::load" );8586__BEGIN__;8788CvFileNode* model_node = 0;8990CV_CALL( fs = cvOpenFileStorage( filename, 0, CV_STORAGE_READ ));91if( !fs )92EXIT;9394if( name )95model_node = cvGetFileNodeByName( fs, 0, name );96else97{98CvFileNode* root = cvGetRootFileNode( fs );99if( root->data.seq->total > 0 )100model_node = (CvFileNode*)cvGetSeqElem( root->data.seq, 0 );101}102103read( fs, model_node );104105__END__;106107cvReleaseFileStorage( &fs );108}109110111void CvStatModel::write( CvFileStorage*, const char* ) const112{113OPENCV_ERROR( CV_StsNotImplemented, "CvStatModel::write", "" );114}115116void CvStatModel::read( CvFileStorage*, CvFileNode* )117{118OPENCV_ERROR( CV_StsNotImplemented, "CvStatModel::read", "" );119}120121CvMat* icvGenerateRandomClusterCenters ( int seed, const CvMat* data,122int num_of_clusters, CvMat* _centers )123{124CvMat* centers = _centers;125126CV_FUNCNAME("icvGenerateRandomClusterCenters");127__BEGIN__;128129CvRNG rng;130CvMat data_comp, centers_comp;131CvPoint minLoc, maxLoc; // Not used, just for function "cvMinMaxLoc"132double minVal, maxVal;133int i;134int dim = data ? data->cols : 0;135136if( ICV_IS_MAT_OF_TYPE(data, CV_32FC1) )137{138if( _centers && !ICV_IS_MAT_OF_TYPE (_centers, CV_32FC1) )139{140CV_ERROR(CV_StsBadArg,"");141}142else if( !_centers )143CV_CALL(centers = cvCreateMat (num_of_clusters, dim, CV_32FC1));144}145else if( ICV_IS_MAT_OF_TYPE(data, CV_64FC1) )146{147if( _centers && !ICV_IS_MAT_OF_TYPE (_centers, CV_64FC1) )148{149CV_ERROR(CV_StsBadArg,"");150}151else if( !_centers )152CV_CALL(centers = cvCreateMat (num_of_clusters, dim, CV_64FC1));153}154else155CV_ERROR (CV_StsBadArg,"");156157if( num_of_clusters < 1 )158CV_ERROR (CV_StsBadArg,"");159160rng = cvRNG(seed);161for (i = 0; i < dim; i++)162{163CV_CALL(cvGetCol (data, &data_comp, i));164CV_CALL(cvMinMaxLoc (&data_comp, &minVal, &maxVal, &minLoc, &maxLoc));165CV_CALL(cvGetCol (centers, ¢ers_comp, i));166CV_CALL(cvRandArr (&rng, ¢ers_comp, CV_RAND_UNI, cvScalarAll(minVal), cvScalarAll(maxVal)));167}168169__END__;170171if( (cvGetErrStatus () < 0) || (centers != _centers) )172cvReleaseMat (¢ers);173174return _centers ? _centers : centers;175} // end of icvGenerateRandomClusterCenters176177static int CV_CDECL178icvCmpIntegers( const void* a, const void* b )179{180return *(const int*)a - *(const int*)b;181}182183184static int CV_CDECL185icvCmpIntegersPtr( const void* _a, const void* _b )186{187int a = **(const int**)_a;188int b = **(const int**)_b;189return (a < b ? -1 : 0)|(a > b);190}191192193static int icvCmpSparseVecElems( const void* a, const void* b )194{195return ((CvSparseVecElem32f*)a)->idx - ((CvSparseVecElem32f*)b)->idx;196}197198199CvMat*200cvPreprocessIndexArray( const CvMat* idx_arr, int data_arr_size, bool check_for_duplicates )201{202CvMat* idx = 0;203204CV_FUNCNAME( "cvPreprocessIndexArray" );205206__BEGIN__;207208int i, idx_total, idx_selected = 0, step, type, prev = INT_MIN, is_sorted = 1;209uchar* srcb = 0;210int* srci = 0;211int* dsti;212213if( !CV_IS_MAT(idx_arr) )214CV_ERROR( CV_StsBadArg, "Invalid index array" );215216if( idx_arr->rows != 1 && idx_arr->cols != 1 )217CV_ERROR( CV_StsBadSize, "the index array must be 1-dimensional" );218219idx_total = idx_arr->rows + idx_arr->cols - 1;220srcb = idx_arr->data.ptr;221srci = idx_arr->data.i;222223type = CV_MAT_TYPE(idx_arr->type);224step = CV_IS_MAT_CONT(idx_arr->type) ? 1 : idx_arr->step/CV_ELEM_SIZE(type);225226switch( type )227{228case CV_8UC1:229case CV_8SC1:230// idx_arr is array of 1's and 0's -231// i.e. it is a mask of the selected components232if( idx_total != data_arr_size )233CV_ERROR( CV_StsUnmatchedSizes,234"Component mask should contain as many elements as the total number of input variables" );235236for( i = 0; i < idx_total; i++ )237idx_selected += srcb[i*step] != 0;238239if( idx_selected == 0 )240CV_ERROR( CV_StsOutOfRange, "No components/input_variables is selected!" );241242break;243case CV_32SC1:244// idx_arr is array of integer indices of selected components245if( idx_total > data_arr_size )246CV_ERROR( CV_StsOutOfRange,247"index array may not contain more elements than the total number of input variables" );248idx_selected = idx_total;249// check if sorted already250for( i = 0; i < idx_total; i++ )251{252int val = srci[i*step];253if( val >= prev )254{255is_sorted = 0;256break;257}258prev = val;259}260break;261default:262CV_ERROR( CV_StsUnsupportedFormat, "Unsupported index array data type "263"(it should be 8uC1, 8sC1 or 32sC1)" );264}265266CV_CALL( idx = cvCreateMat( 1, idx_selected, CV_32SC1 ));267dsti = idx->data.i;268269if( type < CV_32SC1 )270{271for( i = 0; i < idx_total; i++ )272if( srcb[i*step] )273*dsti++ = i;274}275else276{277for( i = 0; i < idx_total; i++ )278dsti[i] = srci[i*step];279280if( !is_sorted )281qsort( dsti, idx_total, sizeof(dsti[0]), icvCmpIntegers );282283if( dsti[0] < 0 || dsti[idx_total-1] >= data_arr_size )284CV_ERROR( CV_StsOutOfRange, "the index array elements are out of range" );285286if( check_for_duplicates )287{288for( i = 1; i < idx_total; i++ )289if( dsti[i] <= dsti[i-1] )290CV_ERROR( CV_StsBadArg, "There are duplicated index array elements" );291}292}293294__END__;295296if( cvGetErrStatus() < 0 )297cvReleaseMat( &idx );298299return idx;300}301302303CvMat*304cvPreprocessVarType( const CvMat* var_type, const CvMat* var_idx,305int var_count, int* response_type )306{307CvMat* out_var_type = 0;308CV_FUNCNAME( "cvPreprocessVarType" );309310if( response_type )311*response_type = -1;312313__BEGIN__;314315int i, tm_size, tm_step;316//int* map = 0;317const uchar* src;318uchar* dst;319320if( !CV_IS_MAT(var_type) )321CV_ERROR( var_type ? CV_StsBadArg : CV_StsNullPtr, "Invalid or absent var_type array" );322323if( var_type->rows != 1 && var_type->cols != 1 )324CV_ERROR( CV_StsBadSize, "var_type array must be 1-dimensional" );325326if( !CV_IS_MASK_ARR(var_type))327CV_ERROR( CV_StsUnsupportedFormat, "type mask must be 8uC1 or 8sC1 array" );328329tm_size = var_type->rows + var_type->cols - 1;330tm_step = var_type->rows == 1 ? 1 : var_type->step/CV_ELEM_SIZE(var_type->type);331332if( /*tm_size != var_count &&*/ tm_size != var_count + 1 )333CV_ERROR( CV_StsBadArg,334"type mask must be of <input var count> + 1 size" );335336if( response_type && tm_size > var_count )337*response_type = var_type->data.ptr[var_count*tm_step] != 0;338339if( var_idx )340{341if( !CV_IS_MAT(var_idx) || CV_MAT_TYPE(var_idx->type) != CV_32SC1 ||342(var_idx->rows != 1 && var_idx->cols != 1) || !CV_IS_MAT_CONT(var_idx->type) )343CV_ERROR( CV_StsBadArg, "var index array should be continuous 1-dimensional integer vector" );344if( var_idx->rows + var_idx->cols - 1 > var_count )345CV_ERROR( CV_StsBadSize, "var index array is too large" );346//map = var_idx->data.i;347var_count = var_idx->rows + var_idx->cols - 1;348}349350CV_CALL( out_var_type = cvCreateMat( 1, var_count, CV_8UC1 ));351src = var_type->data.ptr;352dst = out_var_type->data.ptr;353354for( i = 0; i < var_count; i++ )355{356//int idx = map ? map[i] : i;357assert( (unsigned)/*idx*/i < (unsigned)tm_size );358dst[i] = (uchar)(src[/*idx*/i*tm_step] != 0);359}360361__END__;362363return out_var_type;364}365366367CvMat*368cvPreprocessOrderedResponses( const CvMat* responses, const CvMat* sample_idx, int sample_all )369{370CvMat* out_responses = 0;371372CV_FUNCNAME( "cvPreprocessOrderedResponses" );373374__BEGIN__;375376int i, r_type, r_step;377const int* map = 0;378float* dst;379int sample_count = sample_all;380381if( !CV_IS_MAT(responses) )382CV_ERROR( CV_StsBadArg, "Invalid response array" );383384if( responses->rows != 1 && responses->cols != 1 )385CV_ERROR( CV_StsBadSize, "Response array must be 1-dimensional" );386387if( responses->rows + responses->cols - 1 != sample_count )388CV_ERROR( CV_StsUnmatchedSizes,389"Response array must contain as many elements as the total number of samples" );390391r_type = CV_MAT_TYPE(responses->type);392if( r_type != CV_32FC1 && r_type != CV_32SC1 )393CV_ERROR( CV_StsUnsupportedFormat, "Unsupported response type" );394395r_step = responses->step ? responses->step / CV_ELEM_SIZE(responses->type) : 1;396397if( r_type == CV_32FC1 && CV_IS_MAT_CONT(responses->type) && !sample_idx )398{399out_responses = cvCloneMat( responses );400EXIT;401}402403if( sample_idx )404{405if( !CV_IS_MAT(sample_idx) || CV_MAT_TYPE(sample_idx->type) != CV_32SC1 ||406(sample_idx->rows != 1 && sample_idx->cols != 1) || !CV_IS_MAT_CONT(sample_idx->type) )407CV_ERROR( CV_StsBadArg, "sample index array should be continuous 1-dimensional integer vector" );408if( sample_idx->rows + sample_idx->cols - 1 > sample_count )409CV_ERROR( CV_StsBadSize, "sample index array is too large" );410map = sample_idx->data.i;411sample_count = sample_idx->rows + sample_idx->cols - 1;412}413414CV_CALL( out_responses = cvCreateMat( 1, sample_count, CV_32FC1 ));415416dst = out_responses->data.fl;417if( r_type == CV_32FC1 )418{419const float* src = responses->data.fl;420for( i = 0; i < sample_count; i++ )421{422int idx = map ? map[i] : i;423assert( (unsigned)idx < (unsigned)sample_all );424dst[i] = src[idx*r_step];425}426}427else428{429const int* src = responses->data.i;430for( i = 0; i < sample_count; i++ )431{432int idx = map ? map[i] : i;433assert( (unsigned)idx < (unsigned)sample_all );434dst[i] = (float)src[idx*r_step];435}436}437438__END__;439440return out_responses;441}442443CvMat*444cvPreprocessCategoricalResponses( const CvMat* responses,445const CvMat* sample_idx, int sample_all,446CvMat** out_response_map, CvMat** class_counts )447{448CvMat* out_responses = 0;449int** response_ptr = 0;450451CV_FUNCNAME( "cvPreprocessCategoricalResponses" );452453if( out_response_map )454*out_response_map = 0;455456if( class_counts )457*class_counts = 0;458459__BEGIN__;460461int i, r_type, r_step;462int cls_count = 1, prev_cls, prev_i;463const int* map = 0;464const int* srci;465const float* srcfl;466int* dst;467int* cls_map;468int* cls_counts = 0;469int sample_count = sample_all;470471if( !CV_IS_MAT(responses) )472CV_ERROR( CV_StsBadArg, "Invalid response array" );473474if( responses->rows != 1 && responses->cols != 1 )475CV_ERROR( CV_StsBadSize, "Response array must be 1-dimensional" );476477if( responses->rows + responses->cols - 1 != sample_count )478CV_ERROR( CV_StsUnmatchedSizes,479"Response array must contain as many elements as the total number of samples" );480481r_type = CV_MAT_TYPE(responses->type);482if( r_type != CV_32FC1 && r_type != CV_32SC1 )483CV_ERROR( CV_StsUnsupportedFormat, "Unsupported response type" );484485r_step = responses->rows == 1 ? 1 : responses->step / CV_ELEM_SIZE(responses->type);486487if( sample_idx )488{489if( !CV_IS_MAT(sample_idx) || CV_MAT_TYPE(sample_idx->type) != CV_32SC1 ||490(sample_idx->rows != 1 && sample_idx->cols != 1) || !CV_IS_MAT_CONT(sample_idx->type) )491CV_ERROR( CV_StsBadArg, "sample index array should be continuous 1-dimensional integer vector" );492if( sample_idx->rows + sample_idx->cols - 1 > sample_count )493CV_ERROR( CV_StsBadSize, "sample index array is too large" );494map = sample_idx->data.i;495sample_count = sample_idx->rows + sample_idx->cols - 1;496}497498CV_CALL( out_responses = cvCreateMat( 1, sample_count, CV_32SC1 ));499500if( !out_response_map )501CV_ERROR( CV_StsNullPtr, "out_response_map pointer is NULL" );502503CV_CALL( response_ptr = (int**)cvAlloc( sample_count*sizeof(response_ptr[0])));504505srci = responses->data.i;506srcfl = responses->data.fl;507dst = out_responses->data.i;508509for( i = 0; i < sample_count; i++ )510{511int idx = map ? map[i] : i;512assert( (unsigned)idx < (unsigned)sample_all );513if( r_type == CV_32SC1 )514dst[i] = srci[idx*r_step];515else516{517float rf = srcfl[idx*r_step];518int ri = cvRound(rf);519if( ri != rf )520{521char buf[100];522sprintf( buf, "response #%d is not integral", idx );523CV_ERROR( CV_StsBadArg, buf );524}525dst[i] = ri;526}527response_ptr[i] = dst + i;528}529530qsort( response_ptr, sample_count, sizeof(int*), icvCmpIntegersPtr );531532// count the classes533for( i = 1; i < sample_count; i++ )534cls_count += *response_ptr[i] != *response_ptr[i-1];535536if( cls_count < 2 )537CV_ERROR( CV_StsBadArg, "There is only a single class" );538539CV_CALL( *out_response_map = cvCreateMat( 1, cls_count, CV_32SC1 ));540541if( class_counts )542{543CV_CALL( *class_counts = cvCreateMat( 1, cls_count, CV_32SC1 ));544cls_counts = (*class_counts)->data.i;545}546547// compact the class indices and build the map548prev_cls = ~*response_ptr[0];549cls_count = -1;550cls_map = (*out_response_map)->data.i;551552for( i = 0, prev_i = -1; i < sample_count; i++ )553{554int cur_cls = *response_ptr[i];555if( cur_cls != prev_cls )556{557if( cls_counts && cls_count >= 0 )558cls_counts[cls_count] = i - prev_i;559cls_map[++cls_count] = prev_cls = cur_cls;560prev_i = i;561}562*response_ptr[i] = cls_count;563}564565if( cls_counts )566cls_counts[cls_count] = i - prev_i;567568__END__;569570cvFree( &response_ptr );571572return out_responses;573}574575576const float**577cvGetTrainSamples( const CvMat* train_data, int tflag,578const CvMat* var_idx, const CvMat* sample_idx,579int* _var_count, int* _sample_count,580bool always_copy_data )581{582float** samples = 0;583584CV_FUNCNAME( "cvGetTrainSamples" );585586__BEGIN__;587588int i, j, var_count, sample_count, s_step, v_step;589bool copy_data;590const float* data;591const int *s_idx, *v_idx;592593if( !CV_IS_MAT(train_data) )594CV_ERROR( CV_StsBadArg, "Invalid or NULL training data matrix" );595596var_count = var_idx ? var_idx->cols + var_idx->rows - 1 :597tflag == CV_ROW_SAMPLE ? train_data->cols : train_data->rows;598sample_count = sample_idx ? sample_idx->cols + sample_idx->rows - 1 :599tflag == CV_ROW_SAMPLE ? train_data->rows : train_data->cols;600601if( _var_count )602*_var_count = var_count;603604if( _sample_count )605*_sample_count = sample_count;606607copy_data = tflag != CV_ROW_SAMPLE || var_idx || always_copy_data;608609CV_CALL( samples = (float**)cvAlloc(sample_count*sizeof(samples[0]) +610(copy_data ? 1 : 0)*var_count*sample_count*sizeof(samples[0][0])) );611data = train_data->data.fl;612s_step = train_data->step / sizeof(samples[0][0]);613v_step = 1;614s_idx = sample_idx ? sample_idx->data.i : 0;615v_idx = var_idx ? var_idx->data.i : 0;616617if( !copy_data )618{619for( i = 0; i < sample_count; i++ )620samples[i] = (float*)(data + (s_idx ? s_idx[i] : i)*s_step);621}622else623{624samples[0] = (float*)(samples + sample_count);625if( tflag != CV_ROW_SAMPLE )626CV_SWAP( s_step, v_step, i );627628for( i = 0; i < sample_count; i++ )629{630float* dst = samples[i] = samples[0] + i*var_count;631const float* src = data + (s_idx ? s_idx[i] : i)*s_step;632633if( !v_idx )634for( j = 0; j < var_count; j++ )635dst[j] = src[j*v_step];636else637for( j = 0; j < var_count; j++ )638dst[j] = src[v_idx[j]*v_step];639}640}641642__END__;643644return (const float**)samples;645}646647648void649cvCheckTrainData( const CvMat* train_data, int tflag,650const CvMat* missing_mask,651int* var_all, int* sample_all )652{653CV_FUNCNAME( "cvCheckTrainData" );654655if( var_all )656*var_all = 0;657658if( sample_all )659*sample_all = 0;660661__BEGIN__;662663// check parameter types and sizes664if( !CV_IS_MAT(train_data) || CV_MAT_TYPE(train_data->type) != CV_32FC1 )665CV_ERROR( CV_StsBadArg, "train data must be floating-point matrix" );666667if( missing_mask )668{669if( !CV_IS_MAT(missing_mask) || !CV_IS_MASK_ARR(missing_mask) ||670!CV_ARE_SIZES_EQ(train_data, missing_mask) )671CV_ERROR( CV_StsBadArg,672"missing value mask must be 8-bit matrix of the same size as training data" );673}674675if( tflag != CV_ROW_SAMPLE && tflag != CV_COL_SAMPLE )676CV_ERROR( CV_StsBadArg,677"Unknown training data layout (must be CV_ROW_SAMPLE or CV_COL_SAMPLE)" );678679if( var_all )680*var_all = tflag == CV_ROW_SAMPLE ? train_data->cols : train_data->rows;681682if( sample_all )683*sample_all = tflag == CV_ROW_SAMPLE ? train_data->rows : train_data->cols;684685__END__;686}687688689int690cvPrepareTrainData( const char* /*funcname*/,691const CvMat* train_data, int tflag,692const CvMat* responses, int response_type,693const CvMat* var_idx,694const CvMat* sample_idx,695bool always_copy_data,696const float*** out_train_samples,697int* _sample_count,698int* _var_count,699int* _var_all,700CvMat** out_responses,701CvMat** out_response_map,702CvMat** out_var_idx,703CvMat** out_sample_idx )704{705int ok = 0;706CvMat* _var_idx = 0;707CvMat* _sample_idx = 0;708CvMat* _responses = 0;709int sample_all = 0, sample_count = 0, var_all = 0, var_count = 0;710711CV_FUNCNAME( "cvPrepareTrainData" );712713// step 0. clear all the output pointers to ensure we do not try714// to call free() with uninitialized pointers715if( out_responses )716*out_responses = 0;717718if( out_response_map )719*out_response_map = 0;720721if( out_var_idx )722*out_var_idx = 0;723724if( out_sample_idx )725*out_sample_idx = 0;726727if( out_train_samples )728*out_train_samples = 0;729730if( _sample_count )731*_sample_count = 0;732733if( _var_count )734*_var_count = 0;735736if( _var_all )737*_var_all = 0;738739__BEGIN__;740741if( !out_train_samples )742CV_ERROR( CV_StsBadArg, "output pointer to train samples is NULL" );743744CV_CALL( cvCheckTrainData( train_data, tflag, 0, &var_all, &sample_all ));745746if( sample_idx )747CV_CALL( _sample_idx = cvPreprocessIndexArray( sample_idx, sample_all ));748if( var_idx )749CV_CALL( _var_idx = cvPreprocessIndexArray( var_idx, var_all ));750751if( responses )752{753if( !out_responses )754CV_ERROR( CV_StsNullPtr, "output response pointer is NULL" );755756if( response_type == CV_VAR_NUMERICAL )757{758CV_CALL( _responses = cvPreprocessOrderedResponses( responses,759_sample_idx, sample_all ));760}761else762{763CV_CALL( _responses = cvPreprocessCategoricalResponses( responses,764_sample_idx, sample_all, out_response_map, 0 ));765}766}767768CV_CALL( *out_train_samples =769cvGetTrainSamples( train_data, tflag, _var_idx, _sample_idx,770&var_count, &sample_count, always_copy_data ));771772ok = 1;773774__END__;775776if( ok )777{778if( out_responses )779*out_responses = _responses, _responses = 0;780781if( out_var_idx )782*out_var_idx = _var_idx, _var_idx = 0;783784if( out_sample_idx )785*out_sample_idx = _sample_idx, _sample_idx = 0;786787if( _sample_count )788*_sample_count = sample_count;789790if( _var_count )791*_var_count = var_count;792793if( _var_all )794*_var_all = var_all;795}796else797{798if( out_response_map )799cvReleaseMat( out_response_map );800cvFree( out_train_samples );801}802803if( _responses != responses )804cvReleaseMat( &_responses );805cvReleaseMat( &_var_idx );806cvReleaseMat( &_sample_idx );807808return ok;809}810811812typedef struct CvSampleResponsePair813{814const float* sample;815const uchar* mask;816int response;817int index;818}819CvSampleResponsePair;820821822static int823CV_CDECL icvCmpSampleResponsePairs( const void* a, const void* b )824{825int ra = ((const CvSampleResponsePair*)a)->response;826int rb = ((const CvSampleResponsePair*)b)->response;827int ia = ((const CvSampleResponsePair*)a)->index;828int ib = ((const CvSampleResponsePair*)b)->index;829830return ra < rb ? -1 : ra > rb ? 1 : ia - ib;831//return (ra > rb ? -1 : 0)|(ra < rb);832}833834835void836cvSortSamplesByClasses( const float** samples, const CvMat* classes,837int* class_ranges, const uchar** mask )838{839CvSampleResponsePair* pairs = 0;840CV_FUNCNAME( "cvSortSamplesByClasses" );841842__BEGIN__;843844int i, k = 0, sample_count;845846if( !samples || !classes || !class_ranges )847CV_ERROR( CV_StsNullPtr, "INTERNAL ERROR: some of the args are NULL pointers" );848849if( classes->rows != 1 || CV_MAT_TYPE(classes->type) != CV_32SC1 )850CV_ERROR( CV_StsBadArg, "classes array must be a single row of integers" );851852sample_count = classes->cols;853CV_CALL( pairs = (CvSampleResponsePair*)cvAlloc( (sample_count+1)*sizeof(pairs[0])));854855for( i = 0; i < sample_count; i++ )856{857pairs[i].sample = samples[i];858pairs[i].mask = (mask) ? (mask[i]) : 0;859pairs[i].response = classes->data.i[i];860pairs[i].index = i;861assert( classes->data.i[i] >= 0 );862}863864qsort( pairs, sample_count, sizeof(pairs[0]), icvCmpSampleResponsePairs );865pairs[sample_count].response = -1;866class_ranges[0] = 0;867868for( i = 0; i < sample_count; i++ )869{870samples[i] = pairs[i].sample;871if (mask)872mask[i] = pairs[i].mask;873classes->data.i[i] = pairs[i].response;874875if( pairs[i].response != pairs[i+1].response )876class_ranges[++k] = i+1;877}878879__END__;880881cvFree( &pairs );882}883884885void886cvPreparePredictData( const CvArr* _sample, int dims_all,887const CvMat* comp_idx, int class_count,888const CvMat* prob, float** _row_sample,889int as_sparse )890{891float* row_sample = 0;892int* inverse_comp_idx = 0;893894CV_FUNCNAME( "cvPreparePredictData" );895896__BEGIN__;897898const CvMat* sample = (const CvMat*)_sample;899float* sample_data;900int sample_step;901int is_sparse = CV_IS_SPARSE_MAT(sample);902int d, sizes[CV_MAX_DIM];903int i, dims_selected;904int vec_size;905906if( !is_sparse && !CV_IS_MAT(sample) )907CV_ERROR( !sample ? CV_StsNullPtr : CV_StsBadArg, "The sample is not a valid vector" );908909if( cvGetElemType( sample ) != CV_32FC1 )910CV_ERROR( CV_StsUnsupportedFormat, "Input sample must have 32fC1 type" );911912CV_CALL( d = cvGetDims( sample, sizes ));913914if( !((is_sparse && d == 1) || (!is_sparse && d == 2 && (sample->rows == 1 || sample->cols == 1))) )915CV_ERROR( CV_StsBadSize, "Input sample must be 1-dimensional vector" );916917if( d == 1 )918sizes[1] = 1;919920if( sizes[0] + sizes[1] - 1 != dims_all )921CV_ERROR( CV_StsUnmatchedSizes,922"The sample size is different from what has been used for training" );923924if( !_row_sample )925CV_ERROR( CV_StsNullPtr, "INTERNAL ERROR: The row_sample pointer is NULL" );926927if( comp_idx && (!CV_IS_MAT(comp_idx) || comp_idx->rows != 1 ||928CV_MAT_TYPE(comp_idx->type) != CV_32SC1) )929CV_ERROR( CV_StsBadArg, "INTERNAL ERROR: invalid comp_idx" );930931dims_selected = comp_idx ? comp_idx->cols : dims_all;932933if( prob )934{935if( !CV_IS_MAT(prob) )936CV_ERROR( CV_StsBadArg, "The output matrix of probabilities is invalid" );937938if( (prob->rows != 1 && prob->cols != 1) ||939(CV_MAT_TYPE(prob->type) != CV_32FC1 &&940CV_MAT_TYPE(prob->type) != CV_64FC1) )941CV_ERROR( CV_StsBadSize,942"The matrix of probabilities must be 1-dimensional vector of 32fC1 type" );943944if( prob->rows + prob->cols - 1 != class_count )945CV_ERROR( CV_StsUnmatchedSizes,946"The vector of probabilities must contain as many elements as "947"the number of classes in the training set" );948}949950vec_size = !as_sparse ? dims_selected*sizeof(row_sample[0]) :951(dims_selected + 1)*sizeof(CvSparseVecElem32f);952953if( CV_IS_MAT(sample) )954{955sample_data = sample->data.fl;956sample_step = CV_IS_MAT_CONT(sample->type) ? 1 : sample->step/sizeof(row_sample[0]);957958if( !comp_idx && CV_IS_MAT_CONT(sample->type) && !as_sparse )959*_row_sample = sample_data;960else961{962CV_CALL( row_sample = (float*)cvAlloc( vec_size ));963964if( !comp_idx )965for( i = 0; i < dims_selected; i++ )966row_sample[i] = sample_data[sample_step*i];967else968{969int* comp = comp_idx->data.i;970for( i = 0; i < dims_selected; i++ )971row_sample[i] = sample_data[sample_step*comp[i]];972}973974*_row_sample = row_sample;975}976977if( as_sparse )978{979const float* src = (const float*)row_sample;980CvSparseVecElem32f* dst = (CvSparseVecElem32f*)row_sample;981982dst[dims_selected].idx = -1;983for( i = dims_selected - 1; i >= 0; i-- )984{985dst[i].idx = i;986dst[i].val = src[i];987}988}989}990else991{992CvSparseNode* node;993CvSparseMatIterator mat_iterator;994const CvSparseMat* sparse = (const CvSparseMat*)sample;995assert( is_sparse );996997node = cvInitSparseMatIterator( sparse, &mat_iterator );998CV_CALL( row_sample = (float*)cvAlloc( vec_size ));9991000if( comp_idx )1001{1002CV_CALL( inverse_comp_idx = (int*)cvAlloc( dims_all*sizeof(int) ));1003memset( inverse_comp_idx, -1, dims_all*sizeof(int) );1004for( i = 0; i < dims_selected; i++ )1005inverse_comp_idx[comp_idx->data.i[i]] = i;1006}10071008if( !as_sparse )1009{1010memset( row_sample, 0, vec_size );10111012for( ; node != 0; node = cvGetNextSparseNode(&mat_iterator) )1013{1014int idx = *CV_NODE_IDX( sparse, node );1015if( inverse_comp_idx )1016{1017idx = inverse_comp_idx[idx];1018if( idx < 0 )1019continue;1020}1021row_sample[idx] = *(float*)CV_NODE_VAL( sparse, node );1022}1023}1024else1025{1026CvSparseVecElem32f* ptr = (CvSparseVecElem32f*)row_sample;10271028for( ; node != 0; node = cvGetNextSparseNode(&mat_iterator) )1029{1030int idx = *CV_NODE_IDX( sparse, node );1031if( inverse_comp_idx )1032{1033idx = inverse_comp_idx[idx];1034if( idx < 0 )1035continue;1036}1037ptr->idx = idx;1038ptr->val = *(float*)CV_NODE_VAL( sparse, node );1039ptr++;1040}10411042qsort( row_sample, ptr - (CvSparseVecElem32f*)row_sample,1043sizeof(ptr[0]), icvCmpSparseVecElems );1044ptr->idx = -1;1045}10461047*_row_sample = row_sample;1048}10491050__END__;10511052if( inverse_comp_idx )1053cvFree( &inverse_comp_idx );10541055if( cvGetErrStatus() < 0 && _row_sample )1056{1057cvFree( &row_sample );1058*_row_sample = 0;1059}1060}106110621063static void1064icvConvertDataToSparse( const uchar* src, int src_step, int src_type,1065uchar* dst, int dst_step, int dst_type,1066CvSize size, int* idx )1067{1068CV_FUNCNAME( "icvConvertDataToSparse" );10691070__BEGIN__;10711072int i, j;1073src_type = CV_MAT_TYPE(src_type);1074dst_type = CV_MAT_TYPE(dst_type);10751076if( CV_MAT_CN(src_type) != 1 || CV_MAT_CN(dst_type) != 1 )1077CV_ERROR( CV_StsUnsupportedFormat, "The function supports only single-channel arrays" );10781079if( src_step == 0 )1080src_step = CV_ELEM_SIZE(src_type);10811082if( dst_step == 0 )1083dst_step = CV_ELEM_SIZE(dst_type);10841085// if there is no "idx" and if both arrays are continuous,1086// do the whole processing (copying or conversion) in a single loop1087if( !idx && CV_ELEM_SIZE(src_type)*size.width == src_step &&1088CV_ELEM_SIZE(dst_type)*size.width == dst_step )1089{1090size.width *= size.height;1091size.height = 1;1092}10931094if( src_type == dst_type )1095{1096int full_width = CV_ELEM_SIZE(dst_type)*size.width;10971098if( full_width == sizeof(int) ) // another common case: copy int's or float's1099for( i = 0; i < size.height; i++, src += src_step )1100*(int*)(dst + dst_step*(idx ? idx[i] : i)) = *(int*)src;1101else1102for( i = 0; i < size.height; i++, src += src_step )1103memcpy( dst + dst_step*(idx ? idx[i] : i), src, full_width );1104}1105else if( src_type == CV_32SC1 && (dst_type == CV_32FC1 || dst_type == CV_64FC1) )1106for( i = 0; i < size.height; i++, src += src_step )1107{1108uchar* _dst = dst + dst_step*(idx ? idx[i] : i);1109if( dst_type == CV_32FC1 )1110for( j = 0; j < size.width; j++ )1111((float*)_dst)[j] = (float)((int*)src)[j];1112else1113for( j = 0; j < size.width; j++ )1114((double*)_dst)[j] = ((int*)src)[j];1115}1116else if( (src_type == CV_32FC1 || src_type == CV_64FC1) && dst_type == CV_32SC1 )1117for( i = 0; i < size.height; i++, src += src_step )1118{1119uchar* _dst = dst + dst_step*(idx ? idx[i] : i);1120if( src_type == CV_32FC1 )1121for( j = 0; j < size.width; j++ )1122((int*)_dst)[j] = cvRound(((float*)src)[j]);1123else1124for( j = 0; j < size.width; j++ )1125((int*)_dst)[j] = cvRound(((double*)src)[j]);1126}1127else if( (src_type == CV_32FC1 && dst_type == CV_64FC1) ||1128(src_type == CV_64FC1 && dst_type == CV_32FC1) )1129for( i = 0; i < size.height; i++, src += src_step )1130{1131uchar* _dst = dst + dst_step*(idx ? idx[i] : i);1132if( src_type == CV_32FC1 )1133for( j = 0; j < size.width; j++ )1134((double*)_dst)[j] = ((float*)src)[j];1135else1136for( j = 0; j < size.width; j++ )1137((float*)_dst)[j] = (float)((double*)src)[j];1138}1139else1140CV_ERROR( CV_StsUnsupportedFormat, "Unsupported combination of input and output vectors" );11411142__END__;1143}114411451146void1147cvWritebackLabels( const CvMat* labels, CvMat* dst_labels,1148const CvMat* centers, CvMat* dst_centers,1149const CvMat* probs, CvMat* dst_probs,1150const CvMat* sample_idx, int samples_all,1151const CvMat* comp_idx, int dims_all )1152{1153CV_FUNCNAME( "cvWritebackLabels" );11541155__BEGIN__;11561157int samples_selected = samples_all, dims_selected = dims_all;11581159if( dst_labels && !CV_IS_MAT(dst_labels) )1160CV_ERROR( CV_StsBadArg, "Array of output labels is not a valid matrix" );11611162if( dst_centers )1163if( !ICV_IS_MAT_OF_TYPE(dst_centers, CV_32FC1) &&1164!ICV_IS_MAT_OF_TYPE(dst_centers, CV_64FC1) )1165CV_ERROR( CV_StsBadArg, "Array of cluster centers is not a valid matrix" );11661167if( dst_probs && !CV_IS_MAT(dst_probs) )1168CV_ERROR( CV_StsBadArg, "Probability matrix is not valid" );11691170if( sample_idx )1171{1172CV_ASSERT( sample_idx->rows == 1 && CV_MAT_TYPE(sample_idx->type) == CV_32SC1 );1173samples_selected = sample_idx->cols;1174}11751176if( comp_idx )1177{1178CV_ASSERT( comp_idx->rows == 1 && CV_MAT_TYPE(comp_idx->type) == CV_32SC1 );1179dims_selected = comp_idx->cols;1180}11811182if( dst_labels && (!labels || labels->data.ptr != dst_labels->data.ptr) )1183{1184if( !labels )1185CV_ERROR( CV_StsNullPtr, "NULL labels" );11861187CV_ASSERT( labels->rows == 1 );11881189if( dst_labels->rows != 1 && dst_labels->cols != 1 )1190CV_ERROR( CV_StsBadSize, "Array of output labels should be 1d vector" );11911192if( dst_labels->rows + dst_labels->cols - 1 != samples_all )1193CV_ERROR( CV_StsUnmatchedSizes,1194"Size of vector of output labels is not equal to the total number of input samples" );11951196CV_ASSERT( labels->cols == samples_selected );11971198CV_CALL( icvConvertDataToSparse( labels->data.ptr, labels->step, labels->type,1199dst_labels->data.ptr, dst_labels->step, dst_labels->type,1200cvSize( 1, samples_selected ), sample_idx ? sample_idx->data.i : 0 ));1201}12021203if( dst_centers && (!centers || centers->data.ptr != dst_centers->data.ptr) )1204{1205int i;12061207if( !centers )1208CV_ERROR( CV_StsNullPtr, "NULL centers" );12091210if( centers->rows != dst_centers->rows )1211CV_ERROR( CV_StsUnmatchedSizes, "Invalid number of rows in matrix of output centers" );12121213if( dst_centers->cols != dims_all )1214CV_ERROR( CV_StsUnmatchedSizes,1215"Number of columns in matrix of output centers is "1216"not equal to the total number of components in the input samples" );12171218CV_ASSERT( centers->cols == dims_selected );12191220for( i = 0; i < centers->rows; i++ )1221CV_CALL( icvConvertDataToSparse( centers->data.ptr + i*centers->step, 0, centers->type,1222dst_centers->data.ptr + i*dst_centers->step, 0, dst_centers->type,1223cvSize( 1, dims_selected ), comp_idx ? comp_idx->data.i : 0 ));1224}12251226if( dst_probs && (!probs || probs->data.ptr != dst_probs->data.ptr) )1227{1228if( !probs )1229CV_ERROR( CV_StsNullPtr, "NULL probs" );12301231if( probs->cols != dst_probs->cols )1232CV_ERROR( CV_StsUnmatchedSizes, "Invalid number of columns in output probability matrix" );12331234if( dst_probs->rows != samples_all )1235CV_ERROR( CV_StsUnmatchedSizes,1236"Number of rows in output probability matrix is "1237"not equal to the total number of input samples" );12381239CV_ASSERT( probs->rows == samples_selected );12401241CV_CALL( icvConvertDataToSparse( probs->data.ptr, probs->step, probs->type,1242dst_probs->data.ptr, dst_probs->step, dst_probs->type,1243cvSize( probs->cols, samples_selected ),1244sample_idx ? sample_idx->data.i : 0 ));1245}12461247__END__;1248}12491250#if 01251CV_IMPL void1252cvStatModelMultiPredict( const CvStatModel* stat_model,1253const CvArr* predict_input,1254int flags, CvMat* predict_output,1255CvMat* probs, const CvMat* sample_idx )1256{1257CvMemStorage* storage = 0;1258CvMat* sample_idx_buffer = 0;1259CvSparseMat** sparse_rows = 0;1260int samples_selected = 0;12611262CV_FUNCNAME( "cvStatModelMultiPredict" );12631264__BEGIN__;12651266int i;1267int predict_output_step = 1, sample_idx_step = 1;1268int type;1269int d, sizes[CV_MAX_DIM];1270int tflag = flags == CV_COL_SAMPLE;1271int samples_all, dims_all;1272int is_sparse = CV_IS_SPARSE_MAT(predict_input);1273CvMat predict_input_part;1274CvArr* sample = &predict_input_part;1275CvMat probs_part;1276CvMat* probs1 = probs ? &probs_part : 0;12771278if( !CV_IS_STAT_MODEL(stat_model) )1279CV_ERROR( !stat_model ? CV_StsNullPtr : CV_StsBadArg, "Invalid statistical model" );12801281if( !stat_model->predict )1282CV_ERROR( CV_StsNotImplemented, "There is no \"predict\" method" );12831284if( !predict_input || !predict_output )1285CV_ERROR( CV_StsNullPtr, "NULL input or output matrices" );12861287if( !is_sparse && !CV_IS_MAT(predict_input) )1288CV_ERROR( CV_StsBadArg, "predict_input should be a matrix or a sparse matrix" );12891290if( !CV_IS_MAT(predict_output) )1291CV_ERROR( CV_StsBadArg, "predict_output should be a matrix" );12921293type = cvGetElemType( predict_input );1294if( type != CV_32FC1 ||1295(CV_MAT_TYPE(predict_output->type) != CV_32FC1 &&1296CV_MAT_TYPE(predict_output->type) != CV_32SC1 ))1297CV_ERROR( CV_StsUnsupportedFormat, "The input or output matrix has unsupported format" );12981299CV_CALL( d = cvGetDims( predict_input, sizes ));1300if( d > 2 )1301CV_ERROR( CV_StsBadSize, "The input matrix should be 1- or 2-dimensional" );13021303if( !tflag )1304{1305samples_all = samples_selected = sizes[0];1306dims_all = sizes[1];1307}1308else1309{1310samples_all = samples_selected = sizes[1];1311dims_all = sizes[0];1312}13131314if( sample_idx )1315{1316if( !CV_IS_MAT(sample_idx) )1317CV_ERROR( CV_StsBadArg, "Invalid sample_idx matrix" );13181319if( sample_idx->cols != 1 && sample_idx->rows != 1 )1320CV_ERROR( CV_StsBadSize, "sample_idx must be 1-dimensional matrix" );13211322samples_selected = sample_idx->rows + sample_idx->cols - 1;13231324if( CV_MAT_TYPE(sample_idx->type) == CV_32SC1 )1325{1326if( samples_selected > samples_all )1327CV_ERROR( CV_StsBadSize, "sample_idx is too large vector" );1328}1329else if( samples_selected != samples_all )1330CV_ERROR( CV_StsUnmatchedSizes, "sample_idx has incorrect size" );13311332sample_idx_step = sample_idx->step ?1333sample_idx->step / CV_ELEM_SIZE(sample_idx->type) : 1;1334}13351336if( predict_output->rows != 1 && predict_output->cols != 1 )1337CV_ERROR( CV_StsBadSize, "predict_output should be a 1-dimensional matrix" );13381339if( predict_output->rows + predict_output->cols - 1 != samples_all )1340CV_ERROR( CV_StsUnmatchedSizes, "predict_output and predict_input have uncoordinated sizes" );13411342predict_output_step = predict_output->step ?1343predict_output->step / CV_ELEM_SIZE(predict_output->type) : 1;13441345if( probs )1346{1347if( !CV_IS_MAT(probs) )1348CV_ERROR( CV_StsBadArg, "Invalid matrix of probabilities" );13491350if( probs->rows != samples_all )1351CV_ERROR( CV_StsUnmatchedSizes,1352"matrix of probabilities must have as many rows as the total number of samples" );13531354if( CV_MAT_TYPE(probs->type) != CV_32FC1 )1355CV_ERROR( CV_StsUnsupportedFormat, "matrix of probabilities must have 32fC1 type" );1356}13571358if( is_sparse )1359{1360CvSparseNode* node;1361CvSparseMatIterator mat_iterator;1362CvSparseMat* sparse = (CvSparseMat*)predict_input;13631364if( sample_idx && CV_MAT_TYPE(sample_idx->type) == CV_32SC1 )1365{1366CV_CALL( sample_idx_buffer = cvCreateMat( 1, samples_all, CV_8UC1 ));1367cvZero( sample_idx_buffer );1368for( i = 0; i < samples_selected; i++ )1369sample_idx_buffer->data.ptr[sample_idx->data.i[i*sample_idx_step]] = 1;1370samples_selected = samples_all;1371sample_idx = sample_idx_buffer;1372sample_idx_step = 1;1373}13741375CV_CALL( sparse_rows = (CvSparseMat**)cvAlloc( samples_selected*sizeof(sparse_rows[0])));1376for( i = 0; i < samples_selected; i++ )1377{1378if( sample_idx && sample_idx->data.ptr[i*sample_idx_step] == 0 )1379continue;1380CV_CALL( sparse_rows[i] = cvCreateSparseMat( 1, &dims_all, type ));1381if( !storage )1382storage = sparse_rows[i]->heap->storage;1383else1384{1385// hack: to decrease memory footprint, make all the sparse matrices1386// reside in the same storage1387int elem_size = sparse_rows[i]->heap->elem_size;1388cvReleaseMemStorage( &sparse_rows[i]->heap->storage );1389sparse_rows[i]->heap = cvCreateSet( 0, sizeof(CvSet), elem_size, storage );1390}1391}13921393// put each row (or column) of predict_input into separate sparse matrix.1394node = cvInitSparseMatIterator( sparse, &mat_iterator );1395for( ; node != 0; node = cvGetNextSparseNode( &mat_iterator ))1396{1397int* idx = CV_NODE_IDX( sparse, node );1398int idx0 = idx[tflag ^ 1];1399int idx1 = idx[tflag];14001401if( sample_idx && sample_idx->data.ptr[idx0*sample_idx_step] == 0 )1402continue;14031404assert( sparse_rows[idx0] != 0 );1405*(float*)cvPtrND( sparse, &idx1, 0, 1, 0 ) = *(float*)CV_NODE_VAL( sparse, node );1406}1407}14081409for( i = 0; i < samples_selected; i++ )1410{1411int idx = i;1412float response;14131414if( sample_idx )1415{1416if( CV_MAT_TYPE(sample_idx->type) == CV_32SC1 )1417{1418idx = sample_idx->data.i[i*sample_idx_step];1419if( (unsigned)idx >= (unsigned)samples_all )1420CV_ERROR( CV_StsOutOfRange, "Some of sample_idx elements are out of range" );1421}1422else if( CV_MAT_TYPE(sample_idx->type) == CV_8UC1 &&1423sample_idx->data.ptr[i*sample_idx_step] == 0 )1424continue;1425}14261427if( !is_sparse )1428{1429if( !tflag )1430cvGetRow( predict_input, &predict_input_part, idx );1431else1432{1433cvGetCol( predict_input, &predict_input_part, idx );1434}1435}1436else1437sample = sparse_rows[idx];14381439if( probs )1440cvGetRow( probs, probs1, idx );14411442CV_CALL( response = stat_model->predict( stat_model, (CvMat*)sample, probs1 ));14431444if( CV_MAT_TYPE(predict_output->type) == CV_32FC1 )1445predict_output->data.fl[idx*predict_output_step] = response;1446else1447{1448CV_ASSERT( cvRound(response) == response );1449predict_output->data.i[idx*predict_output_step] = cvRound(response);1450}1451}14521453__END__;14541455if( sparse_rows )1456{1457int i;1458for( i = 0; i < samples_selected; i++ )1459if( sparse_rows[i] )1460{1461sparse_rows[i]->heap->storage = 0;1462cvReleaseSparseMat( &sparse_rows[i] );1463}1464cvFree( &sparse_rows );1465}14661467cvReleaseMat( &sample_idx_buffer );1468cvReleaseMemStorage( &storage );1469}1470#endif14711472// By P. Yarykin - begin -14731474void cvCombineResponseMaps (CvMat* _responses,1475const CvMat* old_response_map,1476CvMat* new_response_map,1477CvMat** out_response_map)1478{1479int** old_data = NULL;1480int** new_data = NULL;14811482CV_FUNCNAME ("cvCombineResponseMaps");1483__BEGIN__14841485int i,j;1486int old_n, new_n, out_n;1487int samples, free_response;1488int* first;1489int* responses;1490int* out_data;14911492if( out_response_map )1493*out_response_map = 0;14941495// Check input data.1496if ((!ICV_IS_MAT_OF_TYPE (_responses, CV_32SC1)) ||1497(!ICV_IS_MAT_OF_TYPE (old_response_map, CV_32SC1)) ||1498(!ICV_IS_MAT_OF_TYPE (new_response_map, CV_32SC1)))1499{1500CV_ERROR (CV_StsBadArg, "Some of input arguments is not the CvMat")1501}15021503// Prepare sorted responses.1504first = new_response_map->data.i;1505new_n = new_response_map->cols;1506CV_CALL (new_data = (int**)cvAlloc (new_n * sizeof (new_data[0])));1507for (i = 0; i < new_n; i++)1508new_data[i] = first + i;1509qsort (new_data, new_n, sizeof(int*), icvCmpIntegersPtr);15101511first = old_response_map->data.i;1512old_n = old_response_map->cols;1513CV_CALL (old_data = (int**)cvAlloc (old_n * sizeof (old_data[0])));1514for (i = 0; i < old_n; i++)1515old_data[i] = first + i;1516qsort (old_data, old_n, sizeof(int*), icvCmpIntegersPtr);15171518// Count the number of different responses.1519for (i = 0, j = 0, out_n = 0; i < old_n && j < new_n; out_n++)1520{1521if (*old_data[i] == *new_data[j])1522{1523i++;1524j++;1525}1526else if (*old_data[i] < *new_data[j])1527i++;1528else1529j++;1530}1531out_n += old_n - i + new_n - j;15321533// Create and fill the result response maps.1534CV_CALL (*out_response_map = cvCreateMat (1, out_n, CV_32SC1));1535out_data = (*out_response_map)->data.i;1536memcpy (out_data, first, old_n * sizeof (int));15371538free_response = old_n;1539for (i = 0, j = 0; i < old_n && j < new_n; )1540{1541if (*old_data[i] == *new_data[j])1542{1543*new_data[j] = (int)(old_data[i] - first);1544i++;1545j++;1546}1547else if (*old_data[i] < *new_data[j])1548i++;1549else1550{1551out_data[free_response] = *new_data[j];1552*new_data[j] = free_response++;1553j++;1554}1555}1556for (; j < new_n; j++)1557{1558out_data[free_response] = *new_data[j];1559*new_data[j] = free_response++;1560}1561CV_ASSERT (free_response == out_n);15621563// Change <responses> according to out response map.1564samples = _responses->cols + _responses->rows - 1;1565responses = _responses->data.i;1566first = new_response_map->data.i;1567for (i = 0; i < samples; i++)1568{1569responses[i] = first[responses[i]];1570}15711572__END__15731574cvFree(&old_data);1575cvFree(&new_data);15761577}157815791580static int icvGetNumberOfCluster( double* prob_vector, int num_of_clusters, float r,1581float outlier_thresh, int normalize_probs )1582{1583int max_prob_loc = 0;15841585CV_FUNCNAME("icvGetNumberOfCluster");1586__BEGIN__;15871588double prob, maxprob, sum;1589int i;15901591CV_ASSERT(prob_vector);1592CV_ASSERT(num_of_clusters >= 0);15931594maxprob = prob_vector[0];1595max_prob_loc = 0;1596sum = maxprob;1597for( i = 1; i < num_of_clusters; i++ )1598{1599prob = prob_vector[i];1600sum += prob;1601if( prob > maxprob )1602{1603max_prob_loc = i;1604maxprob = prob;1605}1606}1607if( normalize_probs && fabs(sum - 1.) > FLT_EPSILON )1608{1609for( i = 0; i < num_of_clusters; i++ )1610prob_vector[i] /= sum;1611}1612if( fabs(r - 1.) > FLT_EPSILON && fabs(sum - 1.) < outlier_thresh )1613max_prob_loc = -1;16141615__END__;16161617return max_prob_loc;16181619} // End of icvGetNumberOfCluster162016211622void icvFindClusterLabels( const CvMat* probs, float outlier_thresh, float r,1623const CvMat* labels )1624{1625CvMat* counts = 0;16261627CV_FUNCNAME("icvFindClusterLabels");1628__BEGIN__;16291630int nclusters, nsamples;1631int i, j;1632double* probs_data;16331634CV_ASSERT( ICV_IS_MAT_OF_TYPE(probs, CV_64FC1) );1635CV_ASSERT( ICV_IS_MAT_OF_TYPE(labels, CV_32SC1) );16361637nclusters = probs->cols;1638nsamples = probs->rows;1639CV_ASSERT( nsamples == labels->cols );16401641CV_CALL( counts = cvCreateMat( 1, nclusters + 1, CV_32SC1 ) );1642CV_CALL( cvSetZero( counts ));1643for( i = 0; i < nsamples; i++ )1644{1645labels->data.i[i] = icvGetNumberOfCluster( probs->data.db + i*probs->cols,1646nclusters, r, outlier_thresh, 1 );1647counts->data.i[labels->data.i[i] + 1]++;1648}1649CV_ASSERT((int)cvSum(counts).val[0] == nsamples);1650// Filling empty clusters with the vector, that has the maximal probability1651for( j = 0; j < nclusters; j++ ) // outliers are ignored1652{1653int maxprob_loc = -1;1654double maxprob = 0;16551656if( counts->data.i[j+1] ) // j-th class is not empty1657continue;1658// look for the presentative, which is not lonely in it's cluster1659// and that has a maximal probability among all these vectors1660probs_data = probs->data.db;1661for( i = 0; i < nsamples; i++, probs_data++ )1662{1663int label = labels->data.i[i];1664double prob;1665if( counts->data.i[label+1] == 0 ||1666(counts->data.i[label+1] <= 1 && label != -1) )1667continue;1668prob = *probs_data;1669if( prob >= maxprob )1670{1671maxprob = prob;1672maxprob_loc = i;1673}1674}1675// maxprob_loc == 0 <=> number of vectors less then number of clusters1676CV_ASSERT( maxprob_loc >= 0 );1677counts->data.i[labels->data.i[maxprob_loc] + 1]--;1678labels->data.i[maxprob_loc] = j;1679counts->data.i[j + 1]++;1680}16811682__END__;16831684cvReleaseMat( &counts );1685} // End of icvFindClusterLabels16861687/* End of file */168816891690