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