Path: blob/master/apps/traincascade/haarfeatures.cpp
16337 views
#include "opencv2/core.hpp"1#include "opencv2/imgproc.hpp"23#include "haarfeatures.h"4#include "cascadeclassifier.h"56using namespace std;7using namespace cv;89CvHaarFeatureParams::CvHaarFeatureParams() : mode(BASIC)10{11name = HFP_NAME;12}1314CvHaarFeatureParams::CvHaarFeatureParams( int _mode ) : mode( _mode )15{16name = HFP_NAME;17}1819void CvHaarFeatureParams::init( const CvFeatureParams& fp )20{21CvFeatureParams::init( fp );22mode = ((const CvHaarFeatureParams&)fp).mode;23}2425void CvHaarFeatureParams::write( FileStorage &fs ) const26{27CvFeatureParams::write( fs );28string modeStr = mode == BASIC ? CC_MODE_BASIC :29mode == CORE ? CC_MODE_CORE :30mode == ALL ? CC_MODE_ALL : string();31CV_Assert( !modeStr.empty() );32fs << CC_MODE << modeStr;33}3435bool CvHaarFeatureParams::read( const FileNode &node )36{37if( !CvFeatureParams::read( node ) )38return false;3940FileNode rnode = node[CC_MODE];41if( !rnode.isString() )42return false;43string modeStr;44rnode >> modeStr;45mode = !modeStr.compare( CC_MODE_BASIC ) ? BASIC :46!modeStr.compare( CC_MODE_CORE ) ? CORE :47!modeStr.compare( CC_MODE_ALL ) ? ALL : -1;48return (mode >= 0);49}5051void CvHaarFeatureParams::printDefaults() const52{53CvFeatureParams::printDefaults();54cout << " [-mode <" CC_MODE_BASIC << "(default) | "55<< CC_MODE_CORE <<" | " << CC_MODE_ALL << endl;56}5758void CvHaarFeatureParams::printAttrs() const59{60CvFeatureParams::printAttrs();61string mode_str = mode == BASIC ? CC_MODE_BASIC :62mode == CORE ? CC_MODE_CORE :63mode == ALL ? CC_MODE_ALL : 0;64cout << "mode: " << mode_str << endl;65}6667bool CvHaarFeatureParams::scanAttr( const string prmName, const string val)68{69if ( !CvFeatureParams::scanAttr( prmName, val ) )70{71if( !prmName.compare("-mode") )72{73mode = !val.compare( CC_MODE_CORE ) ? CORE :74!val.compare( CC_MODE_ALL ) ? ALL :75!val.compare( CC_MODE_BASIC ) ? BASIC : -1;76if (mode == -1)77return false;78}79return false;80}81return true;82}8384//--------------------- HaarFeatureEvaluator ----------------8586void CvHaarEvaluator::init(const CvFeatureParams *_featureParams,87int _maxSampleCount, Size _winSize )88{89CV_Assert(_maxSampleCount > 0);90int cols = (_winSize.width + 1) * (_winSize.height + 1);91sum.create((int)_maxSampleCount, cols, CV_32SC1);92tilted.create((int)_maxSampleCount, cols, CV_32SC1);93normfactor.create(1, (int)_maxSampleCount, CV_32FC1);94CvFeatureEvaluator::init( _featureParams, _maxSampleCount, _winSize );95}9697void CvHaarEvaluator::setImage(const Mat& img, uchar clsLabel, int idx)98{99CV_DbgAssert( !sum.empty() && !tilted.empty() && !normfactor.empty() );100CvFeatureEvaluator::setImage( img, clsLabel, idx);101Mat innSum(winSize.height + 1, winSize.width + 1, sum.type(), sum.ptr<int>((int)idx));102Mat innSqSum;103if (((const CvHaarFeatureParams*)featureParams)->mode == CvHaarFeatureParams::ALL)104{105Mat innTilted(winSize.height + 1, winSize.width + 1, tilted.type(), tilted.ptr<int>((int)idx));106integral(img, innSum, innSqSum, innTilted);107}108else109integral(img, innSum, innSqSum);110normfactor.ptr<float>(0)[idx] = calcNormFactor( innSum, innSqSum );111}112113void CvHaarEvaluator::writeFeatures( FileStorage &fs, const Mat& featureMap ) const114{115_writeFeatures( features, fs, featureMap );116}117118void CvHaarEvaluator::writeFeature(FileStorage &fs, int fi) const119{120CV_DbgAssert( fi < (int)features.size() );121features[fi].write(fs);122}123124void CvHaarEvaluator::generateFeatures()125{126int mode = ((const CvHaarFeatureParams*)((CvFeatureParams*)featureParams))->mode;127int offset = winSize.width + 1;128for( int x = 0; x < winSize.width; x++ )129{130for( int y = 0; y < winSize.height; y++ )131{132for( int dx = 1; dx <= winSize.width; dx++ )133{134for( int dy = 1; dy <= winSize.height; dy++ )135{136// haar_x2137if ( (x+dx*2 <= winSize.width) && (y+dy <= winSize.height) )138{139features.push_back( Feature( offset, false,140x, y, dx*2, dy, -1,141x+dx, y, dx , dy, +2 ) );142}143// haar_y2144if ( (x+dx <= winSize.width) && (y+dy*2 <= winSize.height) )145{146features.push_back( Feature( offset, false,147x, y, dx, dy*2, -1,148x, y+dy, dx, dy, +2 ) );149}150// haar_x3151if ( (x+dx*3 <= winSize.width) && (y+dy <= winSize.height) )152{153features.push_back( Feature( offset, false,154x, y, dx*3, dy, -1,155x+dx, y, dx , dy, +3 ) );156}157// haar_y3158if ( (x+dx <= winSize.width) && (y+dy*3 <= winSize.height) )159{160features.push_back( Feature( offset, false,161x, y, dx, dy*3, -1,162x, y+dy, dx, dy, +3 ) );163}164if( mode != CvHaarFeatureParams::BASIC )165{166// haar_x4167if ( (x+dx*4 <= winSize.width) && (y+dy <= winSize.height) )168{169features.push_back( Feature( offset, false,170x, y, dx*4, dy, -1,171x+dx, y, dx*2, dy, +2 ) );172}173// haar_y4174if ( (x+dx <= winSize.width ) && (y+dy*4 <= winSize.height) )175{176features.push_back( Feature( offset, false,177x, y, dx, dy*4, -1,178x, y+dy, dx, dy*2, +2 ) );179}180}181// x2_y2182if ( (x+dx*2 <= winSize.width) && (y+dy*2 <= winSize.height) )183{184features.push_back( Feature( offset, false,185x, y, dx*2, dy*2, -1,186x, y, dx, dy, +2,187x+dx, y+dy, dx, dy, +2 ) );188}189if (mode != CvHaarFeatureParams::BASIC)190{191if ( (x+dx*3 <= winSize.width) && (y+dy*3 <= winSize.height) )192{193features.push_back( Feature( offset, false,194x , y , dx*3, dy*3, -1,195x+dx, y+dy, dx , dy , +9) );196}197}198if (mode == CvHaarFeatureParams::ALL)199{200// tilted haar_x2201if ( (x+2*dx <= winSize.width) && (y+2*dx+dy <= winSize.height) && (x-dy>= 0) )202{203features.push_back( Feature( offset, true,204x, y, dx*2, dy, -1,205x, y, dx, dy, +2 ) );206}207// tilted haar_y2208if ( (x+dx <= winSize.width) && (y+dx+2*dy <= winSize.height) && (x-2*dy>= 0) )209{210features.push_back( Feature( offset, true,211x, y, dx, 2*dy, -1,212x, y, dx, dy, +2 ) );213}214// tilted haar_x3215if ( (x+3*dx <= winSize.width) && (y+3*dx+dy <= winSize.height) && (x-dy>= 0) )216{217features.push_back( Feature( offset, true,218x, y, dx*3, dy, -1,219x+dx, y+dx, dx, dy, +3 ) );220}221// tilted haar_y3222if ( (x+dx <= winSize.width) && (y+dx+3*dy <= winSize.height) && (x-3*dy>= 0) )223{224features.push_back( Feature( offset, true,225x, y, dx, 3*dy, -1,226x-dy, y+dy, dx, dy, +3 ) );227}228// tilted haar_x4229if ( (x+4*dx <= winSize.width) && (y+4*dx+dy <= winSize.height) && (x-dy>= 0) )230{231features.push_back( Feature( offset, true,232x, y, dx*4, dy, -1,233x+dx, y+dx, dx*2, dy, +2 ) );234}235// tilted haar_y4236if ( (x+dx <= winSize.width) && (y+dx+4*dy <= winSize.height) && (x-4*dy>= 0) )237{238features.push_back( Feature( offset, true,239x, y, dx, 4*dy, -1,240x-dy, y+dy, dx, 2*dy, +2 ) );241}242}243}244}245}246}247numFeatures = (int)features.size();248}249250CvHaarEvaluator::Feature::Feature()251{252tilted = false;253rect[0].r = rect[1].r = rect[2].r = Rect(0,0,0,0);254rect[0].weight = rect[1].weight = rect[2].weight = 0;255}256257CvHaarEvaluator::Feature::Feature( int offset, bool _tilted,258int x0, int y0, int w0, int h0, float wt0,259int x1, int y1, int w1, int h1, float wt1,260int x2, int y2, int w2, int h2, float wt2 )261{262tilted = _tilted;263264rect[0].r.x = x0;265rect[0].r.y = y0;266rect[0].r.width = w0;267rect[0].r.height = h0;268rect[0].weight = wt0;269270rect[1].r.x = x1;271rect[1].r.y = y1;272rect[1].r.width = w1;273rect[1].r.height = h1;274rect[1].weight = wt1;275276rect[2].r.x = x2;277rect[2].r.y = y2;278rect[2].r.width = w2;279rect[2].r.height = h2;280rect[2].weight = wt2;281282if( !tilted )283{284for( int j = 0; j < CV_HAAR_FEATURE_MAX; j++ )285{286if( rect[j].weight == 0.0F )287break;288CV_SUM_OFFSETS( fastRect[j].p0, fastRect[j].p1, fastRect[j].p2, fastRect[j].p3, rect[j].r, offset )289}290}291else292{293for( int j = 0; j < CV_HAAR_FEATURE_MAX; j++ )294{295if( rect[j].weight == 0.0F )296break;297CV_TILTED_OFFSETS( fastRect[j].p0, fastRect[j].p1, fastRect[j].p2, fastRect[j].p3, rect[j].r, offset )298}299}300}301302void CvHaarEvaluator::Feature::write( FileStorage &fs ) const303{304fs << CC_RECTS << "[";305for( int ri = 0; ri < CV_HAAR_FEATURE_MAX && rect[ri].r.width != 0; ++ri )306{307fs << "[:" << rect[ri].r.x << rect[ri].r.y <<308rect[ri].r.width << rect[ri].r.height << rect[ri].weight << "]";309}310fs << "]" << CC_TILTED << tilted;311}312313314