Home | History | Annotate | Download | only in traincascade
      1 #include "opencv2/core.hpp"
      2 #include "opencv2/imgproc.hpp"
      3 
      4 #include "haarfeatures.h"
      5 #include "cascadeclassifier.h"
      6 
      7 using namespace std;
      8 using namespace cv;
      9 
     10 CvHaarFeatureParams::CvHaarFeatureParams() : mode(BASIC)
     11 {
     12     name = HFP_NAME;
     13 }
     14 
     15 CvHaarFeatureParams::CvHaarFeatureParams( int _mode ) : mode( _mode )
     16 {
     17     name = HFP_NAME;
     18 }
     19 
     20 void CvHaarFeatureParams::init( const CvFeatureParams& fp )
     21 {
     22     CvFeatureParams::init( fp );
     23     mode = ((const CvHaarFeatureParams&)fp).mode;
     24 }
     25 
     26 void CvHaarFeatureParams::write( FileStorage &fs ) const
     27 {
     28     CvFeatureParams::write( fs );
     29     string modeStr = mode == BASIC ? CC_MODE_BASIC :
     30                      mode == CORE ? CC_MODE_CORE :
     31                      mode == ALL ? CC_MODE_ALL : string();
     32     CV_Assert( !modeStr.empty() );
     33     fs << CC_MODE << modeStr;
     34 }
     35 
     36 bool CvHaarFeatureParams::read( const FileNode &node )
     37 {
     38     if( !CvFeatureParams::read( node ) )
     39         return false;
     40 
     41     FileNode rnode = node[CC_MODE];
     42     if( !rnode.isString() )
     43         return false;
     44     string modeStr;
     45     rnode >> modeStr;
     46     mode = !modeStr.compare( CC_MODE_BASIC ) ? BASIC :
     47            !modeStr.compare( CC_MODE_CORE ) ? CORE :
     48            !modeStr.compare( CC_MODE_ALL ) ? ALL : -1;
     49     return (mode >= 0);
     50 }
     51 
     52 void CvHaarFeatureParams::printDefaults() const
     53 {
     54     CvFeatureParams::printDefaults();
     55     cout << "  [-mode <" CC_MODE_BASIC << "(default) | "
     56             << CC_MODE_CORE <<" | " << CC_MODE_ALL << endl;
     57 }
     58 
     59 void CvHaarFeatureParams::printAttrs() const
     60 {
     61     CvFeatureParams::printAttrs();
     62     string mode_str = mode == BASIC ? CC_MODE_BASIC :
     63                        mode == CORE ? CC_MODE_CORE :
     64                        mode == ALL ? CC_MODE_ALL : 0;
     65     cout << "mode: " <<  mode_str << endl;
     66 }
     67 
     68 bool CvHaarFeatureParams::scanAttr( const string prmName, const string val)
     69 {
     70     if ( !CvFeatureParams::scanAttr( prmName, val ) )
     71     {
     72         if( !prmName.compare("-mode") )
     73         {
     74             mode = !val.compare( CC_MODE_CORE ) ? CORE :
     75                    !val.compare( CC_MODE_ALL ) ? ALL :
     76                    !val.compare( CC_MODE_BASIC ) ? BASIC : -1;
     77             if (mode == -1)
     78                 return false;
     79         }
     80         return false;
     81     }
     82     return true;
     83 }
     84 
     85 //--------------------- HaarFeatureEvaluator ----------------
     86 
     87 void CvHaarEvaluator::init(const CvFeatureParams *_featureParams,
     88                            int _maxSampleCount, Size _winSize )
     89 {
     90     CV_Assert(_maxSampleCount > 0);
     91     int cols = (_winSize.width + 1) * (_winSize.height + 1);
     92     sum.create((int)_maxSampleCount, cols, CV_32SC1);
     93     tilted.create((int)_maxSampleCount, cols, CV_32SC1);
     94     normfactor.create(1, (int)_maxSampleCount, CV_32FC1);
     95     CvFeatureEvaluator::init( _featureParams, _maxSampleCount, _winSize );
     96 }
     97 
     98 void CvHaarEvaluator::setImage(const Mat& img, uchar clsLabel, int idx)
     99 {
    100     CV_DbgAssert( !sum.empty() && !tilted.empty() && !normfactor.empty() );
    101     CvFeatureEvaluator::setImage( img, clsLabel, idx);
    102     Mat innSum(winSize.height + 1, winSize.width + 1, sum.type(), sum.ptr<int>((int)idx));
    103     Mat innTilted(winSize.height + 1, winSize.width + 1, tilted.type(), tilted.ptr<int>((int)idx));
    104     Mat innSqSum;
    105     integral(img, innSum, innSqSum, innTilted);
    106     normfactor.ptr<float>(0)[idx] = calcNormFactor( innSum, innSqSum );
    107 }
    108 
    109 void CvHaarEvaluator::writeFeatures( FileStorage &fs, const Mat& featureMap ) const
    110 {
    111     _writeFeatures( features, fs, featureMap );
    112 }
    113 
    114 void CvHaarEvaluator::writeFeature(FileStorage &fs, int fi) const
    115 {
    116     CV_DbgAssert( fi < (int)features.size() );
    117     features[fi].write(fs);
    118 }
    119 
    120 void CvHaarEvaluator::generateFeatures()
    121 {
    122     int mode = ((const CvHaarFeatureParams*)((CvFeatureParams*)featureParams))->mode;
    123     int offset = winSize.width + 1;
    124     for( int x = 0; x < winSize.width; x++ )
    125     {
    126         for( int y = 0; y < winSize.height; y++ )
    127         {
    128             for( int dx = 1; dx <= winSize.width; dx++ )
    129             {
    130                 for( int dy = 1; dy <= winSize.height; dy++ )
    131                 {
    132                     // haar_x2
    133                     if ( (x+dx*2 <= winSize.width) && (y+dy <= winSize.height) )
    134                     {
    135                         features.push_back( Feature( offset, false,
    136                             x,    y, dx*2, dy, -1,
    137                             x+dx, y, dx  , dy, +2 ) );
    138                     }
    139                     // haar_y2
    140                     if ( (x+dx <= winSize.width) && (y+dy*2 <= winSize.height) )
    141                     {
    142                         features.push_back( Feature( offset, false,
    143                             x,    y, dx, dy*2, -1,
    144                             x, y+dy, dx, dy,   +2 ) );
    145                     }
    146                     // haar_x3
    147                     if ( (x+dx*3 <= winSize.width) && (y+dy <= winSize.height) )
    148                     {
    149                         features.push_back( Feature( offset, false,
    150                             x,    y, dx*3, dy, -1,
    151                             x+dx, y, dx  , dy, +3 ) );
    152                     }
    153                     // haar_y3
    154                     if ( (x+dx <= winSize.width) && (y+dy*3 <= winSize.height) )
    155                     {
    156                         features.push_back( Feature( offset, false,
    157                             x, y,    dx, dy*3, -1,
    158                             x, y+dy, dx, dy,   +3 ) );
    159                     }
    160                     if( mode != CvHaarFeatureParams::BASIC )
    161                     {
    162                         // haar_x4
    163                         if ( (x+dx*4 <= winSize.width) && (y+dy <= winSize.height) )
    164                         {
    165                             features.push_back( Feature( offset, false,
    166                                 x,    y, dx*4, dy, -1,
    167                                 x+dx, y, dx*2, dy, +2 ) );
    168                         }
    169                         // haar_y4
    170                         if ( (x+dx <= winSize.width ) && (y+dy*4 <= winSize.height) )
    171                         {
    172                             features.push_back( Feature( offset, false,
    173                                 x, y,    dx, dy*4, -1,
    174                                 x, y+dy, dx, dy*2, +2 ) );
    175                         }
    176                     }
    177                     // x2_y2
    178                     if ( (x+dx*2 <= winSize.width) && (y+dy*2 <= winSize.height) )
    179                     {
    180                         features.push_back( Feature( offset, false,
    181                             x,    y,    dx*2, dy*2, -1,
    182                             x,    y,    dx,   dy,   +2,
    183                             x+dx, y+dy, dx,   dy,   +2 ) );
    184                     }
    185                     if (mode != CvHaarFeatureParams::BASIC)
    186                     {
    187                         if ( (x+dx*3 <= winSize.width) && (y+dy*3 <= winSize.height) )
    188                         {
    189                             features.push_back( Feature( offset, false,
    190                                 x   , y   , dx*3, dy*3, -1,
    191                                 x+dx, y+dy, dx  , dy  , +9) );
    192                         }
    193                     }
    194                     if (mode == CvHaarFeatureParams::ALL)
    195                     {
    196                         // tilted haar_x2
    197                         if ( (x+2*dx <= winSize.width) && (y+2*dx+dy <= winSize.height) && (x-dy>= 0) )
    198                         {
    199                             features.push_back( Feature( offset, true,
    200                                 x, y, dx*2, dy, -1,
    201                                 x, y, dx,   dy, +2 ) );
    202                         }
    203                         // tilted haar_y2
    204                         if ( (x+dx <= winSize.width) && (y+dx+2*dy <= winSize.height) && (x-2*dy>= 0) )
    205                         {
    206                             features.push_back( Feature( offset, true,
    207                                 x, y, dx, 2*dy, -1,
    208                                 x, y, dx, dy,   +2 ) );
    209                         }
    210                         // tilted haar_x3
    211                         if ( (x+3*dx <= winSize.width) && (y+3*dx+dy <= winSize.height) && (x-dy>= 0) )
    212                         {
    213                             features.push_back( Feature( offset, true,
    214                                 x,    y,    dx*3, dy, -1,
    215                                 x+dx, y+dx, dx,   dy, +3 ) );
    216                         }
    217                         // tilted haar_y3
    218                         if ( (x+dx <= winSize.width) && (y+dx+3*dy <= winSize.height) && (x-3*dy>= 0) )
    219                         {
    220                             features.push_back( Feature( offset, true,
    221                                 x,    y,    dx, 3*dy, -1,
    222                                 x-dy, y+dy, dx, dy,   +3 ) );
    223                         }
    224                         // tilted haar_x4
    225                         if ( (x+4*dx <= winSize.width) && (y+4*dx+dy <= winSize.height) && (x-dy>= 0) )
    226                         {
    227                             features.push_back( Feature( offset, true,
    228                                 x,    y,    dx*4, dy, -1,
    229                                 x+dx, y+dx, dx*2, dy, +2 ) );
    230                         }
    231                         // tilted haar_y4
    232                         if ( (x+dx <= winSize.width) && (y+dx+4*dy <= winSize.height) && (x-4*dy>= 0) )
    233                         {
    234                             features.push_back( Feature( offset, true,
    235                                 x,    y,    dx, 4*dy, -1,
    236                                 x-dy, y+dy, dx, 2*dy, +2 ) );
    237                         }
    238                     }
    239                 }
    240             }
    241         }
    242     }
    243     numFeatures = (int)features.size();
    244 }
    245 
    246 CvHaarEvaluator::Feature::Feature()
    247 {
    248     tilted = false;
    249     rect[0].r = rect[1].r = rect[2].r = Rect(0,0,0,0);
    250     rect[0].weight = rect[1].weight = rect[2].weight = 0;
    251 }
    252 
    253 CvHaarEvaluator::Feature::Feature( int offset, bool _tilted,
    254                                           int x0, int y0, int w0, int h0, float wt0,
    255                                           int x1, int y1, int w1, int h1, float wt1,
    256                                           int x2, int y2, int w2, int h2, float wt2 )
    257 {
    258     tilted = _tilted;
    259 
    260     rect[0].r.x = x0;
    261     rect[0].r.y = y0;
    262     rect[0].r.width  = w0;
    263     rect[0].r.height = h0;
    264     rect[0].weight   = wt0;
    265 
    266     rect[1].r.x = x1;
    267     rect[1].r.y = y1;
    268     rect[1].r.width  = w1;
    269     rect[1].r.height = h1;
    270     rect[1].weight   = wt1;
    271 
    272     rect[2].r.x = x2;
    273     rect[2].r.y = y2;
    274     rect[2].r.width  = w2;
    275     rect[2].r.height = h2;
    276     rect[2].weight   = wt2;
    277 
    278     if( !tilted )
    279     {
    280         for( int j = 0; j < CV_HAAR_FEATURE_MAX; j++ )
    281         {
    282             if( rect[j].weight == 0.0F )
    283                 break;
    284             CV_SUM_OFFSETS( fastRect[j].p0, fastRect[j].p1, fastRect[j].p2, fastRect[j].p3, rect[j].r, offset )
    285         }
    286     }
    287     else
    288     {
    289         for( int j = 0; j < CV_HAAR_FEATURE_MAX; j++ )
    290         {
    291             if( rect[j].weight == 0.0F )
    292                 break;
    293             CV_TILTED_OFFSETS( fastRect[j].p0, fastRect[j].p1, fastRect[j].p2, fastRect[j].p3, rect[j].r, offset )
    294         }
    295     }
    296 }
    297 
    298 void CvHaarEvaluator::Feature::write( FileStorage &fs ) const
    299 {
    300     fs << CC_RECTS << "[";
    301     for( int ri = 0; ri < CV_HAAR_FEATURE_MAX && rect[ri].r.width != 0; ++ri )
    302     {
    303         fs << "[:" << rect[ri].r.x << rect[ri].r.y <<
    304             rect[ri].r.width << rect[ri].r.height << rect[ri].weight << "]";
    305     }
    306     fs << "]" << CC_TILTED << tilted;
    307 }
    308