Histogram of oriented gradients (orientation discretized in 12 bins) taken at random positions and scales.
Strongly inspired from francoisfleuret/zk_v2.
/** Author: Charles Dubout (charles.dubout@idiap.ch) * * Histogram of oriented gradients taken at random positions and scales. * Strongly inspired from francoisfleuret/zk_v2. */#include <mash/heuristic.h>#include <cmath>#include <cstdlib>#include <vector>usingnamespaceMash;//------------------------------------------------------------------------------/// The 'hog' heuristic class//------------------------------------------------------------------------------classhogHeuristic:publicHeuristic{//_____ Implementation of Heuristic __________public:hogHeuristic();virtualvoidinit();virtualunsignedintdim();virtualvoidprepareForImage();virtualvoidfinishForImage();virtualscalar_tcomputeFeature(unsignedintfeature_index);private:// The number of rectanglesstaticconstunsignedintNB_RECTS=2000;// The number of histogram binsstaticconstunsignedintNB_BINS=12;// Type of a rectanglestructRect{// Coordinates of the region where to compute the histogramintxMin,yMin,xMax,yMax;// The bin the rectangle is looking atunsignedintbin;};// The rectanglesstd::vector<Rect>rects_;// The 12 integral images used to calculate the HoG'sstd::vector<scalar_t>sats_[NB_BINS];// The width of the current imageunsignedintwidth_;};//------------------------------------------------------------------------------/// Creation function of the heuristic//------------------------------------------------------------------------------extern"C"Heuristic*new_heuristic(){returnnewhogHeuristic();}/************************* IMPLEMENTATION OF Heuristic ************************/hogHeuristic::hogHeuristic():rects_(NB_RECTS){// Nothing to do}voidhogHeuristic::init(){// Compute the size of the region of interestconstintroi_size=roi_extent*2+1;// Randomize the nbRects rectangles (4 = minimum size of a rectangle)for(unsignedintr=0;r<NB_RECTS;++r){do{rects_[r].xMin=(std::rand()%roi_size)-(int)roi_extent;rects_[r].yMin=(std::rand()%roi_size)-(int)roi_extent;rects_[r].xMax=(std::rand()%roi_size)-(int)roi_extent;rects_[r].yMax=(std::rand()%roi_size)-(int)roi_extent;}while((rects_[r].xMax<=rects_[r].xMin)||(rects_[r].yMax<=rects_[r].yMin));rects_[r].bin=std::rand()%NB_BINS;}}unsignedinthogHeuristic::dim(){returnNB_RECTS;}voidhogHeuristic::prepareForImage(){// Get the size of the imageconstunsignedintwidth=image->width();constunsignedintheight=image->height();// Initialize the integral imagesfor(unsignedintb=0;b<NB_BINS;++b){sats_[b].resize(width*height,0);}// Get the pixels values of the imagebyte_t**pixels=image->grayLines();// Compute the gradient at every pixelfor(unsignedinty=1;y<height-1;++y){for(unsignedintx=1;x<width-1;++x){scalar_tdx=(int)pixels[y][x+1]-(int)pixels[y][x-1];scalar_tdy=(int)pixels[y+1][x]-(int)pixels[y-1][x];// Compute the magnitude and the orientationscalar_tmagnitude=std::sqrt(dx*dx+dy*dy)/2/255;if(magnitude>0){// In the range [-pi, pi]scalar_ttheta=std::atan2(dy,dx);// Convert theta to the range [0, NB_BINS]constscalar_tpi=3.1415926536;theta=(theta+pi)*NB_BINS/(2*pi);// Just to make sure it's really [0, NB_BINS)if(theta>=NB_BINS){theta=0;}// Bilinear interpolationunsignedinttheta0=(int)theta;unsignedinttheta1=theta0+1;scalar_talpha=theta-theta0;if(theta1==NB_BINS){theta1=0;}sats_[theta0][y*width+x]+=(1-alpha)*magnitude;sats_[theta1][y*width+x]+=alpha*magnitude;}}}// Convert the gradient images to integral images// Integral image formula: sat(D) = i(D) + sat(B) + sat(D) - sat(A)for(unsignedintb=0;b<NB_BINS;++b){for(unsignedinty=1;y<height;++y){for(unsignedintx=1;x<width;++x){sats_[b][y*width+x]+=sats_[b][y*width+x-1]+sats_[b][(y-1)*width+x]-sats_[b][(y-1)*width+x-1];}}}// Save the width of the current imagewidth_=width;}voidhogHeuristic::finishForImage(){// Clear the integral imagesfor(unsignedinti=0;i<NB_BINS;++i){sats_[i].clear();}}scalar_thogHeuristic::computeFeature(unsignedintfeature_index){constintxMin=(int)coordinates.x+rects_[feature_index].xMin;constintyMin=(int)coordinates.y+rects_[feature_index].yMin;constintxMax=(int)coordinates.x+rects_[feature_index].xMax;constintyMax=(int)coordinates.y+rects_[feature_index].yMax;constunsignedintbin=rects_[feature_index].bin;// Integral image formula: sum = sat(A) + sat(C) - sat(B) - sat(D)returnsats_[bin][yMin*width_+xMin]+sats_[bin][yMax*width_+xMax]-sats_[bin][yMin*width_+xMax]-sats_[bin][yMax*width_+xMin];}