X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=apps%2Fhaartraining%2Fsrc%2Fcvboost.cpp;fp=apps%2Fhaartraining%2Fsrc%2Fcvboost.cpp;h=0000000000000000000000000000000000000000;hb=e4c14cdbdf2fe805e79cd96ded236f57e7b89060;hp=16ee895b1bb644cf664cfe97280919af11d1639e;hpb=454138ff8a20f6edb9b65a910101403d8b520643;p=opencv diff --git a/apps/haartraining/src/cvboost.cpp b/apps/haartraining/src/cvboost.cpp deleted file mode 100644 index 16ee895..0000000 --- a/apps/haartraining/src/cvboost.cpp +++ /dev/null @@ -1,3793 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// Intel License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000, Intel Corporation, all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of Intel Corporation may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ - -#ifdef HAVE_CONFIG_H - #include -#endif - -#ifdef HAVE_MALLOC_H - #include -#endif - -#include -#include -#include -#include - -#include -#include - -#include <_cvcommon.h> -#include - -#ifdef _OPENMP -#include -#endif /* _OPENMP */ - -#define CV_BOOST_IMPL - -typedef struct CvValArray -{ - uchar* data; - size_t step; -} CvValArray; - -#define CMP_VALUES( idx1, idx2 ) \ - ( *( (float*) (aux->data + ((int) (idx1)) * aux->step ) ) < \ - *( (float*) (aux->data + ((int) (idx2)) * aux->step ) ) ) - -CV_IMPLEMENT_QSORT_EX( icvSortIndexedValArray_16s, short, CMP_VALUES, CvValArray* ) - -CV_IMPLEMENT_QSORT_EX( icvSortIndexedValArray_32s, int, CMP_VALUES, CvValArray* ) - -CV_IMPLEMENT_QSORT_EX( icvSortIndexedValArray_32f, float, CMP_VALUES, CvValArray* ) - -CV_BOOST_IMPL -void cvGetSortedIndices( CvMat* val, CvMat* idx, int sortcols ) -{ - int idxtype = 0; - uchar* data = NULL; - size_t istep = 0; - size_t jstep = 0; - - int i = 0; - int j = 0; - - CvValArray va; - - assert( idx != NULL ); - assert( val != NULL ); - - idxtype = CV_MAT_TYPE( idx->type ); - assert( idxtype == CV_16SC1 || idxtype == CV_32SC1 || idxtype == CV_32FC1 ); - assert( CV_MAT_TYPE( val->type ) == CV_32FC1 ); - if( sortcols ) - { - assert( idx->rows == val->cols ); - assert( idx->cols == val->rows ); - istep = CV_ELEM_SIZE( val->type ); - jstep = val->step; - } - else - { - assert( idx->rows == val->rows ); - assert( idx->cols == val->cols ); - istep = val->step; - jstep = CV_ELEM_SIZE( val->type ); - } - - va.data = val->data.ptr; - va.step = jstep; - switch( idxtype ) - { - case CV_16SC1: - for( i = 0; i < idx->rows; i++ ) - { - for( j = 0; j < idx->cols; j++ ) - { - CV_MAT_ELEM( *idx, short, i, j ) = (short) j; - } - icvSortIndexedValArray_16s( (short*) (idx->data.ptr + i * idx->step), - idx->cols, &va ); - va.data += istep; - } - break; - - case CV_32SC1: - for( i = 0; i < idx->rows; i++ ) - { - for( j = 0; j < idx->cols; j++ ) - { - CV_MAT_ELEM( *idx, int, i, j ) = j; - } - icvSortIndexedValArray_32s( (int*) (idx->data.ptr + i * idx->step), - idx->cols, &va ); - va.data += istep; - } - break; - - case CV_32FC1: - for( i = 0; i < idx->rows; i++ ) - { - for( j = 0; j < idx->cols; j++ ) - { - CV_MAT_ELEM( *idx, float, i, j ) = (float) j; - } - icvSortIndexedValArray_32f( (float*) (idx->data.ptr + i * idx->step), - idx->cols, &va ); - va.data += istep; - } - break; - - default: - assert( 0 ); - break; - } -} - -CV_BOOST_IMPL -void cvReleaseStumpClassifier( CvClassifier** classifier ) -{ - cvFree( classifier ); - *classifier = 0; -} - -CV_BOOST_IMPL -float cvEvalStumpClassifier( CvClassifier* classifier, CvMat* sample ) -{ - assert( classifier != NULL ); - assert( sample != NULL ); - assert( CV_MAT_TYPE( sample->type ) == CV_32FC1 ); - - if( (CV_MAT_ELEM( (*sample), float, 0, - ((CvStumpClassifier*) classifier)->compidx )) < - ((CvStumpClassifier*) classifier)->threshold ) - { - return ((CvStumpClassifier*) classifier)->left; - } - else - { - return ((CvStumpClassifier*) classifier)->right; - } - - return 0.0F; -} - -#define ICV_DEF_FIND_STUMP_THRESHOLD( suffix, type, error ) \ -CV_BOOST_IMPL int icvFindStumpThreshold_##suffix( \ - uchar* data, size_t datastep, \ - uchar* wdata, size_t wstep, \ - uchar* ydata, size_t ystep, \ - uchar* idxdata, size_t idxstep, int num, \ - float* lerror, \ - float* rerror, \ - float* threshold, float* left, float* right, \ - float* sumw, float* sumwy, float* sumwyy ) \ -{ \ - int found = 0; \ - float wyl = 0.0F; \ - float wl = 0.0F; \ - float wyyl = 0.0F; \ - float wyr = 0.0F; \ - float wr = 0.0F; \ - \ - float curleft = 0.0F; \ - float curright = 0.0F; \ - float* prevval = NULL; \ - float* curval = NULL; \ - float curlerror = 0.0F; \ - float currerror = 0.0F; \ - float wposl; \ - float wposr; \ - \ - int i = 0; \ - int idx = 0; \ - \ - wposl = wposr = 0.0F; \ - if( *sumw == FLT_MAX ) \ - { \ - /* calculate sums */ \ - float *y = NULL; \ - float *w = NULL; \ - float wy = 0.0F; \ - \ - *sumw = 0.0F; \ - *sumwy = 0.0F; \ - *sumwyy = 0.0F; \ - for( i = 0; i < num; i++ ) \ - { \ - idx = (int) ( *((type*) (idxdata + i*idxstep)) ); \ - w = (float*) (wdata + idx * wstep); \ - *sumw += *w; \ - y = (float*) (ydata + idx * ystep); \ - wy = (*w) * (*y); \ - *sumwy += wy; \ - *sumwyy += wy * (*y); \ - } \ - } \ - \ - for( i = 0; i < num; i++ ) \ - { \ - idx = (int) ( *((type*) (idxdata + i*idxstep)) ); \ - curval = (float*) (data + idx * datastep); \ - /* for debug purpose */ \ - if( i > 0 ) assert( (*prevval) <= (*curval) ); \ - \ - wyr = *sumwy - wyl; \ - wr = *sumw - wl; \ - \ - if( wl > 0.0 ) curleft = wyl / wl; \ - else curleft = 0.0F; \ - \ - if( wr > 0.0 ) curright = wyr / wr; \ - else curright = 0.0F; \ - \ - error \ - \ - if( curlerror + currerror < (*lerror) + (*rerror) ) \ - { \ - (*lerror) = curlerror; \ - (*rerror) = currerror; \ - *threshold = *curval; \ - if( i > 0 ) { \ - *threshold = 0.5F * (*threshold + *prevval); \ - } \ - *left = curleft; \ - *right = curright; \ - found = 1; \ - } \ - \ - do \ - { \ - wl += *((float*) (wdata + idx * wstep)); \ - wyl += (*((float*) (wdata + idx * wstep))) \ - * (*((float*) (ydata + idx * ystep))); \ - wyyl += *((float*) (wdata + idx * wstep)) \ - * (*((float*) (ydata + idx * ystep))) \ - * (*((float*) (ydata + idx * ystep))); \ - } \ - while( (++i) < num && \ - ( *((float*) (data + (idx = \ - (int) ( *((type*) (idxdata + i*idxstep))) ) * datastep)) \ - == *curval ) ); \ - --i; \ - prevval = curval; \ - } /* for each value */ \ - \ - return found; \ -} - -/* misclassification error - * err = MIN( wpos, wneg ); - */ -#define ICV_DEF_FIND_STUMP_THRESHOLD_MISC( suffix, type ) \ - ICV_DEF_FIND_STUMP_THRESHOLD( misc_##suffix, type, \ - wposl = 0.5F * ( wl + wyl ); \ - wposr = 0.5F * ( wr + wyr ); \ - curleft = 0.5F * ( 1.0F + curleft ); \ - curright = 0.5F * ( 1.0F + curright ); \ - curlerror = MIN( wposl, wl - wposl ); \ - currerror = MIN( wposr, wr - wposr ); \ - ) - -/* gini error - * err = 2 * wpos * wneg /(wpos + wneg) - */ -#define ICV_DEF_FIND_STUMP_THRESHOLD_GINI( suffix, type ) \ - ICV_DEF_FIND_STUMP_THRESHOLD( gini_##suffix, type, \ - wposl = 0.5F * ( wl + wyl ); \ - wposr = 0.5F * ( wr + wyr ); \ - curleft = 0.5F * ( 1.0F + curleft ); \ - curright = 0.5F * ( 1.0F + curright ); \ - curlerror = 2.0F * wposl * ( 1.0F - curleft ); \ - currerror = 2.0F * wposr * ( 1.0F - curright ); \ - ) - -#define CV_ENTROPY_THRESHOLD FLT_MIN - -/* entropy error - * err = - wpos * log(wpos / (wpos + wneg)) - wneg * log(wneg / (wpos + wneg)) - */ -#define ICV_DEF_FIND_STUMP_THRESHOLD_ENTROPY( suffix, type ) \ - ICV_DEF_FIND_STUMP_THRESHOLD( entropy_##suffix, type, \ - wposl = 0.5F * ( wl + wyl ); \ - wposr = 0.5F * ( wr + wyr ); \ - curleft = 0.5F * ( 1.0F + curleft ); \ - curright = 0.5F * ( 1.0F + curright ); \ - curlerror = currerror = 0.0F; \ - if( curleft > CV_ENTROPY_THRESHOLD ) \ - curlerror -= wposl * logf( curleft ); \ - if( curleft < 1.0F - CV_ENTROPY_THRESHOLD ) \ - curlerror -= (wl - wposl) * logf( 1.0F - curleft ); \ - \ - if( curright > CV_ENTROPY_THRESHOLD ) \ - currerror -= wposr * logf( curright ); \ - if( curright < 1.0F - CV_ENTROPY_THRESHOLD ) \ - currerror -= (wr - wposr) * logf( 1.0F - curright ); \ - ) - -/* least sum of squares error */ -#define ICV_DEF_FIND_STUMP_THRESHOLD_SQ( suffix, type ) \ - ICV_DEF_FIND_STUMP_THRESHOLD( sq_##suffix, type, \ - /* calculate error (sum of squares) */ \ - /* err = sum( w * (y - left(rigt)Val)^2 ) */ \ - curlerror = wyyl + curleft * curleft * wl - 2.0F * curleft * wyl; \ - currerror = (*sumwyy) - wyyl + curright * curright * wr - 2.0F * curright * wyr; \ - ) - -ICV_DEF_FIND_STUMP_THRESHOLD_MISC( 16s, short ) - -ICV_DEF_FIND_STUMP_THRESHOLD_MISC( 32s, int ) - -ICV_DEF_FIND_STUMP_THRESHOLD_MISC( 32f, float ) - - -ICV_DEF_FIND_STUMP_THRESHOLD_GINI( 16s, short ) - -ICV_DEF_FIND_STUMP_THRESHOLD_GINI( 32s, int ) - -ICV_DEF_FIND_STUMP_THRESHOLD_GINI( 32f, float ) - - -ICV_DEF_FIND_STUMP_THRESHOLD_ENTROPY( 16s, short ) - -ICV_DEF_FIND_STUMP_THRESHOLD_ENTROPY( 32s, int ) - -ICV_DEF_FIND_STUMP_THRESHOLD_ENTROPY( 32f, float ) - - -ICV_DEF_FIND_STUMP_THRESHOLD_SQ( 16s, short ) - -ICV_DEF_FIND_STUMP_THRESHOLD_SQ( 32s, int ) - -ICV_DEF_FIND_STUMP_THRESHOLD_SQ( 32f, float ) - -typedef int (*CvFindThresholdFunc)( uchar* data, size_t datastep, - uchar* wdata, size_t wstep, - uchar* ydata, size_t ystep, - uchar* idxdata, size_t idxstep, int num, - float* lerror, - float* rerror, - float* threshold, float* left, float* right, - float* sumw, float* sumwy, float* sumwyy ); - -CvFindThresholdFunc findStumpThreshold_16s[4] = { - icvFindStumpThreshold_misc_16s, - icvFindStumpThreshold_gini_16s, - icvFindStumpThreshold_entropy_16s, - icvFindStumpThreshold_sq_16s - }; - -CvFindThresholdFunc findStumpThreshold_32s[4] = { - icvFindStumpThreshold_misc_32s, - icvFindStumpThreshold_gini_32s, - icvFindStumpThreshold_entropy_32s, - icvFindStumpThreshold_sq_32s - }; - -CvFindThresholdFunc findStumpThreshold_32f[4] = { - icvFindStumpThreshold_misc_32f, - icvFindStumpThreshold_gini_32f, - icvFindStumpThreshold_entropy_32f, - icvFindStumpThreshold_sq_32f - }; - -CV_BOOST_IMPL -CvClassifier* cvCreateStumpClassifier( CvMat* trainData, - int flags, - CvMat* trainClasses, - CvMat* typeMask, - CvMat* missedMeasurementsMask, - CvMat* compIdx, - CvMat* sampleIdx, - CvMat* weights, - CvClassifierTrainParams* trainParams - ) -{ - CvStumpClassifier* stump = NULL; - int m = 0; /* number of samples */ - int n = 0; /* number of components */ - uchar* data = NULL; - int cstep = 0; - int sstep = 0; - uchar* ydata = NULL; - int ystep = 0; - uchar* idxdata = NULL; - int idxstep = 0; - int l = 0; /* number of indices */ - uchar* wdata = NULL; - int wstep = 0; - - int* idx = NULL; - int i = 0; - - float sumw = FLT_MAX; - float sumw1 = FLT_MAX; - float sumw0 = FLT_MAX; - float sumwy = FLT_MAX; - float sumwyy = FLT_MAX; - - assert( trainData != NULL ); - assert( CV_MAT_TYPE( trainData->type ) == CV_32FC1 ); - assert( trainClasses != NULL ); - assert( CV_MAT_TYPE( trainClasses->type ) == CV_32FC1 ); - assert( missedMeasurementsMask == NULL ); - assert( compIdx == NULL ); - assert( weights != NULL ); - assert( CV_MAT_TYPE( weights->type ) == CV_32FC1 ); - assert( trainParams != NULL ); - - data = trainData->data.ptr; - if( CV_IS_ROW_SAMPLE( flags ) ) - { - cstep = CV_ELEM_SIZE( trainData->type ); - sstep = trainData->step; - m = trainData->rows; - n = trainData->cols; - } - else - { - sstep = CV_ELEM_SIZE( trainData->type ); - cstep = trainData->step; - m = trainData->cols; - n = trainData->rows; - } - - ydata = trainClasses->data.ptr; - if( trainClasses->rows == 1 ) - { - assert( trainClasses->cols == m ); - ystep = CV_ELEM_SIZE( trainClasses->type ); - } - else - { - assert( trainClasses->rows == m ); - ystep = trainClasses->step; - } - - wdata = weights->data.ptr; - if( weights->rows == 1 ) - { - assert( weights->cols == m ); - wstep = CV_ELEM_SIZE( weights->type ); - } - else - { - assert( weights->rows == m ); - wstep = weights->step; - } - - l = m; - if( sampleIdx != NULL ) - { - assert( CV_MAT_TYPE( sampleIdx->type ) == CV_32FC1 ); - - idxdata = sampleIdx->data.ptr; - if( sampleIdx->rows == 1 ) - { - l = sampleIdx->cols; - idxstep = CV_ELEM_SIZE( sampleIdx->type ); - } - else - { - l = sampleIdx->rows; - idxstep = sampleIdx->step; - } - assert( l <= m ); - } - - idx = (int*) cvAlloc( l * sizeof( int ) ); - stump = (CvStumpClassifier*) cvAlloc( sizeof( CvStumpClassifier) ); - - /* START */ - memset( (void*) stump, 0, sizeof( CvStumpClassifier ) ); - - stump->eval = cvEvalStumpClassifier; - stump->tune = NULL; - stump->save = NULL; - stump->release = cvReleaseStumpClassifier; - - stump->lerror = FLT_MAX; - stump->rerror = FLT_MAX; - stump->left = 0.0F; - stump->right = 0.0F; - - /* copy indices */ - if( sampleIdx != NULL ) - { - for( i = 0; i < l; i++ ) - { - idx[i] = (int) *((float*) (idxdata + i*idxstep)); - } - } - else - { - for( i = 0; i < l; i++ ) - { - idx[i] = i; - } - } - - for( i = 0; i < n; i++ ) - { - CvValArray va; - - va.data = data + i * ((size_t) cstep); - va.step = sstep; - icvSortIndexedValArray_32s( idx, l, &va ); - if( findStumpThreshold_32s[(int) ((CvStumpTrainParams*) trainParams)->error] - ( data + i * ((size_t) cstep), sstep, - wdata, wstep, ydata, ystep, (uchar*) idx, sizeof( int ), l, - &(stump->lerror), &(stump->rerror), - &(stump->threshold), &(stump->left), &(stump->right), - &sumw, &sumwy, &sumwyy ) ) - { - stump->compidx = i; - } - } /* for each component */ - - /* END */ - - cvFree( &idx ); - - if( ((CvStumpTrainParams*) trainParams)->type == CV_CLASSIFICATION_CLASS ) - { - stump->left = 2.0F * (stump->left >= 0.5F) - 1.0F; - stump->right = 2.0F * (stump->right >= 0.5F) - 1.0F; - } - - return (CvClassifier*) stump; -} - -/* - * cvCreateMTStumpClassifier - * - * Multithreaded stump classifier constructor - * Includes huge train data support through callback function - */ -CV_BOOST_IMPL -CvClassifier* cvCreateMTStumpClassifier( CvMat* trainData, - int flags, - CvMat* trainClasses, - CvMat* typeMask, - CvMat* missedMeasurementsMask, - CvMat* compIdx, - CvMat* sampleIdx, - CvMat* weights, - CvClassifierTrainParams* trainParams ) -{ - CvStumpClassifier* stump = NULL; - int m = 0; /* number of samples */ - int n = 0; /* number of components */ - uchar* data = NULL; - size_t cstep = 0; - size_t sstep = 0; - int datan = 0; /* num components */ - uchar* ydata = NULL; - size_t ystep = 0; - uchar* idxdata = NULL; - size_t idxstep = 0; - int l = 0; /* number of indices */ - uchar* wdata = NULL; - size_t wstep = 0; - - uchar* sorteddata = NULL; - int sortedtype = 0; - size_t sortedcstep = 0; /* component step */ - size_t sortedsstep = 0; /* sample step */ - int sortedn = 0; /* num components */ - int sortedm = 0; /* num samples */ - - char* filter = NULL; - int i = 0; - - int compidx = 0; - int stumperror; - int portion; - - /* private variables */ - CvMat mat; - CvValArray va; - float lerror; - float rerror; - float left; - float right; - float threshold; - int optcompidx; - - float sumw; - float sumwy; - float sumwyy; - - int t_compidx; - int t_n; - - int ti; - int tj; - int tk; - - uchar* t_data; - size_t t_cstep; - size_t t_sstep; - - size_t matcstep; - size_t matsstep; - - int* t_idx; - /* end private variables */ - - assert( trainParams != NULL ); - assert( trainClasses != NULL ); - assert( CV_MAT_TYPE( trainClasses->type ) == CV_32FC1 ); - assert( missedMeasurementsMask == NULL ); - assert( compIdx == NULL ); - - stumperror = (int) ((CvMTStumpTrainParams*) trainParams)->error; - - ydata = trainClasses->data.ptr; - if( trainClasses->rows == 1 ) - { - m = trainClasses->cols; - ystep = CV_ELEM_SIZE( trainClasses->type ); - } - else - { - m = trainClasses->rows; - ystep = trainClasses->step; - } - - wdata = weights->data.ptr; - if( weights->rows == 1 ) - { - assert( weights->cols == m ); - wstep = CV_ELEM_SIZE( weights->type ); - } - else - { - assert( weights->rows == m ); - wstep = weights->step; - } - - if( ((CvMTStumpTrainParams*) trainParams)->sortedIdx != NULL ) - { - sortedtype = - CV_MAT_TYPE( ((CvMTStumpTrainParams*) trainParams)->sortedIdx->type ); - assert( sortedtype == CV_16SC1 || sortedtype == CV_32SC1 - || sortedtype == CV_32FC1 ); - sorteddata = ((CvMTStumpTrainParams*) trainParams)->sortedIdx->data.ptr; - sortedsstep = CV_ELEM_SIZE( sortedtype ); - sortedcstep = ((CvMTStumpTrainParams*) trainParams)->sortedIdx->step; - sortedn = ((CvMTStumpTrainParams*) trainParams)->sortedIdx->rows; - sortedm = ((CvMTStumpTrainParams*) trainParams)->sortedIdx->cols; - } - - if( trainData == NULL ) - { - assert( ((CvMTStumpTrainParams*) trainParams)->getTrainData != NULL ); - n = ((CvMTStumpTrainParams*) trainParams)->numcomp; - assert( n > 0 ); - } - else - { - assert( CV_MAT_TYPE( trainData->type ) == CV_32FC1 ); - data = trainData->data.ptr; - if( CV_IS_ROW_SAMPLE( flags ) ) - { - cstep = CV_ELEM_SIZE( trainData->type ); - sstep = trainData->step; - assert( m == trainData->rows ); - datan = n = trainData->cols; - } - else - { - sstep = CV_ELEM_SIZE( trainData->type ); - cstep = trainData->step; - assert( m == trainData->cols ); - datan = n = trainData->rows; - } - if( ((CvMTStumpTrainParams*) trainParams)->getTrainData != NULL ) - { - n = ((CvMTStumpTrainParams*) trainParams)->numcomp; - } - } - assert( datan <= n ); - - if( sampleIdx != NULL ) - { - assert( CV_MAT_TYPE( sampleIdx->type ) == CV_32FC1 ); - idxdata = sampleIdx->data.ptr; - idxstep = ( sampleIdx->rows == 1 ) - ? CV_ELEM_SIZE( sampleIdx->type ) : sampleIdx->step; - l = ( sampleIdx->rows == 1 ) ? sampleIdx->cols : sampleIdx->rows; - - if( sorteddata != NULL ) - { - filter = (char*) cvAlloc( sizeof( char ) * m ); - memset( (void*) filter, 0, sizeof( char ) * m ); - for( i = 0; i < l; i++ ) - { - filter[(int) *((float*) (idxdata + i * idxstep))] = (char) 1; - } - } - } - else - { - l = m; - } - - stump = (CvStumpClassifier*) cvAlloc( sizeof( CvStumpClassifier) ); - - /* START */ - memset( (void*) stump, 0, sizeof( CvStumpClassifier ) ); - - portion = ((CvMTStumpTrainParams*)trainParams)->portion; - - if( portion < 1 ) - { - /* auto portion */ - portion = n; - #ifdef _OPENMP - portion /= omp_get_max_threads(); - #endif /* _OPENMP */ - } - - stump->eval = cvEvalStumpClassifier; - stump->tune = NULL; - stump->save = NULL; - stump->release = cvReleaseStumpClassifier; - - stump->lerror = FLT_MAX; - stump->rerror = FLT_MAX; - stump->left = 0.0F; - stump->right = 0.0F; - - compidx = 0; - #ifdef _OPENMP - #pragma omp parallel private(mat, va, lerror, rerror, left, right, threshold, \ - optcompidx, sumw, sumwy, sumwyy, t_compidx, t_n, \ - ti, tj, tk, t_data, t_cstep, t_sstep, matcstep, \ - matsstep, t_idx) - #endif /* _OPENMP */ - { - lerror = FLT_MAX; - rerror = FLT_MAX; - left = 0.0F; - right = 0.0F; - threshold = 0.0F; - optcompidx = 0; - - sumw = FLT_MAX; - sumwy = FLT_MAX; - sumwyy = FLT_MAX; - - t_compidx = 0; - t_n = 0; - - ti = 0; - tj = 0; - tk = 0; - - t_data = NULL; - t_cstep = 0; - t_sstep = 0; - - matcstep = 0; - matsstep = 0; - - t_idx = NULL; - - mat.data.ptr = NULL; - - if( datan < n ) - { - /* prepare matrix for callback */ - if( CV_IS_ROW_SAMPLE( flags ) ) - { - mat = cvMat( m, portion, CV_32FC1, 0 ); - matcstep = CV_ELEM_SIZE( mat.type ); - matsstep = mat.step; - } - else - { - mat = cvMat( portion, m, CV_32FC1, 0 ); - matcstep = mat.step; - matsstep = CV_ELEM_SIZE( mat.type ); - } - mat.data.ptr = (uchar*) cvAlloc( sizeof( float ) * mat.rows * mat.cols ); - } - - if( filter != NULL || sortedn < n ) - { - t_idx = (int*) cvAlloc( sizeof( int ) * m ); - if( sortedn == 0 || filter == NULL ) - { - if( idxdata != NULL ) - { - for( ti = 0; ti < l; ti++ ) - { - t_idx[ti] = (int) *((float*) (idxdata + ti * idxstep)); - } - } - else - { - for( ti = 0; ti < l; ti++ ) - { - t_idx[ti] = ti; - } - } - } - } - - #ifdef _OPENMP - #pragma omp critical(c_compidx) - #endif /* _OPENMP */ - { - t_compidx = compidx; - compidx += portion; - } - while( t_compidx < n ) - { - t_n = portion; - if( t_compidx < datan ) - { - t_n = ( t_n < (datan - t_compidx) ) ? t_n : (datan - t_compidx); - t_data = data; - t_cstep = cstep; - t_sstep = sstep; - } - else - { - t_n = ( t_n < (n - t_compidx) ) ? t_n : (n - t_compidx); - t_cstep = matcstep; - t_sstep = matsstep; - t_data = mat.data.ptr - t_compidx * ((size_t) t_cstep ); - - /* calculate components */ - ((CvMTStumpTrainParams*)trainParams)->getTrainData( &mat, - sampleIdx, compIdx, t_compidx, t_n, - ((CvMTStumpTrainParams*)trainParams)->userdata ); - } - - if( sorteddata != NULL ) - { - if( filter != NULL ) - { - /* have sorted indices and filter */ - switch( sortedtype ) - { - case CV_16SC1: - for( ti = t_compidx; ti < MIN( sortedn, t_compidx + t_n ); ti++ ) - { - tk = 0; - for( tj = 0; tj < sortedm; tj++ ) - { - int curidx = (int) ( *((short*) (sorteddata - + ti * sortedcstep + tj * sortedsstep)) ); - if( filter[curidx] != 0 ) - { - t_idx[tk++] = curidx; - } - } - if( findStumpThreshold_32s[stumperror]( - t_data + ti * t_cstep, t_sstep, - wdata, wstep, ydata, ystep, - (uchar*) t_idx, sizeof( int ), tk, - &lerror, &rerror, - &threshold, &left, &right, - &sumw, &sumwy, &sumwyy ) ) - { - optcompidx = ti; - } - } - break; - case CV_32SC1: - for( ti = t_compidx; ti < MIN( sortedn, t_compidx + t_n ); ti++ ) - { - tk = 0; - for( tj = 0; tj < sortedm; tj++ ) - { - int curidx = (int) ( *((int*) (sorteddata - + ti * sortedcstep + tj * sortedsstep)) ); - if( filter[curidx] != 0 ) - { - t_idx[tk++] = curidx; - } - } - if( findStumpThreshold_32s[stumperror]( - t_data + ti * t_cstep, t_sstep, - wdata, wstep, ydata, ystep, - (uchar*) t_idx, sizeof( int ), tk, - &lerror, &rerror, - &threshold, &left, &right, - &sumw, &sumwy, &sumwyy ) ) - { - optcompidx = ti; - } - } - break; - case CV_32FC1: - for( ti = t_compidx; ti < MIN( sortedn, t_compidx + t_n ); ti++ ) - { - tk = 0; - for( tj = 0; tj < sortedm; tj++ ) - { - int curidx = (int) ( *((float*) (sorteddata - + ti * sortedcstep + tj * sortedsstep)) ); - if( filter[curidx] != 0 ) - { - t_idx[tk++] = curidx; - } - } - if( findStumpThreshold_32s[stumperror]( - t_data + ti * t_cstep, t_sstep, - wdata, wstep, ydata, ystep, - (uchar*) t_idx, sizeof( int ), tk, - &lerror, &rerror, - &threshold, &left, &right, - &sumw, &sumwy, &sumwyy ) ) - { - optcompidx = ti; - } - } - break; - default: - assert( 0 ); - break; - } - } - else - { - /* have sorted indices */ - switch( sortedtype ) - { - case CV_16SC1: - for( ti = t_compidx; ti < MIN( sortedn, t_compidx + t_n ); ti++ ) - { - if( findStumpThreshold_16s[stumperror]( - t_data + ti * t_cstep, t_sstep, - wdata, wstep, ydata, ystep, - sorteddata + ti * sortedcstep, sortedsstep, sortedm, - &lerror, &rerror, - &threshold, &left, &right, - &sumw, &sumwy, &sumwyy ) ) - { - optcompidx = ti; - } - } - break; - case CV_32SC1: - for( ti = t_compidx; ti < MIN( sortedn, t_compidx + t_n ); ti++ ) - { - if( findStumpThreshold_32s[stumperror]( - t_data + ti * t_cstep, t_sstep, - wdata, wstep, ydata, ystep, - sorteddata + ti * sortedcstep, sortedsstep, sortedm, - &lerror, &rerror, - &threshold, &left, &right, - &sumw, &sumwy, &sumwyy ) ) - { - optcompidx = ti; - } - } - break; - case CV_32FC1: - for( ti = t_compidx; ti < MIN( sortedn, t_compidx + t_n ); ti++ ) - { - if( findStumpThreshold_32f[stumperror]( - t_data + ti * t_cstep, t_sstep, - wdata, wstep, ydata, ystep, - sorteddata + ti * sortedcstep, sortedsstep, sortedm, - &lerror, &rerror, - &threshold, &left, &right, - &sumw, &sumwy, &sumwyy ) ) - { - optcompidx = ti; - } - } - break; - default: - assert( 0 ); - break; - } - } - } - - ti = MAX( t_compidx, MIN( sortedn, t_compidx + t_n ) ); - for( ; ti < t_compidx + t_n; ti++ ) - { - va.data = t_data + ti * t_cstep; - va.step = t_sstep; - icvSortIndexedValArray_32s( t_idx, l, &va ); - if( findStumpThreshold_32s[stumperror]( - t_data + ti * t_cstep, t_sstep, - wdata, wstep, ydata, ystep, - (uchar*)t_idx, sizeof( int ), l, - &lerror, &rerror, - &threshold, &left, &right, - &sumw, &sumwy, &sumwyy ) ) - { - optcompidx = ti; - } - } - #ifdef _OPENMP - #pragma omp critical(c_compidx) - #endif /* _OPENMP */ - { - t_compidx = compidx; - compidx += portion; - } - } /* while have training data */ - - /* get the best classifier */ - #ifdef _OPENMP - #pragma omp critical(c_beststump) - #endif /* _OPENMP */ - { - if( lerror + rerror < stump->lerror + stump->rerror ) - { - stump->lerror = lerror; - stump->rerror = rerror; - stump->compidx = optcompidx; - stump->threshold = threshold; - stump->left = left; - stump->right = right; - } - } - - /* free allocated memory */ - if( mat.data.ptr != NULL ) - { - cvFree( &(mat.data.ptr) ); - } - if( t_idx != NULL ) - { - cvFree( &t_idx ); - } - } /* end of parallel region */ - - /* END */ - - /* free allocated memory */ - if( filter != NULL ) - { - cvFree( &filter ); - } - - if( ((CvMTStumpTrainParams*) trainParams)->type == CV_CLASSIFICATION_CLASS ) - { - stump->left = 2.0F * (stump->left >= 0.5F) - 1.0F; - stump->right = 2.0F * (stump->right >= 0.5F) - 1.0F; - } - - return (CvClassifier*) stump; -} - -CV_BOOST_IMPL -float cvEvalCARTClassifier( CvClassifier* classifier, CvMat* sample ) -{ - CV_FUNCNAME( "cvEvalCARTClassifier" ); - - int idx; - - __BEGIN__; - - - CV_ASSERT( classifier != NULL ); - CV_ASSERT( sample != NULL ); - CV_ASSERT( CV_MAT_TYPE( sample->type ) == CV_32FC1 ); - CV_ASSERT( sample->rows == 1 || sample->cols == 1 ); - - idx = 0; - if( sample->rows == 1 ) - { - do - { - if( (CV_MAT_ELEM( (*sample), float, 0, - ((CvCARTClassifier*) classifier)->compidx[idx] )) < - ((CvCARTClassifier*) classifier)->threshold[idx] ) - { - idx = ((CvCARTClassifier*) classifier)->left[idx]; - } - else - { - idx = ((CvCARTClassifier*) classifier)->right[idx]; - } - } while( idx > 0 ); - } - else - { - do - { - if( (CV_MAT_ELEM( (*sample), float, - ((CvCARTClassifier*) classifier)->compidx[idx], 0 )) < - ((CvCARTClassifier*) classifier)->threshold[idx] ) - { - idx = ((CvCARTClassifier*) classifier)->left[idx]; - } - else - { - idx = ((CvCARTClassifier*) classifier)->right[idx]; - } - } while( idx > 0 ); - } - - __END__; - - return ((CvCARTClassifier*) classifier)->val[-idx]; -} - -CV_BOOST_IMPL -float cvEvalCARTClassifierIdx( CvClassifier* classifier, CvMat* sample ) -{ - CV_FUNCNAME( "cvEvalCARTClassifierIdx" ); - - int idx; - - __BEGIN__; - - - CV_ASSERT( classifier != NULL ); - CV_ASSERT( sample != NULL ); - CV_ASSERT( CV_MAT_TYPE( sample->type ) == CV_32FC1 ); - CV_ASSERT( sample->rows == 1 || sample->cols == 1 ); - - idx = 0; - if( sample->rows == 1 ) - { - do - { - if( (CV_MAT_ELEM( (*sample), float, 0, - ((CvCARTClassifier*) classifier)->compidx[idx] )) < - ((CvCARTClassifier*) classifier)->threshold[idx] ) - { - idx = ((CvCARTClassifier*) classifier)->left[idx]; - } - else - { - idx = ((CvCARTClassifier*) classifier)->right[idx]; - } - } while( idx > 0 ); - } - else - { - do - { - if( (CV_MAT_ELEM( (*sample), float, - ((CvCARTClassifier*) classifier)->compidx[idx], 0 )) < - ((CvCARTClassifier*) classifier)->threshold[idx] ) - { - idx = ((CvCARTClassifier*) classifier)->left[idx]; - } - else - { - idx = ((CvCARTClassifier*) classifier)->right[idx]; - } - } while( idx > 0 ); - } - - __END__; - - return (float) (-idx); -} - -CV_BOOST_IMPL -void cvReleaseCARTClassifier( CvClassifier** classifier ) -{ - cvFree( classifier ); - *classifier = NULL; -} - -void CV_CDECL icvDefaultSplitIdx_R( int compidx, float threshold, - CvMat* idx, CvMat** left, CvMat** right, - void* userdata ) -{ - CvMat* trainData = (CvMat*) userdata; - int i = 0; - - *left = cvCreateMat( 1, trainData->rows, CV_32FC1 ); - *right = cvCreateMat( 1, trainData->rows, CV_32FC1 ); - (*left)->cols = (*right)->cols = 0; - if( idx == NULL ) - { - for( i = 0; i < trainData->rows; i++ ) - { - if( CV_MAT_ELEM( *trainData, float, i, compidx ) < threshold ) - { - (*left)->data.fl[(*left)->cols++] = (float) i; - } - else - { - (*right)->data.fl[(*right)->cols++] = (float) i; - } - } - } - else - { - uchar* idxdata; - int idxnum; - int idxstep; - int index; - - idxdata = idx->data.ptr; - idxnum = (idx->rows == 1) ? idx->cols : idx->rows; - idxstep = (idx->rows == 1) ? CV_ELEM_SIZE( idx->type ) : idx->step; - for( i = 0; i < idxnum; i++ ) - { - index = (int) *((float*) (idxdata + i * idxstep)); - if( CV_MAT_ELEM( *trainData, float, index, compidx ) < threshold ) - { - (*left)->data.fl[(*left)->cols++] = (float) index; - } - else - { - (*right)->data.fl[(*right)->cols++] = (float) index; - } - } - } -} - -void CV_CDECL icvDefaultSplitIdx_C( int compidx, float threshold, - CvMat* idx, CvMat** left, CvMat** right, - void* userdata ) -{ - CvMat* trainData = (CvMat*) userdata; - int i = 0; - - *left = cvCreateMat( 1, trainData->cols, CV_32FC1 ); - *right = cvCreateMat( 1, trainData->cols, CV_32FC1 ); - (*left)->cols = (*right)->cols = 0; - if( idx == NULL ) - { - for( i = 0; i < trainData->cols; i++ ) - { - if( CV_MAT_ELEM( *trainData, float, compidx, i ) < threshold ) - { - (*left)->data.fl[(*left)->cols++] = (float) i; - } - else - { - (*right)->data.fl[(*right)->cols++] = (float) i; - } - } - } - else - { - uchar* idxdata; - int idxnum; - int idxstep; - int index; - - idxdata = idx->data.ptr; - idxnum = (idx->rows == 1) ? idx->cols : idx->rows; - idxstep = (idx->rows == 1) ? CV_ELEM_SIZE( idx->type ) : idx->step; - for( i = 0; i < idxnum; i++ ) - { - index = (int) *((float*) (idxdata + i * idxstep)); - if( CV_MAT_ELEM( *trainData, float, compidx, index ) < threshold ) - { - (*left)->data.fl[(*left)->cols++] = (float) index; - } - else - { - (*right)->data.fl[(*right)->cols++] = (float) index; - } - } - } -} - -/* internal structure used in CART creation */ -typedef struct CvCARTNode -{ - CvMat* sampleIdx; - CvStumpClassifier* stump; - int parent; - int leftflag; - float errdrop; -} CvCARTNode; - -CV_BOOST_IMPL -CvClassifier* cvCreateCARTClassifier( CvMat* trainData, - int flags, - CvMat* trainClasses, - CvMat* typeMask, - CvMat* missedMeasurementsMask, - CvMat* compIdx, - CvMat* sampleIdx, - CvMat* weights, - CvClassifierTrainParams* trainParams ) -{ - CvCARTClassifier* cart = NULL; - size_t datasize = 0; - int count = 0; - int i = 0; - int j = 0; - - CvCARTNode* intnode = NULL; - CvCARTNode* list = NULL; - int listcount = 0; - CvMat* lidx = NULL; - CvMat* ridx = NULL; - - float maxerrdrop = 0.0F; - int idx = 0; - - void (*splitIdxCallback)( int compidx, float threshold, - CvMat* idx, CvMat** left, CvMat** right, - void* userdata ); - void* userdata; - - count = ((CvCARTTrainParams*) trainParams)->count; - - assert( count > 0 ); - - datasize = sizeof( *cart ) + (sizeof( float ) + 3 * sizeof( int )) * count + - sizeof( float ) * (count + 1); - - cart = (CvCARTClassifier*) cvAlloc( datasize ); - memset( cart, 0, datasize ); - - cart->count = count; - - cart->eval = cvEvalCARTClassifier; - cart->save = NULL; - cart->release = cvReleaseCARTClassifier; - - cart->compidx = (int*) (cart + 1); - cart->threshold = (float*) (cart->compidx + count); - cart->left = (int*) (cart->threshold + count); - cart->right = (int*) (cart->left + count); - cart->val = (float*) (cart->right + count); - - datasize = sizeof( CvCARTNode ) * (count + count); - intnode = (CvCARTNode*) cvAlloc( datasize ); - memset( intnode, 0, datasize ); - list = (CvCARTNode*) (intnode + count); - - splitIdxCallback = ((CvCARTTrainParams*) trainParams)->splitIdx; - userdata = ((CvCARTTrainParams*) trainParams)->userdata; - if( splitIdxCallback == NULL ) - { - splitIdxCallback = ( CV_IS_ROW_SAMPLE( flags ) ) - ? icvDefaultSplitIdx_R : icvDefaultSplitIdx_C; - userdata = trainData; - } - - /* create root of the tree */ - intnode[0].sampleIdx = sampleIdx; - intnode[0].stump = (CvStumpClassifier*) - ((CvCARTTrainParams*) trainParams)->stumpConstructor( trainData, flags, - trainClasses, typeMask, missedMeasurementsMask, compIdx, sampleIdx, weights, - ((CvCARTTrainParams*) trainParams)->stumpTrainParams ); - cart->left[0] = cart->right[0] = 0; - - /* build tree */ - listcount = 0; - for( i = 1; i < count; i++ ) - { - /* split last added node */ - splitIdxCallback( intnode[i-1].stump->compidx, intnode[i-1].stump->threshold, - intnode[i-1].sampleIdx, &lidx, &ridx, userdata ); - - if( intnode[i-1].stump->lerror != 0.0F ) - { - list[listcount].sampleIdx = lidx; - list[listcount].stump = (CvStumpClassifier*) - ((CvCARTTrainParams*) trainParams)->stumpConstructor( trainData, flags, - trainClasses, typeMask, missedMeasurementsMask, compIdx, - list[listcount].sampleIdx, - weights, ((CvCARTTrainParams*) trainParams)->stumpTrainParams ); - list[listcount].errdrop = intnode[i-1].stump->lerror - - (list[listcount].stump->lerror + list[listcount].stump->rerror); - list[listcount].leftflag = 1; - list[listcount].parent = i-1; - listcount++; - } - else - { - cvReleaseMat( &lidx ); - } - if( intnode[i-1].stump->rerror != 0.0F ) - { - list[listcount].sampleIdx = ridx; - list[listcount].stump = (CvStumpClassifier*) - ((CvCARTTrainParams*) trainParams)->stumpConstructor( trainData, flags, - trainClasses, typeMask, missedMeasurementsMask, compIdx, - list[listcount].sampleIdx, - weights, ((CvCARTTrainParams*) trainParams)->stumpTrainParams ); - list[listcount].errdrop = intnode[i-1].stump->rerror - - (list[listcount].stump->lerror + list[listcount].stump->rerror); - list[listcount].leftflag = 0; - list[listcount].parent = i-1; - listcount++; - } - else - { - cvReleaseMat( &ridx ); - } - - if( listcount == 0 ) break; - - /* find the best node to be added to the tree */ - idx = 0; - maxerrdrop = list[idx].errdrop; - for( j = 1; j < listcount; j++ ) - { - if( list[j].errdrop > maxerrdrop ) - { - idx = j; - maxerrdrop = list[j].errdrop; - } - } - intnode[i] = list[idx]; - if( list[idx].leftflag ) - { - cart->left[list[idx].parent] = i; - } - else - { - cart->right[list[idx].parent] = i; - } - if( idx != (listcount - 1) ) - { - list[idx] = list[listcount - 1]; - } - listcount--; - } - - /* fill fields */ - j = 0; - cart->count = 0; - for( i = 0; i < count && (intnode[i].stump != NULL); i++ ) - { - cart->count++; - cart->compidx[i] = intnode[i].stump->compidx; - cart->threshold[i] = intnode[i].stump->threshold; - - /* leaves */ - if( cart->left[i] <= 0 ) - { - cart->left[i] = -j; - cart->val[j] = intnode[i].stump->left; - j++; - } - if( cart->right[i] <= 0 ) - { - cart->right[i] = -j; - cart->val[j] = intnode[i].stump->right; - j++; - } - } - - /* CLEAN UP */ - for( i = 0; i < count && (intnode[i].stump != NULL); i++ ) - { - intnode[i].stump->release( (CvClassifier**) &(intnode[i].stump) ); - if( i != 0 ) - { - cvReleaseMat( &(intnode[i].sampleIdx) ); - } - } - for( i = 0; i < listcount; i++ ) - { - list[i].stump->release( (CvClassifier**) &(list[i].stump) ); - cvReleaseMat( &(list[i].sampleIdx) ); - } - - cvFree( &intnode ); - - return (CvClassifier*) cart; -} - -/****************************************************************************************\ -* Boosting * -\****************************************************************************************/ - -typedef struct CvBoostTrainer -{ - CvBoostType type; - int count; /* (idx) ? number_of_indices : number_of_samples */ - int* idx; - float* F; -} CvBoostTrainer; - -/* - * cvBoostStartTraining, cvBoostNextWeakClassifier, cvBoostEndTraining - * - * These functions perform training of 2-class boosting classifier - * using ANY appropriate weak classifier - */ - -CV_BOOST_IMPL -CvBoostTrainer* icvBoostStartTraining( CvMat* trainClasses, - CvMat* weakTrainVals, - CvMat* weights, - CvMat* sampleIdx, - CvBoostType type ) -{ - uchar* ydata; - int ystep; - int m; - uchar* traindata; - int trainstep; - int trainnum; - int i; - int idx; - - size_t datasize; - CvBoostTrainer* ptr; - - int idxnum; - int idxstep; - uchar* idxdata; - - assert( trainClasses != NULL ); - assert( CV_MAT_TYPE( trainClasses->type ) == CV_32FC1 ); - assert( weakTrainVals != NULL ); - assert( CV_MAT_TYPE( weakTrainVals->type ) == CV_32FC1 ); - - CV_MAT2VEC( *trainClasses, ydata, ystep, m ); - CV_MAT2VEC( *weakTrainVals, traindata, trainstep, trainnum ); - - assert( m == trainnum ); - - idxnum = 0; - idxstep = 0; - idxdata = NULL; - if( sampleIdx ) - { - CV_MAT2VEC( *sampleIdx, idxdata, idxstep, idxnum ); - } - - datasize = sizeof( *ptr ) + sizeof( *ptr->idx ) * idxnum; - ptr = (CvBoostTrainer*) cvAlloc( datasize ); - memset( ptr, 0, datasize ); - ptr->F = NULL; - ptr->idx = NULL; - - ptr->count = m; - ptr->type = type; - - if( idxnum > 0 ) - { - CvScalar s; - - ptr->idx = (int*) (ptr + 1); - ptr->count = idxnum; - for( i = 0; i < ptr->count; i++ ) - { - cvRawDataToScalar( idxdata + i*idxstep, CV_MAT_TYPE( sampleIdx->type ), &s ); - ptr->idx[i] = (int) s.val[0]; - } - } - for( i = 0; i < ptr->count; i++ ) - { - idx = (ptr->idx) ? ptr->idx[i] : i; - - *((float*) (traindata + idx * trainstep)) = - 2.0F * (*((float*) (ydata + idx * ystep))) - 1.0F; - } - - return ptr; -} - -/* - * - * Discrete AdaBoost functions - * - */ -CV_BOOST_IMPL -float icvBoostNextWeakClassifierDAB( CvMat* weakEvalVals, - CvMat* trainClasses, - CvMat* weakTrainVals, - CvMat* weights, - CvBoostTrainer* trainer ) -{ - uchar* evaldata; - int evalstep; - int m; - uchar* ydata; - int ystep; - int ynum; - uchar* wdata; - int wstep; - int wnum; - - float sumw; - float err; - int i; - int idx; - - assert( weakEvalVals != NULL ); - assert( CV_MAT_TYPE( weakEvalVals->type ) == CV_32FC1 ); - assert( trainClasses != NULL ); - assert( CV_MAT_TYPE( trainClasses->type ) == CV_32FC1 ); - assert( weights != NULL ); - assert( CV_MAT_TYPE( weights ->type ) == CV_32FC1 ); - - CV_MAT2VEC( *weakEvalVals, evaldata, evalstep, m ); - CV_MAT2VEC( *trainClasses, ydata, ystep, ynum ); - CV_MAT2VEC( *weights, wdata, wstep, wnum ); - - assert( m == ynum ); - assert( m == wnum ); - - sumw = 0.0F; - err = 0.0F; - for( i = 0; i < trainer->count; i++ ) - { - idx = (trainer->idx) ? trainer->idx[i] : i; - - sumw += *((float*) (wdata + idx*wstep)); - err += (*((float*) (wdata + idx*wstep))) * - ( (*((float*) (evaldata + idx*evalstep))) != - 2.0F * (*((float*) (ydata + idx*ystep))) - 1.0F ); - } - err /= sumw; - err = -cvLogRatio( err ); - - for( i = 0; i < trainer->count; i++ ) - { - idx = (trainer->idx) ? trainer->idx[i] : i; - - *((float*) (wdata + idx*wstep)) *= expf( err * - ((*((float*) (evaldata + idx*evalstep))) != - 2.0F * (*((float*) (ydata + idx*ystep))) - 1.0F) ); - sumw += *((float*) (wdata + idx*wstep)); - } - for( i = 0; i < trainer->count; i++ ) - { - idx = (trainer->idx) ? trainer->idx[i] : i; - - *((float*) (wdata + idx * wstep)) /= sumw; - } - - return err; -} - -/* - * - * Real AdaBoost functions - * - */ -CV_BOOST_IMPL -float icvBoostNextWeakClassifierRAB( CvMat* weakEvalVals, - CvMat* trainClasses, - CvMat* weakTrainVals, - CvMat* weights, - CvBoostTrainer* trainer ) -{ - uchar* evaldata; - int evalstep; - int m; - uchar* ydata; - int ystep; - int ynum; - uchar* wdata; - int wstep; - int wnum; - - float sumw; - int i, idx; - - assert( weakEvalVals != NULL ); - assert( CV_MAT_TYPE( weakEvalVals->type ) == CV_32FC1 ); - assert( trainClasses != NULL ); - assert( CV_MAT_TYPE( trainClasses->type ) == CV_32FC1 ); - assert( weights != NULL ); - assert( CV_MAT_TYPE( weights ->type ) == CV_32FC1 ); - - CV_MAT2VEC( *weakEvalVals, evaldata, evalstep, m ); - CV_MAT2VEC( *trainClasses, ydata, ystep, ynum ); - CV_MAT2VEC( *weights, wdata, wstep, wnum ); - - assert( m == ynum ); - assert( m == wnum ); - - - sumw = 0.0F; - for( i = 0; i < trainer->count; i++ ) - { - idx = (trainer->idx) ? trainer->idx[i] : i; - - *((float*) (wdata + idx*wstep)) *= expf( (-(*((float*) (ydata + idx*ystep))) + 0.5F) - * cvLogRatio( *((float*) (evaldata + idx*evalstep)) ) ); - sumw += *((float*) (wdata + idx*wstep)); - } - for( i = 0; i < trainer->count; i++ ) - { - idx = (trainer->idx) ? trainer->idx[i] : i; - - *((float*) (wdata + idx*wstep)) /= sumw; - } - - return 1.0F; -} - -/* - * - * LogitBoost functions - * - */ -#define CV_LB_PROB_THRESH 0.01F -#define CV_LB_WEIGHT_THRESHOLD 0.0001F - -CV_BOOST_IMPL -void icvResponsesAndWeightsLB( int num, uchar* wdata, int wstep, - uchar* ydata, int ystep, - uchar* fdata, int fstep, - uchar* traindata, int trainstep, - int* indices ) -{ - int i, idx; - float p; - - for( i = 0; i < num; i++ ) - { - idx = (indices) ? indices[i] : i; - - p = 1.0F / (1.0F + expf( -(*((float*) (fdata + idx*fstep)))) ); - *((float*) (wdata + idx*wstep)) = MAX( p * (1.0F - p), CV_LB_WEIGHT_THRESHOLD ); - if( *((float*) (ydata + idx*ystep)) == 1.0F ) - { - *((float*) (traindata + idx*trainstep)) = - 1.0F / (MAX( p, CV_LB_PROB_THRESH )); - } - else - { - *((float*) (traindata + idx*trainstep)) = - -1.0F / (MAX( 1.0F - p, CV_LB_PROB_THRESH )); - } - } -} - -CV_BOOST_IMPL -CvBoostTrainer* icvBoostStartTrainingLB( CvMat* trainClasses, - CvMat* weakTrainVals, - CvMat* weights, - CvMat* sampleIdx, - CvBoostType type ) -{ - size_t datasize; - CvBoostTrainer* ptr; - - uchar* ydata; - int ystep; - int m; - uchar* traindata; - int trainstep; - int trainnum; - uchar* wdata; - int wstep; - int wnum; - int i; - - int idxnum; - int idxstep; - uchar* idxdata; - - assert( trainClasses != NULL ); - assert( CV_MAT_TYPE( trainClasses->type ) == CV_32FC1 ); - assert( weakTrainVals != NULL ); - assert( CV_MAT_TYPE( weakTrainVals->type ) == CV_32FC1 ); - assert( weights != NULL ); - assert( CV_MAT_TYPE( weights->type ) == CV_32FC1 ); - - CV_MAT2VEC( *trainClasses, ydata, ystep, m ); - CV_MAT2VEC( *weakTrainVals, traindata, trainstep, trainnum ); - CV_MAT2VEC( *weights, wdata, wstep, wnum ); - - assert( m == trainnum ); - assert( m == wnum ); - - - idxnum = 0; - idxstep = 0; - idxdata = NULL; - if( sampleIdx ) - { - CV_MAT2VEC( *sampleIdx, idxdata, idxstep, idxnum ); - } - - datasize = sizeof( *ptr ) + sizeof( *ptr->F ) * m + sizeof( *ptr->idx ) * idxnum; - ptr = (CvBoostTrainer*) cvAlloc( datasize ); - memset( ptr, 0, datasize ); - ptr->F = (float*) (ptr + 1); - ptr->idx = NULL; - - ptr->count = m; - ptr->type = type; - - if( idxnum > 0 ) - { - CvScalar s; - - ptr->idx = (int*) (ptr->F + m); - ptr->count = idxnum; - for( i = 0; i < ptr->count; i++ ) - { - cvRawDataToScalar( idxdata + i*idxstep, CV_MAT_TYPE( sampleIdx->type ), &s ); - ptr->idx[i] = (int) s.val[0]; - } - } - - for( i = 0; i < m; i++ ) - { - ptr->F[i] = 0.0F; - } - - icvResponsesAndWeightsLB( ptr->count, wdata, wstep, ydata, ystep, - (uchar*) ptr->F, sizeof( *ptr->F ), - traindata, trainstep, ptr->idx ); - - return ptr; -} - -CV_BOOST_IMPL -float icvBoostNextWeakClassifierLB( CvMat* weakEvalVals, - CvMat* trainClasses, - CvMat* weakTrainVals, - CvMat* weights, - CvBoostTrainer* trainer ) -{ - uchar* evaldata; - int evalstep; - int m; - uchar* ydata; - int ystep; - int ynum; - uchar* traindata; - int trainstep; - int trainnum; - uchar* wdata; - int wstep; - int wnum; - int i, idx; - - assert( weakEvalVals != NULL ); - assert( CV_MAT_TYPE( weakEvalVals->type ) == CV_32FC1 ); - assert( trainClasses != NULL ); - assert( CV_MAT_TYPE( trainClasses->type ) == CV_32FC1 ); - assert( weakTrainVals != NULL ); - assert( CV_MAT_TYPE( weakTrainVals->type ) == CV_32FC1 ); - assert( weights != NULL ); - assert( CV_MAT_TYPE( weights ->type ) == CV_32FC1 ); - - CV_MAT2VEC( *weakEvalVals, evaldata, evalstep, m ); - CV_MAT2VEC( *trainClasses, ydata, ystep, ynum ); - CV_MAT2VEC( *weakTrainVals, traindata, trainstep, trainnum ); - CV_MAT2VEC( *weights, wdata, wstep, wnum ); - - assert( m == ynum ); - assert( m == wnum ); - assert( m == trainnum ); - //assert( m == trainer->count ); - - for( i = 0; i < trainer->count; i++ ) - { - idx = (trainer->idx) ? trainer->idx[i] : i; - - trainer->F[idx] += *((float*) (evaldata + idx * evalstep)); - } - - icvResponsesAndWeightsLB( trainer->count, wdata, wstep, ydata, ystep, - (uchar*) trainer->F, sizeof( *trainer->F ), - traindata, trainstep, trainer->idx ); - - return 1.0F; -} - -/* - * - * Gentle AdaBoost - * - */ -CV_BOOST_IMPL -float icvBoostNextWeakClassifierGAB( CvMat* weakEvalVals, - CvMat* trainClasses, - CvMat* weakTrainVals, - CvMat* weights, - CvBoostTrainer* trainer ) -{ - uchar* evaldata; - int evalstep; - int m; - uchar* ydata; - int ystep; - int ynum; - uchar* wdata; - int wstep; - int wnum; - - int i, idx; - float sumw; - - assert( weakEvalVals != NULL ); - assert( CV_MAT_TYPE( weakEvalVals->type ) == CV_32FC1 ); - assert( trainClasses != NULL ); - assert( CV_MAT_TYPE( trainClasses->type ) == CV_32FC1 ); - assert( weights != NULL ); - assert( CV_MAT_TYPE( weights->type ) == CV_32FC1 ); - - CV_MAT2VEC( *weakEvalVals, evaldata, evalstep, m ); - CV_MAT2VEC( *trainClasses, ydata, ystep, ynum ); - CV_MAT2VEC( *weights, wdata, wstep, wnum ); - - assert( m == ynum ); - assert( m == wnum ); - - sumw = 0.0F; - for( i = 0; i < trainer->count; i++ ) - { - idx = (trainer->idx) ? trainer->idx[i] : i; - - *((float*) (wdata + idx*wstep)) *= - expf( -(*((float*) (evaldata + idx*evalstep))) - * ( 2.0F * (*((float*) (ydata + idx*ystep))) - 1.0F ) ); - sumw += *((float*) (wdata + idx*wstep)); - } - - for( i = 0; i < trainer->count; i++ ) - { - idx = (trainer->idx) ? trainer->idx[i] : i; - - *((float*) (wdata + idx*wstep)) /= sumw; - } - - return 1.0F; -} - -typedef CvBoostTrainer* (*CvBoostStartTraining)( CvMat* trainClasses, - CvMat* weakTrainVals, - CvMat* weights, - CvMat* sampleIdx, - CvBoostType type ); - -typedef float (*CvBoostNextWeakClassifier)( CvMat* weakEvalVals, - CvMat* trainClasses, - CvMat* weakTrainVals, - CvMat* weights, - CvBoostTrainer* data ); - -CvBoostStartTraining startTraining[4] = { - icvBoostStartTraining, - icvBoostStartTraining, - icvBoostStartTrainingLB, - icvBoostStartTraining - }; - -CvBoostNextWeakClassifier nextWeakClassifier[4] = { - icvBoostNextWeakClassifierDAB, - icvBoostNextWeakClassifierRAB, - icvBoostNextWeakClassifierLB, - icvBoostNextWeakClassifierGAB - }; - -/* - * - * Dispatchers - * - */ -CV_BOOST_IMPL -CvBoostTrainer* cvBoostStartTraining( CvMat* trainClasses, - CvMat* weakTrainVals, - CvMat* weights, - CvMat* sampleIdx, - CvBoostType type ) -{ - return startTraining[type]( trainClasses, weakTrainVals, weights, sampleIdx, type ); -} - -CV_BOOST_IMPL -void cvBoostEndTraining( CvBoostTrainer** trainer ) -{ - cvFree( trainer ); - *trainer = NULL; -} - -CV_BOOST_IMPL -float cvBoostNextWeakClassifier( CvMat* weakEvalVals, - CvMat* trainClasses, - CvMat* weakTrainVals, - CvMat* weights, - CvBoostTrainer* trainer ) -{ - return nextWeakClassifier[trainer->type]( weakEvalVals, trainClasses, - weakTrainVals, weights, trainer ); -} - -/****************************************************************************************\ -* Boosted tree models * -\****************************************************************************************/ - -typedef struct CvBtTrainer -{ - /* {{ external */ - CvMat* trainData; - int flags; - - CvMat* trainClasses; - int m; - uchar* ydata; - int ystep; - - CvMat* sampleIdx; - int numsamples; - - float param[2]; - CvBoostType type; - int numclasses; - /* }} external */ - - CvMTStumpTrainParams stumpParams; - CvCARTTrainParams cartParams; - - float* f; /* F_(m-1) */ - CvMat* y; /* yhat */ - CvMat* weights; - CvBoostTrainer* boosttrainer; -} CvBtTrainer; - -/* - * cvBtStart, cvBtNext, cvBtEnd - * - * These functions perform iterative training of - * 2-class (CV_DABCLASS - CV_GABCLASS, CV_L2CLASS), K-class (CV_LKCLASS) classifier - * or fit regression model (CV_LSREG, CV_LADREG, CV_MREG) - * using decision tree as a weak classifier. - */ - -typedef void (*CvZeroApproxFunc)( float* approx, CvBtTrainer* trainer ); - -/* Mean zero approximation */ -void icvZeroApproxMean( float* approx, CvBtTrainer* trainer ) -{ - int i; - int idx; - - approx[0] = 0.0F; - for( i = 0; i < trainer->numsamples; i++ ) - { - idx = icvGetIdxAt( trainer->sampleIdx, i ); - approx[0] += *((float*) (trainer->ydata + idx * trainer->ystep)); - } - approx[0] /= (float) trainer->numsamples; -} - -/* - * Median zero approximation - */ -void icvZeroApproxMed( float* approx, CvBtTrainer* trainer ) -{ - int i; - int idx; - - for( i = 0; i < trainer->numsamples; i++ ) - { - idx = icvGetIdxAt( trainer->sampleIdx, i ); - trainer->f[i] = *((float*) (trainer->ydata + idx * trainer->ystep)); - } - - icvSort_32f( trainer->f, trainer->numsamples, 0 ); - approx[0] = trainer->f[trainer->numsamples / 2]; -} - -/* - * 0.5 * log( mean(y) / (1 - mean(y)) ) where y in {0, 1} - */ -void icvZeroApproxLog( float* approx, CvBtTrainer* trainer ) -{ - float y_mean; - - icvZeroApproxMean( &y_mean, trainer ); - approx[0] = 0.5F * cvLogRatio( y_mean ); -} - -/* - * 0 zero approximation - */ -void icvZeroApprox0( float* approx, CvBtTrainer* trainer ) -{ - int i; - - for( i = 0; i < trainer->numclasses; i++ ) - { - approx[i] = 0.0F; - } -} - -static CvZeroApproxFunc icvZeroApproxFunc[] = -{ - icvZeroApprox0, /* CV_DABCLASS */ - icvZeroApprox0, /* CV_RABCLASS */ - icvZeroApprox0, /* CV_LBCLASS */ - icvZeroApprox0, /* CV_GABCLASS */ - icvZeroApproxLog, /* CV_L2CLASS */ - icvZeroApprox0, /* CV_LKCLASS */ - icvZeroApproxMean, /* CV_LSREG */ - icvZeroApproxMed, /* CV_LADREG */ - icvZeroApproxMed, /* CV_MREG */ -}; - -CV_BOOST_IMPL -void cvBtNext( CvCARTClassifier** trees, CvBtTrainer* trainer ); - -CV_BOOST_IMPL -CvBtTrainer* cvBtStart( CvCARTClassifier** trees, - CvMat* trainData, - int flags, - CvMat* trainClasses, - CvMat* sampleIdx, - int numsplits, - CvBoostType type, - int numclasses, - float* param ) -{ - CvBtTrainer* ptr; - - CV_FUNCNAME( "cvBtStart" ); - - __BEGIN__; - - size_t data_size; - float* zero_approx; - int m; - int i, j; - - if( trees == NULL ) - { - CV_ERROR( CV_StsNullPtr, "Invalid trees parameter" ); - } - - if( type < CV_DABCLASS || type > CV_MREG ) - { - CV_ERROR( CV_StsUnsupportedFormat, "Unsupported type parameter" ); - } - if( type == CV_LKCLASS ) - { - CV_ASSERT( numclasses >= 2 ); - } - else - { - numclasses = 1; - } - - m = MAX( trainClasses->rows, trainClasses->cols ); - ptr = NULL; - data_size = sizeof( *ptr ); - if( type > CV_GABCLASS ) - { - data_size += m * numclasses * sizeof( *(ptr->f) ); - } - CV_CALL( ptr = (CvBtTrainer*) cvAlloc( data_size ) ); - memset( ptr, 0, data_size ); - ptr->f = (float*) (ptr + 1); - - ptr->trainData = trainData; - ptr->flags = flags; - ptr->trainClasses = trainClasses; - CV_MAT2VEC( *trainClasses, ptr->ydata, ptr->ystep, ptr->m ); - - memset( &(ptr->cartParams), 0, sizeof( ptr->cartParams ) ); - memset( &(ptr->stumpParams), 0, sizeof( ptr->stumpParams ) ); - - switch( type ) - { - case CV_DABCLASS: - ptr->stumpParams.error = CV_MISCLASSIFICATION; - ptr->stumpParams.type = CV_CLASSIFICATION_CLASS; - break; - case CV_RABCLASS: - ptr->stumpParams.error = CV_GINI; - ptr->stumpParams.type = CV_CLASSIFICATION; - break; - default: - ptr->stumpParams.error = CV_SQUARE; - ptr->stumpParams.type = CV_REGRESSION; - } - ptr->cartParams.count = numsplits; - ptr->cartParams.stumpTrainParams = (CvClassifierTrainParams*) &(ptr->stumpParams); - ptr->cartParams.stumpConstructor = cvCreateMTStumpClassifier; - - ptr->param[0] = param[0]; - ptr->param[1] = param[1]; - ptr->type = type; - ptr->numclasses = numclasses; - - CV_CALL( ptr->y = cvCreateMat( 1, m, CV_32FC1 ) ); - ptr->sampleIdx = sampleIdx; - ptr->numsamples = ( sampleIdx == NULL ) ? ptr->m - : MAX( sampleIdx->rows, sampleIdx->cols ); - - ptr->weights = cvCreateMat( 1, m, CV_32FC1 ); - cvSet( ptr->weights, cvScalar( 1.0 ) ); - - if( type <= CV_GABCLASS ) - { - ptr->boosttrainer = cvBoostStartTraining( ptr->trainClasses, ptr->y, - ptr->weights, NULL, type ); - - CV_CALL( cvBtNext( trees, ptr ) ); - } - else - { - data_size = sizeof( *zero_approx ) * numclasses; - CV_CALL( zero_approx = (float*) cvAlloc( data_size ) ); - icvZeroApproxFunc[type]( zero_approx, ptr ); - for( i = 0; i < m; i++ ) - { - for( j = 0; j < numclasses; j++ ) - { - ptr->f[i * numclasses + j] = zero_approx[j]; - } - } - - CV_CALL( cvBtNext( trees, ptr ) ); - - for( i = 0; i < numclasses; i++ ) - { - for( j = 0; j <= trees[i]->count; j++ ) - { - trees[i]->val[j] += zero_approx[i]; - } - } - CV_CALL( cvFree( &zero_approx ) ); - } - - __END__; - - return ptr; -} - -void icvBtNext_LSREG( CvCARTClassifier** trees, CvBtTrainer* trainer ) -{ - int i; - - /* yhat_i = y_i - F_(m-1)(x_i) */ - for( i = 0; i < trainer->m; i++ ) - { - trainer->y->data.fl[i] = - *((float*) (trainer->ydata + i * trainer->ystep)) - trainer->f[i]; - } - - trees[0] = (CvCARTClassifier*) cvCreateCARTClassifier( trainer->trainData, - trainer->flags, - trainer->y, NULL, NULL, NULL, trainer->sampleIdx, trainer->weights, - (CvClassifierTrainParams*) &trainer->cartParams ); -} - - -void icvBtNext_LADREG( CvCARTClassifier** trees, CvBtTrainer* trainer ) -{ - CvCARTClassifier* ptr; - int i, j; - CvMat sample; - int sample_step; - uchar* sample_data; - int index; - - int data_size; - int* idx; - float* resp; - int respnum; - float val; - - data_size = trainer->m * sizeof( *idx ); - idx = (int*) cvAlloc( data_size ); - data_size = trainer->m * sizeof( *resp ); - resp = (float*) cvAlloc( data_size ); - - /* yhat_i = sign(y_i - F_(m-1)(x_i)) */ - for( i = 0; i < trainer->numsamples; i++ ) - { - index = icvGetIdxAt( trainer->sampleIdx, i ); - trainer->y->data.fl[index] = (float) - CV_SIGN( *((float*) (trainer->ydata + index * trainer->ystep)) - - trainer->f[index] ); - } - - ptr = (CvCARTClassifier*) cvCreateCARTClassifier( trainer->trainData, trainer->flags, - trainer->y, NULL, NULL, NULL, trainer->sampleIdx, trainer->weights, - (CvClassifierTrainParams*) &trainer->cartParams ); - - CV_GET_SAMPLE( *trainer->trainData, trainer->flags, 0, sample ); - CV_GET_SAMPLE_STEP( *trainer->trainData, trainer->flags, sample_step ); - sample_data = sample.data.ptr; - for( i = 0; i < trainer->numsamples; i++ ) - { - index = icvGetIdxAt( trainer->sampleIdx, i ); - sample.data.ptr = sample_data + index * sample_step; - idx[index] = (int) cvEvalCARTClassifierIdx( (CvClassifier*) ptr, &sample ); - } - for( j = 0; j <= ptr->count; j++ ) - { - respnum = 0; - for( i = 0; i < trainer->numsamples; i++ ) - { - index = icvGetIdxAt( trainer->sampleIdx, i ); - if( idx[index] == j ) - { - resp[respnum++] = *((float*) (trainer->ydata + index * trainer->ystep)) - - trainer->f[index]; - } - } - if( respnum > 0 ) - { - icvSort_32f( resp, respnum, 0 ); - val = resp[respnum / 2]; - } - else - { - val = 0.0F; - } - ptr->val[j] = val; - } - - cvFree( &idx ); - cvFree( &resp ); - - trees[0] = ptr; -} - - -void icvBtNext_MREG( CvCARTClassifier** trees, CvBtTrainer* trainer ) -{ - CvCARTClassifier* ptr; - int i, j; - CvMat sample; - int sample_step; - uchar* sample_data; - - int data_size; - int* idx; - float* resid; - float* resp; - int respnum; - float rhat; - float val; - float delta; - int index; - - data_size = trainer->m * sizeof( *idx ); - idx = (int*) cvAlloc( data_size ); - data_size = trainer->m * sizeof( *resp ); - resp = (float*) cvAlloc( data_size ); - data_size = trainer->m * sizeof( *resid ); - resid = (float*) cvAlloc( data_size ); - - /* resid_i = (y_i - F_(m-1)(x_i)) */ - for( i = 0; i < trainer->numsamples; i++ ) - { - index = icvGetIdxAt( trainer->sampleIdx, i ); - resid[index] = *((float*) (trainer->ydata + index * trainer->ystep)) - - trainer->f[index]; - /* for delta */ - resp[i] = (float) fabs( resid[index] ); - } - - /* delta = quantile_alpha{abs(resid_i)} */ - icvSort_32f( resp, trainer->numsamples, 0 ); - delta = resp[(int)(trainer->param[1] * (trainer->numsamples - 1))]; - - /* yhat_i */ - for( i = 0; i < trainer->numsamples; i++ ) - { - index = icvGetIdxAt( trainer->sampleIdx, i ); - trainer->y->data.fl[index] = MIN( delta, ((float) fabs( resid[index] )) ) * - CV_SIGN( resid[index] ); - } - - ptr = (CvCARTClassifier*) cvCreateCARTClassifier( trainer->trainData, trainer->flags, - trainer->y, NULL, NULL, NULL, trainer->sampleIdx, trainer->weights, - (CvClassifierTrainParams*) &trainer->cartParams ); - - CV_GET_SAMPLE( *trainer->trainData, trainer->flags, 0, sample ); - CV_GET_SAMPLE_STEP( *trainer->trainData, trainer->flags, sample_step ); - sample_data = sample.data.ptr; - for( i = 0; i < trainer->numsamples; i++ ) - { - index = icvGetIdxAt( trainer->sampleIdx, i ); - sample.data.ptr = sample_data + index * sample_step; - idx[index] = (int) cvEvalCARTClassifierIdx( (CvClassifier*) ptr, &sample ); - } - for( j = 0; j <= ptr->count; j++ ) - { - respnum = 0; - - for( i = 0; i < trainer->numsamples; i++ ) - { - index = icvGetIdxAt( trainer->sampleIdx, i ); - if( idx[index] == j ) - { - resp[respnum++] = *((float*) (trainer->ydata + index * trainer->ystep)) - - trainer->f[index]; - } - } - if( respnum > 0 ) - { - /* rhat = median(y_i - F_(m-1)(x_i)) */ - icvSort_32f( resp, respnum, 0 ); - rhat = resp[respnum / 2]; - - /* val = sum{sign(r_i - rhat_i) * min(delta, abs(r_i - rhat_i)} - * r_i = y_i - F_(m-1)(x_i) - */ - val = 0.0F; - for( i = 0; i < respnum; i++ ) - { - val += CV_SIGN( resp[i] - rhat ) - * MIN( delta, (float) fabs( resp[i] - rhat ) ); - } - - val = rhat + val / (float) respnum; - } - else - { - val = 0.0F; - } - - ptr->val[j] = val; - - } - - cvFree( &resid ); - cvFree( &resp ); - cvFree( &idx ); - - trees[0] = ptr; -} - -//#define CV_VAL_MAX 1e304 - -//#define CV_LOG_VAL_MAX 700.0 - -#define CV_VAL_MAX 1e+8 - -#define CV_LOG_VAL_MAX 18.0 - -void icvBtNext_L2CLASS( CvCARTClassifier** trees, CvBtTrainer* trainer ) -{ - CvCARTClassifier* ptr; - int i, j; - CvMat sample; - int sample_step; - uchar* sample_data; - - int data_size; - int* idx; - int respnum; - float val; - double val_f; - - float sum_weights; - float* weights; - float* sorted_weights; - CvMat* trimmed_idx; - CvMat* sample_idx; - int index; - int trimmed_num; - - data_size = trainer->m * sizeof( *idx ); - idx = (int*) cvAlloc( data_size ); - - data_size = trainer->m * sizeof( *weights ); - weights = (float*) cvAlloc( data_size ); - data_size = trainer->m * sizeof( *sorted_weights ); - sorted_weights = (float*) cvAlloc( data_size ); - - /* yhat_i = (4 * y_i - 2) / ( 1 + exp( (4 * y_i - 2) * F_(m-1)(x_i) ) ). - * y_i in {0, 1} - */ - sum_weights = 0.0F; - for( i = 0; i < trainer->numsamples; i++ ) - { - index = icvGetIdxAt( trainer->sampleIdx, i ); - val = 4.0F * (*((float*) (trainer->ydata + index * trainer->ystep))) - 2.0F; - val_f = val * trainer->f[index]; - val_f = ( val_f < CV_LOG_VAL_MAX ) ? exp( val_f ) : CV_LOG_VAL_MAX; - val = (float) ( (double) val / ( 1.0 + val_f ) ); - trainer->y->data.fl[index] = val; - val = (float) fabs( val ); - weights[index] = val * (2.0F - val); - sorted_weights[i] = weights[index]; - sum_weights += sorted_weights[i]; - } - - trimmed_idx = NULL; - sample_idx = trainer->sampleIdx; - trimmed_num = trainer->numsamples; - if( trainer->param[1] < 1.0F ) - { - /* perform weight trimming */ - - float threshold; - int count; - - icvSort_32f( sorted_weights, trainer->numsamples, 0 ); - - sum_weights *= (1.0F - trainer->param[1]); - - i = -1; - do { sum_weights -= sorted_weights[++i]; } - while( sum_weights > 0.0F && i < (trainer->numsamples - 1) ); - - threshold = sorted_weights[i]; - - while( i > 0 && sorted_weights[i-1] == threshold ) i--; - - if( i > 0 ) - { - trimmed_num = trainer->numsamples - i; - trimmed_idx = cvCreateMat( 1, trimmed_num, CV_32FC1 ); - count = 0; - for( i = 0; i < trainer->numsamples; i++ ) - { - index = icvGetIdxAt( trainer->sampleIdx, i ); - if( weights[index] >= threshold ) - { - CV_MAT_ELEM( *trimmed_idx, float, 0, count ) = (float) index; - count++; - } - } - - assert( count == trimmed_num ); - - sample_idx = trimmed_idx; - - printf( "Used samples %%: %g\n", - (float) trimmed_num / (float) trainer->numsamples * 100.0F ); - } - } - - ptr = (CvCARTClassifier*) cvCreateCARTClassifier( trainer->trainData, trainer->flags, - trainer->y, NULL, NULL, NULL, sample_idx, trainer->weights, - (CvClassifierTrainParams*) &trainer->cartParams ); - - CV_GET_SAMPLE( *trainer->trainData, trainer->flags, 0, sample ); - CV_GET_SAMPLE_STEP( *trainer->trainData, trainer->flags, sample_step ); - sample_data = sample.data.ptr; - for( i = 0; i < trimmed_num; i++ ) - { - index = icvGetIdxAt( sample_idx, i ); - sample.data.ptr = sample_data + index * sample_step; - idx[index] = (int) cvEvalCARTClassifierIdx( (CvClassifier*) ptr, &sample ); - } - for( j = 0; j <= ptr->count; j++ ) - { - respnum = 0; - val = 0.0F; - sum_weights = 0.0F; - for( i = 0; i < trimmed_num; i++ ) - { - index = icvGetIdxAt( sample_idx, i ); - if( idx[index] == j ) - { - val += trainer->y->data.fl[index]; - sum_weights += weights[index]; - respnum++; - } - } - if( sum_weights > 0.0F ) - { - val /= sum_weights; - } - else - { - val = 0.0F; - } - ptr->val[j] = val; - } - - if( trimmed_idx != NULL ) cvReleaseMat( &trimmed_idx ); - cvFree( &sorted_weights ); - cvFree( &weights ); - cvFree( &idx ); - - trees[0] = ptr; -} - -void icvBtNext_LKCLASS( CvCARTClassifier** trees, CvBtTrainer* trainer ) -{ - int i, j, k, kk, num; - CvMat sample; - int sample_step; - uchar* sample_data; - - int data_size; - int* idx; - int respnum; - float val; - - float sum_weights; - float* weights; - float* sorted_weights; - CvMat* trimmed_idx; - CvMat* sample_idx; - int index; - int trimmed_num; - double sum_exp_f; - double exp_f; - double f_k; - - data_size = trainer->m * sizeof( *idx ); - idx = (int*) cvAlloc( data_size ); - data_size = trainer->m * sizeof( *weights ); - weights = (float*) cvAlloc( data_size ); - data_size = trainer->m * sizeof( *sorted_weights ); - sorted_weights = (float*) cvAlloc( data_size ); - trimmed_idx = cvCreateMat( 1, trainer->numsamples, CV_32FC1 ); - - for( k = 0; k < trainer->numclasses; k++ ) - { - /* yhat_i = y_i - p_k(x_i), y_i in {0, 1} */ - /* p_k(x_i) = exp(f_k(x_i)) / (sum_exp_f(x_i)) */ - sum_weights = 0.0F; - for( i = 0; i < trainer->numsamples; i++ ) - { - index = icvGetIdxAt( trainer->sampleIdx, i ); - /* p_k(x_i) = 1 / (1 + sum(exp(f_kk(x_i) - f_k(x_i)))), kk != k */ - num = index * trainer->numclasses; - f_k = (double) trainer->f[num + k]; - sum_exp_f = 1.0; - for( kk = 0; kk < trainer->numclasses; kk++ ) - { - if( kk == k ) continue; - exp_f = (double) trainer->f[num + kk] - f_k; - exp_f = (exp_f < CV_LOG_VAL_MAX) ? exp( exp_f ) : CV_VAL_MAX; - if( exp_f == CV_VAL_MAX || exp_f >= (CV_VAL_MAX - sum_exp_f) ) - { - sum_exp_f = CV_VAL_MAX; - break; - } - sum_exp_f += exp_f; - } - - val = (float) ( (*((float*) (trainer->ydata + index * trainer->ystep))) - == (float) k ); - val -= (float) ( (sum_exp_f == CV_VAL_MAX) ? 0.0 : ( 1.0 / sum_exp_f ) ); - - assert( val >= -1.0F ); - assert( val <= 1.0F ); - - trainer->y->data.fl[index] = val; - val = (float) fabs( val ); - weights[index] = val * (1.0F - val); - sorted_weights[i] = weights[index]; - sum_weights += sorted_weights[i]; - } - - sample_idx = trainer->sampleIdx; - trimmed_num = trainer->numsamples; - if( trainer->param[1] < 1.0F ) - { - /* perform weight trimming */ - - float threshold; - int count; - - icvSort_32f( sorted_weights, trainer->numsamples, 0 ); - - sum_weights *= (1.0F - trainer->param[1]); - - i = -1; - do { sum_weights -= sorted_weights[++i]; } - while( sum_weights > 0.0F && i < (trainer->numsamples - 1) ); - - threshold = sorted_weights[i]; - - while( i > 0 && sorted_weights[i-1] == threshold ) i--; - - if( i > 0 ) - { - trimmed_num = trainer->numsamples - i; - trimmed_idx->cols = trimmed_num; - count = 0; - for( i = 0; i < trainer->numsamples; i++ ) - { - index = icvGetIdxAt( trainer->sampleIdx, i ); - if( weights[index] >= threshold ) - { - CV_MAT_ELEM( *trimmed_idx, float, 0, count ) = (float) index; - count++; - } - } - - assert( count == trimmed_num ); - - sample_idx = trimmed_idx; - - printf( "k: %d Used samples %%: %g\n", k, - (float) trimmed_num / (float) trainer->numsamples * 100.0F ); - } - } /* weight trimming */ - - trees[k] = (CvCARTClassifier*) cvCreateCARTClassifier( trainer->trainData, - trainer->flags, trainer->y, NULL, NULL, NULL, sample_idx, trainer->weights, - (CvClassifierTrainParams*) &trainer->cartParams ); - - CV_GET_SAMPLE( *trainer->trainData, trainer->flags, 0, sample ); - CV_GET_SAMPLE_STEP( *trainer->trainData, trainer->flags, sample_step ); - sample_data = sample.data.ptr; - for( i = 0; i < trimmed_num; i++ ) - { - index = icvGetIdxAt( sample_idx, i ); - sample.data.ptr = sample_data + index * sample_step; - idx[index] = (int) cvEvalCARTClassifierIdx( (CvClassifier*) trees[k], - &sample ); - } - for( j = 0; j <= trees[k]->count; j++ ) - { - respnum = 0; - val = 0.0F; - sum_weights = 0.0F; - for( i = 0; i < trimmed_num; i++ ) - { - index = icvGetIdxAt( sample_idx, i ); - if( idx[index] == j ) - { - val += trainer->y->data.fl[index]; - sum_weights += weights[index]; - respnum++; - } - } - if( sum_weights > 0.0F ) - { - val = ((float) (trainer->numclasses - 1)) * val / - ((float) (trainer->numclasses)) / sum_weights; - } - else - { - val = 0.0F; - } - trees[k]->val[j] = val; - } - } /* for each class */ - - cvReleaseMat( &trimmed_idx ); - cvFree( &sorted_weights ); - cvFree( &weights ); - cvFree( &idx ); -} - - -void icvBtNext_XXBCLASS( CvCARTClassifier** trees, CvBtTrainer* trainer ) -{ - float alpha; - int i; - CvMat* weak_eval_vals; - CvMat* sample_idx; - int num_samples; - CvMat sample; - uchar* sample_data; - int sample_step; - - weak_eval_vals = cvCreateMat( 1, trainer->m, CV_32FC1 ); - - sample_idx = cvTrimWeights( trainer->weights, trainer->sampleIdx, - trainer->param[1] ); - num_samples = ( sample_idx == NULL ) - ? trainer->m : MAX( sample_idx->rows, sample_idx->cols ); - - printf( "Used samples %%: %g\n", - (float) num_samples / (float) trainer->numsamples * 100.0F ); - - trees[0] = (CvCARTClassifier*) cvCreateCARTClassifier( trainer->trainData, - trainer->flags, trainer->y, NULL, NULL, NULL, - sample_idx, trainer->weights, - (CvClassifierTrainParams*) &trainer->cartParams ); - - /* evaluate samples */ - CV_GET_SAMPLE( *trainer->trainData, trainer->flags, 0, sample ); - CV_GET_SAMPLE_STEP( *trainer->trainData, trainer->flags, sample_step ); - sample_data = sample.data.ptr; - - for( i = 0; i < trainer->m; i++ ) - { - sample.data.ptr = sample_data + i * sample_step; - weak_eval_vals->data.fl[i] = trees[0]->eval( (CvClassifier*) trees[0], &sample ); - } - - alpha = cvBoostNextWeakClassifier( weak_eval_vals, trainer->trainClasses, - trainer->y, trainer->weights, trainer->boosttrainer ); - - /* multiply tree by alpha */ - for( i = 0; i <= trees[0]->count; i++ ) - { - trees[0]->val[i] *= alpha; - } - if( trainer->type == CV_RABCLASS ) - { - for( i = 0; i <= trees[0]->count; i++ ) - { - trees[0]->val[i] = cvLogRatio( trees[0]->val[i] ); - } - } - - if( sample_idx != NULL && sample_idx != trainer->sampleIdx ) - { - cvReleaseMat( &sample_idx ); - } - cvReleaseMat( &weak_eval_vals ); -} - -typedef void (*CvBtNextFunc)( CvCARTClassifier** trees, CvBtTrainer* trainer ); - -static CvBtNextFunc icvBtNextFunc[] = -{ - icvBtNext_XXBCLASS, - icvBtNext_XXBCLASS, - icvBtNext_XXBCLASS, - icvBtNext_XXBCLASS, - icvBtNext_L2CLASS, - icvBtNext_LKCLASS, - icvBtNext_LSREG, - icvBtNext_LADREG, - icvBtNext_MREG -}; - -CV_BOOST_IMPL -void cvBtNext( CvCARTClassifier** trees, CvBtTrainer* trainer ) -{ - - CV_FUNCNAME( "cvBtNext" ); - - __BEGIN__; - - int i, j; - int index; - CvMat sample; - int sample_step; - uchar* sample_data; - - icvBtNextFunc[trainer->type]( trees, trainer ); - - /* shrinkage */ - if( trainer->param[0] != 1.0F ) - { - for( j = 0; j < trainer->numclasses; j++ ) - { - for( i = 0; i <= trees[j]->count; i++ ) - { - trees[j]->val[i] *= trainer->param[0]; - } - } - } - - if( trainer->type > CV_GABCLASS ) - { - /* update F_(m-1) */ - CV_GET_SAMPLE( *(trainer->trainData), trainer->flags, 0, sample ); - CV_GET_SAMPLE_STEP( *(trainer->trainData), trainer->flags, sample_step ); - sample_data = sample.data.ptr; - for( i = 0; i < trainer->numsamples; i++ ) - { - index = icvGetIdxAt( trainer->sampleIdx, i ); - sample.data.ptr = sample_data + index * sample_step; - for( j = 0; j < trainer->numclasses; j++ ) - { - trainer->f[index * trainer->numclasses + j] += - trees[j]->eval( (CvClassifier*) (trees[j]), &sample ); - } - } - } - - __END__; -} - -CV_BOOST_IMPL -void cvBtEnd( CvBtTrainer** trainer ) -{ - CV_FUNCNAME( "cvBtEnd" ); - - __BEGIN__; - - if( trainer == NULL || (*trainer) == NULL ) - { - CV_ERROR( CV_StsNullPtr, "Invalid trainer parameter" ); - } - - if( (*trainer)->y != NULL ) - { - CV_CALL( cvReleaseMat( &((*trainer)->y) ) ); - } - if( (*trainer)->weights != NULL ) - { - CV_CALL( cvReleaseMat( &((*trainer)->weights) ) ); - } - if( (*trainer)->boosttrainer != NULL ) - { - CV_CALL( cvBoostEndTraining( &((*trainer)->boosttrainer) ) ); - } - CV_CALL( cvFree( trainer ) ); - - __END__; -} - -/****************************************************************************************\ -* Boosted tree model as a classifier * -\****************************************************************************************/ - -CV_BOOST_IMPL -float cvEvalBtClassifier( CvClassifier* classifier, CvMat* sample ) -{ - float val; - - CV_FUNCNAME( "cvEvalBtClassifier" ); - - __BEGIN__; - - int i; - - val = 0.0F; - if( CV_IS_TUNABLE( classifier->flags ) ) - { - CvSeqReader reader; - CvCARTClassifier* tree; - - CV_CALL( cvStartReadSeq( ((CvBtClassifier*) classifier)->seq, &reader ) ); - for( i = 0; i < ((CvBtClassifier*) classifier)->numiter; i++ ) - { - CV_READ_SEQ_ELEM( tree, reader ); - val += tree->eval( (CvClassifier*) tree, sample ); - } - } - else - { - CvCARTClassifier** ptree; - - ptree = ((CvBtClassifier*) classifier)->trees; - for( i = 0; i < ((CvBtClassifier*) classifier)->numiter; i++ ) - { - val += (*ptree)->eval( (CvClassifier*) (*ptree), sample ); - ptree++; - } - } - - __END__; - - return val; -} - -CV_BOOST_IMPL -float cvEvalBtClassifier2( CvClassifier* classifier, CvMat* sample ) -{ - float val; - - CV_FUNCNAME( "cvEvalBtClassifier2" ); - - __BEGIN__; - - CV_CALL( val = cvEvalBtClassifier( classifier, sample ) ); - - __END__; - - return (float) (val >= 0.0F); -} - -CV_BOOST_IMPL -float cvEvalBtClassifierK( CvClassifier* classifier, CvMat* sample ) -{ - int cls; - - CV_FUNCNAME( "cvEvalBtClassifierK" ); - - __BEGIN__; - - int i, k; - float max_val; - int numclasses; - - float* vals; - size_t data_size; - - numclasses = ((CvBtClassifier*) classifier)->numclasses; - data_size = sizeof( *vals ) * numclasses; - CV_CALL( vals = (float*) cvAlloc( data_size ) ); - memset( vals, 0, data_size ); - - if( CV_IS_TUNABLE( classifier->flags ) ) - { - CvSeqReader reader; - CvCARTClassifier* tree; - - CV_CALL( cvStartReadSeq( ((CvBtClassifier*) classifier)->seq, &reader ) ); - for( i = 0; i < ((CvBtClassifier*) classifier)->numiter; i++ ) - { - for( k = 0; k < numclasses; k++ ) - { - CV_READ_SEQ_ELEM( tree, reader ); - vals[k] += tree->eval( (CvClassifier*) tree, sample ); - } - } - - } - else - { - CvCARTClassifier** ptree; - - ptree = ((CvBtClassifier*) classifier)->trees; - for( i = 0; i < ((CvBtClassifier*) classifier)->numiter; i++ ) - { - for( k = 0; k < numclasses; k++ ) - { - vals[k] += (*ptree)->eval( (CvClassifier*) (*ptree), sample ); - ptree++; - } - } - } - - cls = 0; - max_val = vals[cls]; - for( k = 1; k < numclasses; k++ ) - { - if( vals[k] > max_val ) - { - max_val = vals[k]; - cls = k; - } - } - - CV_CALL( cvFree( &vals ) ); - - __END__; - - return (float) cls; -} - -typedef float (*CvEvalBtClassifier)( CvClassifier* classifier, CvMat* sample ); - -static CvEvalBtClassifier icvEvalBtClassifier[] = -{ - cvEvalBtClassifier2, - cvEvalBtClassifier2, - cvEvalBtClassifier2, - cvEvalBtClassifier2, - cvEvalBtClassifier2, - cvEvalBtClassifierK, - cvEvalBtClassifier, - cvEvalBtClassifier, - cvEvalBtClassifier -}; - -CV_BOOST_IMPL -int cvSaveBtClassifier( CvClassifier* classifier, const char* filename ) -{ - CV_FUNCNAME( "cvSaveBtClassifier" ); - - __BEGIN__; - - FILE* file; - int i, j; - CvSeqReader reader; - CvCARTClassifier* tree; - - CV_ASSERT( classifier ); - CV_ASSERT( filename ); - - if( !icvMkDir( filename ) || !(file = fopen( filename, "w" )) ) - { - CV_ERROR( CV_StsError, "Unable to create file" ); - } - - if( CV_IS_TUNABLE( classifier->flags ) ) - { - CV_CALL( cvStartReadSeq( ((CvBtClassifier*) classifier)->seq, &reader ) ); - } - fprintf( file, "%d %d\n%d\n%d\n", (int) ((CvBtClassifier*) classifier)->type, - ((CvBtClassifier*) classifier)->numclasses, - ((CvBtClassifier*) classifier)->numfeatures, - ((CvBtClassifier*) classifier)->numiter ); - - for( i = 0; i < ((CvBtClassifier*) classifier)->numclasses * - ((CvBtClassifier*) classifier)->numiter; i++ ) - { - if( CV_IS_TUNABLE( classifier->flags ) ) - { - CV_READ_SEQ_ELEM( tree, reader ); - } - else - { - tree = ((CvBtClassifier*) classifier)->trees[i]; - } - - fprintf( file, "%d\n", tree->count ); - for( j = 0; j < tree->count; j++ ) - { - fprintf( file, "%d %g %d %d\n", tree->compidx[j], - tree->threshold[j], - tree->left[j], - tree->right[j] ); - } - for( j = 0; j <= tree->count; j++ ) - { - fprintf( file, "%g ", tree->val[j] ); - } - fprintf( file, "\n" ); - } - - fclose( file ); - - __END__; - - return 1; -} - - -CV_BOOST_IMPL -void cvReleaseBtClassifier( CvClassifier** ptr ) -{ - CV_FUNCNAME( "cvReleaseBtClassifier" ); - - __BEGIN__; - - int i; - - if( ptr == NULL || *ptr == NULL ) - { - CV_ERROR( CV_StsNullPtr, "" ); - } - if( CV_IS_TUNABLE( (*ptr)->flags ) ) - { - CvSeqReader reader; - CvCARTClassifier* tree; - - CV_CALL( cvStartReadSeq( ((CvBtClassifier*) *ptr)->seq, &reader ) ); - for( i = 0; i < ((CvBtClassifier*) *ptr)->numclasses * - ((CvBtClassifier*) *ptr)->numiter; i++ ) - { - CV_READ_SEQ_ELEM( tree, reader ); - tree->release( (CvClassifier**) (&tree) ); - } - CV_CALL( cvReleaseMemStorage( &(((CvBtClassifier*) *ptr)->seq->storage) ) ); - } - else - { - CvCARTClassifier** ptree; - - ptree = ((CvBtClassifier*) *ptr)->trees; - for( i = 0; i < ((CvBtClassifier*) *ptr)->numclasses * - ((CvBtClassifier*) *ptr)->numiter; i++ ) - { - (*ptree)->release( (CvClassifier**) ptree ); - ptree++; - } - } - - CV_CALL( cvFree( ptr ) ); - *ptr = NULL; - - __END__; -} - -void cvTuneBtClassifier( CvClassifier* classifier, CvMat*, int flags, - CvMat*, CvMat* , CvMat*, CvMat*, CvMat* ) -{ - CV_FUNCNAME( "cvTuneBtClassifier" ); - - __BEGIN__; - - size_t data_size; - - if( CV_IS_TUNABLE( flags ) ) - { - if( !CV_IS_TUNABLE( classifier->flags ) ) - { - CV_ERROR( CV_StsUnsupportedFormat, - "Classifier does not support tune function" ); - } - else - { - /* tune classifier */ - CvCARTClassifier** trees; - - printf( "Iteration %d\n", ((CvBtClassifier*) classifier)->numiter + 1 ); - - data_size = sizeof( *trees ) * ((CvBtClassifier*) classifier)->numclasses; - CV_CALL( trees = (CvCARTClassifier**) cvAlloc( data_size ) ); - CV_CALL( cvBtNext( trees, - (CvBtTrainer*) ((CvBtClassifier*) classifier)->trainer ) ); - CV_CALL( cvSeqPushMulti( ((CvBtClassifier*) classifier)->seq, - trees, ((CvBtClassifier*) classifier)->numclasses ) ); - CV_CALL( cvFree( &trees ) ); - ((CvBtClassifier*) classifier)->numiter++; - } - } - else - { - if( CV_IS_TUNABLE( classifier->flags ) ) - { - /* convert */ - void* ptr; - - assert( ((CvBtClassifier*) classifier)->seq->total == - ((CvBtClassifier*) classifier)->numiter * - ((CvBtClassifier*) classifier)->numclasses ); - - data_size = sizeof( ((CvBtClassifier*) classifier)->trees[0] ) * - ((CvBtClassifier*) classifier)->seq->total; - CV_CALL( ptr = cvAlloc( data_size ) ); - CV_CALL( cvCvtSeqToArray( ((CvBtClassifier*) classifier)->seq, ptr ) ); - CV_CALL( cvReleaseMemStorage( - &(((CvBtClassifier*) classifier)->seq->storage) ) ); - ((CvBtClassifier*) classifier)->trees = (CvCARTClassifier**) ptr; - classifier->flags &= ~CV_TUNABLE; - CV_CALL( cvBtEnd( (CvBtTrainer**) - &(((CvBtClassifier*) classifier)->trainer )) ); - ((CvBtClassifier*) classifier)->trainer = NULL; - } - } - - __END__; -} - -CvBtClassifier* icvAllocBtClassifier( CvBoostType type, int flags, int numclasses, - int numiter ) -{ - CvBtClassifier* ptr; - size_t data_size; - - assert( numclasses >= 1 ); - assert( numiter >= 0 ); - assert( ( numclasses == 1 ) || (type == CV_LKCLASS) ); - - data_size = sizeof( *ptr ); - ptr = (CvBtClassifier*) cvAlloc( data_size ); - memset( ptr, 0, data_size ); - - if( CV_IS_TUNABLE( flags ) ) - { - ptr->seq = cvCreateSeq( 0, sizeof( *(ptr->seq) ), sizeof( *(ptr->trees) ), - cvCreateMemStorage() ); - ptr->numiter = 0; - } - else - { - data_size = numclasses * numiter * sizeof( *(ptr->trees) ); - ptr->trees = (CvCARTClassifier**) cvAlloc( data_size ); - memset( ptr->trees, 0, data_size ); - - ptr->numiter = numiter; - } - - ptr->flags = flags; - ptr->numclasses = numclasses; - ptr->type = type; - - ptr->eval = icvEvalBtClassifier[(int) type]; - ptr->tune = cvTuneBtClassifier; - ptr->save = cvSaveBtClassifier; - ptr->release = cvReleaseBtClassifier; - - return ptr; -} - -CV_BOOST_IMPL -CvClassifier* cvCreateBtClassifier( CvMat* trainData, - int flags, - CvMat* trainClasses, - CvMat* typeMask, - CvMat* missedMeasurementsMask, - CvMat* compIdx, - CvMat* sampleIdx, - CvMat* weights, - CvClassifierTrainParams* trainParams ) -{ - CvBtClassifier* ptr; - - CV_FUNCNAME( "cvCreateBtClassifier" ); - - __BEGIN__; - CvBoostType type; - int num_classes; - int num_iter; - int i; - CvCARTClassifier** trees; - size_t data_size; - - CV_ASSERT( trainData != NULL ); - CV_ASSERT( trainClasses != NULL ); - CV_ASSERT( typeMask == NULL ); - CV_ASSERT( missedMeasurementsMask == NULL ); - CV_ASSERT( compIdx == NULL ); - CV_ASSERT( weights == NULL ); - CV_ASSERT( trainParams != NULL ); - - type = ((CvBtClassifierTrainParams*) trainParams)->type; - - if( type >= CV_DABCLASS && type <= CV_GABCLASS && sampleIdx ) - { - CV_ERROR( CV_StsBadArg, "Sample indices are not supported for this type" ); - } - - if( type == CV_LKCLASS ) - { - double min_val; - double max_val; - - cvMinMaxLoc( trainClasses, &min_val, &max_val ); - num_classes = (int) (max_val + 1.0); - - CV_ASSERT( num_classes >= 2 ); - } - else - { - num_classes = 1; - } - num_iter = ((CvBtClassifierTrainParams*) trainParams)->numiter; - - CV_ASSERT( num_iter > 0 ); - - ptr = icvAllocBtClassifier( type, CV_TUNABLE | flags, num_classes, num_iter ); - ptr->numfeatures = (CV_IS_ROW_SAMPLE( flags )) ? trainData->cols : trainData->rows; - - i = 0; - - printf( "Iteration %d\n", 1 ); - - data_size = sizeof( *trees ) * ptr->numclasses; - CV_CALL( trees = (CvCARTClassifier**) cvAlloc( data_size ) ); - - CV_CALL( ptr->trainer = cvBtStart( trees, trainData, flags, trainClasses, sampleIdx, - ((CvBtClassifierTrainParams*) trainParams)->numsplits, type, num_classes, - &(((CvBtClassifierTrainParams*) trainParams)->param[0]) ) ); - - CV_CALL( cvSeqPushMulti( ptr->seq, trees, ptr->numclasses ) ); - CV_CALL( cvFree( &trees ) ); - ptr->numiter++; - - for( i = 1; i < num_iter; i++ ) - { - ptr->tune( (CvClassifier*) ptr, NULL, CV_TUNABLE, NULL, NULL, NULL, NULL, NULL ); - } - if( !CV_IS_TUNABLE( flags ) ) - { - /* convert */ - ptr->tune( (CvClassifier*) ptr, NULL, 0, NULL, NULL, NULL, NULL, NULL ); - } - - __END__; - - return (CvClassifier*) ptr; -} - -CV_BOOST_IMPL -CvClassifier* cvCreateBtClassifierFromFile( const char* filename ) -{ - CvBtClassifier* ptr; - - CV_FUNCNAME( "cvCreateBtClassifierFromFile" ); - - __BEGIN__; - - FILE* file; - int i, j; - int data_size; - int num_classifiers; - int num_features; - int num_classes; - int type; - - CV_ASSERT( filename != NULL ); - - ptr = NULL; - file = fopen( filename, "r" ); - if( !file ) - { - CV_ERROR( CV_StsError, "Unable to open file" ); - } - - fscanf( file, "%d %d %d %d", &type, &num_classes, &num_features, &num_classifiers ); - - CV_ASSERT( type >= (int) CV_DABCLASS && type <= (int) CV_MREG ); - CV_ASSERT( num_features > 0 ); - CV_ASSERT( num_classifiers > 0 ); - - if( (CvBoostType) type != CV_LKCLASS ) - { - num_classes = 1; - } - ptr = icvAllocBtClassifier( (CvBoostType) type, 0, num_classes, num_classifiers ); - ptr->numfeatures = num_features; - - for( i = 0; i < num_classes * num_classifiers; i++ ) - { - int count; - CvCARTClassifier* tree; - - fscanf( file, "%d", &count ); - - data_size = sizeof( *tree ) - + count * ( sizeof( *(tree->compidx) ) + sizeof( *(tree->threshold) ) + - sizeof( *(tree->right) ) + sizeof( *(tree->left) ) ) - + (count + 1) * ( sizeof( *(tree->val) ) ); - CV_CALL( tree = (CvCARTClassifier*) cvAlloc( data_size ) ); - memset( tree, 0, data_size ); - tree->eval = cvEvalCARTClassifier; - tree->tune = NULL; - tree->save = NULL; - tree->release = cvReleaseCARTClassifier; - tree->compidx = (int*) ( tree + 1 ); - tree->threshold = (float*) ( tree->compidx + count ); - tree->left = (int*) ( tree->threshold + count ); - tree->right = (int*) ( tree->left + count ); - tree->val = (float*) ( tree->right + count ); - - tree->count = count; - for( j = 0; j < tree->count; j++ ) - { - fscanf( file, "%d %g %d %d", &(tree->compidx[j]), - &(tree->threshold[j]), - &(tree->left[j]), - &(tree->right[j]) ); - } - for( j = 0; j <= tree->count; j++ ) - { - fscanf( file, "%g", &(tree->val[j]) ); - } - ptr->trees[i] = tree; - } - - fclose( file ); - - __END__; - - return (CvClassifier*) ptr; -} - -/****************************************************************************************\ -* Utility functions * -\****************************************************************************************/ - -CV_BOOST_IMPL -CvMat* cvTrimWeights( CvMat* weights, CvMat* idx, float factor ) -{ - CvMat* ptr; - - CV_FUNCNAME( "cvTrimWeights" ); - __BEGIN__; - int i, index, num; - float sum_weights; - uchar* wdata; - size_t wstep; - int wnum; - float threshold; - int count; - float* sorted_weights; - - CV_ASSERT( CV_MAT_TYPE( weights->type ) == CV_32FC1 ); - - ptr = idx; - sorted_weights = NULL; - - if( factor > 0.0F && factor < 1.0F ) - { - size_t data_size; - - CV_MAT2VEC( *weights, wdata, wstep, wnum ); - num = ( idx == NULL ) ? wnum : MAX( idx->rows, idx->cols ); - - data_size = num * sizeof( *sorted_weights ); - sorted_weights = (float*) cvAlloc( data_size ); - memset( sorted_weights, 0, data_size ); - - sum_weights = 0.0F; - for( i = 0; i < num; i++ ) - { - index = icvGetIdxAt( idx, i ); - sorted_weights[i] = *((float*) (wdata + index * wstep)); - sum_weights += sorted_weights[i]; - } - - icvSort_32f( sorted_weights, num, 0 ); - - sum_weights *= (1.0F - factor); - - i = -1; - do { sum_weights -= sorted_weights[++i]; } - while( sum_weights > 0.0F && i < (num - 1) ); - - threshold = sorted_weights[i]; - - while( i > 0 && sorted_weights[i-1] == threshold ) i--; - - if( i > 0 || ( idx != NULL && CV_MAT_TYPE( idx->type ) != CV_32FC1 ) ) - { - CV_CALL( ptr = cvCreateMat( 1, num - i, CV_32FC1 ) ); - count = 0; - for( i = 0; i < num; i++ ) - { - index = icvGetIdxAt( idx, i ); - if( *((float*) (wdata + index * wstep)) >= threshold ) - { - CV_MAT_ELEM( *ptr, float, 0, count ) = (float) index; - count++; - } - } - - assert( count == ptr->cols ); - } - cvFree( &sorted_weights ); - } - - __END__; - - return ptr; -} - - -CV_BOOST_IMPL -void cvReadTrainData( const char* filename, int flags, - CvMat** trainData, - CvMat** trainClasses ) -{ - - CV_FUNCNAME( "cvReadTrainData" ); - - __BEGIN__; - - FILE* file; - int m, n; - int i, j; - float val; - - if( filename == NULL ) - { - CV_ERROR( CV_StsNullPtr, "filename must be specified" ); - } - if( trainData == NULL ) - { - CV_ERROR( CV_StsNullPtr, "trainData must be not NULL" ); - } - if( trainClasses == NULL ) - { - CV_ERROR( CV_StsNullPtr, "trainClasses must be not NULL" ); - } - - *trainData = NULL; - *trainClasses = NULL; - file = fopen( filename, "r" ); - if( !file ) - { - CV_ERROR( CV_StsError, "Unable to open file" ); - } - - fscanf( file, "%d %d", &m, &n ); - - if( CV_IS_ROW_SAMPLE( flags ) ) - { - CV_CALL( *trainData = cvCreateMat( m, n, CV_32FC1 ) ); - } - else - { - CV_CALL( *trainData = cvCreateMat( n, m, CV_32FC1 ) ); - } - - CV_CALL( *trainClasses = cvCreateMat( 1, m, CV_32FC1 ) ); - - for( i = 0; i < m; i++ ) - { - for( j = 0; j < n; j++ ) - { - fscanf( file, "%f", &val ); - if( CV_IS_ROW_SAMPLE( flags ) ) - { - CV_MAT_ELEM( **trainData, float, i, j ) = val; - } - else - { - CV_MAT_ELEM( **trainData, float, j, i ) = val; - } - } - fscanf( file, "%f", &val ); - CV_MAT_ELEM( **trainClasses, float, 0, i ) = val; - } - - fclose( file ); - - __END__; - -} - -CV_BOOST_IMPL -void cvWriteTrainData( const char* filename, int flags, - CvMat* trainData, CvMat* trainClasses, CvMat* sampleIdx ) -{ - CV_FUNCNAME( "cvWriteTrainData" ); - - __BEGIN__; - - FILE* file; - int m, n; - int i, j; - int clsrow; - int count; - int idx; - CvScalar sc; - - if( filename == NULL ) - { - CV_ERROR( CV_StsNullPtr, "filename must be specified" ); - } - if( trainData == NULL || CV_MAT_TYPE( trainData->type ) != CV_32FC1 ) - { - CV_ERROR( CV_StsUnsupportedFormat, "Invalid trainData" ); - } - if( CV_IS_ROW_SAMPLE( flags ) ) - { - m = trainData->rows; - n = trainData->cols; - } - else - { - n = trainData->rows; - m = trainData->cols; - } - if( trainClasses == NULL || CV_MAT_TYPE( trainClasses->type ) != CV_32FC1 || - MIN( trainClasses->rows, trainClasses->cols ) != 1 ) - { - CV_ERROR( CV_StsUnsupportedFormat, "Invalid trainClasses" ); - } - clsrow = (trainClasses->rows == 1); - if( m != ( (clsrow) ? trainClasses->cols : trainClasses->rows ) ) - { - CV_ERROR( CV_StsUnmatchedSizes, "Incorrect trainData and trainClasses sizes" ); - } - - if( sampleIdx != NULL ) - { - count = (sampleIdx->rows == 1) ? sampleIdx->cols : sampleIdx->rows; - } - else - { - count = m; - } - - - file = fopen( filename, "w" ); - if( !file ) - { - CV_ERROR( CV_StsError, "Unable to create file" ); - } - - fprintf( file, "%d %d\n", count, n ); - - for( i = 0; i < count; i++ ) - { - if( sampleIdx ) - { - if( sampleIdx->rows == 1 ) - { - sc = cvGet2D( sampleIdx, 0, i ); - } - else - { - sc = cvGet2D( sampleIdx, i, 0 ); - } - idx = (int) sc.val[0]; - } - else - { - idx = i; - } - for( j = 0; j < n; j++ ) - { - fprintf( file, "%g ", ( (CV_IS_ROW_SAMPLE( flags )) - ? CV_MAT_ELEM( *trainData, float, idx, j ) - : CV_MAT_ELEM( *trainData, float, j, idx ) ) ); - } - fprintf( file, "%g\n", ( (clsrow) - ? CV_MAT_ELEM( *trainClasses, float, 0, idx ) - : CV_MAT_ELEM( *trainClasses, float, idx, 0 ) ) ); - } - - fclose( file ); - - __END__; -} - - -#define ICV_RAND_SHUFFLE( suffix, type ) \ -void icvRandShuffle_##suffix( uchar* data, size_t step, int num ) \ -{ \ - CvRandState state; \ - time_t seed; \ - type tmp; \ - int i; \ - float rn; \ - \ - time( &seed ); \ - \ - cvRandInit( &state, (double) 0, (double) 0, (int)seed ); \ - for( i = 0; i < (num-1); i++ ) \ - { \ - rn = ((float) cvRandNext( &state )) / (1.0F + UINT_MAX); \ - CV_SWAP( *((type*)(data + i * step)), \ - *((type*)(data + ( i + (int)( rn * (num - i ) ) )* step)), \ - tmp ); \ - } \ -} - -ICV_RAND_SHUFFLE( 8U, uchar ) - -ICV_RAND_SHUFFLE( 16S, short ) - -ICV_RAND_SHUFFLE( 32S, int ) - -ICV_RAND_SHUFFLE( 32F, float ) - -CV_BOOST_IMPL -void cvRandShuffleVec( CvMat* mat ) -{ - CV_FUNCNAME( "cvRandShuffle" ); - - __BEGIN__; - - uchar* data; - size_t step; - int num; - - if( (mat == NULL) || !CV_IS_MAT( mat ) || MIN( mat->rows, mat->cols ) != 1 ) - { - CV_ERROR( CV_StsUnsupportedFormat, "" ); - } - - CV_MAT2VEC( *mat, data, step, num ); - switch( CV_MAT_TYPE( mat->type ) ) - { - case CV_8UC1: - icvRandShuffle_8U( data, step, num); - break; - case CV_16SC1: - icvRandShuffle_16S( data, step, num); - break; - case CV_32SC1: - icvRandShuffle_32S( data, step, num); - break; - case CV_32FC1: - icvRandShuffle_32F( data, step, num); - break; - default: - CV_ERROR( CV_StsUnsupportedFormat, "" ); - } - - __END__; -} - -/* End of file. */