现在的位置: 首页 > 综合 > 正文

sift算法研究(3)c语言实现sift算法、下

2013年08月07日 ⁄ 综合 ⁄ 共 26026字 ⁄ 字号 评论关闭

 作者:July、二零一一年三月十二日
出处:http://blog.csdn.net/v_JULY_v
参考:Rob Hess维护的sift 库
环境:windows xp+vc6.0
条件:c语言实现。
说明:本BLOG内会陆续一一实现所有经典算法
------------------------

本文接上,教你一步一步用c语言实现sift算法、上,而来:
函数编写
    ok,接上文,咱们一个一个的来编写main函数中所涉及到所有函数,这也是本文的关键部分:

  1. //下采样原来的图像,返回缩小2倍尺寸的图像   
  2. CvMat * halfSizeImage(CvMat * im)   
  3. {  
  4.  unsigned int i,j;  
  5.  int w = im->cols/2;  
  6.  int h = im->rows/2;   
  7.  CvMat *imnew = cvCreateMat(h, w, CV_32FC1);  
  8.    
  9. #define Im(ROW,COL) ((float *)(im->data.fl + im->step/sizeof(float) *(ROW)))[(COL)]
      
  10. #define Imnew(ROW,COL) ((float *)(imnew->data.fl + imnew->step/sizeof(float) *(ROW)))[(COL)]
      
  11.  for ( j = 0; j < h; j++)   
  12.   for ( i = 0; i < w; i++)   
  13.    Imnew(j,i)=Im(j*2, i*2);  
  14.   return imnew;  
  15. }  
  16.   
  17. //上采样原来的图像,返回放大2倍尺寸的图像
      
  18. CvMat * doubleSizeImage(CvMat * im)   
  19. {  
  20.  unsigned int i,j;  
  21.  int w = im->cols*2;  
  22.  int h = im->rows*2;   
  23.  CvMat *imnew = cvCreateMat(h, w, CV_32FC1);  
  24.    
  25. #define Im(ROW,COL) ((float *)(im->data.fl + im->step/sizeof(float) *(ROW)))[(COL)]
      
  26. #define Imnew(ROW,COL) ((float *)(imnew->data.fl + imnew->step/sizeof(float) *(ROW)))[(COL)]
      
  27.    
  28.  for ( j = 0; j < h; j++)   
  29.   for ( i = 0; i < w; i++)   
  30.    Imnew(j,i)=Im(j/2, i/2);  
  31.     
  32.   return imnew;  
  33. }  
  34.   
  35. //上采样原来的图像,返回放大2倍尺寸的线性插值图像
      
  36. CvMat * doubleSizeImage2(CvMat * im)   
  37. {  
  38.  unsigned int i,j;  
  39.  int w = im->cols*2;  
  40.  int h = im->rows*2;   
  41.  CvMat *imnew = cvCreateMat(h, w, CV_32FC1);  
  42.    
  43. #define Im(ROW,COL) ((float *)(im->data.fl + im->step/sizeof(float) *(ROW)))[(COL)]
      
  44. #define Imnew(ROW,COL) ((float *)(imnew->data.fl + imnew->step/sizeof(float) *(ROW)))[(COL)]
      
  45.    
  46.  // fill every pixel so we don't have to worry about skipping pixels later
      
  47.  for ( j = 0; j < h; j++)   
  48.  {  
  49.   for ( i = 0; i < w; i++)   
  50.   {  
  51.    Imnew(j,i)=Im(j/2, i/2);  
  52.   }  
  53.  }  
  54.  /* 
  55.  A B C 
  56.  E F G 
  57.  H I J 
  58.  pixels A C H J are pixels from original image 
  59.  pixels B E G I F are interpolated pixels 
  60.  */  
  61.  // interpolate pixels B and I
      
  62.  for ( j = 0; j < h; j += 2)  
  63.   for ( i = 1; i < w - 1; i += 2)  
  64.    Imnew(j,i)=0.5*(Im(j/2, i/2)+Im(j/2, i/2+1));  
  65.   // interpolate pixels E and G
      
  66.   for ( j = 1; j < h - 1; j += 2)  
  67.    for ( i = 0; i < w; i += 2)  
  68.     Imnew(j,i)=0.5*(Im(j/2, i/2)+Im(j/2+1, i/2));  
  69.    // interpolate pixel F
      
  70.    for ( j = 1; j < h - 1; j += 2)  
  71.     for ( i = 1; i < w - 1; i += 2)  
  72.      Imnew(j,i)=0.25*(Im(j/2, i/2)+Im(j/2+1, i/2)+Im(j/2, i/2+1)+Im(j/2+1, i/2+1));  
  73.     return imnew;  
  74. }  
  75.   
  76. //双线性插值,返回像素间的灰度值   
  77. float getPixelBI(CvMat * im, float col, float row)   
  78. {  
  79.  int irow, icol;  
  80.  float rfrac, cfrac;  
  81.  float row1 = 0, row2 = 0;  
  82.  int width=im->cols;  
  83.  int height=im->rows;  
  84. #define ImMat(ROW,COL) ((float *)(im->data.fl + im->step/sizeof(float) *(ROW)))[(COL)]
      
  85.    
  86.  irow = (int) row;  
  87.  icol = (int) col;  
  88.    
  89.  if (irow < 0 || irow >= height  
  90.   || icol < 0 || icol >= width)  
  91.   return 0;  
  92.  if (row > height - 1)  
  93.   row = height - 1;  
  94.  if (col > width - 1)  
  95.   col = width - 1;  
  96.  rfrac = 1.0 - (row - (float) irow);  
  97.  cfrac = 1.0 - (col - (float) icol);  
  98.  if (cfrac < 1)   
  99.  {  
  100.   row1 = cfrac * ImMat(irow,icol) + (1.0 - cfrac) * ImMat(irow,icol+1);  
  101.  }   
  102.  else   
  103.  {  
  104.   row1 = ImMat(irow,icol);  
  105.  }  
  106.  if (rfrac < 1)   
  107.  {  
  108.   if (cfrac < 1)   
  109.   {  
  110.    row2 = cfrac * ImMat(irow+1,icol) + (1.0 - cfrac) * ImMat(irow+1,icol+1);  
  111.   } else   
  112.   {  
  113.    row2 = ImMat(irow+1,icol);  
  114.   }  
  115.  }  
  116.  return rfrac * row1 + (1.0 - rfrac) * row2;  
  117. }  
  118.   
  119. //矩阵归一化   
  120. void normalizeMat(CvMat* mat)   
  121. {  
  122. #define Mat(ROW,COL) ((float *)(mat->data.fl + mat->step/sizeof(float) *(ROW)))[(COL)]
      
  123.  float sum = 0;  
  124.    
  125.  for (unsigned int j = 0; j < mat->rows; j++)   
  126.   for (unsigned int i = 0; i < mat->cols; i++)   
  127.    sum += Mat(j,i);  
  128.   for ( j = 0; j < mat->rows; j++)   
  129.    for (unsigned int i = 0; i < mat->rows; i++)   
  130.     Mat(j,i) /= sum;  
  131. }  
  132.   
  133. //向量归一化   
  134. void normalizeVec(float* vec, int dim)   
  135. {  
  136.     unsigned int i;  
  137.  float sum = 0;  
  138.  for ( i = 0; i < dim; i++)  
  139.   sum += vec[i];  
  140.  for ( i = 0; i < dim; i++)  
  141.   vec[i] /= sum;  
  142. }  
  143.   
  144. //得到向量的欧式长度,2-范数   
  145. float GetVecNorm( float* vec, int dim )  
  146. {  
  147.  float sum=0.0;  
  148.  for (unsigned int i=0;i<dim;i++)  
  149.   sum+=vec[i]*vec[i];  
  150.     return sqrt(sum);  
  151. }  
  152.   
  153. //产生1D高斯核   
  154. float* GaussianKernel1D(float sigma, int dim)   
  155. {  
  156.    
  157.  unsigned int i;  
  158.  //printf("GaussianKernel1D(): Creating 1x%d vector for sigma=%.3f gaussian kernel/n", dim, sigma);
      
  159.    
  160.  float *kern=(float*)malloc( dim*sizeof(float) );  
  161.  float s2 = sigma * sigma;  
  162.  int c = dim / 2;  
  163.  float m= 1.0/(sqrt(2.0 * CV_PI) * sigma);  
  164.     double v;   
  165.  for ( i = 0; i < (dim + 1) / 2; i++)   
  166.  {  
  167.   v = m * exp(-(1.0*i*i)/(2.0 * s2)) ;  
  168.   kern[c+i] = v;  
  169.   kern[c-i] = v;  
  170.  }  
  171.  //   normalizeVec(kern, dim);
      
  172.  // for ( i = 0; i < dim; i++)   
  173.  //  printf("%f  ", kern[i]);
      
  174.  //  printf("/n");   
  175.  return kern;  
  176. }  
  177.   
  178. //产生2D高斯核矩阵   
  179. CvMat* GaussianKernel2D(float sigma)   
  180. {  
  181.  // int dim = (int) max(3.0f, GAUSSKERN * sigma);
      
  182.     int dim = (int) max(3.0f, 2.0 * GAUSSKERN *sigma + 1.0f);  
  183.  // make dim odd   
  184.  if (dim % 2 == 0)  
  185.   dim++;  
  186.  //printf("GaussianKernel(): Creating %dx%d matrix for sigma=%.3f gaussian/n", dim, dim, sigma);
      
  187.  CvMat* mat=cvCreateMat(dim, dim, CV_32FC1);  
  188. #define Mat(ROW,COL) ((float *)(mat->data.fl + mat->step/sizeof(float) *(ROW)))[(COL)]
      
  189.  float s2 = sigma * sigma;  
  190.  int c = dim / 2;  
  191.  //printf("%d %d/n", mat.size(), mat[0].size());
      
  192.     float m= 1.0/(sqrt(2.0 * CV_PI) * sigma);  
  193.  for (int i = 0; i < (dim + 1) / 2; i++)   
  194.  {  
  195.   for (int j = 0; j < (dim + 1) / 2; j++)   
  196.   {  
  197.    //printf("%d %d %d/n", c, i, j);
      
  198.    float v = m * exp(-(1.0*i*i + 1.0*j*j) / (2.0 * s2));  
  199.    Mat(c+i,c+j) =v;  
  200.    Mat(c-i,c+j) =v;  
  201.    Mat(c+i,c-j) =v;  
  202.    Mat(c-i,c-j) =v;  
  203.   }  
  204.  }  
  205.  // normalizeMat(mat);
      
  206.  return mat;  
  207. }  
  208.   
  209. //x方向像素处作卷积   
  210. float ConvolveLocWidth(float* kernel, int dim, CvMat * src, int x, int y)   
  211. {  
  212. #define Src(ROW,COL) ((float *)(src->data.fl + src->step/sizeof(float) *(ROW)))[(COL)]
      
  213.     unsigned int i;  
  214.  float pixel = 0;  
  215.     int col;  
  216.  int cen = dim / 2;  
  217.  //printf("ConvolveLoc(): Applying convoluation at location (%d, %d)/n", x, y);
      
  218.  for ( i = 0; i < dim; i++)   
  219.  {  
  220.   col = x + (i - cen);  
  221.   if (col < 0)  
  222.    col = 0;  
  223.   if (col >= src->cols)  
  224.    col = src->cols - 1;  
  225.   pixel += kernel[i] * Src(y,col);  
  226.  }  
  227.  if (pixel > 1)  
  228.   pixel = 1;  
  229.  return pixel;  
  230. }  
  231.   
  232. //x方向作卷积   
  233. void Convolve1DWidth(float* kern, int dim, CvMat * src, CvMat * dst)   
  234. {  
  235. #define DST(ROW,COL) ((float *)(dst->data.fl + dst->step/sizeof(float) *(ROW)))[(COL)]
      
  236.  unsigned int i,j;  
  237.    
  238.  for ( j = 0; j < src->rows; j++)   
  239.  {  
  240.   for ( i = 0; i < src->cols; i++)   
  241.   {  
  242.    //printf("%d, %d/n", i, j);   
  243.    DST(j,i) = ConvolveLocWidth(kern, dim, src, i, j);  
  244.   }  
  245.  }  
  246. }  
  247.   
  248. //y方向像素处作卷积   
  249. float ConvolveLocHeight(float* kernel, int dim, CvMat * src, int x, int y)   
  250. {  
  251. #define Src(ROW,COL) ((float *)(src->data.fl + src->step/sizeof(float) *(ROW)))[(COL)]
      
  252.     unsigned int j;  
  253.  float pixel = 0;  
  254.  int cen = dim / 2;  
  255.  //printf("ConvolveLoc(): Applying convoluation at location (%d, %d)/n", x, y);
      
  256.  for ( j = 0; j < dim; j++)   
  257.  {  
  258.   int row = y + (j - cen);  
  259.   if (row < 0)  
  260.    row = 0;  
  261.   if (row >= src->rows)  
  262.    row = src->rows - 1;  
  263.   pixel += kernel[j] * Src(row,x);  
  264.  }  
  265.  if (pixel > 1)  
  266.   pixel = 1;  
  267.  return pixel;  
  268. }  
  269.   
  270. //y方向作卷积   
  271. void Convolve1DHeight(float* kern, int dim, CvMat * src, CvMat * dst)   
  272. {  
  273. #define Dst(ROW,COL) ((float *)(dst->data.fl + dst->step/sizeof(float) *(ROW)))[(COL)]
      
  274.     unsigned int i,j;  
  275.  for ( j = 0; j < src->rows; j++)   
  276.  {  
  277.   for ( i = 0; i < src->cols; i++)   
  278.   {  
  279.    //printf("%d, %d/n", i, j);
      
  280.    Dst(j,i) = ConvolveLocHeight(kern, dim, src, i, j);  
  281.   }  
  282.  }  
  283. }  
  284.   
  285. //卷积模糊图像   
  286. int BlurImage(CvMat * src, CvMat * dst, float sigma)   
  287. {  
  288.  float* convkernel;  
  289.  int dim = (int) max(3.0f, 2.0 * GAUSSKERN * sigma + 1.0f);  
  290.     CvMat *tempMat;  
  291.  // make dim odd   
  292.  if (dim % 2 == 0)  
  293.   dim++;  
  294.  tempMat = cvCreateMat(src->rows, src->cols, CV_32FC1);  
  295.  convkernel = GaussianKernel1D(sigma, dim);  
  296.    
  297.  Convolve1DWidth(convkernel, dim, src, tempMat);  
  298.  Convolve1DHeight(convkernel, dim, tempMat, dst);  
  299.  cvReleaseMat(&tempMat);  
  300.  return dim;  
  301. }  

