haarfeatures.cpp 11 KB

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