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 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 } 308