五个步骤

    ok,接下来,进入重点部分,咱们依据上文介绍的sift算法的几个步骤,来一一实现这些函数。
    为了版述清晰,再贴一下,主函数,顺便再加强下对sift 算法的五个步骤的认识:

1、SIFT算法第一步:图像预处理
CvMat *ScaleInitImage(CvMat * im) ;                  //金字塔初始化
2、SIFT算法第二步:建立高斯金字塔函数
ImageOctaves* BuildGaussianOctaves(CvMat * image) ;  //建立高斯金字塔
3、SIFT算法第三步:特征点位置检测,最后确定特征点的位置
int DetectKeypoint(int numoctaves, ImageOctaves *GaussianPyr);
4、SIFT算法第四步:计算高斯图像的梯度方向和幅值,计算各个特征点的主方向
void ComputeGrad_DirecandMag(int numoctaves, ImageOctaves *GaussianPyr);
5、SIFT算法第五步:抽取各个特征点处的特征描述字
void ExtractFeatureDescriptors(int numoctaves, ImageOctaves *GaussianPyr);

ok,接下来一一具体实现这几个函数:
SIFT算法第一步
    SIFT算法第一步:扩大图像,预滤波剔除噪声,得到金字塔的最底层-第一阶的第一层:

  1. CvMat *ScaleInitImage(CvMat * im)   
  2. {  
  3.     double sigma,preblur_sigma;  
  4.  CvMat *imMat;  
  5.  CvMat * dst;  
  6.  CvMat *tempMat;  
  7.  //首先对图像进行平滑滤波,抑制噪声   
  8.  imMat = cvCreateMat(im->rows, im->cols, CV_32FC1);  
  9.     BlurImage(im, imMat, INITSIGMA);  
  10.  //针对两种情况分别进行处理:初始化放大原始图像或者在原图像基础上进行后续操作
      
  11.  //建立金字塔的最底层   
  12.  if (DOUBLE_BASE_IMAGE_SIZE)   
  13.  {  
  14.   tempMat = doubleSizeImage2(imMat);//对扩大两倍的图像进行二次采样,采样率为0.5,采用线性插值
      
  15. #define TEMPMAT(ROW,COL) ((float *)(tempMat->data.fl + tempMat->step/sizeof(float) * (ROW)))[(COL)]
      
  16.     
  17.   dst = cvCreateMat(tempMat->rows, tempMat->cols, CV_32FC1);  
  18.   preblur_sigma = 1.0;//sqrt(2 - 4*INITSIGMA*INITSIGMA);
      
  19.         BlurImage(tempMat, dst, preblur_sigma);   
  20.     
  21.   // The initial blurring for the first image of the first octave of the pyramid.
      
  22.         sigma = sqrt( (4*INITSIGMA*INITSIGMA) + preblur_sigma * preblur_sigma );  
  23.   //  sigma = sqrt(SIGMA * SIGMA - INITSIGMA * INITSIGMA * 4);
      
  24.   //printf("Init Sigma: %f/n", sigma);
      
  25.   BlurImage(dst, tempMat, sigma);       //得到金字塔的最底层-放大2倍的图像
      
  26.   cvReleaseMat( &dst );   
  27.   return tempMat;  
  28.  }   
  29.  else   
  30.  {  
  31.   dst = cvCreateMat(im->rows, im->cols, CV_32FC1);  
  32.   //sigma = sqrt(SIGMA * SIGMA - INITSIGMA * INITSIGMA);
      
  33.   preblur_sigma = 1.0;//sqrt(2 - 4*INITSIGMA*INITSIGMA);
      
  34.   sigma = sqrt( (4*INITSIGMA*INITSIGMA) + preblur_sigma * preblur_sigma );  
  35.   //printf("Init Sigma: %f/n", sigma);
      
  36.   BlurImage(imMat, dst, sigma);        //得到金字塔的最底层:原始图像大小
      
  37.   return dst;  
  38.  }   
  39. }  

  

