HOGfeatures.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. #include "opencv2/core.hpp"
  2. #include "opencv2/imgproc.hpp"
  3. #include "HOGfeatures.h"
  4. #include "cascadeclassifier.h"
  5. using namespace std;
  6. using namespace cv;
  7. CvHOGFeatureParams::CvHOGFeatureParams()
  8. {
  9. maxCatCount = 0;
  10. name = HOGF_NAME;
  11. featSize = N_BINS * N_CELLS;
  12. }
  13. void CvHOGEvaluator::init(const CvFeatureParams *_featureParams, int _maxSampleCount, Size _winSize)
  14. {
  15. CV_Assert( _maxSampleCount > 0);
  16. int cols = (_winSize.width + 1) * (_winSize.height + 1);
  17. for (int bin = 0; bin < N_BINS; bin++)
  18. {
  19. hist.push_back(Mat(_maxSampleCount, cols, CV_32FC1));
  20. }
  21. normSum.create( (int)_maxSampleCount, cols, CV_32FC1 );
  22. CvFeatureEvaluator::init( _featureParams, _maxSampleCount, _winSize );
  23. }
  24. void CvHOGEvaluator::setImage(const Mat &img, uchar clsLabel, int idx)
  25. {
  26. CV_DbgAssert( !hist.empty());
  27. CvFeatureEvaluator::setImage( img, clsLabel, idx );
  28. vector<Mat> integralHist;
  29. for (int bin = 0; bin < N_BINS; bin++)
  30. {
  31. integralHist.push_back( Mat(winSize.height + 1, winSize.width + 1, hist[bin].type(), hist[bin].ptr<float>((int)idx)) );
  32. }
  33. Mat integralNorm(winSize.height + 1, winSize.width + 1, normSum.type(), normSum.ptr<float>((int)idx));
  34. integralHistogram(img, integralHist, integralNorm, (int)N_BINS);
  35. }
  36. //void CvHOGEvaluator::writeFeatures( FileStorage &fs, const Mat& featureMap ) const
  37. //{
  38. // _writeFeatures( features, fs, featureMap );
  39. //}
  40. void CvHOGEvaluator::writeFeatures( FileStorage &fs, const Mat& featureMap ) const
  41. {
  42. int featIdx;
  43. int componentIdx;
  44. const Mat_<int>& featureMap_ = (const Mat_<int>&)featureMap;
  45. fs << FEATURES << "[";
  46. for ( int fi = 0; fi < featureMap.cols; fi++ )
  47. if ( featureMap_(0, fi) >= 0 )
  48. {
  49. fs << "{";
  50. featIdx = fi / getFeatureSize();
  51. componentIdx = fi % getFeatureSize();
  52. features[featIdx].write( fs, componentIdx );
  53. fs << "}";
  54. }
  55. fs << "]";
  56. }
  57. void CvHOGEvaluator::generateFeatures()
  58. {
  59. int offset = winSize.width + 1;
  60. Size blockStep;
  61. int x, y, t, w, h;
  62. for (t = 8; t <= winSize.width/2; t+=8) //t = size of a cell. blocksize = 4*cellSize
  63. {
  64. blockStep = Size(4,4);
  65. w = 2*t; //width of a block
  66. h = 2*t; //height of a block
  67. for (x = 0; x <= winSize.width - w; x += blockStep.width)
  68. {
  69. for (y = 0; y <= winSize.height - h; y += blockStep.height)
  70. {
  71. features.push_back(Feature(offset, x, y, t, t));
  72. }
  73. }
  74. w = 2*t;
  75. h = 4*t;
  76. for (x = 0; x <= winSize.width - w; x += blockStep.width)
  77. {
  78. for (y = 0; y <= winSize.height - h; y += blockStep.height)
  79. {
  80. features.push_back(Feature(offset, x, y, t, 2*t));
  81. }
  82. }
  83. w = 4*t;
  84. h = 2*t;
  85. for (x = 0; x <= winSize.width - w; x += blockStep.width)
  86. {
  87. for (y = 0; y <= winSize.height - h; y += blockStep.height)
  88. {
  89. features.push_back(Feature(offset, x, y, 2*t, t));
  90. }
  91. }
  92. }
  93. numFeatures = (int)features.size();
  94. }
  95. CvHOGEvaluator::Feature::Feature()
  96. {
  97. for (int i = 0; i < N_CELLS; i++)
  98. {
  99. rect[i] = Rect(0, 0, 0, 0);
  100. }
  101. }
  102. CvHOGEvaluator::Feature::Feature( int offset, int x, int y, int cellW, int cellH )
  103. {
  104. rect[0] = Rect(x, y, cellW, cellH); //cell0
  105. rect[1] = Rect(x+cellW, y, cellW, cellH); //cell1
  106. rect[2] = Rect(x, y+cellH, cellW, cellH); //cell2
  107. rect[3] = Rect(x+cellW, y+cellH, cellW, cellH); //cell3
  108. for (int i = 0; i < N_CELLS; i++)
  109. {
  110. CV_SUM_OFFSETS(fastRect[i].p0, fastRect[i].p1, fastRect[i].p2, fastRect[i].p3, rect[i], offset);
  111. }
  112. }
  113. void CvHOGEvaluator::Feature::write(FileStorage &fs) const
  114. {
  115. fs << CC_RECTS << "[";
  116. for( int i = 0; i < N_CELLS; i++ )
  117. {
  118. fs << "[:" << rect[i].x << rect[i].y << rect[i].width << rect[i].height << "]";
  119. }
  120. fs << "]";
  121. }
  122. //cell and bin idx writing
  123. //void CvHOGEvaluator::Feature::write(FileStorage &fs, int varIdx) const
  124. //{
  125. // int featComponent = varIdx % (N_CELLS * N_BINS);
  126. // int cellIdx = featComponent / N_BINS;
  127. // int binIdx = featComponent % N_BINS;
  128. //
  129. // fs << CC_RECTS << "[:" << rect[cellIdx].x << rect[cellIdx].y <<
  130. // rect[cellIdx].width << rect[cellIdx].height << binIdx << "]";
  131. //}
  132. //cell[0] and featComponent idx writing. By cell[0] it's possible to recover all block
  133. //All block is necessary for block normalization
  134. void CvHOGEvaluator::Feature::write(FileStorage &fs, int featComponentIdx) const
  135. {
  136. fs << CC_RECT << "[:" << rect[0].x << rect[0].y <<
  137. rect[0].width << rect[0].height << featComponentIdx << "]";
  138. }
  139. void CvHOGEvaluator::integralHistogram(const Mat &img, vector<Mat> &histogram, Mat &norm, int nbins) const
  140. {
  141. CV_Assert( img.type() == CV_8U || img.type() == CV_8UC3 );
  142. int x, y, binIdx;
  143. Size gradSize(img.size());
  144. Size histSize(histogram[0].size());
  145. Mat grad(gradSize, CV_32F);
  146. Mat qangle(gradSize, CV_8U);
  147. AutoBuffer<int> mapbuf(gradSize.width + gradSize.height + 4);
  148. int* xmap = mapbuf.data() + 1;
  149. int* ymap = xmap + gradSize.width + 2;
  150. const int borderType = (int)BORDER_REPLICATE;
  151. for( x = -1; x < gradSize.width + 1; x++ )
  152. xmap[x] = borderInterpolate(x, gradSize.width, borderType);
  153. for( y = -1; y < gradSize.height + 1; y++ )
  154. ymap[y] = borderInterpolate(y, gradSize.height, borderType);
  155. int width = gradSize.width;
  156. AutoBuffer<float> _dbuf(width*4);
  157. float* dbuf = _dbuf.data();
  158. Mat Dx(1, width, CV_32F, dbuf);
  159. Mat Dy(1, width, CV_32F, dbuf + width);
  160. Mat Mag(1, width, CV_32F, dbuf + width*2);
  161. Mat Angle(1, width, CV_32F, dbuf + width*3);
  162. float angleScale = (float)(nbins/CV_PI);
  163. for( y = 0; y < gradSize.height; y++ )
  164. {
  165. const uchar* currPtr = img.ptr(ymap[y]);
  166. const uchar* prevPtr = img.ptr(ymap[y-1]);
  167. const uchar* nextPtr = img.ptr(ymap[y+1]);
  168. float* gradPtr = grad.ptr<float>(y);
  169. uchar* qanglePtr = qangle.ptr(y);
  170. for( x = 0; x < width; x++ )
  171. {
  172. dbuf[x] = (float)(currPtr[xmap[x+1]] - currPtr[xmap[x-1]]);
  173. dbuf[width + x] = (float)(nextPtr[xmap[x]] - prevPtr[xmap[x]]);
  174. }
  175. cartToPolar( Dx, Dy, Mag, Angle, false );
  176. for( x = 0; x < width; x++ )
  177. {
  178. float mag = dbuf[x+width*2];
  179. float angle = dbuf[x+width*3];
  180. angle = angle*angleScale - 0.5f;
  181. int bidx = cvFloor(angle);
  182. angle -= bidx;
  183. if( bidx < 0 )
  184. bidx += nbins;
  185. else if( bidx >= nbins )
  186. bidx -= nbins;
  187. qanglePtr[x] = (uchar)bidx;
  188. gradPtr[x] = mag;
  189. }
  190. }
  191. integral(grad, norm, grad.depth());
  192. float* histBuf;
  193. const float* magBuf;
  194. const uchar* binsBuf;
  195. int binsStep = (int)( qangle.step / sizeof(uchar) );
  196. int histStep = (int)( histogram[0].step / sizeof(float) );
  197. int magStep = (int)( grad.step / sizeof(float) );
  198. for( binIdx = 0; binIdx < nbins; binIdx++ )
  199. {
  200. histBuf = histogram[binIdx].ptr<float>();
  201. magBuf = grad.ptr<float>();
  202. binsBuf = qangle.ptr();
  203. memset( histBuf, 0, histSize.width * sizeof(histBuf[0]) );
  204. histBuf += histStep + 1;
  205. for( y = 0; y < qangle.rows; y++ )
  206. {
  207. histBuf[-1] = 0.f;
  208. float strSum = 0.f;
  209. for( x = 0; x < qangle.cols; x++ )
  210. {
  211. if( binsBuf[x] == binIdx )
  212. strSum += magBuf[x];
  213. histBuf[x] = histBuf[-histStep + x] + strSum;
  214. }
  215. histBuf += histStep;
  216. binsBuf += binsStep;
  217. magBuf += magStep;
  218. }
  219. }
  220. }