Commit a3840e5469edd4b10a3ef5eb3cf303482568ce32

Authored by Scott Klum
1 parent 4f46567a

Cleaning

Showing 1 changed file with 199 additions and 235 deletions
openbr/core/boost.cpp
@@ -181,6 +181,7 @@ struct CascadeBoostTrainData : CvDTreeTrainData @@ -181,6 +181,7 @@ struct CascadeBoostTrainData : CvDTreeTrainData
181 181
182 virtual CvDTreeNode* subsample_data(const CvMat* _subsample_idx); 182 virtual CvDTreeNode* subsample_data(const CvMat* _subsample_idx);
183 183
  184 + virtual const int* getBufferValues(CvDTreeNode* n, int* labelsBuf, uint64_t vi);
184 virtual const int* get_class_labels(CvDTreeNode* n, int* labelsBuf); 185 virtual const int* get_class_labels(CvDTreeNode* n, int* labelsBuf);
185 virtual const int* get_cv_labels(CvDTreeNode* n, int* labelsBuf); 186 virtual const int* get_cv_labels(CvDTreeNode* n, int* labelsBuf);
186 virtual const int* get_sample_indices(CvDTreeNode* n, int* indicesBuf); 187 virtual const int* get_sample_indices(CvDTreeNode* n, int* indicesBuf);
@@ -192,8 +193,10 @@ struct CascadeBoostTrainData : CvDTreeTrainData @@ -192,8 +193,10 @@ struct CascadeBoostTrainData : CvDTreeTrainData
192 virtual void free_train_data(); 193 virtual void free_train_data();
193 194
194 const FeatureEvaluator* featureEvaluator; 195 const FeatureEvaluator* featureEvaluator;
  196 +
195 cv::Mat valCache; // precalculated feature values (CV_32FC1) 197 cv::Mat valCache; // precalculated feature values (CV_32FC1)
196 CvMat _resp; // for casting 198 CvMat _resp; // for casting
  199 +
