Merge pull request #2181 from asmorkalov:ocv_packaging
[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 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 }