Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/apps/traincascade/HOGfeatures.cpp
16337 views
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
10
CvHOGFeatureParams::CvHOGFeatureParams()
11
{
12
maxCatCount = 0;
13
name = HOGF_NAME;
14
featSize = N_BINS * N_CELLS;
15
}
16
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
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
47
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
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
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
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
127
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 necessary for block normalization
150
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
157
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 = mapbuf.data() + 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.data();
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
252