SIFT算法第二步
    SIFT第二步,建立Gaussian金字塔,给定金字塔第一阶第一层图像后,计算高斯金字塔其他尺度图像,
每一阶的数目由变量SCALESPEROCTAVE决定,给定一个基本图像,计算它的高斯金字塔图像,返回外部向量是阶梯指针,内部向量是每一个阶梯内部的不同尺度图像。

  1. //SIFT算法第二步   
  2. ImageOctaves* BuildGaussianOctaves(CvMat * image)   
  3. {  
  4.     ImageOctaves *octaves;  
  5.  CvMat *tempMat;  
  6.     CvMat *dst;  
  7.  CvMat *temp;  
  8.    
  9.  int i,j;  
  10.  double k = pow(2, 1.0/((float)SCALESPEROCTAVE));  //方差倍数
      
  11.  float preblur_sigma, initial_sigma , sigma1,sigma2,sigma,absolute_sigma,sigma_f;  
  12.  //计算金字塔的阶梯数目   
  13.  int dim = min(image->rows, image->cols);  
  14.     int numoctaves = (int) (log((double) dim) / log(2.0)) - 2;    //金字塔阶数
      
  15.  //限定金字塔的阶梯数   
  16.  numoctaves = min(numoctaves, MAXOCTAVES);  
  17.  //为高斯金塔和DOG金字塔分配内存   
  18.  octaves=(ImageOctaves*) malloc( numoctaves * sizeof(ImageOctaves) );  
  19.     DOGoctaves=(ImageOctaves*) malloc( numoctaves * sizeof(ImageOctaves) );  
  20.    
  21.  printf("BuildGaussianOctaves(): Base image dimension is %dx%d/n", (int)(0.5*(image->cols)), (int)(0.5*(image->rows)) );  
  22.  printf("BuildGaussianOctaves(): Building %d octaves/n", numoctaves);  
  23.    
  24.     // start with initial source image
      
  25.  tempMat=cvCloneMat( image );  
  26.  // preblur_sigma = 1.0;//sqrt(2 - 4*INITSIGMA*INITSIGMA);
      
  27.     initial_sigma = sqrt(2);//sqrt( (4*INITSIGMA*INITSIGMA) + preblur_sigma * preblur_sigma );
      
  28.  //   initial_sigma = sqrt(SIGMA * SIGMA - INITSIGMA * INITSIGMA * 4);
      
  29.       
  30.  //在每一阶金字塔图像中建立不同的尺度图像   
  31.  for ( i = 0; i < numoctaves; i++)   
  32.  {     
  33.   //首先建立金字塔每一阶梯的最底层,其中0阶梯的最底层已经建立好
      
  34.   printf("Building octave %d of dimesion (%d, %d)/n", i, tempMat->cols,tempMat->rows);  
  35.         //为各个阶梯分配内存   
  36.   octaves[i].Octave= (ImageLevels*) malloc( (SCALESPEROCTAVE + 3) * sizeof(ImageLevels) );  
  37.   DOGoctaves[i].Octave= (ImageLevels*) malloc( (SCALESPEROCTAVE + 2) * sizeof(ImageLevels) );  
  38.   //存储各个阶梯的最底层   
  39.   (octaves[i].Octave)[0].Level=tempMat;  
  40.     
  41.   octaves[i].col=tempMat->cols;  
  42.   octaves[i].row=tempMat->rows;  
  43.   DOGoctaves[i].col=tempMat->cols;  
  44.   DOGoctaves[i].row=tempMat->rows;  
  45.   if (DOUBLE_BASE_IMAGE_SIZE)  
  46.             octaves[i].subsample=pow(2,i)*0.5;  
  47.   else  
  48.             octaves[i].subsample=pow(2,i);  
  49.     
  50.   if(i==0)       
  51.   {  
  52.    (octaves[0].Octave)[0].levelsigma = initial_sigma;  
  53.    (octaves[0].Octave)[0].absolute_sigma = initial_sigma;  
  54.    printf("0 scale and blur sigma : %f /n", (octaves[0].subsample) * ((octaves[0].Octave)[0].absolute_sigma));  
  55.   }  
  56.   else  
  57.   {  
  58.    (octaves[i].Octave)[0].levelsigma = (octaves[i-1].Octave)[SCALESPEROCTAVE].levelsigma;  
  59.             (octaves[i].Octave)[0].absolute_sigma = (octaves[i-1].Octave)[SCALESPEROCTAVE].absolute_sigma;  
  60.    printf( "0 scale and blur sigma : %f /n", ((octaves[i].Octave)[0].absolute_sigma) );  
  61.   }  
  62.   sigma = initial_sigma;  
  63.         //建立本阶梯其他层的图像   
  64.   for ( j =  1; j < SCALESPEROCTAVE + 3; j++)   
  65.   {  
  66.    dst = cvCreateMat(tempMat->rows, tempMat->cols, CV_32FC1);//用于存储高斯层
      
  67.    temp = cvCreateMat(tempMat->rows, tempMat->cols, CV_32FC1);//用于存储DOG层
      
  68.    // 2 passes of 1D on original   
  69.    //   if(i!=0)   
  70.    //   {   
  71.    //       sigma1 = pow(k, j - 1) * ((octaves[i-1].Octave)[j-1].levelsigma);
      
  72.    //          sigma2 = pow(k, j) * ((octaves[i].Octave)[j-1].levelsigma);
      
  73.    //       sigma = sqrt(sigma2*sigma2 - sigma1*sigma1);
      
  74.    sigma_f= sqrt(k*k-1)*sigma;  
  75.    //   }   
  76.    //   else   
  77.    //   {   
  78.    //       sigma = sqrt(SIGMA * SIGMA - INITSIGMA * INITSIGMA * 4)*pow(k,j);
      
  79.    //   }     
  80.             sigma = k*sigma;  
  81.    absolute_sigma = sigma * (octaves[i].subsample);  
  82.    printf("%d scale and Blur sigma: %f  /n", j, absolute_sigma);  
  83.      
  84.    (octaves[i].Octave)[j].levelsigma = sigma;  
  85.             (octaves[i].Octave)[j].absolute_sigma = absolute_sigma;  
  86.             //产生高斯层   
  87.    int length=BlurImage((octaves[i].Octave)[j-1].Level, dst, sigma_f);//相应尺度
      
  88.             (octaves[i].Octave)[j].levelsigmalength = length;  
  89.    (octaves[i].Octave)[j].Level=dst;  
  90.             //产生DOG层   
  91.             cvSub( ((octaves[i].Octave)[j]).Level, ((octaves[i].Octave)[j-1]).Level, temp, 0 );  
  92.    //         cvAbsDiff( ((octaves[i].Octave)[j]).Level, ((octaves[i].Octave)[j-1]).Level, temp );
      
  93.             ((DOGoctaves[i].Octave)[j-1]).Level=temp;  
  94.   }  
  95.   // halve the image size for next iteration
      
  96.   tempMat  = halfSizeImage( ( (octaves[i].Octave)[SCALESPEROCTAVE].Level ) );  
  97.  }  
  98.  return octaves;  
  99. }  

  