197 int numPrecalcVal, numPrecalcIdx, channels; 200 int numPrecalcVal, numPrecalcIdx, channels;
198 }; 201 };
199 202
@@ -461,7 +464,10 @@ void CascadeBoostTrainData::setData( const FeatureEvaluator* _featureEvaluator, @@ -461,7 +464,10 @@ void CascadeBoostTrainData::setData( const FeatureEvaluator* _featureEvaluator,
461 464
462 // 1048576 is the number of bytes in a megabyte 465 // 1048576 is the number of bytes in a megabyte
463 numPrecalcVal = min( cvRound((double)_precalcValBufSize*1048576. / (sizeof(float)*sample_count)), var_count ); 466 numPrecalcVal = min( cvRound((double)_precalcValBufSize*1048576. / (sizeof(float)*sample_count)), var_count );
  467 + qDebug("Features Cached: %f", float(numPrecalcVal)/var_count);
  468 +
464 numPrecalcIdx = min( cvRound((double)_precalcIdxBufSize*1048576. / ((is_buf_16u ? sizeof(unsigned short) : sizeof (int))*sample_count)), var_count ); 469 numPrecalcIdx = min( cvRound((double)_precalcIdxBufSize*1048576. / ((is_buf_16u ? sizeof(unsigned short) : sizeof (int))*sample_count)), var_count );
  470 + qDebug("Indices Cached: %f", float(numPrecalcIdx)/var_count);
465 471
466 assert( numPrecalcIdx >= 0 && numPrecalcVal >= 0 ); 472 assert( numPrecalcIdx >= 0 && numPrecalcVal >= 0 );
467 473
@@ -523,8 +529,7 @@ void CascadeBoostTrainData::setData( const FeatureEvaluator* _featureEvaluator, @@ -523,8 +529,7 @@ void CascadeBoostTrainData::setData( const FeatureEvaluator* _featureEvaluator,
523 // now calculate the maximum size of split, 529 // now calculate the maximum size of split,
524 // create memory storage that will keep nodes and splits of the decision tree 530 // create memory storage that will keep nodes and splits of the decision tree
525 // allocate root node and the buffer for the whole training data 531 // allocate root node and the buffer for the whole training data
526 - int maxSplitSize = cvAlign(sizeof(CvDTreeSplit) +  
527 - (MAX(0,sample_count - 33)/32)*sizeof(int),sizeof(void*)); 532 + int maxSplitSize = cvAlign(sizeof(CvDTreeSplit) + (MAX(0,sample_count - 33)/32)*sizeof(int),sizeof(void*));
528 int treeBlockSize = MAX((int)sizeof(CvDTreeNode)*8, maxSplitSize); 533 int treeBlockSize = MAX((int)sizeof(CvDTreeNode)*8, maxSplitSize);
529 treeBlockSize = MAX(treeBlockSize + BlockSizeDelta, MinBlockSize); 534 treeBlockSize = MAX(treeBlockSize + BlockSizeDelta, MinBlockSize);
530 tree_storage = cvCreateMemStorage( treeBlockSize ); 535 tree_storage = cvCreateMemStorage( treeBlockSize );
@@ -592,9 +597,8 @@ const int* CascadeBoostTrainData::get_class_labels( CvDTreeNode* n, int* labelsB @@ -592,9 +597,8 @@ const int* CascadeBoostTrainData::get_class_labels( CvDTreeNode* n, int* labelsB
592 return labelsBuf; 597 return labelsBuf;
593 } 598 }
594 599
595 -const int* CascadeBoostTrainData::get_sample_indices( CvDTreeNode* n, int* indicesBuf ) 600 +const int* CascadeBoostTrainData::getBufferValues(CvDTreeNode* n, int* indicesBuf, uint64_t vi)
596 { 601 {
597 - const uint64 vi = get_work_var_count();  
598 const int* cat_values = 0; 602 const int* cat_values = 0;
599 if (!is_buf_16u) 603 if (!is_buf_16u)
600 cat_values = buf->data.i + n->buf_idx*get_length_subbuf() + vi*sample_count + n->offset; 604 cat_values = buf->data.i + n->buf_idx*get_length_subbuf() + vi*sample_count + n->offset;
@@ -608,84 +612,70 @@ const int* CascadeBoostTrainData::get_sample_indices( CvDTreeNode* n, int* indic @@ -608,84 +612,70 @@ const int* CascadeBoostTrainData::get_sample_indices( CvDTreeNode* n, int* indic
608 return cat_values; 612 return cat_values;
609 } 613 }
610 614
  615 +const int* CascadeBoostTrainData::get_sample_indices( CvDTreeNode* n, int* indicesBuf )
  616 +{
  617 + return getBufferValues(n,indicesBuf,get_work_var_count());
  618 +}
  619 +
611 const int* CascadeBoostTrainData::get_cv_labels( CvDTreeNode* n, int* indicesBuf ) 620 const int* CascadeBoostTrainData::get_cv_labels( CvDTreeNode* n, int* indicesBuf )
612 { 621 {
613 - const uint64 vi = get_work_var_count()-1;  
614 - const int* cat_values = 0;  
615 - if (!is_buf_16u)  
616 - cat_values = buf->data.i + n->buf_idx*get_length_subbuf() + vi*sample_count + n->offset;  
617 - else {  
618 - const unsigned short* short_values = (const unsigned short*)(buf->data.s + n->buf_idx*get_length_subbuf() + vi*sample_count + n->offset);  
619 - for (int i = 0; i < n->sample_count; i++)  
620 - indicesBuf[i] = short_values[i];  
621 - cat_values = indicesBuf;  
622 - }  
623 - return cat_values; 622 + return getBufferValues(n,indicesBuf,get_work_var_count()-1);
624 } 623 }
625 624
626 -void CascadeBoostTrainData::get_ord_var_data( CvDTreeNode* n, int vi, float* ordValuesBuf, int* sortedIndicesBuf,  
627 - const float** ordValues, const int** sortedIndices, int* sampleIndicesBuf ) 625 +void CascadeBoostTrainData::get_ord_var_data( CvDTreeNode* n, int vi, float* ordValuesBuf, int* sortedIndicesBuf, const float** ordValues, const int** sortedIndices, int* sampleIndicesBuf )
628 { 626 {
629 int nodeSampleCount = n->sample_count; 627 int nodeSampleCount = n->sample_count;
  628 +
  629 + // For this node, get our sample indices
630 const int* sampleIndices = get_sample_indices(n, sampleIndicesBuf); 630 const int* sampleIndices = get_sample_indices(n, sampleIndicesBuf);
631 631
632 - if ( vi < numPrecalcIdx )  
633 - {  
634 - if( !is_buf_16u ) 632 + // For this feature (this code refers to features as values, hence vi == value index),
  633 + // have we precalculated (presorted) the training samples by their feature response?
  634 + if (vi < numPrecalcIdx) {
  635 + if (!is_buf_16u)
635 *sortedIndices = buf->data.i + n->buf_idx*get_length_subbuf() + (uint64)vi*sample_count + n->offset; 636 *sortedIndices = buf->data.i + n->buf_idx*get_length_subbuf() + (uint64)vi*sample_count + n->offset;
636 - else  
637 - {  
638 - const unsigned short* shortIndices = (const unsigned short*)(buf->data.s + n->buf_idx*get_length_subbuf() +  
639 - vi*sample_count + n->offset );  
640 - for( int i = 0; i < nodeSampleCount; i++ ) 637 + else {
  638 + const unsigned short* shortIndices = (const unsigned short*)(buf->data.s + n->buf_idx*get_length_subbuf() + (uint64)vi*sample_count + n->offset );
  639 + for (int i = 0; i < nodeSampleCount; i++)
641 sortedIndicesBuf[i] = shortIndices[i]; 640 sortedIndicesBuf[i] = shortIndices[i];
642 -  
643 *sortedIndices = sortedIndicesBuf; 641 *sortedIndices = sortedIndicesBuf;
644 } 642 }
645 643
646 - if( vi < numPrecalcVal )  
647 - {  
648 - for( int i = 0; i < nodeSampleCount; i++ )  
649 - { 644 + // For this feature, have we precalculated all of the feature responses?
  645 + if (vi < numPrecalcVal) {
  646 + for (int i = 0; i < nodeSampleCount; i++) {
650 int idx = (*sortedIndices)[i]; 647 int idx = (*sortedIndices)[i];
651 idx = sampleIndices[idx]; 648 idx = sampleIndices[idx];
652 - ordValuesBuf[i] = valCache.at<float>( vi, idx); 649 + ordValuesBuf[i] = valCache.at<float>(vi, idx);
653 } 650 }
654 - }  
655 - else  
656 - {  
657 - for( int i = 0; i < nodeSampleCount; i++ )  
658 - { 651 + } else {
  652 + for (int i = 0; i < nodeSampleCount; i++) {
659 int idx = (*sortedIndices)[i]; 653 int idx = (*sortedIndices)[i];
660 idx = sampleIndices[idx]; 654 idx = sampleIndices[idx];
661 - ordValuesBuf[i] = (*featureEvaluator)( vi, idx); 655 + ordValuesBuf[i] = (*featureEvaluator)(vi, idx);
662 } 656 }
663 } 657 }
664 - }  
665 - else // vi >= numPrecalcIdx  
666 - { 658 + } else {
667 cv::AutoBuffer<float> abuf(nodeSampleCount); 659 cv::AutoBuffer<float> abuf(nodeSampleCount);
668 float* sampleValues = &abuf[0]; 660 float* sampleValues = &abuf[0];
669 661
670 - if ( vi < numPrecalcVal )  
671 - {  
672 - for( int i = 0; i < nodeSampleCount; i++ )  
673 - { 662 + if (vi < numPrecalcVal) {
  663 + for (int i = 0; i < nodeSampleCount; i++) {
674 sortedIndicesBuf[i] = i; 664 sortedIndicesBuf[i] = i;
675 sampleValues[i] = valCache.at<float>( vi, sampleIndices[i] ); 665 sampleValues[i] = valCache.at<float>( vi, sampleIndices[i] );
676 } 666 }
677 - }  
678 - else  
679 - {  
680 - for( int i = 0; i < nodeSampleCount; i++ )  
681 - { 667 + } else {
  668 + for (int i = 0; i < nodeSampleCount; i++) {
682 sortedIndicesBuf[i] = i; 669 sortedIndicesBuf[i] = i;
683 sampleValues[i] = (*featureEvaluator)( vi, sampleIndices[i]); 670 sampleValues[i] = (*featureEvaluator)( vi, sampleIndices[i]);
684 } 671 }
685 } 672 }
  673 +
686 icvSortIntAux( sortedIndicesBuf, nodeSampleCount, &sampleValues[0] ); 674 icvSortIntAux( sortedIndicesBuf, nodeSampleCount, &sampleValues[0] );
687 - for( int i = 0; i < nodeSampleCount; i++ ) 675 +
  676 + for (int i = 0; i < nodeSampleCount; i++)
688 ordValuesBuf[i] = (&sampleValues[0])[sortedIndicesBuf[i]]; 677 ordValuesBuf[i] = (&sampleValues[0])[sortedIndicesBuf[i]];
  678 +
689 *sortedIndices = sortedIndicesBuf; 679 *sortedIndices = sortedIndicesBuf;
690 } 680 }
691 681
@@ -727,114 +717,117 @@ float CascadeBoostTrainData::getVarValue( int vi, int si ) @@ -727,114 +717,117 @@ float CascadeBoostTrainData::getVarValue( int vi, int si )
727 return (*featureEvaluator)( vi, si ); 717 return (*featureEvaluator)( vi, si );
728 } 718 }
729 719
730 -struct FeatureIdxOnlyPrecalc : ParallelLoopBody 720 +struct Precalc : ParallelLoopBody
731 { 721 {
732 - FeatureIdxOnlyPrecalc( const FeatureEvaluator* _featureEvaluator, CvMat* _buf, int _sample_count, bool _is_buf_16u ) 722 + const FeatureEvaluator* featureEvaluator;
  723 + int sampleCount;
  724 +
  725 + Precalc(const FeatureEvaluator* featureEvaluator, int sampleCount) :
  726 + featureEvaluator(featureEvaluator),
  727 + sampleCount(sampleCount)
  728 + {}
  729 +
  730 + virtual void operator()(const Range& range) const = 0;
  731 +};
  732 +
  733 +struct IndexPrecalc : Precalc
  734 +{
  735 + int* idst;
  736 + unsigned short* udst;
  737 + bool isBufShort;
  738 +
  739 + IndexPrecalc(const FeatureEvaluator* featureEvaluator, CvMat* buf, int sampleCount, bool isBufShort) :
  740 + Precalc(featureEvaluator, sampleCount),
  741 + isBufShort(isBufShort)
  742 + {
  743 + udst = (unsigned short*)buf->data.s;
  744 + idst = buf->data.i;
  745 + }
  746 +
  747 + void setBuffer(int fi, int si) const
733 { 748 {
734 - featureEvaluator = _featureEvaluator;  
735 - sample_count = _sample_count;  
736 - udst = (unsigned short*)_buf->data.s;  
737 - idst = _buf->data.i;  
738 - is_buf_16u = _is_buf_16u; 749 + if (isBufShort) *(udst + (uint64)fi*sampleCount + si) = (unsigned short)si;
  750 + else *(idst + (uint64)fi*sampleCount + si) = si;
739 } 751 }
740 - void operator()( const Range& range ) const 752 +
  753 + void sortBuffer(int fi, float *valCachePtr) const
  754 + {
  755 + if (isBufShort) icvSortUShAux(udst + (uint64)fi*sampleCount, sampleCount, valCachePtr);
  756 + else icvSortIntAux(idst + (uint64)fi*sampleCount, sampleCount, valCachePtr);
  757 + }
  758 +
  759 + virtual void operator()(const Range& range) const
741 { 760 {
742 - cv::AutoBuffer<float> valCache(sample_count); 761 + cv::AutoBuffer<float> valCache(sampleCount);
743 float* valCachePtr = (float*)valCache; 762 float* valCachePtr = (float*)valCache;
744 - for ( int fi = range.start; fi < range.end; fi++)  
745 - {  
746 - for( int si = 0; si < sample_count; si++ )  
747 - {  
748 - valCachePtr[si] = (*featureEvaluator)( fi, si );  
749 - if ( is_buf_16u )  
750 - *(udst + fi*sample_count + si) = (unsigned short)si;  
751 - else  
752 - *(idst + fi*sample_count + si) = si; 763 + for (int fi = range.start; fi < range.end; fi++) {
  764 + for (int si = 0; si < sampleCount; si++) {
  765 + valCachePtr[si] = (*featureEvaluator)(fi, si);
  766 + setBuffer(fi, si);
753 } 767 }
754 - if ( is_buf_16u )  
755 - icvSortUShAux( udst + (uint64)fi*sample_count, sample_count, valCachePtr );  
756 - else  
757 - icvSortIntAux( idst + (uint64)fi*sample_count, sample_count, valCachePtr ); 768 + sortBuffer(fi, valCachePtr);
758 } 769 }
759 } 770 }
760 - const FeatureEvaluator* featureEvaluator;  
761 - int sample_count;  
762 - int* idst;  
763 - unsigned short* udst;  
764 - bool is_buf_16u;  
765 }; 771 };
766 772
767 -struct FeatureValAndIdxPrecalc : ParallelLoopBody 773 +struct FeatureAndIndexPrecalc : IndexPrecalc
768 { 774 {
769 - FeatureValAndIdxPrecalc( const FeatureEvaluator* _featureEvaluator, CvMat* _buf, Mat* _valCache, int _sample_count, bool _is_buf_16u )  
770 - {  
771 - featureEvaluator = _featureEvaluator;  
772 - valCache = _valCache;  
773 - sample_count = _sample_count;  
774 - udst = (unsigned short*)_buf->data.s;  
775 - idst = _buf->data.i;  
776 - is_buf_16u = _is_buf_16u;  
777 - }  
778 - void operator()( const Range& range ) const 775 + Mat *valCache;
  776 +
  777 + FeatureAndIndexPrecalc(const FeatureEvaluator* featureEvaluator, CvMat* buf, Mat* valCache, int sampleCount, bool isBufShort) :
  778 + IndexPrecalc(featureEvaluator, buf, sampleCount, isBufShort),
  779 + valCache(valCache)
  780 + {}
  781 +
  782 + virtual void operator()(const Range& range) const
779 { 783 {
780 - for ( int fi = range.start; fi < range.end; fi++)  
781 - {  
782 - for( int si = 0; si < sample_count; si++ )  
783 - {  
784 - valCache->at<float>(fi,si) = (*featureEvaluator)( fi, si );  
785 - if ( is_buf_16u )  
786 - *(udst + (uint64)fi*sample_count + si) = (unsigned short)si;  
787 - else  
788 - *(idst + (uint64)fi*sample_count + si) = si; 784 + for (int fi = range.start; fi < range.end; fi++) {
  785 + for (int si = 0; si < sampleCount; si++) {
  786 + valCache->at<float>(fi,si) = (*featureEvaluator)(fi, si);
  787 + setBuffer(fi, si);
789 } 788 }
790 - if ( is_buf_16u )  
791 - icvSortUShAux( udst + (uint64)fi*sample_count, sample_count, valCache->ptr<float>(fi) );  
792 - else  
793 - icvSortIntAux( idst + (uint64)fi*sample_count, sample_count, valCache->ptr<float>(fi) ); 789 + sortBuffer(fi, valCache->ptr<float>(fi));
794 } 790 }
795 } 791 }
796 - const FeatureEvaluator* featureEvaluator;  
797 - Mat* valCache;  
798 - int sample_count;  
799 - int* idst;  
800 - unsigned short* udst;  
801 - bool is_buf_16u;  
802 }; 792 };
803 793
804 -struct FeatureValOnlyPrecalc : ParallelLoopBody 794 +struct FeaturePrecalc : Precalc
805 { 795 {
806 - FeatureValOnlyPrecalc( const FeatureEvaluator* _featureEvaluator, Mat* _valCache, int _sample_count )  
807 - {  
808 - featureEvaluator = _featureEvaluator;  
809 - valCache = _valCache;  
810 - sample_count = _sample_count;  
811 - }  
812 - void operator()( const Range& range ) const 796 + Mat *valCache;
  797 +
  798 + FeaturePrecalc(const FeatureEvaluator* featureEvaluator, Mat* valCache, int sampleCount) :
  799 + Precalc(featureEvaluator, sampleCount),
  800 + valCache(valCache)
  801 + {}
  802 +
  803 + virtual void operator()(const Range& range) const
813 { 804 {
814 - for ( int fi = range.start; fi < range.end; fi++)  
815 - for( int si = 0; si < sample_count; si++ )  
816 - valCache->at<float>(fi,si) = (*featureEvaluator)( fi, si ); 805 + for (int fi = range.start; fi < range.end; fi++)
  806 + for (int si = 0; si < sampleCount; si++)
  807 + valCache->at<float>(fi,si) = (*featureEvaluator)(fi, si);
817 } 808 }
818 - const FeatureEvaluator* featureEvaluator;  
819 - Mat* valCache;  
820 - int sample_count;  
821 }; 809 };
822 810
823 void CascadeBoostTrainData::precalculate() 811 void CascadeBoostTrainData::precalculate()
824 { 812 {
825 - int minNum = MIN( numPrecalcVal, numPrecalcIdx); 813 + int minPrecalc = std::min(numPrecalcVal, numPrecalcIdx);
826 814
827 qDebug() << "Starting precalculation..."; 815 qDebug() << "Starting precalculation...";
828 816
829 QTime time; 817 QTime time;
830 time.start(); 818 time.start();
831 819
832 - parallel_for_( Range(numPrecalcVal, numPrecalcIdx),  
833 - FeatureIdxOnlyPrecalc(featureEvaluator, buf, sample_count, is_buf_16u!=0) );  
834 - parallel_for_( Range(0, minNum),  
835 - FeatureValAndIdxPrecalc(featureEvaluator, buf, &valCache, sample_count, is_buf_16u!=0) );  
836 - parallel_for_( Range(minNum, numPrecalcVal),  
837 - FeatureValOnlyPrecalc(featureEvaluator, &valCache, sample_count) ); 820 + // Compute features and sort training samples for feature indices we are not going to cache
  821 + parallel_for_(Range(numPrecalcVal, numPrecalcIdx),
  822 + IndexPrecalc(featureEvaluator, buf, sample_count, is_buf_16u!=0));
  823 +
  824 + // Compute features and sort training samples for features indices we are going to cache
  825 + parallel_for_(Range(0, minPrecalc),
  826 + FeatureAndIndexPrecalc(featureEvaluator, buf, &valCache, sample_count, is_buf_16u!=0));
  827 +
  828 + // Compute feature values for feature indices for which we are not going to sort training samples
  829 + parallel_for_(Range(minPrecalc, numPrecalcVal),
  830 + FeaturePrecalc(featureEvaluator, &valCache, sample_count));
838 831
839 cout << "Precalculation time (ms): " << time.elapsed() << endl; 832 cout << "Precalculation time (ms): " << time.elapsed() << endl;
840 } 833 }
@@ -868,87 +861,85 @@ CvDTreeNode* CascadeBoostTree::predict( int sampleIdx ) const @@ -868,87 +861,85 @@ CvDTreeNode* CascadeBoostTree::predict( int sampleIdx ) const
868 return node; 861 return node;
869 } 862 }
870 863
  864 +// This function splits the training data from the parent node into training
  865 +// data for both child nodes
871 void CascadeBoostTree::split_node_data( CvDTreeNode* node ) 866 void CascadeBoostTree::split_node_data( CvDTreeNode* node )
872 { 867 {
873 - int n = node->sample_count, nl, nr, scount = data->sample_count;  
874 - char* dir = (char*)data->direction->data.ptr;  
875 CvDTreeNode *left = 0, *right = 0; 868 CvDTreeNode *left = 0, *right = 0;
  869 +
  870 + uint64_t nodeSampleCount = node->sample_count;
  871 + uint64_t sampleCount = data->sample_count;
  872 + uint64_t nLeft, nRight;
  873 +
  874 + int workVarCount = data->get_work_var_count();
  875 +
  876 + char* dir = (char*)data->direction->data.ptr;
876 int* newIdx = data->split_buf->data.i; 877 int* newIdx = data->split_buf->data.i;
877 int newBufIdx = data->get_child_buf_idx( node ); 878 int newBufIdx = data->get_child_buf_idx( node );
878 - int workVarCount = data->get_work_var_count();  
879 CvMat* buf = data->buf; 879 CvMat* buf = data->buf;
880 size_t length_buf_row = data->get_length_subbuf(); 880 size_t length_buf_row = data->get_length_subbuf();
881 - cv::AutoBuffer<uchar> inn_buf(n*(3*sizeof(int)+sizeof(float))); 881 + cv::AutoBuffer<uchar> inn_buf(nodeSampleCount*(3*sizeof(int)+sizeof(float)));
882 int* tempBuf = (int*)(uchar*)inn_buf; 882 int* tempBuf = (int*)(uchar*)inn_buf;
883 - bool splitInputData;  
884 883
885 complete_node_dir(node); 884 complete_node_dir(node);
886 885
887 - for( int i = nl = nr = 0; i < n; i++ ) 886 + for (int i = nLeft = nRight = 0; i < nodeSampleCount; i++)
888 { 887 {
889 int d = dir[i]; 888 int d = dir[i];
890 // initialize new indices for splitting ordered variables 889 // initialize new indices for splitting ordered variables
891 - newIdx[i] = (nl & (d-1)) | (nr & -d); // d ? ri : li  
892 - nr += d;  
893 - nl += d^1; 890 + newIdx[i] = (nLeft & (d-1)) | (nRight & -d); // d ? ri : li
  891 + nRight += d;
  892 + nLeft += d^1;
894 } 893 }
895 894
896 - node->left = left = data->new_node( node, nl, newBufIdx, node->offset );  
897 - node->right = right = data->new_node( node, nr, newBufIdx, node->offset + nl ); 895 + node->left = left = data->new_node( node, nLeft, newBufIdx, node->offset );
  896 + node->right = right = data->new_node( node, nRight, newBufIdx, node->offset + nLeft );
898 897
899 - splitInputData = node->depth + 1 < data->params.max_depth &&  
900 - (node->left->sample_count > data->params.min_sample_count ||  
901 - node->right->sample_count > data->params.min_sample_count); 898 + bool splitInputData = node->depth + 1 < data->params.max_depth && (node->left->sample_count > data->params.min_sample_count || node->right->sample_count > data->params.min_sample_count);
902 899
903 - // split ordered variables, keep both halves sorted.  
904 - for( int vi = 0; vi < ((CascadeBoostTrainData*)data)->numPrecalcIdx; vi++ )  
905 - { 900 + const int numPreculatedIndices = ((CascadeBoostTrainData*)data)->numPrecalcIdx;
  901 + for (int vi = 0; vi < numPreculatedIndices; vi++) {
906 int ci = data->get_var_type(vi); 902 int ci = data->get_var_type(vi);
907 if( ci >= 0 || !splitInputData ) 903 if( ci >= 0 || !splitInputData )
908 continue; 904 continue;
909 905
910 int n1 = node->get_num_valid(vi); 906 int n1 = node->get_num_valid(vi);
911 - float *src_val_buf = (float*)(tempBuf + n);  
912 - int *src_sorted_idx_buf = (int*)(src_val_buf + n);  
913 - int *src_sample_idx_buf = src_sorted_idx_buf + n; 907 + float *src_val_buf = (float*)(tempBuf + nodeSampleCount);
  908 + int *src_sorted_idx_buf = (int*)(src_val_buf + nodeSampleCount);
  909 + int *src_sample_idx_buf = src_sorted_idx_buf + nodeSampleCount;
914 const int* src_sorted_idx = 0; 910 const int* src_sorted_idx = 0;
915 const float* src_val = 0; 911 const float* src_val = 0;
  912 +
916 data->get_ord_var_data(node, vi, src_val_buf, src_sorted_idx_buf, &src_val, &src_sorted_idx, src_sample_idx_buf); 913 data->get_ord_var_data(node, vi, src_val_buf, src_sorted_idx_buf, &src_val, &src_sorted_idx, src_sample_idx_buf);
917 914
918 - for(int i = 0; i < n; i++) 915 + for(int i = 0; i < nodeSampleCount; i++)
919 tempBuf[i] = src_sorted_idx[i]; 916 tempBuf[i] = src_sorted_idx[i];
920 917
921 - if (data->is_buf_16u)  
922 - { 918 + if (data->is_buf_16u) {
923 ushort *ldst, *rdst; 919 ushort *ldst, *rdst;
924 - ldst = (ushort*)(buf->data.s + left->buf_idx*length_buf_row +  
925 - vi*scount + left->offset);  
926 - rdst = (ushort*)(ldst + nl); 920 + ldst = (ushort*)(buf->data.s + left->buf_idx*length_buf_row + vi*sampleCount + left->offset);
  921 + rdst = (ushort*)(ldst + nLeft);
927 922
928 // split sorted 923 // split sorted
929 - for( int i = 0; i < n1; i++ )  
930 - { 924 + for (int i = 0; i < n1; i++) {
931 int idx = tempBuf[i]; 925 int idx = tempBuf[i];
932 int d = dir[idx]; 926 int d = dir[idx];
933 idx = newIdx[idx]; 927 idx = newIdx[idx];
934 - if (d)  
935 - { 928 + if (d) {
936 *rdst = (ushort)idx; 929 *rdst = (ushort)idx;
937 rdst++; 930 rdst++;
938 - }  
939 - else  
940 - { 931 + } else {
941 *ldst = (ushort)idx; 932 *ldst = (ushort)idx;
942 ldst++; 933 ldst++;
943 } 934 }
944 } 935 }
945 - CV_Assert( n1 == n ); 936 + CV_Assert( n1 == nodeSampleCount );
946 } 937 }
947 else 938 else
948 { 939 {
949 int *ldst, *rdst; 940 int *ldst, *rdst;
950 - ldst = buf->data.i + left->buf_idx*length_buf_row + (uint64)(vi*scount) + left->offset;  
951 - rdst = buf->data.i + right->buf_idx*length_buf_row + (uint64)(vi*scount) + right->offset; 941 + ldst = buf->data.i + left->buf_idx*length_buf_row + vi*sampleCount + left->offset;
  942 + rdst = buf->data.i + right->buf_idx*length_buf_row + vi*sampleCount + right->offset;
952 943
953 // split sorted 944 // split sorted
954 for( int i = 0; i < n1; i++ ) 945 for( int i = 0; i < n1; i++ )
@@ -967,34 +958,27 @@ void CascadeBoostTree::split_node_data( CvDTreeNode* node ) @@ -967,34 +958,27 @@ void CascadeBoostTree::split_node_data( CvDTreeNode* node )
967 ldst++; 958 ldst++;
968 } 959 }
969 } 960 }
970 - CV_Assert( n1 == n ); 961 + CV_Assert( n1 == nodeSampleCount );
971 } 962 }
972 } 963 }
973 964
974 // split cv_labels using newIdx relocation table 965 // split cv_labels using newIdx relocation table
975 - int *src_lbls_buf = tempBuf + n; 966 + int *src_lbls_buf = tempBuf + nodeSampleCount;
976 const int* src_lbls = data->get_cv_labels(node, src_lbls_buf); 967 const int* src_lbls = data->get_cv_labels(node, src_lbls_buf);
977 968
978 - for(int i = 0; i < n; i++) 969 + for(int i = 0; i < nodeSampleCount; i++)
979 tempBuf[i] = src_lbls[i]; 970 tempBuf[i] = src_lbls[i];
980 971
981 - if (data->is_buf_16u)  
982 - {  
983 - unsigned short *ldst = (unsigned short *)(buf->data.s + left->buf_idx*length_buf_row +  
984 - (workVarCount-1)*scount + left->offset);  
985 - unsigned short *rdst = (unsigned short *)(buf->data.s + right->buf_idx*length_buf_row +  
986 - (workVarCount-1)*scount + right->offset); 972 + if (data->is_buf_16u) {
  973 + unsigned short *ldst = (unsigned short *)(buf->data.s + left->buf_idx*length_buf_row + (workVarCount-1)*sampleCount + left->offset);
  974 + unsigned short *rdst = (unsigned short *)(buf->data.s + right->buf_idx*length_buf_row + (workVarCount-1)*sampleCount + right->offset);
987 975
988 - for( int i = 0; i < n; i++ )  
989 - { 976 + for( int i = 0; i < nodeSampleCount; i++ ) {
990 int idx = tempBuf[i]; 977 int idx = tempBuf[i];
991 - if (dir[i])  
992 - { 978 + if (dir[i]) {
993 *rdst = (unsigned short)idx; 979 *rdst = (unsigned short)idx;
994 rdst++; 980 rdst++;
995 - }  
996 - else  
997 - { 981 + } else {
998 *ldst = (unsigned short)idx; 982 *ldst = (unsigned short)idx;
999 ldst++; 983 ldst++;
1000 } 984 }
@@ -1003,10 +987,10 @@ void CascadeBoostTree::split_node_data( CvDTreeNode* node ) @@ -1003,10 +987,10 @@ void CascadeBoostTree::split_node_data( CvDTreeNode* node )
1003 } 987 }
1004 else 988 else
1005 { 989 {
1006 - int *ldst = buf->data.i + left->buf_idx*length_buf_row + (uint64)(workVarCount-1)*scount + left->offset;  
1007 - int *rdst = buf->data.i + right->buf_idx*length_buf_row + (uint64)(workVarCount-1)*scount + right->offset; 990 + int *ldst = buf->data.i + left->buf_idx*length_buf_row + (workVarCount-1)*sampleCount + left->offset;
  991 + int *rdst = buf->data.i + right->buf_idx*length_buf_row + (workVarCount-1)*sampleCount + right->offset;
1008 992
1009 - for( int i = 0; i < n; i++ ) 993 + for( int i = 0; i < nodeSampleCount; i++ )
1010 { 994 {
1011 int idx = tempBuf[i]; 995 int idx = tempBuf[i];
1012 if (dir[i]) 996 if (dir[i])
@@ -1023,28 +1007,21 @@ void CascadeBoostTree::split_node_data( CvDTreeNode* node ) @@ -1023,28 +1007,21 @@ void CascadeBoostTree::split_node_data( CvDTreeNode* node )
1023 } 1007 }
1024 1008
1025 // split sample indices 1009 // split sample indices
1026 - int *sampleIdx_src_buf = tempBuf + n; 1010 + int *sampleIdx_src_buf = tempBuf + nodeSampleCount;
1027 const int* sampleIdx_src = data->get_sample_indices(node, sampleIdx_src_buf); 1011 const int* sampleIdx_src = data->get_sample_indices(node, sampleIdx_src_buf);
1028 1012
1029 - for(int i = 0; i < n; i++) 1013 + for(int i = 0; i < nodeSampleCount; i++)
1030 tempBuf[i] = sampleIdx_src[i]; 1014 tempBuf[i] = sampleIdx_src[i];
1031 1015
1032 - if (data->is_buf_16u)  
1033 - {  
1034 - unsigned short* ldst = (unsigned short*)(buf->data.s + left->buf_idx*length_buf_row +  
1035 - workVarCount*scount + left->offset);  
1036 - unsigned short* rdst = (unsigned short*)(buf->data.s + right->buf_idx*length_buf_row +  
1037 - workVarCount*scount + right->offset);  
1038 - for (int i = 0; i < n; i++)  
1039 - { 1016 + if (data->is_buf_16u) {
  1017 + unsigned short* ldst = (unsigned short*)(buf->data.s + left->buf_idx*length_buf_row + workVarCount*sampleCount + left->offset);
  1018 + unsigned short* rdst = (unsigned short*)(buf->data.s + right->buf_idx*length_buf_row + workVarCount*sampleCount + right->offset);
  1019 + for (int i = 0; i < nodeSampleCount; i++) {
1040 unsigned short idx = (unsigned short)tempBuf[i]; 1020 unsigned short idx = (unsigned short)tempBuf[i];
1041 - if (dir[i])  
1042 - { 1021 + if (dir[i]) {
1043 *rdst = idx; 1022 *rdst = idx;
1044 rdst++; 1023 rdst++;
1045 - }  
1046 - else  
1047 - { 1024 + } else {
1048 *ldst = idx; 1025 *ldst = idx;
1049 ldst++; 1026 ldst++;
1050 } 1027 }
@@ -1052,9 +1029,9 @@ void CascadeBoostTree::split_node_data( CvDTreeNode* node ) @@ -1052,9 +1029,9 @@ void CascadeBoostTree::split_node_data( CvDTreeNode* node )
1052 } 1029 }
1053 else 1030 else
1054 { 1031 {
1055 - int* ldst = buf->data.i + left->buf_idx*length_buf_row + (uint64)workVarCount*scount + left->offset;  
1056 - int* rdst = buf->data.i + right->buf_idx*length_buf_row + (uint64)workVarCount*scount + right->offset;  
1057 - for (int i = 0; i < n; i++) 1032 + int* ldst = buf->data.i + left->buf_idx*length_buf_row + workVarCount*sampleCount + left->offset;
  1033 + int* rdst = buf->data.i + right->buf_idx*length_buf_row + workVarCount*sampleCount + right->offset;
  1034 + for (int i = 0; i < nodeSampleCount; i++)
1058 { 1035 {
1059 int idx = tempBuf[i]; 1036 int idx = tempBuf[i];
1060 if (dir[i]) 1037 if (dir[i])
@@ -1070,10 +1047,10 @@ void CascadeBoostTree::split_node_data( CvDTreeNode* node ) @@ -1070,10 +1047,10 @@ void CascadeBoostTree::split_node_data( CvDTreeNode* node )
1070 } 1047 }
1071 } 1048 }
1072 1049
1073 - for( int vi = 0; vi < data->var_count; vi++ )  
1074 - {  
1075 - left->set_num_valid(vi, (int)(nl));  
1076 - right->set_num_valid(vi, (int)(nr)); 1050 + const int variableCount = data->var_count;
  1051 + for (int vi = 0; vi < variableCount; vi++) {
  1052 + left->set_num_valid(vi, nLeft);
  1053 + right->set_num_valid(vi, nRight);
1077 } 1054 }
1078 1055
1079 // deallocate the parent node data that is not needed anymore 1056 // deallocate the parent node data that is not needed anymore
@@ -1106,11 +1083,9 @@ void CascadeBoost::train(const FeatureEvaluator* _featureEvaluator, @@ -1106,11 +1083,9 @@ void CascadeBoost::train(const FeatureEvaluator* _featureEvaluator,
1106 cout << "| N | HR | FA |" << endl; 1083 cout << "| N | HR | FA |" << endl;
1107 cout << "+----+---------+---------+" << endl; 1084 cout << "+----+---------+---------+" << endl;
1108 1085
1109 - do  
1110 - { 1086 + do {
1111 CascadeBoostTree* tree = new CascadeBoostTree; 1087 CascadeBoostTree* tree = new CascadeBoostTree;
1112 if (!tree->train( data, subsample_mask, this)) { 1088 if (!tree->train( data, subsample_mask, this)) {
1113 - qDebug() << "Deleting tree!";  
1114 delete tree; 1089 delete tree;
1115 return; 1090 return;
1116 } 1091 }
@@ -1119,9 +1094,8 @@ void CascadeBoost::train(const FeatureEvaluator* _featureEvaluator, @@ -1119,9 +1094,8 @@ void CascadeBoost::train(const FeatureEvaluator* _featureEvaluator,
1119 update_weights(tree); 1094 update_weights(tree);
1120 trim_weights(); 1095 trim_weights();
1121 if (cvCountNonZero(subsample_mask) == 0) { 1096 if (cvCountNonZero(subsample_mask) == 0) {
1122 - qDebug() << "Subsample mask is empty!";  
1123 return; 1097 return;
1124 - } 1098 + }
1125 } 1099 }
1126 while (!isErrDesired() && (classifiers.size() < params.weak_count)); 1100 while (!isErrDesired() && (classifiers.size() < params.weak_count));
1127 1101
@@ -1194,35 +1168,26 @@ void CascadeBoost::update_weights(CvBoostTree* tree) @@ -1194,35 +1168,26 @@ void CascadeBoost::update_weights(CvBoostTree* tree)
1194 weights = cvCreateMat( 1, n, CV_64F ); 1168 weights = cvCreateMat( 1, n, CV_64F );
1195 subtree_weights = cvCreateMat( 1, n + 2, CV_64F ); 1169 subtree_weights = cvCreateMat( 1, n + 2, CV_64F );
1196 1170
1197 - if (data->is_buf_16u)  
1198 - { 1171 + // set the labels to find (from within weak tree learning proc)
  1172 + // the particular sample weight, and where to store the response.
  1173 + if (data->is_buf_16u) {
1199 unsigned short* labels = (unsigned short*)(buf->data.s + data->data_root->buf_idx*length_buf_row + data->data_root->offset + (uint64)(data->work_var_count-1)*data->sample_count); 1174 unsigned short* labels = (unsigned short*)(buf->data.s + data->data_root->buf_idx*length_buf_row + data->data_root->offset + (uint64)(data->work_var_count-1)*data->sample_count);
1200 - for( int i = 0; i < n; i++ )  
1201 - {  
1202 - // save original categorical responses {0,1}, convert them to {-1,1}  
1203 - orig_response->data.i[i] = classLabels[i]*2 - 1;  
1204 - // make all the samples active at start.  
1205 - // later, in trim_weights() deactivate/reactive again some, if need  
1206 - subsample_mask->data.ptr[i] = (uchar)1;  
1207 - // make all the initial weights the same.  
1208 - weights->data.db[i] = w0*p[classLabels[i]];  
1209 - // set the labels to find (from within weak tree learning proc)  
1210 - // the particular sample weight, and where to store the response. 1175 + for (int i = 0; i < n; i++)
1211 labels[i] = (unsigned short)i; 1176 labels[i] = (unsigned short)i;
1212 - }  
1213 - }  
1214 - else  
1215 - { 1177 + } else {
1216 int* labels = buf->data.i + data->data_root->buf_idx*length_buf_row + data->data_root->offset + (uint64)(data->work_var_count-1)*data->sample_count; 1178 int* labels = buf->data.i + data->data_root->buf_idx*length_buf_row + data->data_root->offset + (uint64)(data->work_var_count-1)*data->sample_count;
1217 -  
1218 for( int i = 0; i < n; i++ ) 1179 for( int i = 0; i < n; i++ )
1219 - {  
1220 - // save original categorical responses {0,1}, convert them to {-1,1}  
1221 - orig_response->data.i[i] = classLabels[i]*2 - 1;  
1222 - subsample_mask->data.ptr[i] = (uchar)1;  
1223 - weights->data.db[i] = w0*p[classLabels[i]];  
1224 labels[i] = i; 1180 labels[i] = i;
1225 - } 1181 + }
  1182 +
  1183 + for (int i = 0; i < n; i++) {
  1184 + // save original categorical responses {0,1}, convert them to {-1,1}
  1185 + orig_response->data.i[i] = classLabels[i]*2 - 1;
  1186 + // make all the samples active at start.
  1187 + // later, in trim_weights() deactivate/reactive again some, if need
  1188 + subsample_mask->data.ptr[i] = (uchar)1;
  1189 + // make all the initial weights the same.
  1190 + weights->data.db[i] = w0*p[classLabels[i]];
1226 } 1191 }
1227 1192
1228 if( params.boost_type == LOGIT ) 1193 if( params.boost_type == LOGIT )
@@ -1424,6 +1389,5 @@ bool CascadeBoost::isErrDesired() @@ -1424,6 +1389,5 @@ bool CascadeBoost::isErrDesired()
1424 cout << "|" << endl; 1389 cout << "|" << endl;
1425 cout << "+----+---------+---------+" << endl; 1390 cout << "+----+---------+---------+" << endl;
1426 1391
1427 - qDebug() << falseAlarm << maxFalseAlarm;  
1428 return falseAlarm <= maxFalseAlarm; 1392 return falseAlarm <= maxFalseAlarm;
1429 } 1393 }