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