Merge pull request #2181 from asmorkalov:ocv_packaging
[profile/ivi/opencv.git] / apps / traincascade / boost.cpp
index 18165fd..d1a2b3e 100644 (file)
@@ -1,6 +1,19 @@
 #include "opencv2/core/core.hpp"
 #include "opencv2/core/internal.hpp"
 
+using cv::Size;
+using cv::Mat;
+using cv::Point;
+using cv::FileStorage;
+using cv::Rect;
+using cv::Ptr;
+using cv::FileNode;
+using cv::Mat_;
+using cv::Range;
+using cv::FileNodeIterator;
+using cv::ParallelLoopBody;
+
+
 #include "boost.h"
 #include "cascadeclassifier.h"
 #include <queue>
@@ -160,10 +173,10 @@ CvCascadeBoostParams::CvCascadeBoostParams( int _boostType,
 
 void CvCascadeBoostParams::write( FileStorage &fs ) const
 {
-    String boostTypeStr = boost_type == CvBoost::DISCRETE ? CC_DISCRETE_BOOST :
+    string boostTypeStr = boost_type == CvBoost::DISCRETE ? CC_DISCRETE_BOOST :
                           boost_type == CvBoost::REAL ? CC_REAL_BOOST :
                           boost_type == CvBoost::LOGIT ? CC_LOGIT_BOOST :
-                          boost_type == CvBoost::GENTLE ? CC_GENTLE_BOOST : String();
+                          boost_type == CvBoost::GENTLE ? CC_GENTLE_BOOST : string();
     CV_Assert( !boostTypeStr.empty() );
     fs << CC_BOOST_TYPE << boostTypeStr;
     fs << CC_MINHITRATE << minHitRate;
@@ -175,7 +188,7 @@ void CvCascadeBoostParams::write( FileStorage &fs ) const
 
 bool CvCascadeBoostParams::read( const FileNode &node )
 {
-    String boostTypeStr;
+    string boostTypeStr;
     FileNode rnode = node[CC_BOOST_TYPE];
     rnode >> boostTypeStr;
     boost_type = !boostTypeStr.compare( CC_DISCRETE_BOOST ) ? CvBoost::DISCRETE :
@@ -213,10 +226,10 @@ void CvCascadeBoostParams::printDefaults() const
 
 void CvCascadeBoostParams::printAttrs() const
 {
-    String boostTypeStr = boost_type == CvBoost::DISCRETE ? CC_DISCRETE_BOOST :
+    string boostTypeStr = boost_type == CvBoost::DISCRETE ? CC_DISCRETE_BOOST :
                           boost_type == CvBoost::REAL ? CC_REAL_BOOST :
                           boost_type == CvBoost::LOGIT  ? CC_LOGIT_BOOST :
-                          boost_type == CvBoost::GENTLE ? CC_GENTLE_BOOST : String();
+                          boost_type == CvBoost::GENTLE ? CC_GENTLE_BOOST : string();
     CV_Assert( !boostTypeStr.empty() );
     cout << "boostType: " << boostTypeStr << endl;
     cout << "minHitRate: " << minHitRate << endl;
@@ -226,7 +239,7 @@ void CvCascadeBoostParams::printAttrs() const
     cout << "maxWeakCount: " << weak_count << endl;
 }
 
-bool CvCascadeBoostParams::scanAttr( const String prmName, const String val)
+bool CvCascadeBoostParams::scanAttr( const string prmName, const string val)
 {
     bool res = true;
 
@@ -360,7 +373,7 @@ CvDTreeNode* CvCascadeBoostTrainData::subsample_data( const CvMat* _subsample_id
 
             if (is_buf_16u)
             {
-                unsigned short* udst_idx = (unsigned short*)(buf->data.s + root->buf_idx*buf->cols +
+                unsigned short* udst_idx = (unsigned short*)(buf->data.s + root->buf_idx*get_length_subbuf() +
                     vi*sample_count + data_root->offset);
                 for( int i = 0; i < num_valid; i++ )
                 {
@@ -373,7 +386,7 @@ CvDTreeNode* CvCascadeBoostTrainData::subsample_data( const CvMat* _subsample_id
             }
             else
             {
-                int* idst_idx = buf->data.i + root->buf_idx*buf->cols +
+                int* idst_idx = buf->data.i + root->buf_idx*get_length_subbuf() +
                     vi*sample_count + root->offset;
                 for( int i = 0; i < num_valid; i++ )
                 {
@@ -390,14 +403,14 @@ CvDTreeNode* CvCascadeBoostTrainData::subsample_data( const CvMat* _subsample_id
         const int* src_lbls = get_cv_labels(data_root, (int*)(uchar*)inn_buf);
         if (is_buf_16u)
         {
-            unsigned short* udst = (unsigned short*)(buf->data.s + root->buf_idx*buf->cols +
+            unsigned short* udst = (unsigned short*)(buf->data.s + root->buf_idx*get_length_subbuf() +
                 (workVarCount-1)*sample_count + root->offset);
             for( int i = 0; i < count; i++ )
                 udst[i] = (unsigned short)src_lbls[sidx[i]];
         }
         else
         {
-            int* idst = buf->data.i + root->buf_idx*buf->cols +
+            int* idst = buf->data.i + root->buf_idx*get_length_subbuf() +
                 (workVarCount-1)*sample_count + root->offset;
             for( int i = 0; i < count; i++ )
                 idst[i] = src_lbls[sidx[i]];
@@ -407,14 +420,14 @@ CvDTreeNode* CvCascadeBoostTrainData::subsample_data( const CvMat* _subsample_id
         const int* sample_idx_src = get_sample_indices(data_root, (int*)(uchar*)inn_buf);
         if (is_buf_16u)
         {
-            unsigned short* sample_idx_dst = (unsigned short*)(buf->data.s + root->buf_idx*buf->cols +
+            unsigned short* sample_idx_dst = (unsigned short*)(buf->data.s + root->buf_idx*get_length_subbuf() +
                 workVarCount*sample_count + root->offset);
             for( int i = 0; i < count; i++ )
                 sample_idx_dst[i] = (unsigned short)sample_idx_src[sidx[i]];
         }
         else
         {
-            int* sample_idx_dst = buf->data.i + root->buf_idx*buf->cols +
+            int* sample_idx_dst = buf->data.i + root->buf_idx*get_length_subbuf() +
                 workVarCount*sample_count + root->offset;
             for( int i = 0; i < count; i++ )
                 sample_idx_dst[i] = sample_idx_src[sidx[i]];
@@ -489,6 +502,10 @@ void CvCascadeBoostTrainData::setData( const CvFeatureEvaluator* _featureEvaluat
     int* idst = 0;
     unsigned short* udst = 0;
 
+    uint64 effective_buf_size = 0;
+    int effective_buf_height = 0, effective_buf_width = 0;
+
+
     clear();
     shared = true;
     have_labels = true;
@@ -548,13 +565,28 @@ void CvCascadeBoostTrainData::setData( const CvFeatureEvaluator* _featureEvaluat
     var_type->data.i[var_count] = cat_var_count;
     var_type->data.i[var_count+1] = cat_var_count+1;
     work_var_count = ( cat_var_count ? 0 : numPrecalcIdx ) + 1/*cv_lables*/;
-    buf_size = (work_var_count + 1) * sample_count/*sample_indices*/;
     buf_count = 2;
 
+    buf_size = -1; // the member buf_size is obsolete
+
+    effective_buf_size = (uint64)(work_var_count + 1)*(uint64)sample_count * buf_count; // this is the total size of "CvMat buf" to be allocated
+    effective_buf_width = sample_count;
+    effective_buf_height = work_var_count+1;
+
+    if (effective_buf_width >= effective_buf_height)
+        effective_buf_height *= buf_count;
+    else
+        effective_buf_width *= buf_count;
+
+    if ((uint64)effective_buf_width * (uint64)effective_buf_height != effective_buf_size)
+    {
+        CV_Error(CV_StsBadArg, "The memory buffer cannot be allocated since its size exceeds integer fields limit");
+    }
+
     if ( is_buf_16u )
-        buf = cvCreateMat( buf_count, buf_size, CV_16UC1 );
+        buf = cvCreateMat( effective_buf_height, effective_buf_width, CV_16UC1 );
     else
-        buf = cvCreateMat( buf_count, buf_size, CV_32SC1 );
+        buf = cvCreateMat( effective_buf_height, effective_buf_width, CV_32SC1 );
 
     cat_count = cvCreateMat( 1, cat_var_count + 1, CV_32SC1 );
 
@@ -609,7 +641,7 @@ void CvCascadeBoostTrainData::setData( const CvFeatureEvaluator* _featureEvaluat
     priors_mult = cvCloneMat( priors );
     counts = cvCreateMat( 1, get_num_classes(), CV_32SC1 );
     direction = cvCreateMat( 1, sample_count, CV_8UC1 );
-    split_buf = cvCreateMat( 1, sample_count, CV_32SC1 );
+    split_buf = cvCreateMat( 1, sample_count, CV_32SC1 );//TODO: make a pointer
 }
 
 void CvCascadeBoostTrainData::free_train_data()
@@ -652,10 +684,10 @@ void CvCascadeBoostTrainData::get_ord_var_data( CvDTreeNode* n, int vi, float* o
     if ( vi < numPrecalcIdx )
     {
         if( !is_buf_16u )
-            *sortedIndices = buf->data.i + n->buf_idx*buf->cols + vi*sample_count + n->offset;
+            *sortedIndices = buf->data.i + n->buf_idx*get_length_subbuf() + vi*sample_count + n->offset;
         else
         {
-            const unsigned short* shortIndices = (const unsigned short*)(buf->data.s + n->buf_idx*buf->cols +
+            const unsigned short* shortIndices = (const unsigned short*)(buf->data.s + n->buf_idx*get_length_subbuf() +
                                                     vi*sample_count + n->offset );
             for( int i = 0; i < nodeSampleCount; i++ )
                 sortedIndicesBuf[i] = shortIndices[i];
@@ -747,7 +779,7 @@ float CvCascadeBoostTrainData::getVarValue( int vi, int si )
 }
 
 
-struct FeatureIdxOnlyPrecalc
+struct FeatureIdxOnlyPrecalc : ParallelLoopBody
 {
     FeatureIdxOnlyPrecalc( const CvFeatureEvaluator* _featureEvaluator, CvMat* _buf, int _sample_count, bool _is_buf_16u )
     {
@@ -757,11 +789,11 @@ struct FeatureIdxOnlyPrecalc
         idst = _buf->data.i;
         is_buf_16u = _is_buf_16u;
     }
-    void operator()( const BlockedRange& range ) const
+    void operator()( const Range& range ) const
     {
         cv::AutoBuffer<float> valCache(sample_count);
         float* valCachePtr = (float*)valCache;
-        for ( int fi = range.begin(); fi < range.end(); fi++)
+        for ( int fi = range.start; fi < range.end; fi++)
         {
             for( int si = 0; si < sample_count; si++ )
             {
@@ -784,7 +816,7 @@ struct FeatureIdxOnlyPrecalc
     bool is_buf_16u;
 };
 
-struct FeatureValAndIdxPrecalc
+struct FeatureValAndIdxPrecalc : ParallelLoopBody
 {
     FeatureValAndIdxPrecalc( const CvFeatureEvaluator* _featureEvaluator, CvMat* _buf, Mat* _valCache, int _sample_count, bool _is_buf_16u )
     {
@@ -795,9 +827,9 @@ struct FeatureValAndIdxPrecalc
         idst = _buf->data.i;
         is_buf_16u = _is_buf_16u;
     }
-    void operator()( const BlockedRange& range ) const
+    void operator()( const Range& range ) const
     {
-        for ( int fi = range.begin(); fi < range.end(); fi++)
+        for ( int fi = range.start; fi < range.end; fi++)
         {
             for( int si = 0; si < sample_count; si++ )
             {
@@ -821,7 +853,7 @@ struct FeatureValAndIdxPrecalc
     bool is_buf_16u;
 };
 
-struct FeatureValOnlyPrecalc
+struct FeatureValOnlyPrecalc : ParallelLoopBody
 {
     FeatureValOnlyPrecalc( const CvFeatureEvaluator* _featureEvaluator, Mat* _valCache, int _sample_count )
     {
@@ -829,9 +861,9 @@ struct FeatureValOnlyPrecalc
         valCache = _valCache;
         sample_count = _sample_count;
     }
-    void operator()( const BlockedRange& range ) const
+    void operator()( const Range& range ) const
     {
-        for ( int fi = range.begin(); fi < range.end(); fi++)
+        for ( int fi = range.start; fi < range.end; fi++)
             for( int si = 0; si < sample_count; si++ )
                 valCache->at<float>(fi,si) = (*featureEvaluator)( fi, si );
     }
@@ -845,12 +877,12 @@ void CvCascadeBoostTrainData::precalculate()
     int minNum = MIN( numPrecalcVal, numPrecalcIdx);
 
     double proctime = -TIME( 0 );
-    parallel_for( BlockedRange(numPrecalcVal, numPrecalcIdx),
-                  FeatureIdxOnlyPrecalc(featureEvaluator, buf, sample_count, is_buf_16u!=0) );
-    parallel_for( BlockedRange(0, minNum),
-                  FeatureValAndIdxPrecalc(featureEvaluator, buf, &valCache, sample_count, is_buf_16u!=0) );
-    parallel_for( BlockedRange(minNum, numPrecalcVal),
-                  FeatureValOnlyPrecalc(featureEvaluator, &valCache, sample_count) );
+    parallel_for_( Range(numPrecalcVal, numPrecalcIdx),
+                   FeatureIdxOnlyPrecalc(featureEvaluator, buf, sample_count, is_buf_16u!=0) );
+    parallel_for_( Range(0, minNum),
+                   FeatureValAndIdxPrecalc(featureEvaluator, buf, &valCache, sample_count, is_buf_16u!=0) );
+    parallel_for_( Range(minNum, numPrecalcVal),
+                   FeatureValOnlyPrecalc(featureEvaluator, &valCache, sample_count) );
     cout << "Precalculation time: " << (proctime + TIME( 0 )) << endl;
 }
 
@@ -1027,6 +1059,7 @@ void CvCascadeBoostTree::split_node_data( CvDTreeNode* node )
     int newBufIdx = data->get_child_buf_idx( node );
     int workVarCount = data->get_work_var_count();
     CvMat* buf = data->buf;
+    size_t length_buf_row = data->get_length_subbuf();
     cv::AutoBuffer<uchar> inn_buf(n*(3*sizeof(int)+sizeof(float)));
     int* tempBuf = (int*)(uchar*)inn_buf;
     bool splitInputData;
@@ -1070,7 +1103,7 @@ void CvCascadeBoostTree::split_node_data( CvDTreeNode* node )
         if (data->is_buf_16u)
         {
             ushort *ldst, *rdst;
-            ldst = (ushort*)(buf->data.s + left->buf_idx*buf->cols +
+            ldst = (ushort*)(buf->data.s + left->buf_idx*length_buf_row +
                 vi*scount + left->offset);
             rdst = (ushort*)(ldst + nl);
 
@@ -1096,9 +1129,9 @@ void CvCascadeBoostTree::split_node_data( CvDTreeNode* node )
         else
         {
             int *ldst, *rdst;
-            ldst = buf->data.i + left->buf_idx*buf->cols +
+            ldst = buf->data.i + left->buf_idx*length_buf_row +
                 vi*scount + left->offset;
-            rdst = buf->data.i + right->buf_idx*buf->cols +
+            rdst = buf->data.i + right->buf_idx*length_buf_row +
                 vi*scount + right->offset;
 
             // split sorted
@@ -1131,9 +1164,9 @@ void CvCascadeBoostTree::split_node_data( CvDTreeNode* node )
 
     if (data->is_buf_16u)
     {
-        unsigned short *ldst = (unsigned short *)(buf->data.s + left->buf_idx*buf->cols +
+        unsigned short *ldst = (unsigned short *)(buf->data.s + left->buf_idx*length_buf_row +
             (workVarCount-1)*scount + left->offset);
-        unsigned short *rdst = (unsigned short *)(buf->data.s + right->buf_idx*buf->cols +
+        unsigned short *rdst = (unsigned short *)(buf->data.s + right->buf_idx*length_buf_row +
             (workVarCount-1)*scount + right->offset);
 
         for( int i = 0; i < n; i++ )
@@ -1154,9 +1187,9 @@ void CvCascadeBoostTree::split_node_data( CvDTreeNode* node )
     }
     else
     {
-        int *ldst = buf->data.i + left->buf_idx*buf->cols +
+        int *ldst = buf->data.i + left->buf_idx*length_buf_row +
             (workVarCount-1)*scount + left->offset;
-        int *rdst = buf->data.i + right->buf_idx*buf->cols +
+        int *rdst = buf->data.i + right->buf_idx*length_buf_row +
             (workVarCount-1)*scount + right->offset;
 
         for( int i = 0; i < n; i++ )
@@ -1184,9 +1217,9 @@ void CvCascadeBoostTree::split_node_data( CvDTreeNode* node )
 
     if (data->is_buf_16u)
     {
-        unsigned short* ldst = (unsigned short*)(buf->data.s + left->buf_idx*buf->cols +
+        unsigned short* ldst = (unsigned short*)(buf->data.s + left->buf_idx*length_buf_row +
             workVarCount*scount + left->offset);
-        unsigned short* rdst = (unsigned short*)(buf->data.s + right->buf_idx*buf->cols +
+        unsigned short* rdst = (unsigned short*)(buf->data.s + right->buf_idx*length_buf_row +
             workVarCount*scount + right->offset);
         for (int i = 0; i < n; i++)
         {
@@ -1205,9 +1238,9 @@ void CvCascadeBoostTree::split_node_data( CvDTreeNode* node )
     }
     else
     {
-        int* ldst = buf->data.i + left->buf_idx*buf->cols +
+        int* ldst = buf->data.i + left->buf_idx*length_buf_row +
             workVarCount*scount + left->offset;
-        int* rdst = buf->data.i + right->buf_idx*buf->cols +
+        int* rdst = buf->data.i + right->buf_idx*length_buf_row +
             workVarCount*scount + right->offset;
         for (int i = 0; i < n; i++)
         {
@@ -1257,6 +1290,7 @@ bool CvCascadeBoost::train( const CvFeatureEvaluator* _featureEvaluator,
                            int _precalcValBufSize, int _precalcIdxBufSize,
                            const CvCascadeBoostParams& _params )
 {
+    bool isTrained = false;
     CV_Assert( !data );
     clear();
     data = new CvCascadeBoostTrainData( _featureEvaluator, _numSamples,
@@ -1291,9 +1325,16 @@ bool CvCascadeBoost::train( const CvFeatureEvaluator* _featureEvaluator,
     }
     while( !isErrDesired() && (weak->total < params.weak_count) );
 
-    data->is_classifier = true;
-    data->free_train_data();
-    return true;
+    if(weak->total > 0)
+    {
+        data->is_classifier = true;
+        data->free_train_data();
+        isTrained = true;
+    }
+    else
+        clear();
+
+    return isTrained;
 }
 
 float CvCascadeBoost::predict( int sampleIdx, bool returnSum ) const
@@ -1344,6 +1385,7 @@ void CvCascadeBoost::update_weights( CvBoostTree* tree )
         sampleIdx = data->get_sample_indices( data->data_root, sampleIdxBuf );
     }
     CvMat* buf = data->buf;
+    size_t length_buf_row = data->get_length_subbuf();
     if( !tree ) // before training the first tree, initialize weights and other parameters
     {
         int* classLabelsBuf = (int*)cur_inn_buf_pos; cur_inn_buf_pos = (uchar*)(classLabelsBuf + n);
@@ -1367,7 +1409,7 @@ void CvCascadeBoost::update_weights( CvBoostTree* tree )
 
         if (data->is_buf_16u)
         {
-            unsigned short* labels = (unsigned short*)(buf->data.s + data->data_root->buf_idx*buf->cols +
+            unsigned short* labels = (unsigned short*)(buf->data.s + data->data_root->buf_idx*length_buf_row +
                 data->data_root->offset + (data->work_var_count-1)*data->sample_count);
             for( int i = 0; i < n; i++ )
             {
@@ -1385,7 +1427,7 @@ void CvCascadeBoost::update_weights( CvBoostTree* tree )
         }
         else
         {
-            int* labels = buf->data.i + data->data_root->buf_idx*buf->cols +
+            int* labels = buf->data.i + data->data_root->buf_idx*length_buf_row +
                 data->data_root->offset + (data->work_var_count-1)*data->sample_count;
 
             for( int i = 0; i < n; i++ )