This heuristic calculates corners strength of an image in the Harris-Stephens way
over 3x3 pixels blocks
feature = sum(Ix^2*Iy^2) - sum((Ix*Iy)^2) - 0.04*(sum(Ix^2) + sum(Iy^2))^2
where Ix and Iy are spatial gradients of the image
ref : C.Harris, M.Stephens. A Combined Corner and Edge Detector. 1988
/** Author: vfremont inspired by leonidas/dt_hogs6 This heuristic calculates corners strength of an image in the Harris-Stephens way over 3x3 pixels blocks feature = sum(Ix^2*Iy^2) - sum((Ix*Iy)^2) - 0.04*(sum(Ix^2) + sum(Iy^2))^2 where Ix and Iy are spatial gradients of the image ref : C.Harris, M.Stephens. âA Combined Corner and Edge Detectorâ. 1988*/#include <mash/heuristic.h>usingnamespaceMash;//------------------------------------------------------------------------------// Declaration of the heuristic class//------------------------------------------------------------------------------classcorner:publicHeuristic{//_____ Construction / Destruction __________public:corner();virtual~corner();//_____ Implementation of Heuristic __________public://--------------------------------------------------------------------------/// @brief Called once at the creation of the heuristic////// Pre-computes all the data that will never change during the life-time of/// the heuristic////// When this method is called, the 'roi_extent' attribute is initialized////// @remark The implementation of this method is optional//--------------------------------------------------------------------------virtualvoidinit();//--------------------------------------------------------------------------/// @brief Called once when the heuristic is destroyed////// Frees the memory allocated by the init() method////// @remark This method must be implemented if init() is used and allocated/// some memory//--------------------------------------------------------------------------virtualvoidterminate();//--------------------------------------------------------------------------// Returns the number of features this heuristic computes//// When this method is called, the 'roi_extent' attribute is initialized//--------------------------------------------------------------------------virtualunsignedintdim();//--------------------------------------------------------------------------// Called once per image, before any computation //// Pre-computes from a full image the data the heuristic will need to compute// features at any coordinates in the image//// When this method is called, the following attributes are initialized:// - roi_extent// - image//--------------------------------------------------------------------------virtualvoidprepareForImage();//--------------------------------------------------------------------------// Called once per image, after any computation //// Frees the memory allocated by the prepareForImage() method//--------------------------------------------------------------------------virtualvoidfinishForImage();//--------------------------------------------------------------------------// Called once per coordinates, before any computation//// Pre-computes the data the heuristic will need to compute features at the// given coordinates//// When this method is called, the following attributes are initialized:// - roi_extent// - image// - coordinates//--------------------------------------------------------------------------virtualvoidprepareForCoordinates();//--------------------------------------------------------------------------// Called once per coordinates, after any computation //// Frees the memory allocated by the prepareForCoordinates() method//--------------------------------------------------------------------------virtualvoidfinishForCoordinates();//--------------------------------------------------------------------------// Computes the specified feature//// When this method is called, the following attributes are initialized:// - roi_extent// - image// - coordinates//--------------------------------------------------------------------------virtualscalar_tcomputeFeature(unsignedintfeature_index);//_____ Attributes __________protected:scalar_t*_corner;};//------------------------------------------------------------------------------// Creation function of the heuristic//------------------------------------------------------------------------------extern"C"Heuristic*new_heuristic(){returnnewcorner();}/************************* CONSTRUCTION / DESTRUCTION *************************/corner::corner(){// TODO: Initialization of the attributes that doesn't depend of anything}corner::~corner(){// TODO: Cleanup of the allocated memory still remaining}/************************* IMPLEMENTATION OF Heuristic ************************/voidcorner::init(){// TODO: Initialization of the attributes that depend on the size of the// region of interest}voidcorner::terminate(){// TODO: Cleanup of the memory allocated by the init() method}unsignedintcorner::dim(){unsignedintroi_size=roi_extent*2+1;return(roi_size-2)*(roi_size-2);}voidcorner::prepareForImage(){// TODO: Initialization of the attributes that depend of the whole image}voidcorner::finishForImage(){// TODO: Frees the memory allocated by the prepareForImage() method}voidcorner::prepareForCoordinates(){scalar_ta,b,c,d,e,f,g,h,i;// Compute the coordinates of the top-left pixel of the region of interestunsignedintx0=coordinates.x-roi_extent;unsignedinty0=coordinates.y-roi_extent;unsignedintroi_size=roi_extent*2+1;byte_t**pixels=image->grayLines();scalar_tdx,dy;_corner=newscalar_t[dim()];// spatial gradientsscalar_tIx[image->height()][image->width()];scalar_tIy[image->height()][image->width()];//Calculate gradients (zero padding)for(unsignedinty=0;y<roi_size;y++){for(unsignedintx=0;x<roi_size;x++){if(x==0){dx=pixels[y0+y][x0+x+1];}else{if(x==roi_size-1){dx=-pixels[y0+y][x0+x-1];}else{dx=pixels[y0+y][x0+x+1]-pixels[y0+y][x0+x-1];}}if(y==0){dy=-pixels[y0+y+1][x0+x];}else{if(y==roi_size-1){dy=pixels[y0+y-1][x0+x];}else{dy=-pixels[y0+y+1][x0+x]+pixels[y0+y-1][x0+x];}}dx=dx/255;dy=dy/255;Ix[y0+y][x0+x]=dx;Iy[y0+y][x0+x]=dy;}}unsignedintcount=0;scalar_tsumIx2=0,sumIy2=0,sumIxIy=0;for(unsignedinty=0;y<roi_size-2;++y){for(unsignedintx=0;x<roi_size-2;++x){a=Ix[y0+y][x0+x];b=Ix[y0+y][x0+x+1];c=Ix[y0+y][x0+x+2];d=Ix[y0+y+1][x0+x];e=Ix[y0+y+1][x0+x+1];f=Ix[y0+y+1][x0+x+2];g=Ix[y0+y+2][x0+x];h=Ix[y0+y+2][x0+x+1];i=Ix[y0+y+2][x0+x+2];sumIx2=a*a+b*b+c*c+d*d+e*e+f*f+g*g+i*i;a=Iy[y0+y][x0+x];b=Iy[y0+y][x0+x+1];c=Iy[y0+y][x0+x+2];d=Iy[y0+y+1][x0+x];e=Iy[y0+y+1][x0+x+1];f=Iy[y0+y+1][x0+x+2];g=Iy[y0+y+2][x0+x];h=Iy[y0+y+2][x0+x+1];i=Iy[y0+y+2][x0+x+2];sumIy2=a*a+b*b+c*c+d*d+e*e+f*f+g*g+i*i;a=Ix[y0+y][x0+x]*Iy[y0+y][x0+x];b=Ix[y0+y][x0+x+1]*Iy[y0+y][x0+x+1];c=Ix[y0+y][x0+x+2]*Iy[y0+y][x0+x+2];d=Ix[y0+y+1][x0+x]*Iy[y0+y+1][x0+x];e=Ix[y0+y+1][x0+x+1]*Iy[y0+y+1][x0+x+1];f=Ix[y0+y+1][x0+x+2]*Iy[y0+y+1][x0+x+2];g=Ix[y0+y+2][x0+x]*Iy[y0+y+2][x0+x];h=Ix[y0+y+2][x0+x+1]*Iy[y0+y+2][x0+x+1];i=Ix[y0+y+2][x0+x+2]*Iy[y0+y+2][x0+x+2];sumIxIy=a+b+c+d+e+f+g+i;// Harris corner strength response_corner[count]=(sumIx2*sumIy2-sumIxIy*sumIxIy)-0.04*(sumIx2+sumIy2)*(sumIx2+sumIy2);count++;}}}voidcorner::finishForCoordinates(){delete[]_corner;}scalar_tcorner::computeFeature(unsignedintfeature_index){return_corner[feature_index];}