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 nessesary 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 = (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