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 
CvHaarFeatureParams()10 CvHaarFeatureParams::CvHaarFeatureParams() : mode(BASIC)
11 {
12     name = HFP_NAME;
13 }
14 
CvHaarFeatureParams(int _mode)15 CvHaarFeatureParams::CvHaarFeatureParams( int _mode ) : mode( _mode )
16 {
17     name = HFP_NAME;
18 }
19 
init(const CvFeatureParams & fp)20 void CvHaarFeatureParams::init( const CvFeatureParams& fp )
21 {
22     CvFeatureParams::init( fp );
23     mode = ((const CvHaarFeatureParams&)fp).mode;
24 }
25 
write(FileStorage & fs) const26 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 
read(const FileNode & node)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 
printDefaults() const52 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 
printAttrs() const59 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 
scanAttr(const string prmName,const string val)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 
init(const CvFeatureParams * _featureParams,int _maxSampleCount,Size _winSize)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 
setImage(const Mat & img,uchar clsLabel,int idx)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 
writeFeatures(FileStorage & fs,const Mat & featureMap) const109 void CvHaarEvaluator::writeFeatures( FileStorage &fs, const Mat& featureMap ) const
110 {
111     _writeFeatures( features, fs, featureMap );
112 }
113 
writeFeature(FileStorage & fs,int fi) const114 void CvHaarEvaluator::writeFeature(FileStorage &fs, int fi) const
115 {
116     CV_DbgAssert( fi < (int)features.size() );
117     features[fi].write(fs);
118 }
119 
generateFeatures()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 
Feature()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 
Feature(int offset,bool _tilted,int x0,int y0,int w0,int h0,float wt0,int x1,int y1,int w1,int h1,float wt1,int x2,int y2,int w2,int h2,float wt2)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 
write(FileStorage & fs) const298 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