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