SIFT算法第三步
    SIFT算法第三步,特征点位置检测,最后确定特征点的位置检测DOG金字塔中的局部最大值,找到之后,还要经过两个检验才能确认为特征点:一是它必须有明显的差异,二是他不应该是边缘点,(也就是说,在极值点处的主曲率比应该小于某一个阈值)。

  1. //SIFT算法第三步,特征点位置检测,   
  2. int DetectKeypoint(int numoctaves, ImageOctaves *GaussianPyr)  
  3. {  
  4.     //计算用于DOG极值点检测的主曲率比的阈值   
  5.  double curvature_threshold;  
  6.  curvature_threshold= ((CURVATURE_THRESHOLD + 1)*(CURVATURE_THRESHOLD + 1))/CURVATURE_THRESHOLD;  
  7. #define ImLevels(OCTAVE,LEVEL,ROW,COL) ((float *)(DOGoctaves[(OCTAVE)].Octave[(LEVEL)].Level->data.fl + DOGoctaves[(OCTAVE)].Octave[(LEVEL)].Level->step/sizeof(float) *(ROW)))[(COL)]
      
  8.    
  9.  int   keypoint_count = 0;     
  10.  for (int i=0; i<numoctaves; i++)    
  11.  {          
  12.   for(int j=1;j<SCALESPEROCTAVE+1;j++)//取中间的scaleperoctave个层
      
  13.   {    
  14.    //在图像的有效区域内寻找具有显著性特征的局部最大值   
  15.    //float sigma=(GaussianPyr[i].Octave)[j].levelsigma;
      
  16.    //int dim = (int) (max(3.0f, 2.0*GAUSSKERN *sigma + 1.0f)*0.5);
      
  17.    int dim = (int)(0.5*((GaussianPyr[i].Octave)[j].levelsigmalength)+0.5);  
  18.    for (int m=dim;m<((DOGoctaves[i].row)-dim);m++)   
  19.     for(int n=dim;n<((DOGoctaves[i].col)-dim);n++)  
  20.     {       
  21.      if ( fabs(ImLevels(i,j,m,n))>= CONTRAST_THRESHOLD )  
  22.      {  
  23.         
  24.       if ( ImLevels(i,j,m,n)!=0.0 )  //1、首先是非零
      
  25.       {  
  26.        float inf_val=ImLevels(i,j,m,n);  
  27.        if(( (inf_val <= ImLevels(i,j-1,m-1,n-1))&&  
  28.         (inf_val <= ImLevels(i,j-1,m  ,n-1))&&  
  29.         (inf_val <= ImLevels(i,j-1,m+1,n-1))&&  
  30.         (inf_val <= ImLevels(i,j-1,m-1,n  ))&&  
  31.         (inf_val <= ImLevels(i,j-1,m  ,n  ))&&  
  32.         (inf_val <= ImLevels(i,j-1,m+1,n  ))&&  
  33.         (inf_val <= ImLevels(i,j-1,m-1,n+1))&&  
  34.         (inf_val <= ImLevels(i,j-1,m  ,n+1))&&  
  35.         (inf_val <= ImLevels(i,j-1,m+1,n+1))&&    //底层的小尺度9
      
  36.           
  37.         (inf_val <= ImLevels(i,j,m-1,n-1))&&  

抱歉!评论已关闭.