⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sift.cpp

📁 linux操作系统下的sift算法
💻 CPP
📖 第 1 页 / 共 3 页
字号:
             fast_abs(b[0]) < 1.5 &&             fast_abs(b[1]) < 1.5 &&             fast_abs(b[2]) < 1.5 &&             xn >= 0    &&             xn <= ow-1 &&             yn >= 0    &&             yn <= oh-1 &&             sn >= smin &&             sn <= smax ) {                        diter->o  = o ;                   diter->ix = x ;            diter->iy = y ;            diter->is = s ;            diter->x = xn * xperiod ;             diter->y = yn * xperiod ;             diter->s = sn ;            diter->sigma = getScaleFromIndex(o,sn) ;            ++diter ;          }        }      } // next candidate keypoint      // prepare for next octave      keypoints.resize( diter - keypoints.begin() ) ;      nValidatedKeypoints = keypoints.size() ;    } // refine block  } // next octave}// ===================================================================//                                       computeKeypointOrientations()// -------------------------------------------------------------------/** @brief Compute modulus and phase of the gradient ** ** The function computes the modulus and the angle of the gradient of ** the specified octave @a o. The result is stored in a temporary ** internal buffer accessed by computeKeypointDescriptor() and ** computeKeypointOrientations(). ** ** The SIFT detector provides keypoint with scale index s in the ** range @c smin+1 and @c smax-2. As such, the buffer contains only ** these levels. ** ** If called mutliple time on the same data, the function exits ** immediately. ** ** @param o octave of interest. **/voidSift::prepareGrad(int o){   int const ow = getOctaveWidth(o) ;  int const oh = getOctaveHeight(o) ;  int const xo = 1 ;  int const yo = ow ;  int const so = oh*ow ;  if( ! tempIsGrad || tempOctave != o ) {    // compute dx/dy    for(int s = smin+1 ; s <= smax-2 ; ++s) {      for(int y = 1 ; y < oh-1 ; ++y ) {        pixel_t* src  = getLevel(o, s) + xo + yo*y ;                pixel_t* end  = src + ow - 1 ;        pixel_t* grad = 2 * (xo + yo*y + (s - smin -1)*so) + temp ;        while(src != end) {          VL::float_t Gx = 0.5 * ( *(src+xo) - *(src-xo) ) ;          VL::float_t Gy = 0.5 * ( *(src+yo) - *(src-yo) ) ;          VL::float_t m = fast_sqrt( Gx*Gx + Gy*Gy ) ;          VL::float_t t = fast_mod_2pi( fast_atan2(Gy, Gx) + VL::float_t(2*M_PI) );          *grad++ = pixel_t( m ) ;          *grad++ = pixel_t( t ) ;          ++src ;        }      }    }  }    tempIsGrad = true ;  tempOctave = o ;}/** @brief Compute the orientation(s) of a keypoint ** ** The function computes the orientation of the specified keypoint. ** The function returns up to four different orientations, obtained ** as strong peaks of the histogram of gradient orientations (a ** keypoint can theoretically generate more than four orientations, ** but this is very unlikely). ** ** @remark The function needs to compute the gradient modululs and ** orientation of the Gaussian scale space octave to which the ** keypoint belongs. The result is cached, but discarded if different ** octaves are visited. Thereofre it is much quicker to evaluate the ** keypoints in their natural octave order. ** ** The keypoint must lie within the scale space. In particular, the ** scale index is supposed to be in the range @c smin+1 and @c smax-1 ** (this is from the SIFT detector). If this is not the case, the ** computation is silently aborted and no orientations are returned. ** ** @param angles buffers to store the resulting angles. ** @param keypoint keypoint to process. ** @return number of orientations found. **/intSift::computeKeypointOrientations(VL::float_t angles [4], Keypoint keypoint){  int const   nbins = 36 ;  VL::float_t const winFactor = 1.5 ;  VL::float_t hist [nbins] ;  // octave  int o = keypoint.o ;  VL::float_t xperiod = getOctaveSamplingPeriod(o) ;  // offsets to move in the Gaussian scale space octave  const int ow = getOctaveWidth(o) ;  const int oh = getOctaveHeight(o) ;  const int xo = 2 ;  const int yo = xo * ow ;  const int so = yo * oh ;  // keypoint fractional geometry  VL::float_t x     = keypoint.x / xperiod ;  VL::float_t y     = keypoint.y / xperiod ;  VL::float_t sigma = keypoint.sigma / xperiod ;    // shall we use keypoints.ix,iy,is here?  int xi = ((int) (x+0.5)) ;   int yi = ((int) (y+0.5)) ;  int si = keypoint.is ;    VL::float_t const sigmaw = winFactor * sigma ;  int W = (int) floor(3.0 * sigmaw) ;    // skip the keypoint if it is out of bounds  if(o  < omin   ||     o  >=omin+O ||     xi < 0      ||      xi > ow-1   ||      yi < 0      ||      yi > oh-1   ||      si < smin+1 ||      si > smax-2 ) {    std::cerr<<"!"<<std::endl ;    return 0 ;  }    // make sure that the gradient buffer is filled with octave o  prepareGrad(o) ;  // clear the SIFT histogram  std::fill(hist, hist + nbins, 0) ;  // fill the SIFT histogram  pixel_t* pt = temp + xi * xo + yi * yo + si * (so - smin -1) ;#undef at#define at(dx,dy) (*(pt + (dx)*xo + (dy)*yo))  for(int ys = std::max(-W, 1-yi) ; ys <= std::min(+W, oh -2 -yi) ; ++ys) {    for(int xs = std::max(-W, 1-xi) ; xs <= std::min(+W, ow -2 -xi) ; ++xs) {            VL::float_t dx = xi + xs - x;      VL::float_t dy = yi + ys - y;      VL::float_t r2 = dx*dx + dy*dy ;      // limit to a circular window      if(r2 >= W*W+0.5) continue ;      VL::float_t wgt = VL::fast_expn( r2 / (2*sigmaw*sigmaw) ) ;      VL::float_t mod = *(pt + xs*xo + ys*yo) ;      VL::float_t ang = *(pt + xs*xo + ys*yo + 1) ;      //      int bin = (int) floor( nbins * ang / (2*M_PI) ) ;      int bin = (int) floor( nbins * ang / (2*M_PI) ) ;      hist[bin] += mod * wgt ;            }  }    // smooth the histogram#if defined VL_LOWE_STRICT  // Lowe's version apparently has a little issue with orientations  // around + or - pi, which we reproduce here for compatibility  for (int iter = 0; iter < 6; iter++) {    VL::float_t prev  = hist[nbins/2] ;    for (int i = nbins/2-1; i >= -nbins/2 ; --i) {      int const j  = (i     + nbins) % nbins ;      int const jp = (i - 1 + nbins) % nbins ;      VL::float_t newh = (prev + hist[j] + hist[jp]) / 3.0;      prev = hist[j] ;      hist[j] = newh ;    }  }#else  // this is slightly more correct  for (int iter = 0; iter < 6; iter++) {    VL::float_t prev  = hist[nbins-1] ;    VL::float_t first = hist[0] ;    int i ;    for (i = 0; i < nbins - 1; i++) {      VL::float_t newh = (prev + hist[i] + hist[(i+1) % nbins]) / 3.0;      prev = hist[i] ;      hist[i] = newh ;    }    hist[i] = (prev + hist[i] + first)/3.0 ;  }#endif    // find the histogram maximum  VL::float_t maxh = * std::max_element(hist, hist + nbins) ;  // find peaks within 80% from max  int nangles = 0 ;  for(int i = 0 ; i < nbins ; ++i) {    VL::float_t h0 = hist [i] ;    VL::float_t hm = hist [(i-1+nbins) % nbins] ;    VL::float_t hp = hist [(i+1+nbins) % nbins] ;        // is peak?    if( h0 > 0.8*maxh && h0 > hm && h0 > hp ) {            // quadratic interpolation      //      VL::float_t di = -0.5 * (hp-hm) / (hp+hm-2*h0) ;       VL::float_t di = -0.5 * (hp-hm) / (hp+hm-2*h0) ;       VL::float_t th = 2*M_PI*(i+di+0.5)/nbins ;            angles [ nangles++ ] = th ;    }  }  return nangles ;}// ===================================================================//                                         computeKeypointDescriptor()// -------------------------------------------------------------------namespace Detail {/** Normalizes in norm L_2 a descriptor. */voidnormalize_histogram(VL::float_t* L_begin, VL::float_t* L_end){  VL::float_t* L_iter ;  VL::float_t norm = 0.0 ;  for(L_iter = L_begin; L_iter != L_end ; ++L_iter)    norm += (*L_iter) * (*L_iter) ;  norm = fast_sqrt(norm) ;  for(L_iter = L_begin; L_iter != L_end ; ++L_iter)    *L_iter /= norm ;}}/** @brief SIFT descriptor ** ** The function computes the descriptor of the keypoint @a keypoint. ** The function fills the buffer @a descr_pt which must be large ** enough. The funciton uses @a angle0 as rotation of the keypoint. ** By calling the function multiple times, different orientations can ** be evaluated. ** ** @remark The function needs to compute the gradient modululs and ** orientation of the Gaussian scale space octave to which the ** keypoint belongs. The result is cached, but discarded if different ** octaves are visited. Thereofre it is much quicker to evaluate the ** keypoints in their natural octave order. ** ** The function silently abort the computations of keypoints without ** the scale space boundaries. See also siftComputeOrientations(). **/voidSift::computeKeypointDescriptor(VL::float_t* descr_pt, Keypoint keypoint,  VL::float_t angle0){  /* The SIFT descriptor is a  three dimensional histogram of the position   * and orientation of the gradient.  There are NBP bins for each spatial   * dimesions and NBO  bins for the orientation dimesion,  for a total of   * NBP x NBP x NBO bins.   *   * The support  of each  spatial bin  has an extension  of SBP  = 3sigma   * pixels, where sigma is the scale  of the keypoint.  Thus all the bins   * together have a  support SBP x NBP pixels wide  . Since weighting and   * interpolation of  pixel is used, another  half bin is  needed at both   * ends of  the extension. Therefore, we  need a square window  of SBP x   * (NBP + 1) pixels. Finally, since the patch can be arbitrarly rotated,   * we need to consider  a window 2W += sqrt(2) x SBP  x (NBP + 1) pixels   * wide.   */        // octave  int o = keypoint.o ;  VL::float_t xperiod = getOctaveSamplingPeriod(o) ;  // offsets to move in Gaussian scale space octave  const int ow = getOctaveWidth(o) ;  const int oh = getOctaveHeight(o) ;  const int xo = 2 ;  const int yo = xo * ow ;  const int so = yo * oh ;  // keypoint fractional geometry  VL::float_t x     = keypoint.x / xperiod;  VL::float_t y     = keypoint.y / xperiod ;  VL::float_t sigma = keypoint.sigma / xperiod ;  VL::float_t st0   = sinf( angle0 ) ;  VL::float_t ct0   = cosf( angle0 ) ;    // shall we use keypoints.ix,iy,is here?  int xi = ((int) (x+0.5)) ;   int yi = ((int) (y+0.5)) ;  int si = keypoint.is ;  const VL::float_t magnif = 3.0f ;  const int NBO = 8 ;  const int NBP = 4 ;  const VL::float_t SBP = magnif * sigma ;  const int   W = (int) floor (sqrt(2.0) * SBP * (NBP + 1) / 2.0 + 0.5) ;    /* Offsets to move in the descriptor. */  /* Use Lowe's convention. */  const int binto = 1 ;  const int binyo = NBO * NBP ;  const int binxo = NBO ;  // const int bino  = NBO * NBP * NBP ;    int bin ;    // check bounds  if(o  < omin   ||     o  >=omin+O ||     xi < 0      ||      xi > ow-1   ||      yi < 0      ||      yi > oh-1   ||     si < smin+1 ||     si > smax-2 )        return ;    // make sure gradient buffer is up-to-date  prepareGrad(o) ;  std::fill( descr_pt, descr_pt + NBO*NBP*NBP, 0 ) ;  /* Center the scale space and the descriptor on the current keypoint.    * Note that dpt is pointing to the bin of center (SBP/2,SBP/2,0).   */  pixel_t const * pt = temp + xi*xo + yi*yo + (si - smin - 1)*so ;  VL::float_t *  dpt = descr_pt + (NBP/2) * binyo + (NBP/2) * binxo ;     #define atd(dbinx,dbiny,dbint) *(dpt + (dbint)*binto + (dbiny)*binyo + (dbinx)*binxo)        /*   * Process pixels in the intersection of the image rectangle   * (1,1)-(M-1,N-1) and the keypoint bounding box.   */  for(int dyi = std::max(-W, 1-yi) ; dyi <= std::min(+W, oh-2-yi) ; ++dyi) {    for(int dxi = std::max(-W, 1-xi) ; dxi <= std::min(+W, ow-2-xi) ; ++dxi) {            // retrieve       VL::float_t mod   = *( pt + dxi*xo + dyi*yo + 0 ) ;      VL::float_t angle = *( pt + dxi*xo + dyi*yo + 1 ) ;      VL::float_t theta = fast_mod_2pi(-angle + angle0) ; // lowe compatible ?            // fractional displacement      VL::float_t dx = xi + dxi - x;      VL::float_t dy = yi + dyi - y;            // get the displacement normalized w.r.t. the keypoint      // orientation and extension.      VL::float_t nx = ( ct0 * dx + st0 * dy) / SBP ;      VL::float_t ny = (-st0 * dx + ct0 * dy) / SBP ;       VL::float_t nt = NBO * theta / (2*M_PI) ;            // Get the gaussian weight of the sample. The gaussian window      // has a standard deviation equal to NBP/2. Note that dx and dy      // are in the normalized frame, so that -NBP/2 <= dx <= NBP/2.      VL::float_t const wsigma = NBP/2 ;      VL::float_t win = VL::fast_expn((nx*nx + ny*ny)/(2.0 * wsigma * wsigma)) ;            // The sample will be distributed in 8 adjacent bins.      // We start from the ``lower-left'' bin.      int binx = fast_floor( nx - 0.5 ) ;      int biny = fast_floor( ny - 0.5 ) ;      int bint = fast_floor( nt ) ;      VL::float_t rbinx = nx - (binx+0.5) ;      VL::float_t rbiny = ny - (biny+0.5) ;      VL::float_t rbint = nt - bint ;      int dbinx ;      int dbiny ;      int dbint ;      // Distribute the current sample into the 8 adjacent bins      for(dbinx = 0 ; dbinx < 2 ; ++dbinx) {        for(dbiny = 0 ; dbiny < 2 ; ++dbiny) {          for(dbint = 0 ; dbint < 2 ; ++dbint) {                        if( binx+dbinx >= -(NBP/2) &&                binx+dbinx <   (NBP/2) &&                biny+dbiny >= -(NBP/2) &&                biny+dbiny <   (NBP/2) ) {              VL::float_t weight = win                 * mod                 * fast_abs (1 - dbinx - rbinx)                * fast_abs (1 - dbiny - rbiny)                * fast_abs (1 - dbint - rbint) ;                            atd(binx+dbinx, biny+dbiny, (bint+dbint) % NBO) += weight ;            }          }                    }      }    }    }    /* Normalize the histogram to L2 unit length. */          Detail::normalize_histogram(descr_pt, descr_pt + NBO*NBP*NBP) ;    /* Truncate at 0.2. */  for(bin = 0; bin < NBO*NBP*NBP ; ++bin) {    if (descr_pt[bin] > 0.2) descr_pt[bin] = 0.2;  }    /* Normalize again. */  Detail::normalize_histogram(descr_pt, descr_pt + NBO*NBP*NBP) ;}// namespace VL}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -