1 #include "HOGfeatures.h"
\r
2 #include "cascadeclassifier.h"
\r
5 CvHOGFeatureParams::CvHOGFeatureParams()
\r
9 featSize = N_BINS * N_CELLS;
\r
12 void CvHOGEvaluator::init(const CvFeatureParams *_featureParams, int _maxSampleCount, Size _winSize)
\r
14 CV_Assert( _maxSampleCount > 0);
\r
15 int cols = (_winSize.width + 1) * (_winSize.height + 1);
\r
16 for (int bin = 0; bin < N_BINS; bin++)
\r
18 hist.push_back(Mat(_maxSampleCount, cols, CV_32FC1));
\r
20 normSum.create( (int)_maxSampleCount, cols, CV_32FC1 );
\r
21 CvFeatureEvaluator::init( _featureParams, _maxSampleCount, _winSize );
\r
24 void CvHOGEvaluator::setImage(const Mat &img, uchar clsLabel, int idx)
\r
26 CV_DbgAssert( !hist.empty());
\r
27 CvFeatureEvaluator::setImage( img, clsLabel, idx );
\r
28 vector<Mat> integralHist;
\r
29 for (int bin = 0; bin < N_BINS; bin++)
\r
31 integralHist.push_back( Mat(winSize.height + 1, winSize.width + 1, hist[bin].type(), hist[bin].ptr<float>((int)idx)) );
\r
33 Mat integralNorm(winSize.height + 1, winSize.width + 1, normSum.type(), normSum.ptr<float>((int)idx));
\r
34 integralHistogram(img, integralHist, integralNorm, (int)N_BINS);
\r
37 //void CvHOGEvaluator::writeFeatures( FileStorage &fs, const Mat& featureMap ) const
\r
39 // _writeFeatures( features, fs, featureMap );
\r
42 void CvHOGEvaluator::writeFeatures( FileStorage &fs, const Mat& featureMap ) const
\r
46 const Mat_<int>& featureMap_ = (const Mat_<int>&)featureMap;
\r
47 fs << FEATURES << "[";
\r
48 for ( int fi = 0; fi < featureMap.cols; fi++ )
\r
49 if ( featureMap_(0, fi) >= 0 )
\r
52 featIdx = fi / getFeatureSize();
\r
53 componentIdx = fi % getFeatureSize();
\r
54 features[featIdx].write( fs, componentIdx );
\r
60 void CvHOGEvaluator::generateFeatures()
\r
62 int offset = winSize.width + 1;
\r
66 for (t = 8; t <= winSize.width/2; t+=8) //t = size of a cell. blocksize = 4*cellSize
\r
68 blockStep = Size(4,4);
\r
69 w = 2*t; //width of a block
\r
70 h = 2*t; //height of a block
\r
71 for (x = 0; x <= winSize.width - w; x += blockStep.width)
\r
73 for (y = 0; y <= winSize.height - h; y += blockStep.height)
\r
75 features.push_back(Feature(offset, x, y, t, t));
\r
80 for (x = 0; x <= winSize.width - w; x += blockStep.width)
\r
82 for (y = 0; y <= winSize.height - h; y += blockStep.height)
\r
84 features.push_back(Feature(offset, x, y, t, 2*t));
\r
89 for (x = 0; x <= winSize.width - w; x += blockStep.width)
\r
91 for (y = 0; y <= winSize.height - h; y += blockStep.height)
\r
93 features.push_back(Feature(offset, x, y, 2*t, t));
\r
98 numFeatures = (int)features.size();
\r
101 CvHOGEvaluator::Feature::Feature()
\r
103 for (int i = 0; i < N_CELLS; i++)
\r
105 rect[i] = Rect(0, 0, 0, 0);
\r
109 CvHOGEvaluator::Feature::Feature( int offset, int x, int y, int cellW, int cellH )
\r
111 rect[0] = Rect(x, y, cellW, cellH); //cell0
\r
112 rect[1] = Rect(x+cellW, y, cellW, cellH); //cell1
\r
113 rect[2] = Rect(x, y+cellH, cellW, cellH); //cell2
\r
114 rect[3] = Rect(x+cellW, y+cellH, cellW, cellH); //cell3
\r
116 for (int i = 0; i < N_CELLS; i++)
\r
118 CV_SUM_OFFSETS(fastRect[i].p0, fastRect[i].p1, fastRect[i].p2, fastRect[i].p3, rect[i], offset);
\r
122 void CvHOGEvaluator::Feature::write(FileStorage &fs) const
\r
124 fs << CC_RECTS << "[";
\r
125 for( int i = 0; i < N_CELLS; i++ )
\r
127 fs << "[:" << rect[i].x << rect[i].y << rect[i].width << rect[i].height << "]";
\r
132 //cell and bin idx writing
\r
133 //void CvHOGEvaluator::Feature::write(FileStorage &fs, int varIdx) const
\r
135 // int featComponent = varIdx % (N_CELLS * N_BINS);
\r
136 // int cellIdx = featComponent / N_BINS;
\r
137 // int binIdx = featComponent % N_BINS;
\r
139 // fs << CC_RECTS << "[:" << rect[cellIdx].x << rect[cellIdx].y <<
\r
140 // rect[cellIdx].width << rect[cellIdx].height << binIdx << "]";
\r
143 //cell[0] and featComponent idx writing. By cell[0] it's possible to recover all block
\r
144 //All block is nessesary for block normalization
\r
145 void CvHOGEvaluator::Feature::write(FileStorage &fs, int featComponentIdx) const
\r
147 fs << CC_RECT << "[:" << rect[0].x << rect[0].y <<
\r
148 rect[0].width << rect[0].height << featComponentIdx << "]";
\r
152 void CvHOGEvaluator::integralHistogram(const Mat &img, vector<Mat> &histogram, Mat &norm, int nbins) const
\r
154 CV_Assert( img.type() == CV_8U || img.type() == CV_8UC3 );
\r
157 Size gradSize(img.size());
\r
158 Size histSize(histogram[0].size());
\r
159 Mat grad(gradSize, CV_32F);
\r
160 Mat qangle(gradSize, CV_8U);
\r
162 AutoBuffer<int> mapbuf(gradSize.width + gradSize.height + 4);
\r
163 int* xmap = (int*)mapbuf + 1;
\r
164 int* ymap = xmap + gradSize.width + 2;
\r
166 const int borderType = (int)BORDER_REPLICATE;
\r
168 for( x = -1; x < gradSize.width + 1; x++ )
\r
169 xmap[x] = borderInterpolate(x, gradSize.width, borderType);
\r
170 for( y = -1; y < gradSize.height + 1; y++ )
\r
171 ymap[y] = borderInterpolate(y, gradSize.height, borderType);
\r
173 int width = gradSize.width;
\r
174 AutoBuffer<float> _dbuf(width*4);
\r
175 float* dbuf = _dbuf;
\r
176 Mat Dx(1, width, CV_32F, dbuf);
\r
177 Mat Dy(1, width, CV_32F, dbuf + width);
\r
178 Mat Mag(1, width, CV_32F, dbuf + width*2);
\r
179 Mat Angle(1, width, CV_32F, dbuf + width*3);
\r
181 float angleScale = (float)(nbins/CV_PI);
\r
183 for( y = 0; y < gradSize.height; y++ )
\r
185 const uchar* currPtr = img.data + img.step*ymap[y];
\r
186 const uchar* prevPtr = img.data + img.step*ymap[y-1];
\r
187 const uchar* nextPtr = img.data + img.step*ymap[y+1];
\r
188 float* gradPtr = (float*)grad.ptr(y);
\r
189 uchar* qanglePtr = (uchar*)qangle.ptr(y);
\r
191 for( x = 0; x < width; x++ )
\r
193 dbuf[x] = (float)(currPtr[xmap[x+1]] - currPtr[xmap[x-1]]);
\r
194 dbuf[width + x] = (float)(nextPtr[xmap[x]] - prevPtr[xmap[x]]);
\r
196 cartToPolar( Dx, Dy, Mag, Angle, false );
\r
197 for( x = 0; x < width; x++ )
\r
199 float mag = dbuf[x+width*2];
\r
200 float angle = dbuf[x+width*3];
\r
201 angle = angle*angleScale - 0.5f;
\r
202 int bidx = cvFloor(angle);
\r
206 else if( bidx >= nbins )
\r
209 qanglePtr[x] = (uchar)bidx;
\r
213 integral(grad, norm, grad.depth());
\r
216 const float* magBuf;
\r
217 const uchar* binsBuf;
\r
219 int binsStep = (int)( qangle.step / sizeof(uchar) );
\r
220 int histStep = (int)( histogram[0].step / sizeof(float) );
\r
221 int magStep = (int)( grad.step / sizeof(float) );
\r
222 for( binIdx = 0; binIdx < nbins; binIdx++ )
\r
224 histBuf = (float*)histogram[binIdx].data;
\r
225 magBuf = (const float*)grad.data;
\r
226 binsBuf = (const uchar*)qangle.data;
\r
228 memset( histBuf, 0, histSize.width * sizeof(histBuf[0]) );
\r
229 histBuf += histStep + 1;
\r
230 for( y = 0; y < qangle.rows; y++ )
\r
233 float strSum = 0.f;
\r
234 for( x = 0; x < qangle.cols; x++ )
\r
236 if( binsBuf[x] == binIdx )
\r
237 strSum += magBuf[x];
\r
238 histBuf[x] = histBuf[-histStep + x] + strSum;
\r
240 histBuf += histStep;
\r
241 binsBuf += binsStep;
\r