Commit edcbc8b8fbb3e66c4e46c654d101e49e212a700d
1 parent
e4a5aed6
Clean-up and steps towards incorparting representations in the backend
Showing
8 changed files
with
220 additions
and
294 deletions
openbr/core/boost.cpp
| @@ -171,29 +171,6 @@ void CascadeBoostParams::write( FileStorage &fs ) const | @@ -171,29 +171,6 @@ void CascadeBoostParams::write( FileStorage &fs ) const | ||
| 171 | fs << CC_WEAK_COUNT << weak_count; | 171 | fs << CC_WEAK_COUNT << weak_count; |
| 172 | } | 172 | } |
| 173 | 173 | ||
| 174 | -// ----------------------------- Compatibility ---------------------------------- | ||
| 175 | - | ||
| 176 | -BoostBRCompatibility::BoostBRCompatibility(Representation *_representation, int _numSamples) | ||
| 177 | -{ | ||
| 178 | - representation = _representation; | ||
| 179 | - data.create(_numSamples, representation->windowSize().area(), CV_32SC1); | ||
| 180 | - cls.create(_numSamples, 1, CV_32FC1); | ||
| 181 | -} | ||
| 182 | - | ||
| 183 | -void BoostBRCompatibility::setImage(const Mat &img, uchar clsLabel, int idx) | ||
| 184 | -{ | ||
| 185 | - cls.ptr<float>(idx)[0] = clsLabel; | ||
| 186 | - Mat preprocessed = representation->preprocess(img); | ||
| 187 | - Mat copier(representation->windowSize(), CV_32FC1, data.ptr<int>(idx)); | ||
| 188 | - preprocessed.copyTo(copier); | ||
| 189 | -} | ||
| 190 | - | ||
| 191 | -float BoostBRCompatibility::operator ()(int featureIdx, int sampleIdx) const | ||
| 192 | -{ | ||
| 193 | - return representation->evaluate(data.row(sampleIdx).reshape(0, representation->windowSize().height), | ||
| 194 | - QList<int>() << featureIdx).ptr<float>()[0]; | ||
| 195 | -} | ||
| 196 | - | ||
| 197 | //---------------------------- CascadeBoostTrainData ----------------------------- | 174 | //---------------------------- CascadeBoostTrainData ----------------------------- |
| 198 | 175 | ||
| 199 | CvDTreeNode* CascadeBoostTrainData::subsample_data( const CvMat* _subsample_idx ) | 176 | CvDTreeNode* CascadeBoostTrainData::subsample_data( const CvMat* _subsample_idx ) |
| @@ -361,18 +338,18 @@ CvDTreeNode* CascadeBoostTrainData::subsample_data( const CvMat* _subsample_idx | @@ -361,18 +338,18 @@ CvDTreeNode* CascadeBoostTrainData::subsample_data( const CvMat* _subsample_idx | ||
| 361 | return root; | 338 | return root; |
| 362 | } | 339 | } |
| 363 | 340 | ||
| 364 | -CascadeBoostTrainData::CascadeBoostTrainData( const BoostBRCompatibility* _compat, | 341 | +CascadeBoostTrainData::CascadeBoostTrainData( const FeatureEvaluator* _featureEvaluator, |
| 365 | const CvDTreeParams& _params ) | 342 | const CvDTreeParams& _params ) |
| 366 | { | 343 | { |
| 367 | is_classifier = true; | 344 | is_classifier = true; |
| 368 | - var_all = var_count = _compat->numFeatures(); | 345 | + var_all = var_count = (int)_featureEvaluator->getNumFeatures(); |
| 369 | 346 | ||
| 370 | - compat = _compat; | 347 | + featureEvaluator = _featureEvaluator; |
| 371 | shared = true; | 348 | shared = true; |
| 372 | set_params( _params ); | 349 | set_params( _params ); |
| 373 | - max_c_count = MAX( 2, compat->maxCatCount() ); | 350 | + max_c_count = MAX( 2, featureEvaluator->getMaxCatCount() ); |
| 374 | var_type = cvCreateMat( 1, var_count + 2, CV_32SC1 ); | 351 | var_type = cvCreateMat( 1, var_count + 2, CV_32SC1 ); |
| 375 | - if ( compat->maxCatCount() > 0 ) | 352 | + if ( featureEvaluator->getMaxCatCount() > 0 ) |
| 376 | { | 353 | { |
| 377 | numPrecalcIdx = 0; | 354 | numPrecalcIdx = 0; |
| 378 | cat_var_count = var_count; | 355 | cat_var_count = var_count; |
| @@ -402,15 +379,15 @@ CascadeBoostTrainData::CascadeBoostTrainData( const BoostBRCompatibility* _compa | @@ -402,15 +379,15 @@ CascadeBoostTrainData::CascadeBoostTrainData( const BoostBRCompatibility* _compa | ||
| 402 | split_heap = cvCreateSet( 0, sizeof(split_heap[0]), maxSplitSize, tree_storage ); | 379 | split_heap = cvCreateSet( 0, sizeof(split_heap[0]), maxSplitSize, tree_storage ); |
| 403 | } | 380 | } |
| 404 | 381 | ||
| 405 | -CascadeBoostTrainData::CascadeBoostTrainData( const BoostBRCompatibility* _compat, | 382 | +CascadeBoostTrainData::CascadeBoostTrainData( const FeatureEvaluator* _featureEvaluator, |
| 406 | int _numSamples, | 383 | int _numSamples, |
| 407 | int _precalcValBufSize, int _precalcIdxBufSize, | 384 | int _precalcValBufSize, int _precalcIdxBufSize, |
| 408 | const CvDTreeParams& _params ) | 385 | const CvDTreeParams& _params ) |
| 409 | { | 386 | { |
| 410 | - setData( _compat, _numSamples, _precalcValBufSize, _precalcIdxBufSize, _params ); | 387 | + setData( _featureEvaluator, _numSamples, _precalcValBufSize, _precalcIdxBufSize, _params ); |
| 411 | } | 388 | } |
| 412 | 389 | ||
| 413 | -void CascadeBoostTrainData::setData( const BoostBRCompatibility* _compat, | 390 | +void CascadeBoostTrainData::setData( const FeatureEvaluator* _featureEvaluator, |
| 414 | int _numSamples, | 391 | int _numSamples, |
| 415 | int _precalcValBufSize, int _precalcIdxBufSize, | 392 | int _precalcValBufSize, int _precalcIdxBufSize, |
| 416 | const CvDTreeParams& _params ) | 393 | const CvDTreeParams& _params ) |
| @@ -421,7 +398,6 @@ void CascadeBoostTrainData::setData( const BoostBRCompatibility* _compat, | @@ -421,7 +398,6 @@ void CascadeBoostTrainData::setData( const BoostBRCompatibility* _compat, | ||
| 421 | uint64 effective_buf_size = 0; | 398 | uint64 effective_buf_size = 0; |
| 422 | int effective_buf_height = 0, effective_buf_width = 0; | 399 | int effective_buf_height = 0, effective_buf_width = 0; |
| 423 | 400 | ||
| 424 | - | ||
| 425 | clear(); | 401 | clear(); |
| 426 | shared = true; | 402 | shared = true; |
| 427 | have_labels = true; | 403 | have_labels = true; |
| @@ -432,17 +408,18 @@ void CascadeBoostTrainData::setData( const BoostBRCompatibility* _compat, | @@ -432,17 +408,18 @@ void CascadeBoostTrainData::setData( const BoostBRCompatibility* _compat, | ||
| 432 | 408 | ||
| 433 | set_params( _params ); | 409 | set_params( _params ); |
| 434 | 410 | ||
| 435 | - compat = _compat; | 411 | + CV_Assert( _featureEvaluator ); |
| 412 | + featureEvaluator = _featureEvaluator; | ||
| 436 | 413 | ||
| 437 | - max_c_count = MAX( 2, compat->maxCatCount() ); | ||
| 438 | - _resp = compat->getCls(); | 414 | + max_c_count = MAX( 2, featureEvaluator->getMaxCatCount() ); |
| 415 | + _resp = featureEvaluator->getCls(); | ||
| 439 | responses = &_resp; | 416 | responses = &_resp; |
| 440 | // TODO: check responses: elements must be 0 or 1 | 417 | // TODO: check responses: elements must be 0 or 1 |
| 441 | 418 | ||
| 442 | if( _precalcValBufSize < 0 || _precalcIdxBufSize < 0) | 419 | if( _precalcValBufSize < 0 || _precalcIdxBufSize < 0) |
| 443 | CV_Error( CV_StsOutOfRange, "_numPrecalcVal and _numPrecalcIdx must be positive or 0" ); | 420 | CV_Error( CV_StsOutOfRange, "_numPrecalcVal and _numPrecalcIdx must be positive or 0" ); |
| 444 | 421 | ||
| 445 | - var_count = var_all = compat->numFeatures(); | 422 | + var_count = var_all = featureEvaluator->getNumFeatures() * featureEvaluator->getFeatureSize(); |
| 446 | sample_count = _numSamples; | 423 | sample_count = _numSamples; |
| 447 | 424 | ||
| 448 | is_buf_16u = false; | 425 | is_buf_16u = false; |
| @@ -457,7 +434,7 @@ void CascadeBoostTrainData::setData( const BoostBRCompatibility* _compat, | @@ -457,7 +434,7 @@ void CascadeBoostTrainData::setData( const BoostBRCompatibility* _compat, | ||
| 457 | 434 | ||
| 458 | valCache.create( numPrecalcVal, sample_count, CV_32FC1 ); | 435 | valCache.create( numPrecalcVal, sample_count, CV_32FC1 ); |
| 459 | var_type = cvCreateMat( 1, var_count + 2, CV_32SC1 ); | 436 | var_type = cvCreateMat( 1, var_count + 2, CV_32SC1 ); |
| 460 | - if ( compat->maxCatCount() > 0 ) | 437 | + if ( featureEvaluator->getMaxCatCount() > 0 ) |
| 461 | { | 438 | { |
| 462 | numPrecalcIdx = 0; | 439 | numPrecalcIdx = 0; |
| 463 | cat_var_count = var_count; | 440 | cat_var_count = var_count; |
| @@ -623,7 +600,7 @@ void CascadeBoostTrainData::get_ord_var_data( CvDTreeNode* n, int vi, float* ord | @@ -623,7 +600,7 @@ void CascadeBoostTrainData::get_ord_var_data( CvDTreeNode* n, int vi, float* ord | ||
| 623 | { | 600 | { |
| 624 | int idx = (*sortedIndices)[i]; | 601 | int idx = (*sortedIndices)[i]; |
| 625 | idx = sampleIndices[idx]; | 602 | idx = sampleIndices[idx]; |
| 626 | - ordValuesBuf[i] = (*compat)( vi, idx); | 603 | + ordValuesBuf[i] = (*featureEvaluator)( vi, idx); |
| 627 | } | 604 | } |
| 628 | } | 605 | } |
| 629 | } | 606 | } |
| @@ -645,7 +622,7 @@ void CascadeBoostTrainData::get_ord_var_data( CvDTreeNode* n, int vi, float* ord | @@ -645,7 +622,7 @@ void CascadeBoostTrainData::get_ord_var_data( CvDTreeNode* n, int vi, float* ord | ||
| 645 | for( int i = 0; i < nodeSampleCount; i++ ) | 622 | for( int i = 0; i < nodeSampleCount; i++ ) |
| 646 | { | 623 | { |
| 647 | sortedIndicesBuf[i] = i; | 624 | sortedIndicesBuf[i] = i; |
| 648 | - sampleValues[i] = (*compat)( vi, sampleIndices[i]); | 625 | + sampleValues[i] = (*featureEvaluator)( vi, sampleIndices[i]); |
| 649 | } | 626 | } |
| 650 | } | 627 | } |
| 651 | icvSortIntAux( sortedIndicesBuf, nodeSampleCount, &sampleValues[0] ); | 628 | icvSortIntAux( sortedIndicesBuf, nodeSampleCount, &sampleValues[0] ); |
| @@ -673,7 +650,7 @@ const int* CascadeBoostTrainData::get_cat_var_data( CvDTreeNode* n, int vi, int* | @@ -673,7 +650,7 @@ const int* CascadeBoostTrainData::get_cat_var_data( CvDTreeNode* n, int vi, int* | ||
| 673 | if( vi >= numPrecalcVal && vi < var_count ) | 650 | if( vi >= numPrecalcVal && vi < var_count ) |
| 674 | { | 651 | { |
| 675 | for( int i = 0; i < nodeSampleCount; i++ ) | 652 | for( int i = 0; i < nodeSampleCount; i++ ) |
| 676 | - catValuesBuf[i] = (int)(*compat)( vi, sampleIndices[i] ); | 653 | + catValuesBuf[i] = (int)(*featureEvaluator)( vi, sampleIndices[i] ); |
| 677 | } | 654 | } |
| 678 | else | 655 | else |
| 679 | { | 656 | { |
| @@ -688,15 +665,14 @@ float CascadeBoostTrainData::getVarValue( int vi, int si ) | @@ -688,15 +665,14 @@ float CascadeBoostTrainData::getVarValue( int vi, int si ) | ||
| 688 | { | 665 | { |
| 689 | if ( vi < numPrecalcVal && !valCache.empty() ) | 666 | if ( vi < numPrecalcVal && !valCache.empty() ) |
| 690 | return valCache.at<float>( vi, si ); | 667 | return valCache.at<float>( vi, si ); |
| 691 | - return (*compat)( vi, si ); | 668 | + return (*featureEvaluator)( vi, si ); |
| 692 | } | 669 | } |
| 693 | 670 | ||
| 694 | - | ||
| 695 | struct FeatureIdxOnlyPrecalc : ParallelLoopBody | 671 | struct FeatureIdxOnlyPrecalc : ParallelLoopBody |
| 696 | { | 672 | { |
| 697 | - FeatureIdxOnlyPrecalc( const BoostBRCompatibility* _compat, CvMat* _buf, int _sample_count, bool _is_buf_16u ) | 673 | + FeatureIdxOnlyPrecalc( const FeatureEvaluator* _featureEvaluator, CvMat* _buf, int _sample_count, bool _is_buf_16u ) |
| 698 | { | 674 | { |
| 699 | - compat = _compat; | 675 | + featureEvaluator = _featureEvaluator; |
| 700 | sample_count = _sample_count; | 676 | sample_count = _sample_count; |
| 701 | udst = (unsigned short*)_buf->data.s; | 677 | udst = (unsigned short*)_buf->data.s; |
| 702 | idst = _buf->data.i; | 678 | idst = _buf->data.i; |
| @@ -710,7 +686,7 @@ struct FeatureIdxOnlyPrecalc : ParallelLoopBody | @@ -710,7 +686,7 @@ struct FeatureIdxOnlyPrecalc : ParallelLoopBody | ||
| 710 | { | 686 | { |
| 711 | for( int si = 0; si < sample_count; si++ ) | 687 | for( int si = 0; si < sample_count; si++ ) |
| 712 | { | 688 | { |
| 713 | - valCachePtr[si] = (*compat)( fi, si ); | 689 | + valCachePtr[si] = (*featureEvaluator)( fi, si ); |
| 714 | if ( is_buf_16u ) | 690 | if ( is_buf_16u ) |
| 715 | *(udst + fi*sample_count + si) = (unsigned short)si; | 691 | *(udst + fi*sample_count + si) = (unsigned short)si; |
| 716 | else | 692 | else |
| @@ -722,7 +698,7 @@ struct FeatureIdxOnlyPrecalc : ParallelLoopBody | @@ -722,7 +698,7 @@ struct FeatureIdxOnlyPrecalc : ParallelLoopBody | ||
| 722 | icvSortIntAux( idst + fi*sample_count, sample_count, valCachePtr ); | 698 | icvSortIntAux( idst + fi*sample_count, sample_count, valCachePtr ); |
| 723 | } | 699 | } |
| 724 | } | 700 | } |
| 725 | - const BoostBRCompatibility* compat; | 701 | + const FeatureEvaluator* featureEvaluator; |
| 726 | int sample_count; | 702 | int sample_count; |
| 727 | int* idst; | 703 | int* idst; |
| 728 | unsigned short* udst; | 704 | unsigned short* udst; |
| @@ -731,9 +707,9 @@ struct FeatureIdxOnlyPrecalc : ParallelLoopBody | @@ -731,9 +707,9 @@ struct FeatureIdxOnlyPrecalc : ParallelLoopBody | ||
| 731 | 707 | ||
| 732 | struct FeatureValAndIdxPrecalc : ParallelLoopBody | 708 | struct FeatureValAndIdxPrecalc : ParallelLoopBody |
| 733 | { | 709 | { |
| 734 | - FeatureValAndIdxPrecalc( const BoostBRCompatibility* _compat, CvMat* _buf, Mat* _valCache, int _sample_count, bool _is_buf_16u ) | 710 | + FeatureValAndIdxPrecalc( const FeatureEvaluator* _featureEvaluator, CvMat* _buf, Mat* _valCache, int _sample_count, bool _is_buf_16u ) |
| 735 | { | 711 | { |
| 736 | - compat = _compat; | 712 | + featureEvaluator = _featureEvaluator; |
| 737 | valCache = _valCache; | 713 | valCache = _valCache; |
| 738 | sample_count = _sample_count; | 714 | sample_count = _sample_count; |
| 739 | udst = (unsigned short*)_buf->data.s; | 715 | udst = (unsigned short*)_buf->data.s; |
| @@ -746,7 +722,7 @@ struct FeatureValAndIdxPrecalc : ParallelLoopBody | @@ -746,7 +722,7 @@ struct FeatureValAndIdxPrecalc : ParallelLoopBody | ||
| 746 | { | 722 | { |
| 747 | for( int si = 0; si < sample_count; si++ ) | 723 | for( int si = 0; si < sample_count; si++ ) |
| 748 | { | 724 | { |
| 749 | - valCache->at<float>(fi,si) = (*compat)( fi, si ); | 725 | + valCache->at<float>(fi,si) = (*featureEvaluator)( fi, si ); |
| 750 | if ( is_buf_16u ) | 726 | if ( is_buf_16u ) |
| 751 | *(udst + fi*sample_count + si) = (unsigned short)si; | 727 | *(udst + fi*sample_count + si) = (unsigned short)si; |
| 752 | else | 728 | else |
| @@ -758,7 +734,7 @@ struct FeatureValAndIdxPrecalc : ParallelLoopBody | @@ -758,7 +734,7 @@ struct FeatureValAndIdxPrecalc : ParallelLoopBody | ||
| 758 | icvSortIntAux( idst + fi*sample_count, sample_count, valCache->ptr<float>(fi) ); | 734 | icvSortIntAux( idst + fi*sample_count, sample_count, valCache->ptr<float>(fi) ); |
| 759 | } | 735 | } |
| 760 | } | 736 | } |
| 761 | - const BoostBRCompatibility* compat; | 737 | + const FeatureEvaluator* featureEvaluator; |
| 762 | Mat* valCache; | 738 | Mat* valCache; |
| 763 | int sample_count; | 739 | int sample_count; |
| 764 | int* idst; | 740 | int* idst; |
| @@ -768,9 +744,9 @@ struct FeatureValAndIdxPrecalc : ParallelLoopBody | @@ -768,9 +744,9 @@ struct FeatureValAndIdxPrecalc : ParallelLoopBody | ||
| 768 | 744 | ||
| 769 | struct FeatureValOnlyPrecalc : ParallelLoopBody | 745 | struct FeatureValOnlyPrecalc : ParallelLoopBody |
| 770 | { | 746 | { |
| 771 | - FeatureValOnlyPrecalc( const BoostBRCompatibility* _compat, Mat* _valCache, int _sample_count ) | 747 | + FeatureValOnlyPrecalc( const FeatureEvaluator* _featureEvaluator, Mat* _valCache, int _sample_count ) |
| 772 | { | 748 | { |
| 773 | - compat = _compat; | 749 | + featureEvaluator = _featureEvaluator; |
| 774 | valCache = _valCache; | 750 | valCache = _valCache; |
| 775 | sample_count = _sample_count; | 751 | sample_count = _sample_count; |
| 776 | } | 752 | } |
| @@ -778,9 +754,9 @@ struct FeatureValOnlyPrecalc : ParallelLoopBody | @@ -778,9 +754,9 @@ struct FeatureValOnlyPrecalc : ParallelLoopBody | ||
| 778 | { | 754 | { |
| 779 | for ( int fi = range.start; fi < range.end; fi++) | 755 | for ( int fi = range.start; fi < range.end; fi++) |
| 780 | for( int si = 0; si < sample_count; si++ ) | 756 | for( int si = 0; si < sample_count; si++ ) |
| 781 | - valCache->at<float>(fi,si) = (*compat)( fi, si ); | 757 | + valCache->at<float>(fi,si) = (*featureEvaluator)( fi, si ); |
| 782 | } | 758 | } |
| 783 | - const BoostBRCompatibility* compat; | 759 | + const FeatureEvaluator* featureEvaluator; |
| 784 | Mat* valCache; | 760 | Mat* valCache; |
| 785 | int sample_count; | 761 | int sample_count; |
| 786 | }; | 762 | }; |
| @@ -791,11 +767,11 @@ void CascadeBoostTrainData::precalculate() | @@ -791,11 +767,11 @@ void CascadeBoostTrainData::precalculate() | ||
| 791 | 767 | ||
| 792 | double proctime = -TIME( 0 ); | 768 | double proctime = -TIME( 0 ); |
| 793 | parallel_for_( Range(numPrecalcVal, numPrecalcIdx), | 769 | parallel_for_( Range(numPrecalcVal, numPrecalcIdx), |
| 794 | - FeatureIdxOnlyPrecalc(compat, buf, sample_count, is_buf_16u!=0) ); | 770 | + FeatureIdxOnlyPrecalc(featureEvaluator, buf, sample_count, is_buf_16u!=0) ); |
| 795 | parallel_for_( Range(0, minNum), | 771 | parallel_for_( Range(0, minNum), |
| 796 | - FeatureValAndIdxPrecalc(compat, buf, &valCache, sample_count, is_buf_16u!=0) ); | 772 | + FeatureValAndIdxPrecalc(featureEvaluator, buf, &valCache, sample_count, is_buf_16u!=0) ); |
| 797 | parallel_for_( Range(minNum, numPrecalcVal), | 773 | parallel_for_( Range(minNum, numPrecalcVal), |
| 798 | - FeatureValOnlyPrecalc(compat, &valCache, sample_count) ); | 774 | + FeatureValOnlyPrecalc(featureEvaluator, &valCache, sample_count) ); |
| 799 | cout << "Precalculation time: " << (proctime + TIME( 0 )) << endl; | 775 | cout << "Precalculation time: " << (proctime + TIME( 0 )) << endl; |
| 800 | } | 776 | } |
| 801 | 777 | ||
| @@ -807,7 +783,7 @@ CvDTreeNode* CascadeBoostTree::predict( int sampleIdx ) const | @@ -807,7 +783,7 @@ CvDTreeNode* CascadeBoostTree::predict( int sampleIdx ) const | ||
| 807 | if( !node ) | 783 | if( !node ) |
| 808 | CV_Error( CV_StsError, "The tree has not been trained yet" ); | 784 | CV_Error( CV_StsError, "The tree has not been trained yet" ); |
| 809 | 785 | ||
| 810 | - if ( ((CascadeBoostTrainData*)data)->compat->maxCatCount() == 0 ) // ordered | 786 | + if ( ((CascadeBoostTrainData*)data)->featureEvaluator->getMaxCatCount() == 0 ) // ordered |
| 811 | { | 787 | { |
| 812 | while( node->left ) | 788 | while( node->left ) |
| 813 | { | 789 | { |
| @@ -830,7 +806,7 @@ CvDTreeNode* CascadeBoostTree::predict( int sampleIdx ) const | @@ -830,7 +806,7 @@ CvDTreeNode* CascadeBoostTree::predict( int sampleIdx ) const | ||
| 830 | 806 | ||
| 831 | void CascadeBoostTree::write( FileStorage &fs, const Mat& featureMap ) | 807 | void CascadeBoostTree::write( FileStorage &fs, const Mat& featureMap ) |
| 832 | { | 808 | { |
| 833 | - int maxCatCount = ((CascadeBoostTrainData*)data)->compat->maxCatCount(); | 809 | + int maxCatCount = ((CascadeBoostTrainData*)data)->featureEvaluator->getMaxCatCount(); |
| 834 | int subsetN = (maxCatCount + 31)/32; | 810 | int subsetN = (maxCatCount + 31)/32; |
| 835 | queue<CvDTreeNode*> internalNodesQueue; | 811 | queue<CvDTreeNode*> internalNodesQueue; |
| 836 | int size = (int)pow( 2.f, (float)ensemble->get_params().max_depth); | 812 | int size = (int)pow( 2.f, (float)ensemble->get_params().max_depth); |
| @@ -1123,7 +1099,7 @@ void CascadeBoostTree::markFeaturesInMap( Mat& featureMap ) | @@ -1123,7 +1099,7 @@ void CascadeBoostTree::markFeaturesInMap( Mat& featureMap ) | ||
| 1123 | 1099 | ||
| 1124 | //----------------------------------- CascadeBoost -------------------------------------- | 1100 | //----------------------------------- CascadeBoost -------------------------------------- |
| 1125 | 1101 | ||
| 1126 | -bool CascadeBoost::train( const BoostBRCompatibility* _compat, | 1102 | +bool CascadeBoost::train( const FeatureEvaluator* _featureEvaluator, |
| 1127 | int _numSamples, | 1103 | int _numSamples, |
| 1128 | int _precalcValBufSize, int _precalcIdxBufSize, | 1104 | int _precalcValBufSize, int _precalcIdxBufSize, |
| 1129 | const CascadeBoostParams& _params ) | 1105 | const CascadeBoostParams& _params ) |
| @@ -1132,7 +1108,7 @@ bool CascadeBoost::train( const BoostBRCompatibility* _compat, | @@ -1132,7 +1108,7 @@ bool CascadeBoost::train( const BoostBRCompatibility* _compat, | ||
| 1132 | CV_Assert( !data ); | 1108 | CV_Assert( !data ); |
| 1133 | clear(); | 1109 | clear(); |
| 1134 | 1110 | ||
| 1135 | - data = new CascadeBoostTrainData( _compat, _numSamples, | 1111 | + data = new CascadeBoostTrainData( _featureEvaluator, _numSamples, |
| 1136 | _precalcValBufSize, _precalcIdxBufSize, _params ); | 1112 | _precalcValBufSize, _precalcIdxBufSize, _params ); |
| 1137 | 1113 | ||
| 1138 | CvMemStorage *storage = cvCreateMemStorage(); | 1114 | CvMemStorage *storage = cvCreateMemStorage(); |
| @@ -1154,7 +1130,6 @@ bool CascadeBoost::train( const BoostBRCompatibility* _compat, | @@ -1154,7 +1130,6 @@ bool CascadeBoost::train( const BoostBRCompatibility* _compat, | ||
| 1154 | CascadeBoostTree* tree = new CascadeBoostTree; | 1130 | CascadeBoostTree* tree = new CascadeBoostTree; |
| 1155 | if( !tree->train( data, subsample_mask, this ) ) | 1131 | if( !tree->train( data, subsample_mask, this ) ) |
| 1156 | { | 1132 | { |
| 1157 | - qDebug("Couldn't train tree"); | ||
| 1158 | delete tree; | 1133 | delete tree; |
| 1159 | break; | 1134 | break; |
| 1160 | } | 1135 | } |
| @@ -1454,7 +1429,7 @@ bool CascadeBoost::isErrDesired() | @@ -1454,7 +1429,7 @@ bool CascadeBoost::isErrDesired() | ||
| 1454 | vector<float> eval(sCount); | 1429 | vector<float> eval(sCount); |
| 1455 | 1430 | ||
| 1456 | for( int i = 0; i < sCount; i++ ) | 1431 | for( int i = 0; i < sCount; i++ ) |
| 1457 | - if( ((CascadeBoostTrainData*)data)->compat->getCls( i ) == 1.0F ) | 1432 | + if( ((CascadeBoostTrainData*)data)->featureEvaluator->getCls( i ) == 1.0F ) |
| 1458 | eval[numPos++] = predict( i, true ); | 1433 | eval[numPos++] = predict( i, true ); |
| 1459 | icvSortFlt( &eval[0], numPos, 0 ); | 1434 | icvSortFlt( &eval[0], numPos, 0 ); |
| 1460 | int thresholdIdx = (int)((1.0F - minHitRate) * numPos); | 1435 | int thresholdIdx = (int)((1.0F - minHitRate) * numPos); |
| @@ -1467,7 +1442,7 @@ bool CascadeBoost::isErrDesired() | @@ -1467,7 +1442,7 @@ bool CascadeBoost::isErrDesired() | ||
| 1467 | 1442 | ||
| 1468 | for( int i = 0; i < sCount; i++ ) | 1443 | for( int i = 0; i < sCount; i++ ) |
| 1469 | { | 1444 | { |
| 1470 | - if( ((CascadeBoostTrainData*)data)->compat->getCls( i ) == 0.0F ) | 1445 | + if( ((CascadeBoostTrainData*)data)->featureEvaluator->getCls( i ) == 0.0F ) |
| 1471 | { | 1446 | { |
| 1472 | numNeg++; | 1447 | numNeg++; |
| 1473 | if( predict( i ) ) | 1448 | if( predict( i ) ) |
openbr/core/boost.h
| @@ -13,52 +13,36 @@ struct CascadeBoostParams : CvBoostParams | @@ -13,52 +13,36 @@ struct CascadeBoostParams : CvBoostParams | ||
| 13 | float maxFalseAlarm; | 13 | float maxFalseAlarm; |
| 14 | 14 | ||
| 15 | CascadeBoostParams(); | 15 | CascadeBoostParams(); |
| 16 | - CascadeBoostParams( int _boostType, float _minHitRate, float _maxFalseAlarm, | ||
| 17 | - double _weightTrimRate, int _maxDepth, int _maxWeakCount ); | 16 | + CascadeBoostParams(int _boostType, float _minHitRate, float _maxFalseAlarm, |
| 17 | + double _weightTrimRate, int _maxDepth, int _maxWeakCount); | ||
| 18 | virtual ~CascadeBoostParams() {} | 18 | virtual ~CascadeBoostParams() {} |
| 19 | void write( cv::FileStorage &fs ) const; | 19 | void write( cv::FileStorage &fs ) const; |
| 20 | }; | 20 | }; |
| 21 | 21 | ||
| 22 | -struct BoostBRCompatibility | ||
| 23 | -{ | ||
| 24 | - BoostBRCompatibility(Representation *_representation, int _numSamples); | ||
| 25 | - void setImage(const cv::Mat &img, uchar clsLabel, int idx); | ||
| 26 | - float operator()(int featureIdx, int sampleIdx) const; | ||
| 27 | - const cv::Mat &getCls() const { return cls; } | ||
| 28 | - float getCls(int idx) const { return cls.at<float>(idx, 0); } | ||
| 29 | - | ||
| 30 | - int numFeatures() const { return representation->numFeatures(); } | ||
| 31 | - int maxCatCount() const { return 256; } | ||
| 32 | - | ||
| 33 | - Representation *representation; | ||
| 34 | - cv::Mat data, cls; | ||
| 35 | -}; | ||
| 36 | - | ||
| 37 | struct CascadeBoostTrainData : CvDTreeTrainData | 22 | struct CascadeBoostTrainData : CvDTreeTrainData |
| 38 | { | 23 | { |
| 39 | - CascadeBoostTrainData( const BoostBRCompatibility* _compat, | ||
| 40 | - const CvDTreeParams& _params ); | ||
| 41 | - CascadeBoostTrainData( const BoostBRCompatibility* _compat, | ||
| 42 | - int _numSamples, int _precalcValBufSize, int _precalcIdxBufSize, | ||
| 43 | - const CvDTreeParams& _params = CvDTreeParams() ); | ||
| 44 | - virtual void setData( const BoostBRCompatibility* _compat, | 24 | + CascadeBoostTrainData(const FeatureEvaluator* _featureEvaluator, const CvDTreeParams& _params); |
| 25 | + CascadeBoostTrainData(const FeatureEvaluator* _featureEvaluator, | ||
| 45 | int _numSamples, int _precalcValBufSize, int _precalcIdxBufSize, | 26 | int _numSamples, int _precalcValBufSize, int _precalcIdxBufSize, |
| 46 | - const CvDTreeParams& _params=CvDTreeParams() ); | 27 | + const CvDTreeParams& _params = CvDTreeParams()); |
| 28 | + virtual void setData(const FeatureEvaluator* _featureEvaluator, | ||
| 29 | + int _numSamples, int _precalcValBufSize, int _precalcIdxBufSize, | ||
| 30 | + const CvDTreeParams& _params=CvDTreeParams()); | ||
| 47 | void precalculate(); | 31 | void precalculate(); |
| 48 | 32 | ||
| 49 | - virtual CvDTreeNode* subsample_data( const CvMat* _subsample_idx ); | 33 | + virtual CvDTreeNode* subsample_data(const CvMat* _subsample_idx); |
| 50 | 34 | ||
| 51 | - virtual const int* get_class_labels( CvDTreeNode* n, int* labelsBuf ); | ||
| 52 | - virtual const int* get_cv_labels( CvDTreeNode* n, int* labelsBuf); | ||
| 53 | - virtual const int* get_sample_indices( CvDTreeNode* n, int* indicesBuf ); | 35 | + virtual const int* get_class_labels(CvDTreeNode* n, int* labelsBuf); |
| 36 | + virtual const int* get_cv_labels(CvDTreeNode* n, int* labelsBuf); | ||
| 37 | + virtual const int* get_sample_indices(CvDTreeNode* n, int* indicesBuf); | ||
| 54 | 38 | ||
| 55 | - virtual void get_ord_var_data( CvDTreeNode* n, int vi, float* ordValuesBuf, int* sortedIndicesBuf, | ||
| 56 | - const float** ordValues, const int** sortedIndices, int* sampleIndicesBuf ); | ||
| 57 | - virtual const int* get_cat_var_data( CvDTreeNode* n, int vi, int* catValuesBuf ); | ||
| 58 | - virtual float getVarValue( int vi, int si ); | 39 | + virtual void get_ord_var_data(CvDTreeNode* n, int vi, float* ordValuesBuf, int* sortedIndicesBuf, |
| 40 | + const float** ordValues, const int** sortedIndices, int* sampleIndicesBuf); | ||
| 41 | + virtual const int* get_cat_var_data(CvDTreeNode* n, int vi, int* catValuesBuf); | ||
| 42 | + virtual float getVarValue(int vi, int si); | ||
| 59 | virtual void free_train_data(); | 43 | virtual void free_train_data(); |
| 60 | 44 | ||
| 61 | - const BoostBRCompatibility* compat; | 45 | + const FeatureEvaluator* featureEvaluator; |
| 62 | cv::Mat valCache; // precalculated feature values (CV_32FC1) | 46 | cv::Mat valCache; // precalculated feature values (CV_32FC1) |
| 63 | CvMat _resp; // for casting | 47 | CvMat _resp; // for casting |
| 64 | int numPrecalcVal, numPrecalcIdx; | 48 | int numPrecalcVal, numPrecalcIdx; |
| @@ -67,27 +51,29 @@ struct CascadeBoostTrainData : CvDTreeTrainData | @@ -67,27 +51,29 @@ struct CascadeBoostTrainData : CvDTreeTrainData | ||
| 67 | class CascadeBoostTree : public CvBoostTree | 51 | class CascadeBoostTree : public CvBoostTree |
| 68 | { | 52 | { |
| 69 | public: | 53 | public: |
| 70 | - virtual CvDTreeNode* predict( int sampleIdx ) const; | ||
| 71 | - void write( cv::FileStorage &fs, const cv::Mat& featureMap ); | ||
| 72 | - void markFeaturesInMap( cv::Mat& featureMap ); | 54 | + virtual CvDTreeNode* predict(int sampleIdx) const; |
| 55 | + void write(cv::FileStorage &fs, const cv::Mat& featureMap); | ||
| 56 | + void markFeaturesInMap(cv::Mat& featureMap); | ||
| 57 | + | ||
| 73 | protected: | 58 | protected: |
| 74 | - virtual void split_node_data( CvDTreeNode* n ); | 59 | + virtual void split_node_data(CvDTreeNode* n); |
| 75 | }; | 60 | }; |
| 76 | 61 | ||
| 77 | class CascadeBoost : public CvBoost | 62 | class CascadeBoost : public CvBoost |
| 78 | { | 63 | { |
| 79 | public: | 64 | public: |
| 80 | - virtual bool train( const BoostBRCompatibility* _compat, | ||
| 81 | - int _numSamples, int _precalcValBufSize, int _precalcIdxBufSize, | ||
| 82 | - const CascadeBoostParams& _params=CascadeBoostParams() ); | 65 | + virtual bool train(const FeatureEvaluator *_featureEvaluator, |
| 66 | + int _numSamples, int _precalcValBufSize, int _precalcIdxBufSize, | ||
| 67 | + const CascadeBoostParams &_params=CascadeBoostParams()); | ||
| 83 | virtual float predict( int sampleIdx, bool returnSum = false ) const; | 68 | virtual float predict( int sampleIdx, bool returnSum = false ) const; |
| 84 | 69 | ||
| 85 | float getThreshold() const { return threshold; } | 70 | float getThreshold() const { return threshold; } |
| 86 | - void write( cv::FileStorage &fs, const cv::Mat& featureMap ) const; | ||
| 87 | - void markUsedFeaturesInMap( cv::Mat& featureMap ); | 71 | + void write(cv::FileStorage &fs, const cv::Mat& featureMap) const; |
| 72 | + void markUsedFeaturesInMap(cv::Mat& featureMap); | ||
| 73 | + | ||
| 88 | protected: | 74 | protected: |
| 89 | - virtual bool set_params( const CvBoostParams& _params ); | ||
| 90 | - virtual void update_weights( CvBoostTree* tree ); | 75 | + virtual bool set_params(const CvBoostParams& _params); |
| 76 | + virtual void update_weights(CvBoostTree* tree); | ||
| 91 | virtual bool isErrDesired(); | 77 | virtual bool isErrDesired(); |
| 92 | 78 | ||
| 93 | float threshold; | 79 | float threshold; |
openbr/core/cascade.cpp
| @@ -3,17 +3,17 @@ | @@ -3,17 +3,17 @@ | ||
| 3 | #include <iostream> | 3 | #include <iostream> |
| 4 | #include <fstream> | 4 | #include <fstream> |
| 5 | 5 | ||
| 6 | +using namespace std; | ||
| 6 | using namespace br; | 7 | using namespace br; |
| 7 | using namespace cv; | 8 | using namespace cv; |
| 8 | 9 | ||
| 9 | -bool CascadeImageReader::create( const QList<Mat> &_posImages, const QList<Mat> &_negImages, Size _winSize ) | 10 | +bool CascadeImageReader::create(const QList<Mat> &_posImages, const QList<Mat> &_negImages, Size _winSize) |
| 10 | { | 11 | { |
| 11 | posImages = _posImages; | 12 | posImages = _posImages; |
| 12 | negImages = _negImages; | 13 | negImages = _negImages; |
| 13 | winSize = _winSize; | 14 | winSize = _winSize; |
| 14 | 15 | ||
| 15 | - posIdx = 0; negIdx = 0; | ||
| 16 | - round = 0; | 16 | + posIdx = negIdx = 0; |
| 17 | 17 | ||
| 18 | src.create( 0, 0 , CV_8UC1 ); | 18 | src.create( 0, 0 , CV_8UC1 ); |
| 19 | img.create( 0, 0, CV_8UC1 ); | 19 | img.create( 0, 0, CV_8UC1 ); |
| @@ -21,22 +21,32 @@ bool CascadeImageReader::create( const QList<Mat> &_posImages, const QList<Mat> | @@ -21,22 +21,32 @@ bool CascadeImageReader::create( const QList<Mat> &_posImages, const QList<Mat> | ||
| 21 | scale = 1.0F; | 21 | scale = 1.0F; |
| 22 | scaleFactor = 1.4142135623730950488016887242097F; | 22 | scaleFactor = 1.4142135623730950488016887242097F; |
| 23 | stepFactor = 0.5F; | 23 | stepFactor = 0.5F; |
| 24 | + round = 0; | ||
| 24 | 25 | ||
| 25 | return true; | 26 | return true; |
| 26 | } | 27 | } |
| 27 | 28 | ||
| 28 | bool CascadeImageReader::nextNeg() | 29 | bool CascadeImageReader::nextNeg() |
| 29 | { | 30 | { |
| 30 | - src = negImages[negIdx++]; | ||
| 31 | - | ||
| 32 | - round += negIdx / negImages.size(); | ||
| 33 | - round = round % (winSize.width * winSize.height); | ||
| 34 | - negIdx %= negImages.size(); | ||
| 35 | - | ||
| 36 | - offset.x = std::min( (int)round % winSize.width, src.cols - winSize.width ); | ||
| 37 | - offset.y = std::min( (int)round / winSize.width, src.rows - winSize.height ); | 31 | + Point _offset = Point(0,0); |
| 32 | + size_t count = negImages.size(); | ||
| 33 | + for (size_t i = 0; i < count; i++) { | ||
| 34 | + src = negImages[negIdx++]; | ||
| 35 | + if( src.empty() ) | ||
| 36 | + continue; | ||
| 37 | + round += negIdx / count; | ||
| 38 | + round = round % (winSize.width * winSize.height); | ||
| 39 | + negIdx %= count; | ||
| 40 | + | ||
| 41 | + _offset.x = std::min( (int)round % winSize.width, src.cols - winSize.width ); | ||
| 42 | + _offset.y = std::min( (int)round / winSize.width, src.rows - winSize.height ); | ||
| 43 | + if( !src.empty() && src.type() == CV_8UC1 && _offset.x >= 0 && _offset.y >= 0 ) | ||
| 44 | + break; | ||
| 45 | + } | ||
| 38 | 46 | ||
| 39 | - point = offset; | 47 | + if( src.empty() ) |
| 48 | + return false; // no appropriate image | ||
| 49 | + point = offset = _offset; | ||
| 40 | scale = max( ((float)winSize.width + point.x) / ((float)src.cols), | 50 | scale = max( ((float)winSize.width + point.x) / ((float)src.cols), |
| 41 | ((float)winSize.height + point.y) / ((float)src.rows) ); | 51 | ((float)winSize.height + point.y) / ((float)src.rows) ); |
| 42 | 52 | ||
| @@ -56,7 +66,8 @@ bool CascadeImageReader::getNeg( Mat& _img ) | @@ -56,7 +66,8 @@ bool CascadeImageReader::getNeg( Mat& _img ) | ||
| 56 | if ( !nextNeg() ) | 66 | if ( !nextNeg() ) |
| 57 | return false; | 67 | return false; |
| 58 | 68 | ||
| 59 | - Mat mat( winSize.height, winSize.width, CV_8UC1, (void*)(img.data + point.y * img.step + point.x * img.elemSize()), img.step ); | 69 | + Mat mat( winSize.height, winSize.width, CV_8UC1, |
| 70 | + (void*)(img.data + point.y * img.step + point.x * img.elemSize()), img.step ); | ||
| 60 | mat.copyTo(_img); | 71 | mat.copyTo(_img); |
| 61 | 72 | ||
| 62 | if( (int)( point.x + (1.0F + stepFactor ) * winSize.width ) < img.cols ) | 73 | if( (int)( point.x + (1.0F + stepFactor ) * winSize.width ) < img.cols ) |
| @@ -82,11 +93,10 @@ bool CascadeImageReader::getNeg( Mat& _img ) | @@ -82,11 +93,10 @@ bool CascadeImageReader::getNeg( Mat& _img ) | ||
| 82 | return true; | 93 | return true; |
| 83 | } | 94 | } |
| 84 | 95 | ||
| 96 | + | ||
| 85 | bool CascadeImageReader::getPos(Mat &_img) | 97 | bool CascadeImageReader::getPos(Mat &_img) |
| 86 | { | 98 | { |
| 87 | - if (posIdx > (int)posImages.size()) | ||
| 88 | - CV_Error( CV_StsBadArg, "Can not get new positive sample. Not enough positive samples.\n"); | ||
| 89 | - _img = posImages[posIdx++]; | 99 | + posImages[posIdx++].copyTo(_img); |
| 90 | return true; | 100 | return true; |
| 91 | } | 101 | } |
| 92 | 102 | ||
| @@ -95,15 +105,16 @@ bool CascadeImageReader::getPos(Mat &_img) | @@ -95,15 +105,16 @@ bool CascadeImageReader::getPos(Mat &_img) | ||
| 95 | bool BrCascadeClassifier::train(const string _cascadeDirName, | 105 | bool BrCascadeClassifier::train(const string _cascadeDirName, |
| 96 | const QList<Mat> &_posImages, | 106 | const QList<Mat> &_posImages, |
| 97 | const QList<Mat> &_negImages, | 107 | const QList<Mat> &_negImages, |
| 108 | + int _numPos, int _numNeg, | ||
| 98 | int _precalcValBufSize, int _precalcIdxBufSize, | 109 | int _precalcValBufSize, int _precalcIdxBufSize, |
| 99 | - int _numPos, int _numNeg, int _numStages, | ||
| 100 | - Representation *_representation, | 110 | + int _numStages, |
| 111 | + Size _winSize, | ||
| 101 | const CascadeBoostParams& _stageParams) | 112 | const CascadeBoostParams& _stageParams) |
| 102 | { | 113 | { |
| 103 | // Start recording clock ticks for training time output | 114 | // Start recording clock ticks for training time output |
| 104 | const clock_t begin_time = clock(); | 115 | const clock_t begin_time = clock(); |
| 105 | 116 | ||
| 106 | - if( _cascadeDirName.empty() ) | 117 | + if (_cascadeDirName.empty()) |
| 107 | CV_Error( CV_StsBadArg, "_cascadeDirName is NULL" ); | 118 | CV_Error( CV_StsBadArg, "_cascadeDirName is NULL" ); |
| 108 | 119 | ||
| 109 | string dirName; | 120 | string dirName; |
| @@ -112,14 +123,17 @@ bool BrCascadeClassifier::train(const string _cascadeDirName, | @@ -112,14 +123,17 @@ bool BrCascadeClassifier::train(const string _cascadeDirName, | ||
| 112 | else | 123 | else |
| 113 | dirName = _cascadeDirName + '/'; | 124 | dirName = _cascadeDirName + '/'; |
| 114 | 125 | ||
| 115 | - compat = new BoostBRCompatibility(_representation, _numPos + _numNeg); | 126 | + winSize = _winSize; |
| 127 | + | ||
| 116 | numPos = _numPos; | 128 | numPos = _numPos; |
| 117 | numNeg = _numNeg; | 129 | numNeg = _numNeg; |
| 118 | numStages = _numStages; | 130 | numStages = _numStages; |
| 119 | - imgReader.create(_posImages, _negImages, _representation->windowSize()); | 131 | + imgReader.create(_posImages, _negImages, winSize); |
| 120 | 132 | ||
| 121 | stageParams = new CascadeBoostParams; | 133 | stageParams = new CascadeBoostParams; |
| 122 | *stageParams = _stageParams; | 134 | *stageParams = _stageParams; |
| 135 | + featureEvaluator = new FeatureEvaluator; | ||
| 136 | + featureEvaluator->init(numPos + numNeg, winSize); | ||
| 123 | stageClassifiers.reserve( numStages ); | 137 | stageClassifiers.reserve( numStages ); |
| 124 | 138 | ||
| 125 | double requiredLeafFARate = pow( (double) stageParams->maxFalseAlarm, (double) numStages ) / | 139 | double requiredLeafFARate = pow( (double) stageParams->maxFalseAlarm, (double) numStages ) / |
| @@ -127,31 +141,29 @@ bool BrCascadeClassifier::train(const string _cascadeDirName, | @@ -127,31 +141,29 @@ bool BrCascadeClassifier::train(const string _cascadeDirName, | ||
| 127 | double tempLeafFARate; | 141 | double tempLeafFARate; |
| 128 | 142 | ||
| 129 | for (int i = 0; i < numStages; i++) { | 143 | for (int i = 0; i < numStages; i++) { |
| 130 | - qDebug() << endl << "===== TRAINING " << i << "-stage ====="; | ||
| 131 | - qDebug() << "<BEGIN"; | ||
| 132 | - if ( !updateTrainingSet( tempLeafFARate ) ) | ||
| 133 | - { | ||
| 134 | - qDebug() << "Train dataset for temp stage can not be filled. " | ||
| 135 | - "Branch training terminated."; | 144 | + cout << endl << "===== TRAINING " << i << "-stage =====" << endl; |
| 145 | + cout << "<BEGIN" << endl; | ||
| 146 | + if (!updateTrainingSet(tempLeafFARate)) { | ||
| 147 | + cout << "Train dataset for temp stage can not be filled. " | ||
| 148 | + "Branch training terminated." << endl; | ||
| 136 | break; | 149 | break; |
| 137 | } | 150 | } |
| 138 | - if( tempLeafFARate <= requiredLeafFARate ) | ||
| 139 | - { | ||
| 140 | - qDebug() << "Required leaf false alarm rate achieved. " | ||
| 141 | - "Branch training terminated."; | 151 | + if (tempLeafFARate <= requiredLeafFARate) { |
| 152 | + cout << "Required leaf false alarm rate achieved. " | ||
| 153 | + "Branch training terminated." << endl; | ||
| 142 | break; | 154 | break; |
| 143 | } | 155 | } |
| 144 | 156 | ||
| 145 | CascadeBoost* tempStage = new CascadeBoost; | 157 | CascadeBoost* tempStage = new CascadeBoost; |
| 146 | - bool isStageTrained = tempStage->train( (BoostBRCompatibility*)compat, | 158 | + bool isStageTrained = tempStage->train( (FeatureEvaluator*)featureEvaluator, |
| 147 | curNumSamples, _precalcValBufSize, _precalcIdxBufSize, | 159 | curNumSamples, _precalcValBufSize, _precalcIdxBufSize, |
| 148 | *((CascadeBoostParams*)stageParams) ); | 160 | *((CascadeBoostParams*)stageParams) ); |
| 149 | - qDebug() << "END>"; | 161 | + cout << "END>" << endl; |
| 150 | 162 | ||
| 151 | - if(!isStageTrained) | 163 | + if (!isStageTrained) |
| 152 | break; | 164 | break; |
| 153 | 165 | ||
| 154 | - stageClassifiers.push_back( tempStage ); | 166 | + stageClassifiers.push_back(tempStage); |
| 155 | 167 | ||
| 156 | // Output training time up till now | 168 | // Output training time up till now |
| 157 | float seconds = float( clock () - begin_time ) / CLOCKS_PER_SEC; | 169 | float seconds = float( clock () - begin_time ) / CLOCKS_PER_SEC; |
| @@ -159,12 +171,11 @@ bool BrCascadeClassifier::train(const string _cascadeDirName, | @@ -159,12 +171,11 @@ bool BrCascadeClassifier::train(const string _cascadeDirName, | ||
| 159 | int hours = (int(seconds) / 60 / 60) % 24; | 171 | int hours = (int(seconds) / 60 / 60) % 24; |
| 160 | int minutes = (int(seconds) / 60) % 60; | 172 | int minutes = (int(seconds) / 60) % 60; |
| 161 | int seconds_left = int(seconds) % 60; | 173 | int seconds_left = int(seconds) % 60; |
| 162 | - qDebug() << "Training until now has taken " << days << " days " << hours << " hours " << minutes << " minutes " << seconds_left <<" seconds."; | 174 | + cout << "Training until now has taken " << days << " days " << hours << " hours " << minutes << " minutes " << seconds_left <<" seconds." << endl; |
| 163 | } | 175 | } |
| 164 | 176 | ||
| 165 | - if(stageClassifiers.size() == 0) | ||
| 166 | - { | ||
| 167 | - qDebug() << "Cascade classifier can't be trained. Check the used training parameters."; | 177 | + if (stageClassifiers.size() == 0) { |
| 178 | + cout << "Cascade classifier can't be trained. Check the used training parameters." << endl; | ||
| 168 | return false; | 179 | return false; |
| 169 | } | 180 | } |
| 170 | 181 | ||
| @@ -193,7 +204,7 @@ bool BrCascadeClassifier::updateTrainingSet( double& acceptanceRatio) | @@ -193,7 +204,7 @@ bool BrCascadeClassifier::updateTrainingSet( double& acceptanceRatio) | ||
| 193 | int posCount = fillPassedSamples( 0, numPos, true, posConsumed ); | 204 | int posCount = fillPassedSamples( 0, numPos, true, posConsumed ); |
| 194 | if( !posCount ) | 205 | if( !posCount ) |
| 195 | return false; | 206 | return false; |
| 196 | - qDebug() << "POS count : consumed " << posCount << " : " << (int)posConsumed; | 207 | + cout << "POS count : consumed " << posCount << " : " << (int)posConsumed << endl; |
| 197 | 208 | ||
| 198 | int proNumNeg = cvRound( ( ((double)numNeg) * ((double)posCount) ) / numPos ); // apply only a fraction of negative samples. double is required since overflow is possible | 209 | int proNumNeg = cvRound( ( ((double)numNeg) * ((double)posCount) ) / numPos ); // apply only a fraction of negative samples. double is required since overflow is possible |
| 199 | int negCount = fillPassedSamples( posCount, proNumNeg, false, negConsumed ); | 210 | int negCount = fillPassedSamples( posCount, proNumNeg, false, negConsumed ); |
| @@ -202,14 +213,14 @@ bool BrCascadeClassifier::updateTrainingSet( double& acceptanceRatio) | @@ -202,14 +213,14 @@ bool BrCascadeClassifier::updateTrainingSet( double& acceptanceRatio) | ||
| 202 | 213 | ||
| 203 | curNumSamples = posCount + negCount; | 214 | curNumSamples = posCount + negCount; |
| 204 | acceptanceRatio = negConsumed == 0 ? 0 : ( (double)negCount/(double)(int64)negConsumed ); | 215 | acceptanceRatio = negConsumed == 0 ? 0 : ( (double)negCount/(double)(int64)negConsumed ); |
| 205 | - qDebug() << "NEG count : acceptanceRatio " << negCount << " : " << acceptanceRatio; | 216 | + cout << "NEG count : acceptanceRatio " << negCount << " : " << acceptanceRatio << endl; |
| 206 | return true; | 217 | return true; |
| 207 | } | 218 | } |
| 208 | 219 | ||
| 209 | int BrCascadeClassifier::fillPassedSamples( int first, int count, bool isPositive, int64& consumed ) | 220 | int BrCascadeClassifier::fillPassedSamples( int first, int count, bool isPositive, int64& consumed ) |
| 210 | { | 221 | { |
| 211 | int getcount = 0; | 222 | int getcount = 0; |
| 212 | - Mat img(compat->representation->windowSize(), CV_8UC1); | 223 | + Mat img(winSize, CV_8UC1); |
| 213 | for( int i = first; i < first + count; i++ ) | 224 | for( int i = first; i < first + count; i++ ) |
| 214 | { | 225 | { |
| 215 | for( ; ; ) | 226 | for( ; ; ) |
| @@ -220,7 +231,7 @@ int BrCascadeClassifier::fillPassedSamples( int first, int count, bool isPositiv | @@ -220,7 +231,7 @@ int BrCascadeClassifier::fillPassedSamples( int first, int count, bool isPositiv | ||
| 220 | return getcount; | 231 | return getcount; |
| 221 | consumed++; | 232 | consumed++; |
| 222 | 233 | ||
| 223 | - compat->setImage( img, isPositive ? 1 : 0, i ); | 234 | + featureEvaluator->setImage( img, isPositive ? 1 : 0, i ); |
| 224 | if( predict( i ) == 1.0F ) | 235 | if( predict( i ) == 1.0F ) |
| 225 | { | 236 | { |
| 226 | getcount++; | 237 | getcount++; |
| @@ -238,13 +249,18 @@ void BrCascadeClassifier::writeParams( FileStorage &fs ) const | @@ -238,13 +249,18 @@ void BrCascadeClassifier::writeParams( FileStorage &fs ) const | ||
| 238 | fs << CC_FEATURE_TYPE << CC_LBP; | 249 | fs << CC_FEATURE_TYPE << CC_LBP; |
| 239 | fs << CC_HEIGHT << winSize.height; | 250 | fs << CC_HEIGHT << winSize.height; |
| 240 | fs << CC_WIDTH << winSize.width; | 251 | fs << CC_WIDTH << winSize.width; |
| 252 | + | ||
| 241 | fs << CC_STAGE_PARAMS << "{"; stageParams->write( fs ); fs << "}"; | 253 | fs << CC_STAGE_PARAMS << "{"; stageParams->write( fs ); fs << "}"; |
| 242 | - fs << CC_FEATURE_PARAMS << "{"; fs << CC_MAX_CAT_COUNT << 256; fs << CC_FEATURE_SIZE << 1; fs << "}"; | 254 | + |
| 255 | + fs << CC_FEATURE_PARAMS << "{"; | ||
| 256 | + fs << CC_MAX_CAT_COUNT << featureEvaluator->getMaxCatCount(); | ||
| 257 | + fs << CC_FEATURE_SIZE << featureEvaluator->getFeatureSize(); | ||
| 258 | + fs << "}"; | ||
| 243 | } | 259 | } |
| 244 | 260 | ||
| 245 | void BrCascadeClassifier::writeFeatures( FileStorage &fs, const Mat& featureMap ) const | 261 | void BrCascadeClassifier::writeFeatures( FileStorage &fs, const Mat& featureMap ) const |
| 246 | { | 262 | { |
| 247 | - compat->representation->write(fs, featureMap); | 263 | + ((FeatureEvaluator*)((Ptr<FeatureEvaluator>)featureEvaluator))->writeFeatures( fs, featureMap ); |
| 248 | } | 264 | } |
| 249 | 265 | ||
| 250 | void BrCascadeClassifier::writeStages( FileStorage &fs, const Mat& featureMap ) const | 266 | void BrCascadeClassifier::writeStages( FileStorage &fs, const Mat& featureMap ) const |
| @@ -285,7 +301,7 @@ void BrCascadeClassifier::save(const string filename) | @@ -285,7 +301,7 @@ void BrCascadeClassifier::save(const string filename) | ||
| 285 | 301 | ||
| 286 | void BrCascadeClassifier::getUsedFeaturesIdxMap( Mat& featureMap ) | 302 | void BrCascadeClassifier::getUsedFeaturesIdxMap( Mat& featureMap ) |
| 287 | { | 303 | { |
| 288 | - int varCount = compat->numFeatures(); | 304 | + int varCount = featureEvaluator->getNumFeatures() * featureEvaluator->getFeatureSize(); |
| 289 | featureMap.create( 1, varCount, CV_32SC1 ); | 305 | featureMap.create( 1, varCount, CV_32SC1 ); |
| 290 | featureMap.setTo(Scalar(-1)); | 306 | featureMap.setTo(Scalar(-1)); |
| 291 | 307 | ||
| @@ -298,4 +314,3 @@ void BrCascadeClassifier::getUsedFeaturesIdxMap( Mat& featureMap ) | @@ -298,4 +314,3 @@ void BrCascadeClassifier::getUsedFeaturesIdxMap( Mat& featureMap ) | ||
| 298 | featureMap.ptr<int>(0)[fi] = idx++; | 314 | featureMap.ptr<int>(0)[fi] = idx++; |
| 299 | } | 315 | } |
| 300 | 316 | ||
| 301 | - |
openbr/core/cascade.h
| 1 | -#ifndef _CASCADE_H | ||
| 2 | -#define _CASCADE_H | 1 | +#ifndef CASCADE_H |
| 2 | +#define CASCADE_H | ||
| 3 | 3 | ||
| 4 | #include <openbr/openbr_plugin.h> | 4 | #include <openbr/openbr_plugin.h> |
| 5 | #include <opencv2/highgui/highgui.hpp> | 5 | #include <opencv2/highgui/highgui.hpp> |
| @@ -17,9 +17,6 @@ public: | @@ -17,9 +17,6 @@ public: | ||
| 17 | bool getNeg(cv::Mat &_img); | 17 | bool getNeg(cv::Mat &_img); |
| 18 | bool getPos(cv::Mat &_img); | 18 | bool getPos(cv::Mat &_img); |
| 19 | 19 | ||
| 20 | -private: | ||
| 21 | - bool nextNeg(); | ||
| 22 | - | ||
| 23 | QList<cv::Mat> posImages, negImages; | 20 | QList<cv::Mat> posImages, negImages; |
| 24 | 21 | ||
| 25 | int posIdx, negIdx; | 22 | int posIdx, negIdx; |
| @@ -31,42 +28,45 @@ private: | @@ -31,42 +28,45 @@ private: | ||
| 31 | float stepFactor; | 28 | float stepFactor; |
| 32 | size_t round; | 29 | size_t round; |
| 33 | cv::Size winSize; | 30 | cv::Size winSize; |
| 31 | + | ||
| 32 | +private: | ||
| 33 | + bool nextNeg(); | ||
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | + | ||
| 36 | class BrCascadeClassifier | 37 | class BrCascadeClassifier |
| 37 | { | 38 | { |
| 38 | public: | 39 | public: |
| 39 | bool train(const std::string _cascadeDirName, | 40 | bool train(const std::string _cascadeDirName, |
| 40 | - const QList<cv::Mat> &_posImages, | ||
| 41 | - const QList<cv::Mat> &_negImages, | ||
| 42 | - int _precalcValBufSize, int _precalcIdxBufSize, | ||
| 43 | - int _numPos, int _numNeg, int _numStages, | ||
| 44 | - Representation *_representation, | ||
| 45 | - const CascadeBoostParams& _stageParams); | 41 | + const QList<cv::Mat> &_posImages, |
| 42 | + const QList<cv::Mat> &_negImages, | ||
| 43 | + int _numPos, int _numNeg, | ||
| 44 | + int _precalcValBufSize, int _precalcIdxBufSize, | ||
| 45 | + int _numStages, | ||
| 46 | + cv::Size _winSize, | ||
| 47 | + const CascadeBoostParams& _stageParams); | ||
| 46 | private: | 48 | private: |
| 47 | - int predict( int sampleIdx ); | 49 | + int predict(int sampleIdx); |
| 48 | void save(const std::string cascadeDirName); | 50 | void save(const std::string cascadeDirName); |
| 49 | - bool updateTrainingSet( double& acceptanceRatio ); | ||
| 50 | - int fillPassedSamples( int first, int count, bool isPositive, int64& consumed ); | 51 | + bool updateTrainingSet(double& acceptanceRatio); |
| 52 | + int fillPassedSamples(int first, int count, bool isPositive, int64& consumed); | ||
| 51 | 53 | ||
| 52 | - void writeParams( cv::FileStorage &fs ) const; | ||
| 53 | - void writeStages( cv::FileStorage &fs, const cv::Mat& featureMap ) const; | ||
| 54 | - void writeFeatures( cv::FileStorage &fs, const cv::Mat& featureMap ) const; | 54 | + void writeParams(cv::FileStorage &fs) const; |
| 55 | + void writeStages(cv::FileStorage &fs, const cv::Mat& featureMap) const; | ||
| 56 | + void writeFeatures(cv::FileStorage &fs, const cv::Mat& featureMap) const; | ||
| 55 | 57 | ||
| 56 | - void getUsedFeaturesIdxMap( cv::Mat& featureMap ); | 58 | + void getUsedFeaturesIdxMap(cv::Mat& featureMap); |
| 57 | 59 | ||
| 58 | cv::Ptr<CascadeBoostParams> stageParams; | 60 | cv::Ptr<CascadeBoostParams> stageParams; |
| 59 | 61 | ||
| 60 | - cv::Ptr<LBPTrainingEvaluator> featureEvaluator; | ||
| 61 | - cv::Ptr<BoostBRCompatibility> compat; | 62 | + cv::Ptr<FeatureEvaluator> featureEvaluator; |
| 62 | std::vector< cv::Ptr<CascadeBoost> > stageClassifiers; | 63 | std::vector< cv::Ptr<CascadeBoost> > stageClassifiers; |
| 63 | CascadeImageReader imgReader; | 64 | CascadeImageReader imgReader; |
| 64 | - cv::Size winSize; | ||
| 65 | int numStages, curNumSamples; | 65 | int numStages, curNumSamples; |
| 66 | int numPos, numNeg; | 66 | int numPos, numNeg; |
| 67 | + cv::Size winSize; | ||
| 67 | }; | 68 | }; |
| 68 | 69 | ||
| 69 | } // namespace br | 70 | } // namespace br |
| 70 | 71 | ||
| 71 | -#endif // _CASCADE_H | ||
| 72 | - | 72 | +#endif // CASCADE_H |
openbr/core/features.cpp
| 1 | #include "features.h" | 1 | #include "features.h" |
| 2 | -#include "opencvutils.h" | ||
| 3 | 2 | ||
| 4 | using namespace cv; | 3 | using namespace cv; |
| 5 | using namespace br; | 4 | using namespace br; |
| 6 | 5 | ||
| 7 | -// ------------------------------------ LBP Training ----------------------------------------------- | 6 | +//------------------------------------- FeatureEvaluator --------------------------------------- |
| 8 | 7 | ||
| 9 | -void LBPTrainingEvaluator::init(int _maxSampleCount, Size _winSize) | 8 | +void FeatureEvaluator::init(int _maxSampleCount, Size _winSize ) |
| 10 | { | 9 | { |
| 11 | - CV_Assert( _maxSampleCount > 0); | ||
| 12 | - sum.create((int)_maxSampleCount, (_winSize.width + 1) * (_winSize.height + 1), CV_32SC1); | ||
| 13 | - | 10 | + CV_Assert(_maxSampleCount > 0); |
| 14 | winSize = _winSize; | 11 | winSize = _winSize; |
| 15 | numFeatures = 0; | 12 | numFeatures = 0; |
| 16 | - maxCatCount = 256; | 13 | + data.create((int)_maxSampleCount, (_winSize.width + 1) * (_winSize.height + 1), CV_32SC1); |
| 17 | cls.create( (int)_maxSampleCount, 1, CV_32FC1 ); | 14 | cls.create( (int)_maxSampleCount, 1, CV_32FC1 ); |
| 15 | + | ||
| 16 | + maxCatCount = 256; | ||
| 17 | + featSize = 1; | ||
| 18 | + | ||
| 18 | generateFeatures(); | 19 | generateFeatures(); |
| 19 | } | 20 | } |
| 20 | 21 | ||
| 21 | -void LBPTrainingEvaluator::setImage(const Mat &img, uchar clsLabel, int idx) | 22 | +void FeatureEvaluator::setImage(const Mat &img, uchar clsLabel, int idx) |
| 22 | { | 23 | { |
| 23 | - CV_DbgAssert( !sum.empty() ); | 24 | + CV_Assert(img.cols == winSize.width); |
| 25 | + CV_Assert(img.rows == winSize.height); | ||
| 26 | + CV_Assert(idx < cls.rows); | ||
| 24 | cls.ptr<float>(idx)[0] = clsLabel; | 27 | cls.ptr<float>(idx)[0] = clsLabel; |
| 25 | - Mat innSum(winSize.height + 1, winSize.width + 1, sum.type(), sum.ptr<int>((int)idx)); | ||
| 26 | - integral( img, innSum ); | 28 | + Mat integralImg(winSize.height + 1, winSize.width + 1, data.type(), data.ptr<int>(idx)); |
| 29 | + integral(img, integralImg); | ||
| 27 | } | 30 | } |
| 28 | 31 | ||
| 29 | -void LBPTrainingEvaluator::writeFeatures( FileStorage &fs, const Mat& featureMap ) const | 32 | +void FeatureEvaluator::writeFeatures(FileStorage &fs, const Mat &featureMap) const |
| 30 | { | 33 | { |
| 31 | _writeFeatures( features, fs, featureMap ); | 34 | _writeFeatures( features, fs, featureMap ); |
| 32 | } | 35 | } |
| 33 | 36 | ||
| 34 | -void LBPTrainingEvaluator::generateFeatures() | 37 | +void FeatureEvaluator::generateFeatures() |
| 35 | { | 38 | { |
| 36 | int offset = winSize.width + 1; | 39 | int offset = winSize.width + 1; |
| 37 | - for( int x = 0; x < winSize.width; x++ ) | ||
| 38 | - for( int y = 0; y < winSize.height; y++ ) | ||
| 39 | - for( int w = 1; w <= winSize.width / 3; w++ ) | ||
| 40 | - for( int h = 1; h <= winSize.height / 3; h++ ) | ||
| 41 | - if ( (x+3*w <= winSize.width) && (y+3*h <= winSize.height) ) | ||
| 42 | - features.push_back( Feature(offset, x, y, w, h ) ); | 40 | + for (int x = 0; x < winSize.width; x++) |
| 41 | + for (int y = 0; y < winSize.height; y++) | ||
| 42 | + for (int w = 1; w <= winSize.width / 3; w++) | ||
| 43 | + for (int h = 1; h <= winSize.height / 3; h++) | ||
| 44 | + if ((x+3*w <= winSize.width) && (y+3*h <= winSize.height)) | ||
| 45 | + features.push_back(Feature(offset, x, y, w, h )); | ||
| 43 | numFeatures = (int)features.size(); | 46 | numFeatures = (int)features.size(); |
| 44 | } | 47 | } |
| 45 | 48 | ||
| 46 | -LBPTrainingEvaluator::Feature::Feature() | 49 | +FeatureEvaluator::Feature::Feature() |
| 47 | { | 50 | { |
| 48 | rect = cvRect(0, 0, 0, 0); | 51 | rect = cvRect(0, 0, 0, 0); |
| 49 | } | 52 | } |
| 50 | 53 | ||
| 51 | -LBPTrainingEvaluator::Feature::Feature( int offset, int x, int y, int _blockWidth, int _blockHeight ) | 54 | +FeatureEvaluator::Feature::Feature( int offset, int x, int y, int _blockWidth, int _blockHeight ) |
| 52 | { | 55 | { |
| 53 | Rect tr = rect = cvRect(x, y, _blockWidth, _blockHeight); | 56 | Rect tr = rect = cvRect(x, y, _blockWidth, _blockHeight); |
| 54 | CV_SUM_OFFSETS( p[0], p[1], p[4], p[5], tr, offset ) | 57 | CV_SUM_OFFSETS( p[0], p[1], p[4], p[5], tr, offset ) |
| @@ -60,7 +63,7 @@ LBPTrainingEvaluator::Feature::Feature( int offset, int x, int y, int _blockWidt | @@ -60,7 +63,7 @@ LBPTrainingEvaluator::Feature::Feature( int offset, int x, int y, int _blockWidt | ||
| 60 | CV_SUM_OFFSETS( p[8], p[9], p[12], p[13], tr, offset ) | 63 | CV_SUM_OFFSETS( p[8], p[9], p[12], p[13], tr, offset ) |
| 61 | } | 64 | } |
| 62 | 65 | ||
| 63 | -void LBPTrainingEvaluator::Feature::write(FileStorage &fs) const | 66 | +void FeatureEvaluator::Feature::write(FileStorage &fs) const |
| 64 | { | 67 | { |
| 65 | fs << CC_RECT << "[:" << rect.x << rect.y << rect.width << rect.height << "]"; | 68 | fs << CC_RECT << "[:" << rect.x << rect.y << rect.width << rect.height << "]"; |
| 66 | } | 69 | } |
openbr/core/features.h
| @@ -27,7 +27,7 @@ | @@ -27,7 +27,7 @@ | ||
| 27 | #define CC_MINHITRATE "minHitRate" | 27 | #define CC_MINHITRATE "minHitRate" |
| 28 | #define CC_MAXFALSEALARM "maxFalseAlarm" | 28 | #define CC_MAXFALSEALARM "maxFalseAlarm" |
| 29 | #define CC_TRIM_RATE "weightTrimRate" | 29 | #define CC_TRIM_RATE "weightTrimRate" |
| 30 | -#define CC_MAX_DEPTH "maxDepth" | 30 | +#define CC_MAX_DEPTH "maxDeptrh" |
| 31 | #define CC_WEAK_COUNT "maxWeakCount" | 31 | #define CC_WEAK_COUNT "maxWeakCount" |
| 32 | #define CC_STAGE_THRESHOLD "stageThreshold" | 32 | #define CC_STAGE_THRESHOLD "stageThreshold" |
| 33 | #define CC_WEAK_CLASSIFIERS "weakClassifiers" | 33 | #define CC_WEAK_CLASSIFIERS "weakClassifiers" |
| @@ -39,24 +39,9 @@ | @@ -39,24 +39,9 @@ | ||
| 39 | #define CC_MAX_CAT_COUNT "maxCatCount" | 39 | #define CC_MAX_CAT_COUNT "maxCatCount" |
| 40 | #define CC_FEATURE_SIZE "featSize" | 40 | #define CC_FEATURE_SIZE "featSize" |
| 41 | 41 | ||
| 42 | -#define CC_HAAR "HAAR" | ||
| 43 | -#define CC_MODE "mode" | ||
| 44 | -#define CC_MODE_BASIC "BASIC" | ||
| 45 | -#define CC_MODE_CORE "CORE" | ||
| 46 | -#define CC_MODE_ALL "ALL" | ||
| 47 | -#define CC_RECTS "rects" | ||
| 48 | -#define CC_TILTED "tilted" | ||
| 49 | - | ||
| 50 | #define CC_LBP "LBP" | 42 | #define CC_LBP "LBP" |
| 51 | #define CC_RECT "rect" | 43 | #define CC_RECT "rect" |
| 52 | 44 | ||
| 53 | -#define CC_HOG "HOG" | ||
| 54 | -#define CC_HOGMULTI "HOGMulti" | ||
| 55 | - | ||
| 56 | -#define CC_NPD "NPD" | ||
| 57 | -#define CC_POINTS "points" | ||
| 58 | -#define CC_POINT "point" | ||
| 59 | - | ||
| 60 | #ifdef _WIN32 | 45 | #ifdef _WIN32 |
| 61 | #define TIME( arg ) (((double) clock()) / CLOCKS_PER_SEC) | 46 | #define TIME( arg ) (((double) clock()) / CLOCKS_PER_SEC) |
| 62 | #else | 47 | #else |
| @@ -73,43 +58,6 @@ | @@ -73,43 +58,6 @@ | ||
| 73 | /* (x + w, y + h) */ \ | 58 | /* (x + w, y + h) */ \ |
| 74 | (p3) = (rect).x + (rect).width + (step) * ((rect).y + (rect).height); | 59 | (p3) = (rect).x + (rect).width + (step) * ((rect).y + (rect).height); |
| 75 | 60 | ||
| 76 | -#define CV_TILTED_OFFSETS( p0, p1, p2, p3, rect, step ) \ | ||
| 77 | - /* (x, y) */ \ | ||
| 78 | - (p0) = (rect).x + (step) * (rect).y; \ | ||
| 79 | - /* (x - h, y + h) */ \ | ||
| 80 | - (p1) = (rect).x - (rect).height + (step) * ((rect).y + (rect).height);\ | ||
| 81 | - /* (x + w, y + w) */ \ | ||
| 82 | - (p2) = (rect).x + (rect).width + (step) * ((rect).y + (rect).width); \ | ||
| 83 | - /* (x + w - h, y + w + h) */ \ | ||
| 84 | - (p3) = (rect).x + (rect).width - (rect).height \ | ||
| 85 | - + (step) * ((rect).y + (rect).width + (rect).height); | ||
| 86 | - | ||
| 87 | -#define CV_SUM_PTRS( p0, p1, p2, p3, sum, rect, step ) \ | ||
| 88 | - /* (x, y) */ \ | ||
| 89 | - (p0) = sum + (rect).x + (step) * (rect).y, \ | ||
| 90 | - /* (x + w, y) */ \ | ||
| 91 | - (p1) = sum + (rect).x + (rect).width + (step) * (rect).y, \ | ||
| 92 | - /* (x, y + h) */ \ | ||
| 93 | - (p2) = sum + (rect).x + (step) * ((rect).y + (rect).height), \ | ||
| 94 | - /* (x + w, y + h) */ \ | ||
| 95 | - (p3) = sum + (rect).x + (rect).width + (step) * ((rect).y + (rect).height) | ||
| 96 | - | ||
| 97 | -#define CV_TILTED_PTRS( p0, p1, p2, p3, tilted, rect, step ) \ | ||
| 98 | - /* (x, y) */ \ | ||
| 99 | - (p0) = tilted + (rect).x + (step) * (rect).y, \ | ||
| 100 | - /* (x - h, y + h) */ \ | ||
| 101 | - (p1) = tilted + (rect).x - (rect).height + (step) * ((rect).y + (rect).height), \ | ||
| 102 | - /* (x + w, y + w) */ \ | ||
| 103 | - (p2) = tilted + (rect).x + (rect).width + (step) * ((rect).y + (rect).width), \ | ||
| 104 | - /* (x + w - h, y + w + h) */ \ | ||
| 105 | - (p3) = tilted + (rect).x + (rect).width - (rect).height \ | ||
| 106 | - + (step) * ((rect).y + (rect).width + (rect).height) | ||
| 107 | - | ||
| 108 | -#define CALC_SUM_(p0, p1, p2, p3, offset) \ | ||
| 109 | - ((p0)[offset] - (p1)[offset] - (p2)[offset] + (p3)[offset]) | ||
| 110 | - | ||
| 111 | -#define CALC_SUM(rect,offset) CALC_SUM_((rect)[0], (rect)[1], (rect)[2], (rect)[3], offset) | ||
| 112 | - | ||
| 113 | namespace br | 61 | namespace br |
| 114 | { | 62 | { |
| 115 | 63 | ||
| @@ -128,32 +76,30 @@ void _writeFeatures( const std::vector<Feature> features, cv::FileStorage &fs, c | @@ -128,32 +76,30 @@ void _writeFeatures( const std::vector<Feature> features, cv::FileStorage &fs, c | ||
| 128 | fs << "]"; | 76 | fs << "]"; |
| 129 | } | 77 | } |
| 130 | 78 | ||
| 131 | -//------------------------- LBP Feature --------------------------------- | ||
| 132 | - | ||
| 133 | -class LBPTrainingEvaluator | 79 | +class FeatureEvaluator |
| 134 | { | 80 | { |
| 135 | public: | 81 | public: |
| 136 | - virtual ~LBPTrainingEvaluator() {} | ||
| 137 | - virtual void init(int _maxSampleCount, cv::Size _winSize ); | ||
| 138 | - virtual void setImage(const cv::Mat& img, uchar clsLabel, int idx); | ||
| 139 | - virtual float operator()(int featureIdx, int sampleIdx) const { return (float)features[featureIdx].calc( sum, sampleIdx); } | ||
| 140 | - virtual void writeFeatures( cv::FileStorage &fs, const cv::Mat& featureMap ) const; | 82 | + ~FeatureEvaluator() {} |
| 83 | + void init(int _maxSampleCount, cv::Size _winSize); | ||
| 84 | + void setImage(const cv::Mat& img, uchar clsLabel, int idx); | ||
| 85 | + void writeFeatures(cv::FileStorage &fs, const cv::Mat& featureMap) const; | ||
| 86 | + float operator()(int featureIdx, int sampleIdx) const { return (float)features[featureIdx].calc(data, sampleIdx); } | ||
| 141 | 87 | ||
| 142 | int getNumFeatures() const { return numFeatures; } | 88 | int getNumFeatures() const { return numFeatures; } |
| 143 | int getMaxCatCount() const { return maxCatCount; } | 89 | int getMaxCatCount() const { return maxCatCount; } |
| 144 | - int getFeatureSize() const { return 1; } | 90 | + int getFeatureSize() const { return featSize; } |
| 145 | const cv::Mat& getCls() const { return cls; } | 91 | const cv::Mat& getCls() const { return cls; } |
| 146 | float getCls(int si) const { return cls.at<float>(si, 0); } | 92 | float getCls(int si) const { return cls.at<float>(si, 0); } |
| 147 | 93 | ||
| 148 | protected: | 94 | protected: |
| 149 | - virtual void generateFeatures(); | 95 | + void generateFeatures(); |
| 150 | 96 | ||
| 151 | class Feature | 97 | class Feature |
| 152 | { | 98 | { |
| 153 | public: | 99 | public: |
| 154 | Feature(); | 100 | Feature(); |
| 155 | Feature( int offset, int x, int y, int _block_w, int _block_h ); | 101 | Feature( int offset, int x, int y, int _block_w, int _block_h ); |
| 156 | - uchar calc( const cv::Mat& _sum, size_t y ) const; | 102 | + uchar calc( const cv::Mat &data, int y ) const; |
| 157 | void write( cv::FileStorage &fs ) const; | 103 | void write( cv::FileStorage &fs ) const; |
| 158 | 104 | ||
| 159 | cv::Rect rect; | 105 | cv::Rect rect; |
| @@ -161,26 +107,29 @@ protected: | @@ -161,26 +107,29 @@ protected: | ||
| 161 | }; | 107 | }; |
| 162 | std::vector<Feature> features; | 108 | std::vector<Feature> features; |
| 163 | 109 | ||
| 110 | + cv::Mat data, cls; | ||
| 111 | + | ||
| 164 | int npos, nneg; | 112 | int npos, nneg; |
| 165 | - int maxCatCount; | ||
| 166 | int numFeatures; | 113 | int numFeatures; |
| 114 | + int maxCatCount; // 0 in case of numerical features | ||
| 115 | + int featSize; // 1 in case of simple features (HAAR, LBP) and N_BINS(9)*N_CELLS(4) in case of Dalal's HOG features | ||
| 116 | + | ||
| 167 | cv::Size winSize; | 117 | cv::Size winSize; |
| 168 | - cv::Mat cls, sum; | ||
| 169 | }; | 118 | }; |
| 170 | 119 | ||
| 171 | -inline uchar LBPTrainingEvaluator::Feature::calc(const cv::Mat &_sum, size_t y) const | 120 | +inline uchar FeatureEvaluator::Feature::calc(const cv::Mat &data, int y) const |
| 172 | { | 121 | { |
| 173 | - const int* psum = _sum.ptr<int>((int)y); | ||
| 174 | - int cval = psum[p[5]] - psum[p[6]] - psum[p[9]] + psum[p[10]]; | ||
| 175 | - | ||
| 176 | - return (uchar)((psum[p[0]] - psum[p[1]] - psum[p[4]] + psum[p[5]] >= cval ? 128 : 0) | // 0 | ||
| 177 | - (psum[p[1]] - psum[p[2]] - psum[p[5]] + psum[p[6]] >= cval ? 64 : 0) | // 1 | ||
| 178 | - (psum[p[2]] - psum[p[3]] - psum[p[6]] + psum[p[7]] >= cval ? 32 : 0) | // 2 | ||
| 179 | - (psum[p[6]] - psum[p[7]] - psum[p[10]] + psum[p[11]] >= cval ? 16 : 0) | // 5 | ||
| 180 | - (psum[p[10]] - psum[p[11]] - psum[p[14]] + psum[p[15]] >= cval ? 8 : 0) | // 8 | ||
| 181 | - (psum[p[9]] - psum[p[10]] - psum[p[13]] + psum[p[14]] >= cval ? 4 : 0) | // 7 | ||
| 182 | - (psum[p[8]] - psum[p[9]] - psum[p[12]] + psum[p[13]] >= cval ? 2 : 0) | // 6 | ||
| 183 | - (psum[p[4]] - psum[p[5]] - psum[p[8]] + psum[p[9]] >= cval ? 1 : 0)); // 3 | 122 | + const int* ptr = data.ptr<int>(y); |
| 123 | + int cval = ptr[p[5]] - ptr[p[6]] - ptr[p[9]] + ptr[p[10]]; | ||
| 124 | + | ||
| 125 | + return (uchar)((ptr[p[0]] - ptr[p[1]] - ptr[p[4]] + ptr[p[5]] >= cval ? 128 : 0) | // 0 | ||
| 126 | + (ptr[p[1]] - ptr[p[2]] - ptr[p[5]] + ptr[p[6]] >= cval ? 64 : 0) | // 1 | ||
| 127 | + (ptr[p[2]] - ptr[p[3]] - ptr[p[6]] + ptr[p[7]] >= cval ? 32 : 0) | // 2 | ||
| 128 | + (ptr[p[6]] - ptr[p[7]] - ptr[p[10]] + ptr[p[11]] >= cval ? 16 : 0) | // 5 | ||
| 129 | + (ptr[p[10]] - ptr[p[11]] - ptr[p[14]] + ptr[p[15]] >= cval ? 8 : 0) | // 8 | ||
| 130 | + (ptr[p[9]] - ptr[p[10]] - ptr[p[13]] + ptr[p[14]] >= cval ? 4 : 0) | // 7 | ||
| 131 | + (ptr[p[8]] - ptr[p[9]] - ptr[p[12]] + ptr[p[13]] >= cval ? 2 : 0) | // 6 | ||
| 132 | + (ptr[p[4]] - ptr[p[5]] - ptr[p[8]] + ptr[p[9]] >= cval ? 1 : 0)); // 3 | ||
| 184 | } | 133 | } |
| 185 | 134 | ||
| 186 | } // namespace br | 135 | } // namespace br |
openbr/plugins/metadata/cascade.cpp
| @@ -80,20 +80,18 @@ class CascadeTransform : public MetaTransform | @@ -80,20 +80,18 @@ class CascadeTransform : public MetaTransform | ||
| 80 | Q_PROPERTY(int winHeight READ get_winHeight WRITE set_winHeight RESET reset_winHeight STORED false) | 80 | Q_PROPERTY(int winHeight READ get_winHeight WRITE set_winHeight RESET reset_winHeight STORED false) |
| 81 | Q_PROPERTY(int numPos READ get_numPos WRITE set_numPos RESET reset_numPos STORED false) | 81 | Q_PROPERTY(int numPos READ get_numPos WRITE set_numPos RESET reset_numPos STORED false) |
| 82 | Q_PROPERTY(int numNeg READ get_numNeg WRITE set_numNeg RESET reset_numNeg STORED false) | 82 | Q_PROPERTY(int numNeg READ get_numNeg WRITE set_numNeg RESET reset_numNeg STORED false) |
| 83 | - Q_PROPERTY(int numStages READ get_numStages WRITE set_numStages RESET reset_numStages STORED false) | ||
| 84 | 83 | ||
| 85 | BR_PROPERTY(QString, model, "FrontalFace") | 84 | BR_PROPERTY(QString, model, "FrontalFace") |
| 86 | BR_PROPERTY(int, minSize, 64) | 85 | BR_PROPERTY(int, minSize, 64) |
| 87 | BR_PROPERTY(int, minNeighbors, 5) | 86 | BR_PROPERTY(int, minNeighbors, 5) |
| 88 | BR_PROPERTY(bool, ROCMode, false) | 87 | BR_PROPERTY(bool, ROCMode, false) |
| 89 | 88 | ||
| 90 | - BR_PROPERTY(QString, vecFile, "vec.vec") | 89 | + BR_PROPERTY(QString, vecFile, "data.vec") |
| 91 | BR_PROPERTY(QString, negFile, "neg.txt") | 90 | BR_PROPERTY(QString, negFile, "neg.txt") |
| 92 | BR_PROPERTY(int, winWidth, 24) | 91 | BR_PROPERTY(int, winWidth, 24) |
| 93 | BR_PROPERTY(int, winHeight, 24) | 92 | BR_PROPERTY(int, winHeight, 24) |
| 94 | BR_PROPERTY(int, numPos, 1000) | 93 | BR_PROPERTY(int, numPos, 1000) |
| 95 | BR_PROPERTY(int, numNeg, 1000) | 94 | BR_PROPERTY(int, numNeg, 1000) |
| 96 | - BR_PROPERTY(int, numStages, 20) | ||
| 97 | 95 | ||
| 98 | Resource<CascadeClassifier> cascadeResource; | 96 | Resource<CascadeClassifier> cascadeResource; |
| 99 | 97 | ||
| @@ -180,22 +178,21 @@ class CascadeTransform : public MetaTransform | @@ -180,22 +178,21 @@ class CascadeTransform : public MetaTransform | ||
| 180 | // Train transform | 178 | // Train transform |
| 181 | void train(const TemplateList& data) | 179 | void train(const TemplateList& data) |
| 182 | { | 180 | { |
| 183 | - (void) data; | 181 | + (void)data; |
| 182 | + | ||
| 183 | + BrCascadeClassifier classifier; | ||
| 184 | 184 | ||
| 185 | QList<Mat> posImages = getPos(); | 185 | QList<Mat> posImages = getPos(); |
| 186 | QList<Mat> negImages = getNeg(); | 186 | QList<Mat> negImages = getNeg(); |
| 187 | 187 | ||
| 188 | - BrCascadeClassifier classifier; | ||
| 189 | - | ||
| 190 | CascadeBoostParams stageParams(CvBoost::GENTLE, 0.999, 0.5, 0.95, 1, 200); | 188 | CascadeBoostParams stageParams(CvBoost::GENTLE, 0.999, 0.5, 0.95, 1, 200); |
| 191 | 189 | ||
| 192 | - Representation *representation = Representation::make("MBLBP(24,24)", NULL); | ||
| 193 | - | ||
| 194 | QString cascadeDir = Globals->sdkPath + "/share/openbr/models/openbrcascades/" + model; | 190 | QString cascadeDir = Globals->sdkPath + "/share/openbr/models/openbrcascades/" + model; |
| 195 | classifier.train(cascadeDir.toStdString(), | 191 | classifier.train(cascadeDir.toStdString(), |
| 196 | posImages, negImages, | 192 | posImages, negImages, |
| 197 | - 1024, 1024, numPos, numNeg, numStages, | ||
| 198 | - representation, stageParams); | 193 | + numPos, numNeg, 1024, 1024, 12, |
| 194 | + Size(winWidth, winHeight), | ||
| 195 | + stageParams); | ||
| 199 | } | 196 | } |
| 200 | 197 | ||
| 201 | void project(const Template &src, Template &dst) const | 198 | void project(const Template &src, Template &dst) const |
openbr/plugins/representation/mblbp.cpp
| 1 | #include <opencv2/imgproc/imgproc.hpp> | 1 | #include <opencv2/imgproc/imgproc.hpp> |
| 2 | 2 | ||
| 3 | #include <openbr/plugins/openbr_internal.h> | 3 | #include <openbr/plugins/openbr_internal.h> |
| 4 | +#include <openbr/core/opencvutils.h> | ||
| 4 | 5 | ||
| 5 | using namespace cv; | 6 | using namespace cv; |
| 6 | 7 | ||
| @@ -29,12 +30,12 @@ class MBLBPRepresentation : public Representation | @@ -29,12 +30,12 @@ class MBLBPRepresentation : public Representation | ||
| 29 | void init() | 30 | void init() |
| 30 | { | 31 | { |
| 31 | int offset = winWidth + 1; | 32 | int offset = winWidth + 1; |
| 32 | - for( int x = 0; x < winWidth; x++ ) | ||
| 33 | - for( int y = 0; y < winHeight; y++ ) | ||
| 34 | - for( int w = 1; w <= winWidth / 3; w++ ) | ||
| 35 | - for( int h = 1; h <= winHeight / 3; h++ ) | ||
| 36 | - if ( (x+3*w <= winWidth) && (y+3*h <= winHeight) ) | ||
| 37 | - features.push_back( Feature(offset, x, y, w, h ) ); | 33 | + for (int x = 0; x < winWidth; x++ ) |
| 34 | + for (int y = 0; y < winHeight; y++ ) | ||
| 35 | + for (int w = 1; w <= winWidth / 3; w++ ) | ||
| 36 | + for (int h = 1; h <= winHeight / 3; h++ ) | ||
| 37 | + if ((x+3*w <= winWidth) && (y+3*h <= winHeight) ) | ||
| 38 | + features.append(Feature(offset, x, y, w, h ) ); | ||
| 38 | } | 39 | } |
| 39 | 40 | ||
| 40 | Mat preprocess(const Mat &image) const | 41 | Mat preprocess(const Mat &image) const |