Commit b277fd20fe92fa7f3e128e5fbc3724a150aa2149
1 parent
447ef443
Integrated representations into the backend and reformatted into a classifier
Showing
11 changed files
with
131 additions
and
659 deletions
openbr/core/boost.cpp
| ... | ... | @@ -137,6 +137,28 @@ static CvMat* cvPreprocessIndexArray( const CvMat* idx_arr, int data_arr_size, b |
| 137 | 137 | return idx; |
| 138 | 138 | } |
| 139 | 139 | |
| 140 | +//------------------------------------- FeatureEvaluator --------------------------------------- | |
| 141 | + | |
| 142 | +void FeatureEvaluator::init(Representation *_representation, int _maxSampleCount) | |
| 143 | +{ | |
| 144 | + representation = _representation; | |
| 145 | + data.create((int)_maxSampleCount, representation->postWindowSize().area(), CV_32SC1); | |
| 146 | + cls.create( (int)_maxSampleCount, 1, CV_32FC1 ); | |
| 147 | +} | |
| 148 | + | |
| 149 | +void FeatureEvaluator::setImage(const Mat &img, uchar clsLabel, int idx) | |
| 150 | +{ | |
| 151 | + cls.ptr<float>(idx)[0] = clsLabel; | |
| 152 | + | |
| 153 | + Mat integralImg(representation->postWindowSize(), data.type(), data.ptr<int>(idx)); | |
| 154 | + representation->preprocess(img, integralImg); | |
| 155 | +} | |
| 156 | + | |
| 157 | +void FeatureEvaluator::writeFeatures(FileStorage &fs, const Mat &featureMap) const | |
| 158 | +{ | |
| 159 | + representation->write(fs, featureMap); | |
| 160 | +} | |
| 161 | + | |
| 140 | 162 | //----------------------------- CascadeBoostParams ------------------------------------------------- |
| 141 | 163 | |
| 142 | 164 | CascadeBoostParams::CascadeBoostParams() : minHitRate( 0.995F), maxFalseAlarm( 0.5F ) | ... | ... |
openbr/core/boost.h
| 1 | 1 | #ifndef _BOOST_H_ |
| 2 | 2 | #define _BOOST_H_ |
| 3 | 3 | |
| 4 | -#include "features.h" | |
| 5 | 4 | #include "ml.h" |
| 5 | +#include <openbr/openbr_plugin.h> | |
| 6 | + | |
| 7 | +#define CC_CASCADE_FILENAME "cascade.xml" | |
| 8 | +#define CC_PARAMS_FILENAME "params.xml" | |
| 9 | + | |
| 10 | +#define CC_CASCADE_PARAMS "cascadeParams" | |
| 11 | +#define CC_STAGE_TYPE "stageType" | |
| 12 | +#define CC_FEATURE_TYPE "featureType" | |
| 13 | +#define CC_HEIGHT "height" | |
| 14 | +#define CC_WIDTH "width" | |
| 15 | + | |
| 16 | +#define CC_STAGE_NUM "stageNum" | |
| 17 | +#define CC_STAGES "stages" | |
| 18 | +#define CC_STAGE_PARAMS "stageParams" | |
| 19 | + | |
| 20 | +#define CC_BOOST "BOOST" | |
| 21 | +#define CC_BOOST_TYPE "boostType" | |
| 22 | +#define CC_DISCRETE_BOOST "DAB" | |
| 23 | +#define CC_REAL_BOOST "RAB" | |
| 24 | +#define CC_LOGIT_BOOST "LB" | |
| 25 | +#define CC_GENTLE_BOOST "GAB" | |
| 26 | +#define CC_MINHITRATE "minHitRate" | |
| 27 | +#define CC_MAXFALSEALARM "maxFalseAlarm" | |
| 28 | +#define CC_TRIM_RATE "weightTrimRate" | |
| 29 | +#define CC_MAX_DEPTH "maxDeptrh" | |
| 30 | +#define CC_WEAK_COUNT "maxWeakCount" | |
| 31 | +#define CC_STAGE_THRESHOLD "stageThreshold" | |
| 32 | +#define CC_WEAK_CLASSIFIERS "weakClassifiers" | |
| 33 | +#define CC_INTERNAL_NODES "internalNodes" | |
| 34 | +#define CC_LEAF_VALUES "leafValues" | |
| 35 | + | |
| 36 | +#define CC_FEATURES "features" | |
| 37 | +#define CC_FEATURE_PARAMS "featureParams" | |
| 38 | +#define CC_MAX_CAT_COUNT "maxCatCount" | |
| 39 | +#define CC_FEATURE_SIZE "featSize" | |
| 40 | + | |
| 41 | +#define CC_LBP "LBP" | |
| 42 | +#define CC_RECT "rect" | |
| 43 | + | |
| 44 | +#ifdef _WIN32 | |
| 45 | +#define TIME( arg ) (((double) clock()) / CLOCKS_PER_SEC) | |
| 46 | +#else | |
| 47 | +#define TIME( arg ) (time( arg )) | |
| 48 | +#endif | |
| 6 | 49 | |
| 7 | 50 | namespace br |
| 8 | 51 | { |
| 9 | 52 | |
| 53 | +struct FeatureEvaluator | |
| 54 | +{ | |
| 55 | + ~FeatureEvaluator() {} | |
| 56 | + void init(Representation *_representation, int _maxSampleCount); | |
| 57 | + void setImage(const cv::Mat& img, uchar clsLabel, int idx); | |
| 58 | + void writeFeatures(cv::FileStorage &fs, const cv::Mat& featureMap) const; | |
| 59 | + float operator()(int featureIdx, int sampleIdx) const { return representation->evaluate(data.row(sampleIdx), featureIdx); } | |
| 60 | + | |
| 61 | + int getNumFeatures() const { return representation->numFeatures(); } | |
| 62 | + int getMaxCatCount() const { return representation->maxCatCount(); } | |
| 63 | + int getFeatureSize() const { return 1; } | |
| 64 | + const cv::Mat& getCls() const { return cls; } | |
| 65 | + float getCls(int si) const { return cls.at<float>(si, 0); } | |
| 66 | + | |
| 67 | + cv::Mat data, cls; | |
| 68 | + Representation *representation; | |
| 69 | +}; | |
| 70 | + | |
| 10 | 71 | struct CascadeBoostParams : CvBoostParams |
| 11 | 72 | { |
| 12 | 73 | float minHitRate; | ... | ... |
openbr/core/cascade.cpp deleted
| 1 | -#include "cascade.h" | |
| 2 | -#include <stdio.h> | |
| 3 | -#include <iostream> | |
| 4 | -#include <fstream> | |
| 5 | - | |
| 6 | -using namespace std; | |
| 7 | -using namespace br; | |
| 8 | -using namespace cv; | |
| 9 | - | |
| 10 | -bool CascadeImageReader::create(const QList<Mat> &_posImages, const QList<Mat> &_negImages, Size _winSize) | |
| 11 | -{ | |
| 12 | - posImages = _posImages; | |
| 13 | - negImages = _negImages; | |
| 14 | - winSize = _winSize; | |
| 15 | - | |
| 16 | - posIdx = negIdx = 0; | |
| 17 | - | |
| 18 | - src.create( 0, 0 , CV_8UC1 ); | |
| 19 | - img.create( 0, 0, CV_8UC1 ); | |
| 20 | - point = offset = Point( 0, 0 ); | |
| 21 | - scale = 1.0F; | |
| 22 | - scaleFactor = 1.4142135623730950488016887242097F; | |
| 23 | - stepFactor = 0.5F; | |
| 24 | - round = 0; | |
| 25 | - | |
| 26 | - return true; | |
| 27 | -} | |
| 28 | - | |
| 29 | -bool CascadeImageReader::nextNeg() | |
| 30 | -{ | |
| 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 | - } | |
| 46 | - | |
| 47 | - if( src.empty() ) | |
| 48 | - return false; // no appropriate image | |
| 49 | - point = offset = _offset; | |
| 50 | - scale = max( ((float)winSize.width + point.x) / ((float)src.cols), | |
| 51 | - ((float)winSize.height + point.y) / ((float)src.rows) ); | |
| 52 | - | |
| 53 | - Size sz( (int)(scale*src.cols + 0.5F), (int)(scale*src.rows + 0.5F) ); | |
| 54 | - resize( src, img, sz ); | |
| 55 | - return true; | |
| 56 | -} | |
| 57 | - | |
| 58 | -bool CascadeImageReader::getNeg( Mat& _img ) | |
| 59 | -{ | |
| 60 | - CV_Assert( !_img.empty() ); | |
| 61 | - CV_Assert( _img.type() == CV_8UC1 ); | |
| 62 | - CV_Assert( _img.cols == winSize.width ); | |
| 63 | - CV_Assert( _img.rows == winSize.height ); | |
| 64 | - | |
| 65 | - if( img.empty() ) | |
| 66 | - if ( !nextNeg() ) | |
| 67 | - return false; | |
| 68 | - | |
| 69 | - Mat mat( winSize.height, winSize.width, CV_8UC1, | |
| 70 | - (void*)(img.data + point.y * img.step + point.x * img.elemSize()), img.step ); | |
| 71 | - mat.copyTo(_img); | |
| 72 | - | |
| 73 | - if( (int)( point.x + (1.0F + stepFactor ) * winSize.width ) < img.cols ) | |
| 74 | - point.x += (int)(stepFactor * winSize.width); | |
| 75 | - else | |
| 76 | - { | |
| 77 | - point.x = offset.x; | |
| 78 | - if( (int)( point.y + (1.0F + stepFactor ) * winSize.height ) < img.rows ) | |
| 79 | - point.y += (int)(stepFactor * winSize.height); | |
| 80 | - else | |
| 81 | - { | |
| 82 | - point.y = offset.y; | |
| 83 | - scale *= scaleFactor; | |
| 84 | - if( scale <= 1.0F ) | |
| 85 | - resize( src, img, Size( (int)(scale*src.cols), (int)(scale*src.rows) ) ); | |
| 86 | - else | |
| 87 | - { | |
| 88 | - if ( !nextNeg() ) | |
| 89 | - return false; | |
| 90 | - } | |
| 91 | - } | |
| 92 | - } | |
| 93 | - return true; | |
| 94 | -} | |
| 95 | - | |
| 96 | - | |
| 97 | -bool CascadeImageReader::getPos(Mat &_img) | |
| 98 | -{ | |
| 99 | - posImages[posIdx++].copyTo(_img); | |
| 100 | - return true; | |
| 101 | -} | |
| 102 | - | |
| 103 | -//---------------------------- CascadeClassifier -------------------------------------- | |
| 104 | - | |
| 105 | -bool BrCascadeClassifier::train(const string _cascadeDirName, | |
| 106 | - const QList<Mat> &_posImages, | |
| 107 | - const QList<Mat> &_negImages, | |
| 108 | - int _numPos, int _numNeg, | |
| 109 | - int _precalcValBufSize, int _precalcIdxBufSize, | |
| 110 | - int _numStages, | |
| 111 | - Size _winSize, | |
| 112 | - const CascadeBoostParams& _stageParams) | |
| 113 | -{ | |
| 114 | - // Start recording clock ticks for training time output | |
| 115 | - const clock_t begin_time = clock(); | |
| 116 | - | |
| 117 | - if (_cascadeDirName.empty()) | |
| 118 | - CV_Error( CV_StsBadArg, "_cascadeDirName is NULL" ); | |
| 119 | - | |
| 120 | - string dirName; | |
| 121 | - if (_cascadeDirName.find_last_of("/\\") == (_cascadeDirName.length() - 1) ) | |
| 122 | - dirName = _cascadeDirName; | |
| 123 | - else | |
| 124 | - dirName = _cascadeDirName + '/'; | |
| 125 | - | |
| 126 | - winSize = _winSize; | |
| 127 | - | |
| 128 | - numPos = _numPos; | |
| 129 | - numNeg = _numNeg; | |
| 130 | - numStages = _numStages; | |
| 131 | - imgReader.create(_posImages, _negImages, winSize); | |
| 132 | - | |
| 133 | - Representation *representation = Representation::make("MBLBP(24,24)", NULL); | |
| 134 | - | |
| 135 | - stageParams = new CascadeBoostParams; | |
| 136 | - *stageParams = _stageParams; | |
| 137 | - featureEvaluator = new FeatureEvaluator; | |
| 138 | - featureEvaluator->init(representation, numPos + numNeg); | |
| 139 | - stageClassifiers.reserve( numStages ); | |
| 140 | - | |
| 141 | - double requiredLeafFARate = pow( (double) stageParams->maxFalseAlarm, (double) numStages ) / | |
| 142 | - (double)stageParams->max_depth; | |
| 143 | - double tempLeafFARate; | |
| 144 | - | |
| 145 | - for (int i = 0; i < numStages; i++) { | |
| 146 | - cout << endl << "===== TRAINING " << i << "-stage =====" << endl; | |
| 147 | - cout << "<BEGIN" << endl; | |
| 148 | - if (!updateTrainingSet(tempLeafFARate)) { | |
| 149 | - cout << "Train dataset for temp stage can not be filled. " | |
| 150 | - "Branch training terminated." << endl; | |
| 151 | - break; | |
| 152 | - } | |
| 153 | - if (tempLeafFARate <= requiredLeafFARate) { | |
| 154 | - cout << "Required leaf false alarm rate achieved. " | |
| 155 | - "Branch training terminated." << endl; | |
| 156 | - break; | |
| 157 | - } | |
| 158 | - | |
| 159 | - CascadeBoost* tempStage = new CascadeBoost; | |
| 160 | - bool isStageTrained = tempStage->train( (FeatureEvaluator*)featureEvaluator, | |
| 161 | - curNumSamples, _precalcValBufSize, _precalcIdxBufSize, | |
| 162 | - *((CascadeBoostParams*)stageParams) ); | |
| 163 | - cout << "END>" << endl; | |
| 164 | - | |
| 165 | - if (!isStageTrained) | |
| 166 | - break; | |
| 167 | - | |
| 168 | - stageClassifiers.push_back(tempStage); | |
| 169 | - | |
| 170 | - // Output training time up till now | |
| 171 | - float seconds = float( clock () - begin_time ) / CLOCKS_PER_SEC; | |
| 172 | - int days = int(seconds) / 60 / 60 / 24; | |
| 173 | - int hours = (int(seconds) / 60 / 60) % 24; | |
| 174 | - int minutes = (int(seconds) / 60) % 60; | |
| 175 | - int seconds_left = int(seconds) % 60; | |
| 176 | - cout << "Training until now has taken " << days << " days " << hours << " hours " << minutes << " minutes " << seconds_left <<" seconds." << endl; | |
| 177 | - } | |
| 178 | - | |
| 179 | - if (stageClassifiers.size() == 0) { | |
| 180 | - cout << "Cascade classifier can't be trained. Check the used training parameters." << endl; | |
| 181 | - return false; | |
| 182 | - } | |
| 183 | - | |
| 184 | - save(dirName + CC_CASCADE_FILENAME); | |
| 185 | - | |
| 186 | - return true; | |
| 187 | -} | |
| 188 | - | |
| 189 | -int BrCascadeClassifier::predict( int sampleIdx ) | |
| 190 | -{ | |
| 191 | - CV_DbgAssert( sampleIdx < numPos + numNeg ); | |
| 192 | - for (vector< Ptr<CascadeBoost> >::iterator it = stageClassifiers.begin(); | |
| 193 | - it != stageClassifiers.end(); it++ ) | |
| 194 | - { | |
| 195 | - if ( (*it)->predict( sampleIdx ) == 0.f ) | |
| 196 | - return 0; | |
| 197 | - } | |
| 198 | - return 1; | |
| 199 | -} | |
| 200 | - | |
| 201 | -bool BrCascadeClassifier::updateTrainingSet( double& acceptanceRatio) | |
| 202 | -{ | |
| 203 | - int64 posConsumed = 0, negConsumed = 0; | |
| 204 | - imgReader.restart(); | |
| 205 | - | |
| 206 | - int posCount = fillPassedSamples( 0, numPos, true, posConsumed ); | |
| 207 | - if( !posCount ) | |
| 208 | - return false; | |
| 209 | - cout << "POS count : consumed " << posCount << " : " << (int)posConsumed << endl; | |
| 210 | - | |
| 211 | - int proNumNeg = cvRound( ( ((double)numNeg) * ((double)posCount) ) / numPos ); // apply only a fraction of negative samples. double is required since overflow is possible | |
| 212 | - int negCount = fillPassedSamples( posCount, proNumNeg, false, negConsumed ); | |
| 213 | - if ( !negCount ) | |
| 214 | - return false; | |
| 215 | - | |
| 216 | - curNumSamples = posCount + negCount; | |
| 217 | - acceptanceRatio = negConsumed == 0 ? 0 : ( (double)negCount/(double)(int64)negConsumed ); | |
| 218 | - cout << "NEG count : acceptanceRatio " << negCount << " : " << acceptanceRatio << endl; | |
| 219 | - return true; | |
| 220 | -} | |
| 221 | - | |
| 222 | -int BrCascadeClassifier::fillPassedSamples( int first, int count, bool isPositive, int64& consumed ) | |
| 223 | -{ | |
| 224 | - int getcount = 0; | |
| 225 | - Mat img(winSize, CV_8UC1); | |
| 226 | - for( int i = first; i < first + count; i++ ) | |
| 227 | - { | |
| 228 | - for( ; ; ) | |
| 229 | - { | |
| 230 | - bool isGetImg = isPositive ? imgReader.getPos( img ) : | |
| 231 | - imgReader.getNeg( img ); | |
| 232 | - if( !isGetImg ) | |
| 233 | - return getcount; | |
| 234 | - consumed++; | |
| 235 | - | |
| 236 | - featureEvaluator->setImage( img, isPositive ? 1 : 0, i ); | |
| 237 | - if( predict( i ) == 1.0F ) | |
| 238 | - { | |
| 239 | - getcount++; | |
| 240 | - printf("%s current samples: %d\r", isPositive ? "POS":"NEG", getcount); | |
| 241 | - break; | |
| 242 | - } | |
| 243 | - } | |
| 244 | - } | |
| 245 | - return getcount; | |
| 246 | -} | |
| 247 | - | |
| 248 | -void BrCascadeClassifier::writeParams( FileStorage &fs ) const | |
| 249 | -{ | |
| 250 | - fs << CC_STAGE_TYPE << CC_BOOST; | |
| 251 | - fs << CC_FEATURE_TYPE << CC_LBP; | |
| 252 | - fs << CC_HEIGHT << winSize.height; | |
| 253 | - fs << CC_WIDTH << winSize.width; | |
| 254 | - | |
| 255 | - fs << CC_STAGE_PARAMS << "{"; stageParams->write( fs ); fs << "}"; | |
| 256 | - | |
| 257 | - fs << CC_FEATURE_PARAMS << "{"; | |
| 258 | - fs << CC_MAX_CAT_COUNT << featureEvaluator->getMaxCatCount(); | |
| 259 | - fs << CC_FEATURE_SIZE << featureEvaluator->getFeatureSize(); | |
| 260 | - fs << "}"; | |
| 261 | -} | |
| 262 | - | |
| 263 | -void BrCascadeClassifier::writeFeatures( FileStorage &fs, const Mat& featureMap ) const | |
| 264 | -{ | |
| 265 | - ((FeatureEvaluator*)((Ptr<FeatureEvaluator>)featureEvaluator))->writeFeatures( fs, featureMap ); | |
| 266 | -} | |
| 267 | - | |
| 268 | -void BrCascadeClassifier::writeStages( FileStorage &fs, const Mat& featureMap ) const | |
| 269 | -{ | |
| 270 | - char cmnt[30]; | |
| 271 | - int i = 0; | |
| 272 | - fs << CC_STAGES << "["; | |
| 273 | - for( vector< Ptr<CascadeBoost> >::const_iterator it = stageClassifiers.begin(); | |
| 274 | - it != stageClassifiers.end(); it++, i++ ) | |
| 275 | - { | |
| 276 | - sprintf( cmnt, "stage %d", i ); | |
| 277 | - cvWriteComment( fs.fs, cmnt, 0 ); | |
| 278 | - fs << "{"; | |
| 279 | - ((CascadeBoost*)((Ptr<CascadeBoost>)*it))->write( fs, featureMap ); | |
| 280 | - fs << "}"; | |
| 281 | - } | |
| 282 | - fs << "]"; | |
| 283 | -} | |
| 284 | - | |
| 285 | -void BrCascadeClassifier::save(const string filename) | |
| 286 | -{ | |
| 287 | - FileStorage fs( filename, FileStorage::WRITE ); | |
| 288 | - | |
| 289 | - if ( !fs.isOpened() ) | |
| 290 | - return; | |
| 291 | - | |
| 292 | - fs << FileStorage::getDefaultObjectName(filename) << "{"; | |
| 293 | - | |
| 294 | - Mat featureMap; | |
| 295 | - getUsedFeaturesIdxMap( featureMap ); | |
| 296 | - writeParams( fs ); | |
| 297 | - fs << CC_STAGE_NUM << (int)stageClassifiers.size(); | |
| 298 | - writeStages( fs, featureMap ); | |
| 299 | - writeFeatures( fs, featureMap ); | |
| 300 | - | |
| 301 | - fs << "}"; | |
| 302 | -} | |
| 303 | - | |
| 304 | -void BrCascadeClassifier::getUsedFeaturesIdxMap( Mat& featureMap ) | |
| 305 | -{ | |
| 306 | - int varCount = featureEvaluator->getNumFeatures() * featureEvaluator->getFeatureSize(); | |
| 307 | - featureMap.create( 1, varCount, CV_32SC1 ); | |
| 308 | - featureMap.setTo(Scalar(-1)); | |
| 309 | - | |
| 310 | - for( vector< Ptr<CascadeBoost> >::const_iterator it = stageClassifiers.begin(); | |
| 311 | - it != stageClassifiers.end(); it++ ) | |
| 312 | - ((CascadeBoost*)((Ptr<CascadeBoost>)(*it)))->markUsedFeaturesInMap( featureMap ); | |
| 313 | - | |
| 314 | - for( int fi = 0, idx = 0; fi < varCount; fi++ ) | |
| 315 | - if ( featureMap.at<int>(0, fi) >= 0 ) | |
| 316 | - featureMap.ptr<int>(0)[fi] = idx++; | |
| 317 | -} | |
| 318 | - |
openbr/core/cascade.h deleted
| 1 | -#ifndef CASCADE_H | |
| 2 | -#define CASCADE_H | |
| 3 | - | |
| 4 | -#include <openbr/openbr_plugin.h> | |
| 5 | -#include <opencv2/highgui/highgui.hpp> | |
| 6 | -#include "features.h" | |
| 7 | -#include "boost.h" | |
| 8 | - | |
| 9 | -namespace br | |
| 10 | -{ | |
| 11 | - | |
| 12 | -class CascadeImageReader | |
| 13 | -{ | |
| 14 | -public: | |
| 15 | - bool create( const QList<cv::Mat> &_posImages, const QList<cv::Mat> &_negImages, cv::Size _winSize ); | |
| 16 | - void restart() { posIdx = 0; } | |
| 17 | - bool getNeg(cv::Mat &_img); | |
| 18 | - bool getPos(cv::Mat &_img); | |
| 19 | - | |
| 20 | - QList<cv::Mat> posImages, negImages; | |
| 21 | - | |
| 22 | - int posIdx, negIdx; | |
| 23 | - | |
| 24 | - cv::Mat src, img; | |
| 25 | - cv::Point offset, point; | |
| 26 | - float scale; | |
| 27 | - float scaleFactor; | |
| 28 | - float stepFactor; | |
| 29 | - size_t round; | |
| 30 | - cv::Size winSize; | |
| 31 | - | |
| 32 | -private: | |
| 33 | - bool nextNeg(); | |
| 34 | -}; | |
| 35 | - | |
| 36 | - | |
| 37 | -class BrCascadeClassifier | |
| 38 | -{ | |
| 39 | -public: | |
| 40 | - bool train(const std::string _cascadeDirName, | |
| 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); | |
| 48 | -private: | |
| 49 | - int predict(int sampleIdx); | |
| 50 | - void save(const std::string cascadeDirName); | |
| 51 | - bool updateTrainingSet(double& acceptanceRatio); | |
| 52 | - int fillPassedSamples(int first, int count, bool isPositive, int64& consumed); | |
| 53 | - | |
| 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; | |
| 57 | - | |
| 58 | - void getUsedFeaturesIdxMap(cv::Mat& featureMap); | |
| 59 | - | |
| 60 | - cv::Ptr<CascadeBoostParams> stageParams; | |
| 61 | - | |
| 62 | - cv::Ptr<FeatureEvaluator> featureEvaluator; | |
| 63 | - std::vector< cv::Ptr<CascadeBoost> > stageClassifiers; | |
| 64 | - CascadeImageReader imgReader; | |
| 65 | - int numStages, curNumSamples; | |
| 66 | - int numPos, numNeg; | |
| 67 | - cv::Size winSize; | |
| 68 | -}; | |
| 69 | - | |
| 70 | -} // namespace br | |
| 71 | - | |
| 72 | -#endif // CASCADE_H |
openbr/core/features.cpp deleted
| 1 | -#include "features.h" | |
| 2 | - | |
| 3 | -using namespace cv; | |
| 4 | -using namespace br; | |
| 5 | - | |
| 6 | -//------------------------------------- FeatureEvaluator --------------------------------------- | |
| 7 | - | |
| 8 | -void FeatureEvaluator::init(Representation *_representation, int _maxSampleCount) | |
| 9 | -{ | |
| 10 | - representation = _representation; | |
| 11 | - data.create((int)_maxSampleCount, representation->postWindowSize().area(), CV_32SC1); | |
| 12 | - cls.create( (int)_maxSampleCount, 1, CV_32FC1 ); | |
| 13 | -} | |
| 14 | - | |
| 15 | -void FeatureEvaluator::setImage(const Mat &img, uchar clsLabel, int idx) | |
| 16 | -{ | |
| 17 | - cls.ptr<float>(idx)[0] = clsLabel; | |
| 18 | - | |
| 19 | - Mat integralImg(representation->postWindowSize(), data.type(), data.ptr<int>(idx)); | |
| 20 | - representation->preprocess(img, integralImg); | |
| 21 | -} | |
| 22 | - | |
| 23 | -void FeatureEvaluator::writeFeatures(FileStorage &fs, const Mat &featureMap) const | |
| 24 | -{ | |
| 25 | - representation->write(fs, featureMap); | |
| 26 | -} |
openbr/core/features.h deleted
| 1 | -#ifndef FEATURE_H | |
| 2 | -#define FEATURE_H | |
| 3 | - | |
| 4 | -#include <openbr/openbr_plugin.h> | |
| 5 | -#include "opencv2/imgproc/imgproc.hpp" | |
| 6 | -#include <iostream> | |
| 7 | - | |
| 8 | -#define CC_CASCADE_FILENAME "cascade.xml" | |
| 9 | -#define CC_PARAMS_FILENAME "params.xml" | |
| 10 | - | |
| 11 | -#define CC_CASCADE_PARAMS "cascadeParams" | |
| 12 | -#define CC_STAGE_TYPE "stageType" | |
| 13 | -#define CC_FEATURE_TYPE "featureType" | |
| 14 | -#define CC_HEIGHT "height" | |
| 15 | -#define CC_WIDTH "width" | |
| 16 | - | |
| 17 | -#define CC_STAGE_NUM "stageNum" | |
| 18 | -#define CC_STAGES "stages" | |
| 19 | -#define CC_STAGE_PARAMS "stageParams" | |
| 20 | - | |
| 21 | -#define CC_BOOST "BOOST" | |
| 22 | -#define CC_BOOST_TYPE "boostType" | |
| 23 | -#define CC_DISCRETE_BOOST "DAB" | |
| 24 | -#define CC_REAL_BOOST "RAB" | |
| 25 | -#define CC_LOGIT_BOOST "LB" | |
| 26 | -#define CC_GENTLE_BOOST "GAB" | |
| 27 | -#define CC_MINHITRATE "minHitRate" | |
| 28 | -#define CC_MAXFALSEALARM "maxFalseAlarm" | |
| 29 | -#define CC_TRIM_RATE "weightTrimRate" | |
| 30 | -#define CC_MAX_DEPTH "maxDeptrh" | |
| 31 | -#define CC_WEAK_COUNT "maxWeakCount" | |
| 32 | -#define CC_STAGE_THRESHOLD "stageThreshold" | |
| 33 | -#define CC_WEAK_CLASSIFIERS "weakClassifiers" | |
| 34 | -#define CC_INTERNAL_NODES "internalNodes" | |
| 35 | -#define CC_LEAF_VALUES "leafValues" | |
| 36 | - | |
| 37 | -#define CC_FEATURES "features" | |
| 38 | -#define CC_FEATURE_PARAMS "featureParams" | |
| 39 | -#define CC_MAX_CAT_COUNT "maxCatCount" | |
| 40 | -#define CC_FEATURE_SIZE "featSize" | |
| 41 | - | |
| 42 | -#define CC_LBP "LBP" | |
| 43 | -#define CC_RECT "rect" | |
| 44 | - | |
| 45 | -#ifdef _WIN32 | |
| 46 | -#define TIME( arg ) (((double) clock()) / CLOCKS_PER_SEC) | |
| 47 | -#else | |
| 48 | -#define TIME( arg ) (time( arg )) | |
| 49 | -#endif | |
| 50 | - | |
| 51 | -namespace br | |
| 52 | -{ | |
| 53 | - | |
| 54 | -class FeatureEvaluator | |
| 55 | -{ | |
| 56 | -public: | |
| 57 | - ~FeatureEvaluator() {} | |
| 58 | - void init(Representation *_representation, int _maxSampleCount); | |
| 59 | - void setImage(const cv::Mat& img, uchar clsLabel, int idx); | |
| 60 | - void writeFeatures(cv::FileStorage &fs, const cv::Mat& featureMap) const; | |
| 61 | - float operator()(int featureIdx, int sampleIdx) const { return representation->evaluate(data.row(sampleIdx), featureIdx); } | |
| 62 | - | |
| 63 | - int getNumFeatures() const { return representation->numFeatures(); } | |
| 64 | - int getMaxCatCount() const { return representation->maxCatCount(); } | |
| 65 | - int getFeatureSize() const { return 1; } | |
| 66 | - const cv::Mat& getCls() const { return cls; } | |
| 67 | - float getCls(int si) const { return cls.at<float>(si, 0); } | |
| 68 | - | |
| 69 | - cv::Mat data, cls; | |
| 70 | - Representation *representation; | |
| 71 | -}; | |
| 72 | - | |
| 73 | -} // namespace br | |
| 74 | - | |
| 75 | -#endif // FEATURE_H |
openbr/openbr_plugin.h
| ... | ... | @@ -1395,11 +1395,6 @@ class BR_EXPORT Representation : public Object |
| 1395 | 1395 | { |
| 1396 | 1396 | Q_OBJECT |
| 1397 | 1397 | |
| 1398 | - Q_PROPERTY(int winWidth READ get_winWidth WRITE set_winWidth RESET reset_winWidth STORED false) | |
| 1399 | - Q_PROPERTY(int winHeight READ get_winHeight WRITE set_winHeight RESET reset_winHeight STORED false) | |
| 1400 | - BR_PROPERTY(int, winWidth, 24) | |
| 1401 | - BR_PROPERTY(int, winHeight, 24) | |
| 1402 | - | |
| 1403 | 1398 | public: |
| 1404 | 1399 | virtual ~Representation() {} |
| 1405 | 1400 | ... | ... |
openbr/plugins/classification/boostedforest.cpp
openbr/plugins/classification/cascade.cpp
| 1 | +#include <opencv2/imgproc/imgproc.hpp> | |
| 2 | + | |
| 1 | 3 | #include <openbr/plugins/openbr_internal.h> |
| 2 | -#include <openbr/core/features.h> | |
| 3 | 4 | #include <openbr/core/boost.h> |
| 4 | 5 | |
| 5 | 6 | using namespace cv; |
| ... | ... | @@ -9,7 +10,7 @@ namespace br |
| 9 | 10 | |
| 10 | 11 | struct ImageHandler |
| 11 | 12 | { |
| 12 | - bool create( const QList<cv::Mat> &_posImages, const QList<cv::Mat> &_negImages, cv::Size _winSize ) | |
| 13 | + bool create(const QList<Mat> &_posImages, const QList<Mat> &_negImages, Size _winSize) | |
| 13 | 14 | { |
| 14 | 15 | posImages = _posImages; |
| 15 | 16 | negImages = _negImages; |
| ... | ... | @@ -30,72 +31,57 @@ struct ImageHandler |
| 30 | 31 | |
| 31 | 32 | void restart() { posIdx = 0; } |
| 32 | 33 | |
| 33 | - int numPos() const { return posImages.size(); } | |
| 34 | - int numNeg() const { return negImages.size(); } | |
| 35 | - | |
| 36 | - bool nextNeg() | |
| 34 | + void nextNeg() | |
| 37 | 35 | { |
| 38 | - Point _offset = Point(0,0); | |
| 39 | - size_t count = negImages.size(); | |
| 40 | - for (size_t i = 0; i < count; i++) { | |
| 36 | + int count = negImages.size(); | |
| 37 | + for (int i = 0; i < count; i++) { | |
| 41 | 38 | src = negImages[negIdx++]; |
| 42 | - if( src.empty() ) | |
| 43 | - continue; | |
| 39 | + | |
| 44 | 40 | round += negIdx / count; |
| 45 | 41 | round = round % (winSize.width * winSize.height); |
| 46 | 42 | negIdx %= count; |
| 47 | 43 | |
| 48 | - _offset.x = std::min( (int)round % winSize.width, src.cols - winSize.width ); | |
| 49 | - _offset.y = std::min( (int)round / winSize.width, src.rows - winSize.height ); | |
| 50 | - if( !src.empty() && src.type() == CV_8UC1 && _offset.x >= 0 && _offset.y >= 0 ) | |
| 44 | + offset.x = qMin( (int)round % winSize.width, src.cols - winSize.width ); | |
| 45 | + offset.y = qMin( (int)round / winSize.width, src.rows - winSize.height ); | |
| 46 | + if (!src.empty() && src.type() == CV_8UC1 && offset.x >= 0 && offset.y >= 0) | |
| 51 | 47 | break; |
| 52 | 48 | } |
| 53 | 49 | |
| 54 | - if( src.empty() ) | |
| 55 | - return false; // no appropriate image | |
| 56 | - point = offset = _offset; | |
| 57 | - scale = max( ((float)winSize.width + point.x) / ((float)src.cols), | |
| 58 | - ((float)winSize.height + point.y) / ((float)src.rows) ); | |
| 50 | + point = offset; | |
| 51 | + scale = max(((float)winSize.width + point.x) / ((float)src.cols), | |
| 52 | + ((float)winSize.height + point.y) / ((float)src.rows)); | |
| 59 | 53 | |
| 60 | - Size sz( (int)(scale*src.cols + 0.5F), (int)(scale*src.rows + 0.5F) ); | |
| 61 | - resize( src, img, sz ); | |
| 62 | - return true; | |
| 54 | + Size sz((int)(scale*src.cols + 0.5F), (int)(scale*src.rows + 0.5F)); | |
| 55 | + resize(src, img, sz); | |
| 63 | 56 | } |
| 64 | 57 | |
| 65 | - bool getNeg(cv::Mat &_img) | |
| 58 | + bool getNeg(Mat &_img) | |
| 66 | 59 | { |
| 67 | - if( img.empty() ) | |
| 68 | - if ( !nextNeg() ) | |
| 69 | - return false; | |
| 60 | + if (img.empty()) | |
| 61 | + nextNeg(); | |
| 70 | 62 | |
| 71 | - Mat mat( winSize.height, winSize.width, CV_8UC1, | |
| 72 | - (void*)(img.data + point.y * img.step + point.x * img.elemSize()), img.step ); | |
| 73 | - mat.copyTo(_img); | |
| 63 | + Mat m(winSize.height, winSize.width, CV_8UC1, (void*)(img.data + point.y * img.step + point.x * img.elemSize()), img.step); | |
| 64 | + m.copyTo(_img); | |
| 74 | 65 | |
| 75 | - if( (int)( point.x + (1.0F + stepFactor ) * winSize.width ) < img.cols ) | |
| 66 | + if ((int)(point.x + (1.0F + stepFactor) * winSize.width) < img.cols) | |
| 76 | 67 | point.x += (int)(stepFactor * winSize.width); |
| 77 | - else | |
| 78 | - { | |
| 68 | + else { | |
| 79 | 69 | point.x = offset.x; |
| 80 | - if( (int)( point.y + (1.0F + stepFactor ) * winSize.height ) < img.rows ) | |
| 70 | + if ((int)( point.y + (1.0F + stepFactor ) * winSize.height ) < img.rows) | |
| 81 | 71 | point.y += (int)(stepFactor * winSize.height); |
| 82 | - else | |
| 83 | - { | |
| 72 | + else { | |
| 84 | 73 | point.y = offset.y; |
| 85 | 74 | scale *= scaleFactor; |
| 86 | - if( scale <= 1.0F ) | |
| 87 | - resize( src, img, Size( (int)(scale*src.cols), (int)(scale*src.rows) ) ); | |
| 75 | + if (scale <= 1.0F) | |
| 76 | + resize(src, img, Size((int)(scale*src.cols), (int)(scale*src.rows))); | |
| 88 | 77 | else |
| 89 | - { | |
| 90 | - if ( !nextNeg() ) | |
| 91 | - return false; | |
| 92 | - } | |
| 78 | + nextNeg(); | |
| 93 | 79 | } |
| 94 | 80 | } |
| 95 | 81 | return true; |
| 96 | 82 | } |
| 97 | 83 | |
| 98 | - bool getPos(cv::Mat &_img) | |
| 84 | + bool getPos(Mat &_img) | |
| 99 | 85 | { |
| 100 | 86 | if (posIdx >= posImages.size()) |
| 101 | 87 | return false; |
| ... | ... | @@ -104,20 +90,20 @@ struct ImageHandler |
| 104 | 90 | return true; |
| 105 | 91 | } |
| 106 | 92 | |
| 107 | - QList<cv::Mat> posImages, negImages; | |
| 93 | + QList<Mat> posImages, negImages; | |
| 108 | 94 | |
| 109 | 95 | int posIdx, negIdx; |
| 110 | 96 | |
| 111 | - cv::Mat src, img; | |
| 112 | - cv::Point offset, point; | |
| 97 | + Mat src, img; | |
| 98 | + Point offset, point; | |
| 113 | 99 | float scale; |
| 114 | 100 | float scaleFactor; |
| 115 | 101 | float stepFactor; |
| 116 | 102 | size_t round; |
| 117 | - cv::Size winSize; | |
| 103 | + Size winSize; | |
| 118 | 104 | }; |
| 119 | 105 | |
| 120 | -class _CascadeClassifier : public Classifier | |
| 106 | +class CascadeClassifier : public Classifier | |
| 121 | 107 | { |
| 122 | 108 | Q_OBJECT |
| 123 | 109 | |
| ... | ... | @@ -242,6 +228,7 @@ private: |
| 242 | 228 | qFatal("Cannot get another positive sample!"); |
| 243 | 229 | |
| 244 | 230 | if (classify(pos) == 1.0f) { |
| 231 | + printf("POS current samples: %d\r", images.size()); | |
| 245 | 232 | images.append(pos); |
| 246 | 233 | labels.append(1.0f); |
| 247 | 234 | } |
| ... | ... | @@ -257,6 +244,7 @@ private: |
| 257 | 244 | qFatal("Cannot get another negative sample!"); |
| 258 | 245 | |
| 259 | 246 | if (classify(neg) == 1.0f) { |
| 247 | + printf("NEG current samples: %d\r", images.size() - posCount); | |
| 260 | 248 | images.append(neg); |
| 261 | 249 | labels.append(0.0f); |
| 262 | 250 | } |
| ... | ... | @@ -269,7 +257,7 @@ private: |
| 269 | 257 | } |
| 270 | 258 | }; |
| 271 | 259 | |
| 272 | -BR_REGISTER(Classifier, _CascadeClassifier) | |
| 260 | +BR_REGISTER(Classifier, CascadeClassifier) | |
| 273 | 261 | |
| 274 | 262 | } // namespace br |
| 275 | 263 | ... | ... |
openbr/plugins/metadata/cascade.cpp
| ... | ... | @@ -22,7 +22,6 @@ |
| 22 | 22 | #include <openbr/core/opencvutils.h> |
| 23 | 23 | #include <openbr/core/resource.h> |
| 24 | 24 | #include <openbr/core/qtutils.h> |
| 25 | -#include <openbr/core/cascade.h> | |
| 26 | 25 | |
| 27 | 26 | using namespace cv; |
| 28 | 27 | |
| ... | ... | @@ -65,34 +64,19 @@ private: |
| 65 | 64 | * \author Josh Klontz \cite jklontz |
| 66 | 65 | * \author David Crouse \cite dgcrouse |
| 67 | 66 | */ |
| 68 | -class CascadeTransform : public MetaTransform | |
| 67 | +class CascadeTransform : public UntrainableMetaTransform | |
| 69 | 68 | { |
| 70 | 69 | Q_OBJECT |
| 71 | 70 | Q_PROPERTY(QString model READ get_model WRITE set_model RESET reset_model STORED false) |
| 72 | 71 | Q_PROPERTY(int minSize READ get_minSize WRITE set_minSize RESET reset_minSize STORED false) |
| 73 | 72 | Q_PROPERTY(int minNeighbors READ get_minNeighbors WRITE set_minNeighbors RESET reset_minNeighbors STORED false) |
| 74 | 73 | Q_PROPERTY(bool ROCMode READ get_ROCMode WRITE set_ROCMode RESET reset_ROCMode STORED false) |
| 75 | - | |
| 76 | - // Training parameters | |
| 77 | - Q_PROPERTY(QString vecFile READ get_vecFile WRITE set_vecFile RESET reset_vecFile STORED false) | |
| 78 | - Q_PROPERTY(QString negFile READ get_negFile WRITE set_negFile RESET reset_negFile STORED false) | |
| 79 | - Q_PROPERTY(int winWidth READ get_winWidth WRITE set_winWidth RESET reset_winWidth 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) | |
| 82 | - Q_PROPERTY(int numNeg READ get_numNeg WRITE set_numNeg RESET reset_numNeg STORED false) | |
| 83 | 74 | |
| 84 | 75 | BR_PROPERTY(QString, model, "FrontalFace") |
| 85 | 76 | BR_PROPERTY(int, minSize, 64) |
| 86 | 77 | BR_PROPERTY(int, minNeighbors, 5) |
| 87 | 78 | BR_PROPERTY(bool, ROCMode, false) |
| 88 | 79 | |
| 89 | - BR_PROPERTY(QString, vecFile, "data.vec") | |
| 90 | - BR_PROPERTY(QString, negFile, "neg.txt") | |
| 91 | - BR_PROPERTY(int, winWidth, 24) | |
| 92 | - BR_PROPERTY(int, winHeight, 24) | |
| 93 | - BR_PROPERTY(int, numPos, 1000) | |
| 94 | - BR_PROPERTY(int, numNeg, 1000) | |
| 95 | - | |
| 96 | 80 | Resource<CascadeClassifier> cascadeResource; |
| 97 | 81 | |
| 98 | 82 | void init() |
| ... | ... | @@ -101,99 +85,6 @@ class CascadeTransform : public MetaTransform |
| 101 | 85 | if (model == "Ear" || model == "Eye" || model == "FrontalFace" || model == "ProfileFace") |
| 102 | 86 | this->trainable = false; |
| 103 | 87 | } |
| 104 | - | |
| 105 | - QList<Mat> getPos() | |
| 106 | - { | |
| 107 | - FILE *file = fopen(vecFile.toStdString().c_str(), "rb"); | |
| 108 | - if ( !file ) | |
| 109 | - qFatal("Couldn't open the file"); | |
| 110 | - | |
| 111 | - short* vec = 0; | |
| 112 | - int count, vecSize, last, base; | |
| 113 | - | |
| 114 | - short tmp = 0; | |
| 115 | - if( fread( &count, sizeof( count ), 1, file ) != 1 || | |
| 116 | - fread( &vecSize, sizeof( vecSize ), 1, file ) != 1 || | |
| 117 | - fread( &tmp, sizeof( tmp ), 1, file ) != 1 || | |
| 118 | - fread( &tmp, sizeof( tmp ), 1, file ) != 1 ) | |
| 119 | - CV_Error_( CV_StsParseError, ("wrong file format for %s\n", qPrintable(vecFile)) ); | |
| 120 | - base = sizeof( count ) + sizeof( vecSize ) + 2*sizeof( tmp ); | |
| 121 | - | |
| 122 | - last = 0; | |
| 123 | - vec = (short*) cvAlloc( sizeof( *vec ) * vecSize ); | |
| 124 | - CV_Assert( vec ); | |
| 125 | - | |
| 126 | - QList<Mat> posImages; | |
| 127 | - for (int i = 0; i < 35770; i++) { | |
| 128 | - Mat pos(winHeight, winWidth, CV_8UC1); | |
| 129 | - | |
| 130 | - CV_Assert( pos.rows * pos.cols == vecSize ); | |
| 131 | - uchar tmp = 0; | |
| 132 | - size_t elements_read = fread( &tmp, sizeof( tmp ), 1, file ); | |
| 133 | - if( elements_read != 1 ) | |
| 134 | - CV_Error( CV_StsBadArg, "Can not get new positive sample. The most possible reason is " | |
| 135 | - "insufficient count of samples in given vec-file.\n"); | |
| 136 | - elements_read = fread( vec, sizeof( vec[0] ), vecSize, file ); | |
| 137 | - if( elements_read != (size_t)(vecSize) ) | |
| 138 | - CV_Error( CV_StsBadArg, "Can not get new positive sample. Seems that vec-file has incorrect structure.\n"); | |
| 139 | - | |
| 140 | - if( feof( file ) || last++ >= count ) | |
| 141 | - CV_Error( CV_StsBadArg, "Can not get new positive sample. vec-file is over.\n"); | |
| 142 | - | |
| 143 | - for( int r = 0; r < pos.rows; r++ ) | |
| 144 | - for( int c = 0; c < pos.cols; c++ ) | |
| 145 | - pos.ptr(r)[c] = (uchar)vec[r * pos.cols + c]; | |
| 146 | - posImages.append(pos); | |
| 147 | - } | |
| 148 | - return posImages; | |
| 149 | - } | |
| 150 | - | |
| 151 | - QList<Mat> getNeg() | |
| 152 | - { | |
| 153 | - QList<Mat> negs; | |
| 154 | - | |
| 155 | - std::string dirname, str; | |
| 156 | - std::ifstream file(negFile.toStdString().c_str()); | |
| 157 | - | |
| 158 | - size_t pos = negFile.toStdString().rfind('\\'); | |
| 159 | - char dlmrt = '\\'; | |
| 160 | - if (pos == string::npos) | |
| 161 | - { | |
| 162 | - pos = negFile.toStdString().rfind('/'); | |
| 163 | - dlmrt = '/'; | |
| 164 | - } | |
| 165 | - dirname = pos == string::npos ? "" : negFile.toStdString().substr(0, pos) + dlmrt; | |
| 166 | - while( !file.eof() ) | |
| 167 | - { | |
| 168 | - std::getline(file, str); | |
| 169 | - if (str.empty()) break; | |
| 170 | - if (str.at(0) == '#' ) continue; | |
| 171 | - negs.append(imread(dirname + str, CV_LOAD_IMAGE_GRAYSCALE)); | |
| 172 | - } | |
| 173 | - file.close(); | |
| 174 | - | |
| 175 | - return negs; | |
| 176 | - } | |
| 177 | - | |
| 178 | - // Train transform | |
| 179 | - void train(const TemplateList& data) | |
| 180 | - { | |
| 181 | - (void)data; | |
| 182 | - | |
| 183 | - BrCascadeClassifier classifier; | |
| 184 | - | |
| 185 | - QList<Mat> posImages = getPos(); | |
| 186 | - QList<Mat> negImages = getNeg(); | |
| 187 | - | |
| 188 | - CascadeBoostParams stageParams(CvBoost::GENTLE, 0.999, 0.5, 0.95, 1, 200); | |
| 189 | - | |
| 190 | - QString cascadeDir = Globals->sdkPath + "/share/openbr/models/openbrcascades/" + model; | |
| 191 | - classifier.train(cascadeDir.toStdString(), | |
| 192 | - posImages, negImages, | |
| 193 | - numPos, numNeg, 1024, 1024, 12, | |
| 194 | - Size(winWidth, winHeight), | |
| 195 | - stageParams); | |
| 196 | - } | |
| 197 | 88 | |
| 198 | 89 | void project(const Template &src, Template &dst) const |
| 199 | 90 | { | ... | ... |
openbr/plugins/representation/mblbp.cpp
| ... | ... | @@ -22,6 +22,11 @@ class MBLBPRepresentation : public Representation |
| 22 | 22 | { |
| 23 | 23 | Q_OBJECT |
| 24 | 24 | |
| 25 | + Q_PROPERTY(int winWidth READ get_winWidth WRITE set_winWidth RESET reset_winWidth STORED false) | |
| 26 | + Q_PROPERTY(int winHeight READ get_winHeight WRITE set_winHeight RESET reset_winHeight STORED false) | |
| 27 | + BR_PROPERTY(int, winWidth, 24) | |
| 28 | + BR_PROPERTY(int, winHeight, 24) | |
| 29 | + | |
| 25 | 30 | void init() |
| 26 | 31 | { |
| 27 | 32 | int offset = winWidth + 1; |
| ... | ... | @@ -45,9 +50,11 @@ class MBLBPRepresentation : public Representation |
| 45 | 50 | |
| 46 | 51 | Mat evaluate(const Mat &image, const QList<int> &indices) const |
| 47 | 52 | { |
| 48 | - Mat result(1, indices.size(), CV_32FC1); | |
| 49 | - for (int i = 0; i < indices.size(); i++) | |
| 50 | - result.at<float>(i) = (float)features[indices[i]].calc(image); | |
| 53 | + int size = indices.empty() ? numFeatures() : indices.size(); | |
| 54 | + | |
| 55 | + Mat result(1, size, CV_32FC1); | |
| 56 | + for (int i = 0; i < size; i++) | |
| 57 | + result.at<float>(i) = evaluate(image, indices.empty() ? i : indices[i]); | |
| 51 | 58 | return result; |
| 52 | 59 | } |
| 53 | 60 | ... | ... |