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