Global CMake reorganization:
[profile/ivi/opencv.git] / apps / traincascade / HOGfeatures.cpp
1 #include "HOGfeatures.h"\r
2 #include "cascadeclassifier.h"\r
3 \r
4 \r
5 CvHOGFeatureParams::CvHOGFeatureParams()\r
6 {\r
7     maxCatCount = 0;\r
8     name = HOGF_NAME;\r
9     featSize = N_BINS * N_CELLS;\r
10 }\r
11 \r
12 void CvHOGEvaluator::init(const CvFeatureParams *_featureParams, int _maxSampleCount, Size _winSize)\r
13 {\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
17     {\r
18         hist.push_back(Mat(_maxSampleCount, cols, CV_32FC1));\r
19     }\r
20     normSum.create( (int)_maxSampleCount, cols, CV_32FC1 );\r
21     CvFeatureEvaluator::init( _featureParams, _maxSampleCount, _winSize );\r
22 }\r
23 \r
24 void CvHOGEvaluator::setImage(const Mat &img, uchar clsLabel, int idx)\r
25 {\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
30     {\r
31         integralHist.push_back( Mat(winSize.height + 1, winSize.width + 1, hist[bin].type(), hist[bin].ptr<float>((int)idx)) );\r
32     }\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
35 }\r
36 \r
37 //void CvHOGEvaluator::writeFeatures( FileStorage &fs, const Mat& featureMap ) const\r
38 //{\r
39 //    _writeFeatures( features, fs, featureMap );\r
40 //}\r
41 \r
42 void CvHOGEvaluator::writeFeatures( FileStorage &fs, const Mat& featureMap ) const\r
43 {\r
44     int featIdx;\r
45     int componentIdx;\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
50         {\r
51             fs << "{";\r
52             featIdx = fi / getFeatureSize();\r
53             componentIdx = fi % getFeatureSize();\r
54             features[featIdx].write( fs, componentIdx );\r
55             fs << "}";\r
56         }\r
57     fs << "]";  \r
58 }\r
59 \r
60 void CvHOGEvaluator::generateFeatures()\r
61 {\r
62     int offset = winSize.width + 1;\r
63     Size blockStep;\r
64     int x, y, t, w, h;\r
65 \r
66     for (t = 8; t <= winSize.width/2; t+=8) //t = size of a cell. blocksize = 4*cellSize\r
67     {\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
72         {\r
73             for (y = 0; y <= winSize.height - h; y += blockStep.height)\r
74             {\r
75                 features.push_back(Feature(offset, x, y, t, t));\r
76             }\r
77         }\r
78         w = 2*t;\r
79         h = 4*t;\r
80         for (x = 0; x <= winSize.width - w; x += blockStep.width)\r
81         {\r
82             for (y = 0; y <= winSize.height - h; y += blockStep.height)\r
83             {\r
84                 features.push_back(Feature(offset, x, y, t, 2*t));\r
85             }\r
86         }\r
87         w = 4*t;\r
88         h = 2*t; \r
89         for (x = 0; x <= winSize.width - w; x += blockStep.width)\r
90         {\r
91             for (y = 0; y <= winSize.height - h; y += blockStep.height)\r
92             {     \r
93                 features.push_back(Feature(offset, x, y, 2*t, t));\r
94             }\r
95         }\r
96     }\r
97 \r
98     numFeatures = (int)features.size();\r
99 }\r
100 \r
101 CvHOGEvaluator::Feature::Feature()\r
102 {\r
103     for (int i = 0; i < N_CELLS; i++)\r
104     {\r
105         rect[i] = Rect(0, 0, 0, 0);\r
106     }\r
107 }\r
108 \r
109 CvHOGEvaluator::Feature::Feature( int offset, int x, int y, int cellW, int cellH )\r
110 {\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
115 \r
116     for (int i = 0; i < N_CELLS; i++)\r
117     {\r
118         CV_SUM_OFFSETS(fastRect[i].p0, fastRect[i].p1, fastRect[i].p2, fastRect[i].p3, rect[i], offset);\r
119     }\r
120 }\r
121 \r
122 void CvHOGEvaluator::Feature::write(FileStorage &fs) const\r
123 {\r
124     fs << CC_RECTS << "[";\r
125     for( int i = 0; i < N_CELLS; i++ )\r
126     {\r
127         fs << "[:" << rect[i].x << rect[i].y << rect[i].width << rect[i].height << "]";\r
128     }\r
129     fs << "]";\r
130 }\r
131 \r
132 //cell and bin idx writing\r
133 //void CvHOGEvaluator::Feature::write(FileStorage &fs, int varIdx) const\r
134 //{\r
135 //    int featComponent = varIdx % (N_CELLS * N_BINS);\r
136 //    int cellIdx = featComponent / N_BINS;\r
137 //    int binIdx = featComponent % N_BINS;\r
138 //\r
139 //    fs << CC_RECTS << "[:" << rect[cellIdx].x << rect[cellIdx].y << \r
140 //        rect[cellIdx].width << rect[cellIdx].height << binIdx << "]";\r
141 //}\r
142 \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
146 {\r
147     fs << CC_RECT << "[:" << rect[0].x << rect[0].y << \r
148         rect[0].width << rect[0].height << featComponentIdx << "]";\r
149 }\r
150 \r
151 \r
152 void CvHOGEvaluator::integralHistogram(const Mat &img, vector<Mat> &histogram, Mat &norm, int nbins) const\r
153 {\r
154     CV_Assert( img.type() == CV_8U || img.type() == CV_8UC3 );\r
155     int x, y, binIdx;\r
156 \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
161 \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
165 \r
166     const int borderType = (int)BORDER_REPLICATE;\r
167 \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
172 \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
180 \r
181     float angleScale = (float)(nbins/CV_PI);\r
182 \r
183     for( y = 0; y < gradSize.height; y++ )\r
184     {\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
190 \r
191         for( x = 0; x < width; x++ )\r
192         {\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
195         }\r
196         cartToPolar( Dx, Dy, Mag, Angle, false );\r
197         for( x = 0; x < width; x++ )\r
198         {\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
203             angle -= bidx;\r
204             if( bidx < 0 )\r
205                 bidx += nbins;\r
206             else if( bidx >= nbins )\r
207                 bidx -= nbins;\r
208 \r
209             qanglePtr[x] = (uchar)bidx;\r
210             gradPtr[x] = mag;\r
211         }\r
212     }\r
213     integral(grad, norm, grad.depth());\r
214 \r
215     float* histBuf;\r
216     const float* magBuf;\r
217     const uchar* binsBuf;\r
218 \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
223     {\r
224         histBuf = (float*)histogram[binIdx].data;\r
225         magBuf = (const float*)grad.data;\r
226         binsBuf = (const uchar*)qangle.data;\r
227 \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
231         { \r
232             histBuf[-1] = 0.f;\r
233             float strSum = 0.f;\r
234             for( x = 0; x < qangle.cols; x++ )\r
235             {\r
236                 if( binsBuf[x] == binIdx )\r
237                     strSum += magBuf[x];\r
238                 histBuf[x] = histBuf[-histStep + x] + strSum;\r
239             }\r
240             histBuf += histStep;\r
241             binsBuf += binsStep;\r
242             magBuf += magStep;\r
243         }\r
244     }\r
245 }\r