Commit f7e45a9ea0d41f02f684fbc5e7ef7f2ac9607398
1 parent
fe4366bc
Cleanup in core/boost
Showing
2 changed files
with
52 additions
and
81 deletions
openbr/core/boost.cpp
| 1 | +#include <opencv2/imgproc/imgproc.hpp> | ||
| 2 | + | ||
| 1 | #include "boost.h" | 3 | #include "boost.h" |
| 2 | -#include <queue> | ||
| 3 | #include "cxmisc.h" | 4 | #include "cxmisc.h" |
| 4 | 5 | ||
| 5 | using namespace std; | 6 | using namespace std; |
| @@ -16,9 +17,6 @@ logRatio( double val ) | @@ -16,9 +17,6 @@ logRatio( double val ) | ||
| 16 | return log( val/(1. - val) ); | 17 | return log( val/(1. - val) ); |
| 17 | } | 18 | } |
| 18 | 19 | ||
| 19 | -#define CV_CMP_FLT(i,j) (i < j) | ||
| 20 | -static CV_IMPLEMENT_QSORT_EX( icvSortFlt, float, CV_CMP_FLT, const float* ) | ||
| 21 | - | ||
| 22 | #define CV_CMP_NUM_IDX(i,j) (aux[i] < aux[j]) | 20 | #define CV_CMP_NUM_IDX(i,j) (aux[i] < aux[j]) |
| 23 | static CV_IMPLEMENT_QSORT_EX( icvSortIntAux, int, CV_CMP_NUM_IDX, const float* ) | 21 | static CV_IMPLEMENT_QSORT_EX( icvSortIntAux, int, CV_CMP_NUM_IDX, const float* ) |
| 24 | static CV_IMPLEMENT_QSORT_EX( icvSortUShAux, unsigned short, CV_CMP_NUM_IDX, const float* ) | 22 | static CV_IMPLEMENT_QSORT_EX( icvSortUShAux, unsigned short, CV_CMP_NUM_IDX, const float* ) |
| @@ -145,7 +143,7 @@ void FeatureEvaluator::init(Representation *_representation, int _maxSampleCount | @@ -145,7 +143,7 @@ void FeatureEvaluator::init(Representation *_representation, int _maxSampleCount | ||
| 145 | 143 | ||
| 146 | int dx, dy; | 144 | int dx, dy; |
| 147 | Size windowSize = representation->windowSize(&dx, &dy); | 145 | Size windowSize = representation->windowSize(&dx, &dy); |
| 148 | - data.create((int)_maxSampleCount, Size(windowSize.width + dx, windowSize.height + dy).area(), CV_32SC1); | 146 | + data.create((int)_maxSampleCount, (windowSize.width + dx) * (windowSize.height + dy), CV_32SC1); |
| 149 | cls.create( (int)_maxSampleCount, 1, CV_32FC1 ); | 147 | cls.create( (int)_maxSampleCount, 1, CV_32FC1 ); |
| 150 | } | 148 | } |
| 151 | 149 | ||
| @@ -153,10 +151,9 @@ void FeatureEvaluator::setImage(const Mat &img, uchar clsLabel, int idx) | @@ -153,10 +151,9 @@ void FeatureEvaluator::setImage(const Mat &img, uchar clsLabel, int idx) | ||
| 153 | { | 151 | { |
| 154 | cls.ptr<float>(idx)[0] = clsLabel; | 152 | cls.ptr<float>(idx)[0] = clsLabel; |
| 155 | 153 | ||
| 156 | - int dx, dy; | ||
| 157 | - Size windowSize = representation->windowSize(&dx, &dy); | ||
| 158 | - Mat pp(Size(windowSize.width + dx, windowSize.height + dy), data.type(), data.ptr<int>(idx)); | 154 | + Mat pp; |
| 159 | representation->preprocess(img, pp); | 155 | representation->preprocess(img, pp); |
| 156 | + pp.reshape(0, 1).copyTo(data.row(idx)); | ||
| 160 | } | 157 | } |
| 161 | 158 | ||
| 162 | //----------------------------- CascadeBoostParams ------------------------------------------------- | 159 | //----------------------------- CascadeBoostParams ------------------------------------------------- |
| @@ -1031,27 +1028,22 @@ void CascadeBoostTree::split_node_data( CvDTreeNode* node ) | @@ -1031,27 +1028,22 @@ void CascadeBoostTree::split_node_data( CvDTreeNode* node ) | ||
| 1031 | 1028 | ||
| 1032 | //----------------------------------- CascadeBoost -------------------------------------- | 1029 | //----------------------------------- CascadeBoost -------------------------------------- |
| 1033 | 1030 | ||
| 1034 | -bool CascadeBoost::train( const FeatureEvaluator* _featureEvaluator, | ||
| 1035 | - int _numSamples, | ||
| 1036 | - int _precalcValBufSize, int _precalcIdxBufSize, | ||
| 1037 | - const CascadeBoostParams& _params ) | 1031 | +void CascadeBoost::train(const FeatureEvaluator* _featureEvaluator, |
| 1032 | + int _numSamples, | ||
| 1033 | + int _precalcValBufSize, int _precalcIdxBufSize, | ||
| 1034 | + const CascadeBoostParams& _params) | ||
| 1038 | { | 1035 | { |
| 1039 | - bool isTrained = false; | ||
| 1040 | - CV_Assert( !data ); | 1036 | + CV_Assert(!data); |
| 1041 | clear(); | 1037 | clear(); |
| 1042 | 1038 | ||
| 1043 | - data = new CascadeBoostTrainData( _featureEvaluator, _numSamples, | ||
| 1044 | - _precalcValBufSize, _precalcIdxBufSize, _params ); | ||
| 1045 | - | ||
| 1046 | - CvMemStorage *storage = cvCreateMemStorage(); | ||
| 1047 | - weak = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvBoostTree*), storage ); | ||
| 1048 | - storage = 0; | 1039 | + data = new CascadeBoostTrainData(_featureEvaluator, _numSamples, |
| 1040 | + _precalcValBufSize, _precalcIdxBufSize, _params); | ||
| 1049 | 1041 | ||
| 1050 | - set_params( _params ); | ||
| 1051 | - if ( (_params.boost_type == LOGIT) || (_params.boost_type == GENTLE) ) | 1042 | + set_params(_params); |
| 1043 | + if ((_params.boost_type == LOGIT) || (_params.boost_type == GENTLE)) | ||
| 1052 | data->do_responses_copy(); | 1044 | data->do_responses_copy(); |
| 1053 | 1045 | ||
| 1054 | - update_weights( 0 ); | 1046 | + update_weights(0); |
| 1055 | 1047 | ||
| 1056 | cout << "+----+---------+---------+" << endl; | 1048 | cout << "+----+---------+---------+" << endl; |
| 1057 | cout << "| N | HR | FA |" << endl; | 1049 | cout << "| N | HR | FA |" << endl; |
| @@ -1060,63 +1052,43 @@ bool CascadeBoost::train( const FeatureEvaluator* _featureEvaluator, | @@ -1060,63 +1052,43 @@ bool CascadeBoost::train( const FeatureEvaluator* _featureEvaluator, | ||
| 1060 | do | 1052 | do |
| 1061 | { | 1053 | { |
| 1062 | CascadeBoostTree* tree = new CascadeBoostTree; | 1054 | CascadeBoostTree* tree = new CascadeBoostTree; |
| 1063 | - if( !tree->train( data, subsample_mask, this ) ) | ||
| 1064 | - { | 1055 | + if (!tree->train( data, subsample_mask, this)) { |
| 1065 | delete tree; | 1056 | delete tree; |
| 1066 | - break; | 1057 | + return; |
| 1067 | } | 1058 | } |
| 1068 | 1059 | ||
| 1069 | classifiers.append(tree); | 1060 | classifiers.append(tree); |
| 1070 | - cvSeqPush( weak, &tree ); | ||
| 1071 | - update_weights( tree ); | 1061 | + update_weights(tree); |
| 1072 | trim_weights(); | 1062 | trim_weights(); |
| 1073 | - if( cvCountNonZero(subsample_mask) == 0 ) | ||
| 1074 | - break; | ||
| 1075 | - } | ||
| 1076 | - while( !isErrDesired() && (weak->total < params.weak_count) ); | ||
| 1077 | - | ||
| 1078 | - if(weak->total > 0) | ||
| 1079 | - { | ||
| 1080 | - data->is_classifier = true; | ||
| 1081 | - data->free_train_data(); | ||
| 1082 | - isTrained = true; | 1063 | + if (cvCountNonZero(subsample_mask) == 0) |
| 1064 | + return; | ||
| 1083 | } | 1065 | } |
| 1084 | - else | ||
| 1085 | - clear(); | 1066 | + while (!isErrDesired() && (classifiers.size() < params.weak_count)); |
| 1086 | 1067 | ||
| 1087 | - return isTrained; | 1068 | + clear(); |
| 1088 | } | 1069 | } |
| 1089 | 1070 | ||
| 1090 | -float CascadeBoost::predict( int sampleIdx, bool returnSum ) const | 1071 | +float CascadeBoost::predict(int sampleIdx, bool returnSum) const |
| 1091 | { | 1072 | { |
| 1092 | - CV_Assert( weak ); | ||
| 1093 | double sum = 0; | 1073 | double sum = 0; |
| 1074 | + foreach (const CvBoostTree *tree, classifiers) | ||
| 1075 | + sum += ((CascadeBoostTree*)tree)->predict(sampleIdx)->value; | ||
| 1094 | 1076 | ||
| 1095 | - CvSeqReader reader; | ||
| 1096 | - cvStartReadSeq( weak, &reader ); | ||
| 1097 | - cvSetSeqReaderPos( &reader, 0 ); | ||
| 1098 | - for( int i = 0; i < weak->total; i++ ) | ||
| 1099 | - { | ||
| 1100 | - CvBoostTree* wtree; | ||
| 1101 | - CV_READ_SEQ_ELEM( wtree, reader ); | ||
| 1102 | - sum += ((CascadeBoostTree*)wtree)->predict(sampleIdx)->value; | ||
| 1103 | - } | ||
| 1104 | - | ||
| 1105 | - if( !returnSum ) | 1077 | + if (!returnSum) |
| 1106 | sum = sum < threshold - CV_THRESHOLD_EPS ? 0.0 : 1.0; | 1078 | sum = sum < threshold - CV_THRESHOLD_EPS ? 0.0 : 1.0; |
| 1107 | return (float)sum; | 1079 | return (float)sum; |
| 1108 | } | 1080 | } |
| 1109 | 1081 | ||
| 1110 | -bool CascadeBoost::set_params( const CvBoostParams& _params ) | 1082 | +bool CascadeBoost::set_params(const CvBoostParams& _params) |
| 1111 | { | 1083 | { |
| 1112 | minHitRate = ((CascadeBoostParams&)_params).minHitRate; | 1084 | minHitRate = ((CascadeBoostParams&)_params).minHitRate; |
| 1113 | maxFalseAlarm = ((CascadeBoostParams&)_params).maxFalseAlarm; | 1085 | maxFalseAlarm = ((CascadeBoostParams&)_params).maxFalseAlarm; |
| 1114 | - return ( ( minHitRate > 0 ) && ( minHitRate < 1) && | ||
| 1115 | - ( maxFalseAlarm > 0 ) && ( maxFalseAlarm < 1) && | ||
| 1116 | - CvBoost::set_params( _params )); | 1086 | + return (( minHitRate > 0 ) && ( minHitRate < 1) && |
| 1087 | + (maxFalseAlarm > 0 ) && ( maxFalseAlarm < 1) && | ||
| 1088 | + CvBoost::set_params(_params)); | ||
| 1117 | } | 1089 | } |
| 1118 | 1090 | ||
| 1119 | -void CascadeBoost::update_weights( CvBoostTree* tree ) | 1091 | +void CascadeBoost::update_weights(CvBoostTree* tree) |
| 1120 | { | 1092 | { |
| 1121 | int n = data->sample_count; | 1093 | int n = data->sample_count; |
| 1122 | double sumW = 0.; | 1094 | double sumW = 0.; |
| @@ -1359,34 +1331,33 @@ void CascadeBoost::update_weights( CvBoostTree* tree ) | @@ -1359,34 +1331,33 @@ void CascadeBoost::update_weights( CvBoostTree* tree ) | ||
| 1359 | 1331 | ||
| 1360 | bool CascadeBoost::isErrDesired() | 1332 | bool CascadeBoost::isErrDesired() |
| 1361 | { | 1333 | { |
| 1362 | - int sCount = data->sample_count, | ||
| 1363 | - numPos = 0, numNeg = 0, numFalse = 0, numPosTrue = 0; | ||
| 1364 | - vector<float> eval(sCount); | ||
| 1365 | - | ||
| 1366 | - for( int i = 0; i < sCount; i++ ) | ||
| 1367 | - if( ((CascadeBoostTrainData*)data)->featureEvaluator->getCls( i ) == 1.0F ) | ||
| 1368 | - eval[numPos++] = predict( i, true ); | ||
| 1369 | - icvSortFlt( &eval[0], numPos, 0 ); | ||
| 1370 | - int thresholdIdx = (int)((1.0F - minHitRate) * numPos); | ||
| 1371 | - threshold = eval[ thresholdIdx ]; | ||
| 1372 | - numPosTrue = numPos - thresholdIdx; | ||
| 1373 | - for( int i = thresholdIdx - 1; i >= 0; i--) | ||
| 1374 | - if ( abs( eval[i] - threshold) < FLT_EPSILON ) | 1334 | + QList<float> posVals; |
| 1335 | + for (int i = 0; i < data->sample_count; i++) | ||
| 1336 | + if (((CascadeBoostTrainData*)data)->featureEvaluator->getCls(i) == 1.0F) | ||
| 1337 | + posVals.append(predict(i, true)); | ||
| 1338 | + | ||
| 1339 | + std::sort(posVals.begin(), posVals.end()); | ||
| 1340 | + | ||
| 1341 | + int thresholdIdx = (int)((1.0F - minHitRate) * posVals.size()); | ||
| 1342 | + threshold = posVals[thresholdIdx]; | ||
| 1343 | + | ||
| 1344 | + int numPosTrue = posVals.size() - thresholdIdx; | ||
| 1345 | + for (int i = thresholdIdx - 1; i >= 0; i--) | ||
| 1346 | + if (abs(posVals[i] - threshold) < FLT_EPSILON) | ||
| 1375 | numPosTrue++; | 1347 | numPosTrue++; |
| 1376 | - float hitRate = ((float) numPosTrue) / ((float) numPos); | 1348 | + float hitRate = ((float)numPosTrue) / ((float)posVals.size()); |
| 1377 | 1349 | ||
| 1378 | - for( int i = 0; i < sCount; i++ ) | ||
| 1379 | - { | ||
| 1380 | - if( ((CascadeBoostTrainData*)data)->featureEvaluator->getCls( i ) == 0.0F ) | ||
| 1381 | - { | 1350 | + int numNeg = 0, numFalse = 0; |
| 1351 | + for (int i = 0; i < data->sample_count; i++) { | ||
| 1352 | + if (((CascadeBoostTrainData*)data)->featureEvaluator->getCls(i) == 0.0F) { | ||
| 1382 | numNeg++; | 1353 | numNeg++; |
| 1383 | - if( predict( i ) ) | 1354 | + if (predict(i)) |
| 1384 | numFalse++; | 1355 | numFalse++; |
| 1385 | } | 1356 | } |
| 1386 | } | 1357 | } |
| 1387 | - float falseAlarm = ((float) numFalse) / ((float) numNeg); | 1358 | + float falseAlarm = ((float)numFalse) / ((float)numNeg); |
| 1388 | 1359 | ||
| 1389 | - cout << "|"; cout.width(4); cout << right << weak->total; | 1360 | + cout << "|"; cout.width(4); cout << right << classifiers.size(); |
| 1390 | cout << "|"; cout.width(9); cout << right << hitRate; | 1361 | cout << "|"; cout.width(9); cout << right << hitRate; |
| 1391 | cout << "|"; cout.width(9); cout << right << falseAlarm; | 1362 | cout << "|"; cout.width(9); cout << right << falseAlarm; |
| 1392 | cout << "|" << endl; | 1363 | cout << "|" << endl; |
openbr/core/boost.h
| @@ -82,7 +82,7 @@ protected: | @@ -82,7 +82,7 @@ protected: | ||
| 82 | class CascadeBoost : public CvBoost | 82 | class CascadeBoost : public CvBoost |
| 83 | { | 83 | { |
| 84 | public: | 84 | public: |
| 85 | - virtual bool train(const FeatureEvaluator *_featureEvaluator, | 85 | + virtual void train(const FeatureEvaluator *_featureEvaluator, |
| 86 | int _numSamples, int _precalcValBufSize, int _precalcIdxBufSize, | 86 | int _numSamples, int _precalcValBufSize, int _precalcIdxBufSize, |
| 87 | const CascadeBoostParams &_params=CascadeBoostParams()); | 87 | const CascadeBoostParams &_params=CascadeBoostParams()); |
| 88 | virtual float predict( int sampleIdx, bool returnSum = false ) const; | 88 | virtual float predict( int sampleIdx, bool returnSum = false ) const; |