九之再续 教你一步一步用c语言实现sift算法 下

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

                      教你一步一步用c语言实现sift算法、下


作者: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. }  
//下采样原来的图像,返回缩小2倍尺寸的图像CvMat * halfSizeImage(CvMat * im) { unsigned int i,j; int w = im->cols/2; int h = im->rows/2;  CvMat *imnew = cvCreateMat(h, w, CV_32FC1); #define Im(ROW,COL) ((float *)(im->data.fl + im->step/sizeof(float) *(ROW)))[(COL)]#define Imnew(ROW,COL) ((float *)(imnew->data.fl + imnew->step/sizeof(float) *(ROW)))[(COL)] for ( j = 0; j < h; j++)   for ( i = 0; i < w; i++)    Imnew(j,i)=Im(j*2, i*2);  return imnew;}//上采样原来的图像,返回放大2倍尺寸的图像CvMat * doubleSizeImage(CvMat * im) { unsigned int i,j; int w = im->cols*2; int h = im->rows*2;  CvMat *imnew = cvCreateMat(h, w, CV_32FC1); #define Im(ROW,COL) ((float *)(im->data.fl + im->step/sizeof(float) *(ROW)))[(COL)]#define Imnew(ROW,COL) ((float *)(imnew->data.fl + imnew->step/sizeof(float) *(ROW)))[(COL)]  for ( j = 0; j < h; j++)   for ( i = 0; i < w; i++)    Imnew(j,i)=Im(j/2, i/2);    return imnew;}//上采样原来的图像,返回放大2倍尺寸的线性插值图像CvMat * doubleSizeImage2(CvMat * im) { unsigned int i,j; int w = im->cols*2; int h = im->rows*2;  CvMat *imnew = cvCreateMat(h, w, CV_32FC1); #define Im(ROW,COL) ((float *)(im->data.fl + im->step/sizeof(float) *(ROW)))[(COL)]#define Imnew(ROW,COL) ((float *)(imnew->data.fl + imnew->step/sizeof(float) *(ROW)))[(COL)]  // fill every pixel so we don't have to worry about skipping pixels later for ( j = 0; j < h; j++)  {  for ( i = 0; i < w; i++)   {   Imnew(j,i)=Im(j/2, i/2);  } } /* A B C E F G H I J pixels A C H J are pixels from original image pixels B E G I F are interpolated pixels */ // interpolate pixels B and I for ( j = 0; j < h; j += 2)  for ( i = 1; i < w - 1; i += 2)   Imnew(j,i)=0.5*(Im(j/2, i/2)+Im(j/2, i/2+1));  // interpolate pixels E and G  for ( j = 1; j < h - 1; j += 2)   for ( i = 0; i < w; i += 2)    Imnew(j,i)=0.5*(Im(j/2, i/2)+Im(j/2+1, i/2));   // interpolate pixel F   for ( j = 1; j < h - 1; j += 2)    for ( i = 1; i < w - 1; i += 2)     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));    return imnew;}//双线性插值,返回像素间的灰度值float getPixelBI(CvMat * im, float col, float row) { int irow, icol; float rfrac, cfrac; float row1 = 0, row2 = 0; int width=im->cols; int height=im->rows;#define ImMat(ROW,COL) ((float *)(im->data.fl + im->step/sizeof(float) *(ROW)))[(COL)]  irow = (int) row; icol = (int) col;  if (irow < 0 || irow >= height  || icol < 0 || icol >= width)  return 0; if (row > height - 1)  row = height - 1; if (col > width - 1)  col = width - 1; rfrac = 1.0 - (row - (float) irow); cfrac = 1.0 - (col - (float) icol); if (cfrac < 1)  {  row1 = cfrac * ImMat(irow,icol) + (1.0 - cfrac) * ImMat(irow,icol+1); }  else  {  row1 = ImMat(irow,icol); } if (rfrac < 1)  {  if (cfrac < 1)   {   row2 = cfrac * ImMat(irow+1,icol) + (1.0 - cfrac) * ImMat(irow+1,icol+1);  } else   {   row2 = ImMat(irow+1,icol);  } } return rfrac * row1 + (1.0 - rfrac) * row2;}//矩阵归一化void normalizeMat(CvMat* mat) {#define Mat(ROW,COL) ((float *)(mat->data.fl + mat->step/sizeof(float) *(ROW)))[(COL)] float sum = 0;  for (unsigned int j = 0; j < mat->rows; j++)   for (unsigned int i = 0; i < mat->cols; i++)    sum += Mat(j,i);  for ( j = 0; j < mat->rows; j++)    for (unsigned int i = 0; i < mat->rows; i++)     Mat(j,i) /= sum;}//向量归一化void normalizeVec(float* vec, int dim) {    unsigned int i; float sum = 0; for ( i = 0; i < dim; i++)  sum += vec[i]; for ( i = 0; i < dim; i++)  vec[i] /= sum;}//得到向量的欧式长度,2-范数float GetVecNorm( float* vec, int dim ){ float sum=0.0; for (unsigned int i=0;i<dim;i++)  sum+=vec[i]*vec[i];    return sqrt(sum);}//产生1D高斯核float* GaussianKernel1D(float sigma, int dim) {  unsigned int i; //printf("GaussianKernel1D(): Creating 1x%d vector for sigma=%.3f gaussian kernel/n", dim, sigma);  float *kern=(float*)malloc( dim*sizeof(float) ); float s2 = sigma * sigma; int c = dim / 2; float m= 1.0/(sqrt(2.0 * CV_PI) * sigma);    double v;  for ( i = 0; i < (dim + 1) / 2; i++)  {  v = m * exp(-(1.0*i*i)/(2.0 * s2)) ;  kern[c+i] = v;  kern[c-i] = v; } //   normalizeVec(kern, dim); // for ( i = 0; i < dim; i++) //  printf("%f  ", kern[i]); //  printf("/n"); return kern;}//产生2D高斯核矩阵CvMat* GaussianKernel2D(float sigma) { // int dim = (int) max(3.0f, GAUSSKERN * sigma);    int dim = (int) max(3.0f, 2.0 * GAUSSKERN *sigma + 1.0f); // make dim odd if (dim % 2 == 0)  dim++; //printf("GaussianKernel(): Creating %dx%d matrix for sigma=%.3f gaussian/n", dim, dim, sigma); CvMat* mat=cvCreateMat(dim, dim, CV_32FC1);#define Mat(ROW,COL) ((float *)(mat->data.fl + mat->step/sizeof(float) *(ROW)))[(COL)] float s2 = sigma * sigma; int c = dim / 2; //printf("%d %d/n", mat.size(), mat[0].size());    float m= 1.0/(sqrt(2.0 * CV_PI) * sigma); for (int i = 0; i < (dim + 1) / 2; i++)  {  for (int j = 0; j < (dim + 1) / 2; j++)   {   //printf("%d %d %d/n", c, i, j);   float v = m * exp(-(1.0*i*i + 1.0*j*j) / (2.0 * s2));   Mat(c+i,c+j) =v;   Mat(c-i,c+j) =v;   Mat(c+i,c-j) =v;   Mat(c-i,c-j) =v;  } } // normalizeMat(mat); return mat;}//x方向像素处作卷积float ConvolveLocWidth(float* kernel, int dim, CvMat * src, int x, int y) {#define Src(ROW,COL) ((float *)(src->data.fl + src->step/sizeof(float) *(ROW)))[(COL)]    unsigned int i; float pixel = 0;    int col; int cen = dim / 2; //printf("ConvolveLoc(): Applying convoluation at location (%d, %d)/n", x, y); for ( i = 0; i < dim; i++)  {  col = x + (i - cen);  if (col < 0)   col = 0;  if (col >= src->cols)   col = src->cols - 1;  pixel += kernel[i] * Src(y,col); } if (pixel > 1)  pixel = 1; return pixel;}//x方向作卷积void Convolve1DWidth(float* kern, int dim, CvMat * src, CvMat * dst) {#define DST(ROW,COL) ((float *)(dst->data.fl + dst->step/sizeof(float) *(ROW)))[(COL)] unsigned int i,j;  for ( j = 0; j < src->rows; j++)  {  for ( i = 0; i < src->cols; i++)   {   //printf("%d, %d/n", i, j);   DST(j,i) = ConvolveLocWidth(kern, dim, src, i, j);  } }}//y方向像素处作卷积float ConvolveLocHeight(float* kernel, int dim, CvMat * src, int x, int y) {#define Src(ROW,COL) ((float *)(src->data.fl + src->step/sizeof(float) *(ROW)))[(COL)]    unsigned int j; float pixel = 0; int cen = dim / 2; //printf("ConvolveLoc(): Applying convoluation at location (%d, %d)/n", x, y); for ( j = 0; j < dim; j++)  {  int row = y + (j - cen);  if (row < 0)   row = 0;  if (row >= src->rows)   row = src->rows - 1;  pixel += kernel[j] * Src(row,x); } if (pixel > 1)  pixel = 1; return pixel;}//y方向作卷积void Convolve1DHeight(float* kern, int dim, CvMat * src, CvMat * dst) {#define Dst(ROW,COL) ((float *)(dst->data.fl + dst->step/sizeof(float) *(ROW)))[(COL)]    unsigned int i,j; for ( j = 0; j < src->rows; j++)  {  for ( i = 0; i < src->cols; i++)   {   //printf("%d, %d/n", i, j);   Dst(j,i) = ConvolveLocHeight(kern, dim, src, i, j);  } }}//卷积模糊图像int BlurImage(CvMat * src, CvMat * dst, float sigma) { float* convkernel; int dim = (int) max(3.0f, 2.0 * GAUSSKERN * sigma + 1.0f);    CvMat *tempMat; // make dim odd if (dim % 2 == 0)  dim++; tempMat = cvCreateMat(src->rows, src->cols, CV_32FC1); convkernel = GaussianKernel1D(sigma, dim);  Convolve1DWidth(convkernel, dim, src, tempMat); Convolve1DHeight(convkernel, dim, tempMat, dst); cvReleaseMat(&tempMat); return dim;}

五个步骤

    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. }  
CvMat *ScaleInitImage(CvMat * im) {    double sigma,preblur_sigma; CvMat *imMat; CvMat * dst; CvMat *tempMat; //首先对图像进行平滑滤波,抑制噪声 imMat = cvCreateMat(im->rows, im->cols, CV_32FC1);    BlurImage(im, imMat, INITSIGMA); //针对两种情况分别进行处理:初始化放大原始图像或者在原图像基础上进行后续操作 //建立金字塔的最底层 if (DOUBLE_BASE_IMAGE_SIZE)  {  tempMat = doubleSizeImage2(imMat);//对扩大两倍的图像进行二次采样,采样率为0.5,采用线性插值#define TEMPMAT(ROW,COL) ((float *)(tempMat->data.fl + tempMat->step/sizeof(float) * (ROW)))[(COL)]    dst = cvCreateMat(tempMat->rows, tempMat->cols, CV_32FC1);  preblur_sigma = 1.0;//sqrt(2 - 4*INITSIGMA*INITSIGMA);        BlurImage(tempMat, dst, preblur_sigma);     // The initial blurring for the first image of the first octave of the pyramid.        sigma = sqrt( (4*INITSIGMA*INITSIGMA) + preblur_sigma * preblur_sigma );  //  sigma = sqrt(SIGMA * SIGMA - INITSIGMA * INITSIGMA * 4);  //printf("Init Sigma: %f/n", sigma);  BlurImage(dst, tempMat, sigma);       //得到金字塔的最底层-放大2倍的图像  cvReleaseMat( &dst );   return tempMat; }  else  {  dst = cvCreateMat(im->rows, im->cols, CV_32FC1);  //sigma = sqrt(SIGMA * SIGMA - INITSIGMA * INITSIGMA);  preblur_sigma = 1.0;//sqrt(2 - 4*INITSIGMA*INITSIGMA);  sigma = sqrt( (4*INITSIGMA*INITSIGMA) + preblur_sigma * preblur_sigma );  //printf("Init Sigma: %f/n", sigma);  BlurImage(imMat, dst, sigma);        //得到金字塔的最底层:原始图像大小  return dst; } }  

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算法第二步ImageOctaves* BuildGaussianOctaves(CvMat * image) {    ImageOctaves *octaves; CvMat *tempMat;    CvMat *dst; CvMat *temp;  int i,j; double k = pow(2, 1.0/((float)SCALESPEROCTAVE));  //方差倍数 float preblur_sigma, initial_sigma , sigma1,sigma2,sigma,absolute_sigma,sigma_f; //计算金字塔的阶梯数目 int dim = min(image->rows, image->cols);    int numoctaves = (int) (log((double) dim) / log(2.0)) - 2;    //金字塔阶数 //限定金字塔的阶梯数 numoctaves = min(numoctaves, MAXOCTAVES); //为高斯金塔和DOG金字塔分配内存 octaves=(ImageOctaves*) malloc( numoctaves * sizeof(ImageOctaves) );    DOGoctaves=(ImageOctaves*) malloc( numoctaves * sizeof(ImageOctaves) );  printf("BuildGaussianOctaves(): Base image dimension is %dx%d/n", (int)(0.5*(image->cols)), (int)(0.5*(image->rows)) ); printf("BuildGaussianOctaves(): Building %d octaves/n", numoctaves);     // start with initial source image tempMat=cvCloneMat( image ); // preblur_sigma = 1.0;//sqrt(2 - 4*INITSIGMA*INITSIGMA);    initial_sigma = sqrt(2);//sqrt( (4*INITSIGMA*INITSIGMA) + preblur_sigma * preblur_sigma ); //   initial_sigma = sqrt(SIGMA * SIGMA - INITSIGMA * INITSIGMA * 4);     //在每一阶金字塔图像中建立不同的尺度图像 for ( i = 0; i < numoctaves; i++)  {     //首先建立金字塔每一阶梯的最底层,其中0阶梯的最底层已经建立好  printf("Building octave %d of dimesion (%d, %d)/n", i, tempMat->cols,tempMat->rows);        //为各个阶梯分配内存  octaves[i].Octave= (ImageLevels*) malloc( (SCALESPEROCTAVE + 3) * sizeof(ImageLevels) );  DOGoctaves[i].Octave= (ImageLevels*) malloc( (SCALESPEROCTAVE + 2) * sizeof(ImageLevels) );  //存储各个阶梯的最底层  (octaves[i].Octave)[0].Level=tempMat;    octaves[i].col=tempMat->cols;  octaves[i].row=tempMat->rows;  DOGoctaves[i].col=tempMat->cols;  DOGoctaves[i].row=tempMat->rows;  if (DOUBLE_BASE_IMAGE_SIZE)            octaves[i].subsample=pow(2,i)*0.5;  else            octaves[i].subsample=pow(2,i);    if(i==0)       {   (octaves[0].Octave)[0].levelsigma = initial_sigma;   (octaves[0].Octave)[0].absolute_sigma = initial_sigma;   printf("0 scale and blur sigma : %f /n", (octaves[0].subsample) * ((octaves[0].Octave)[0].absolute_sigma));  }  else  {   (octaves[i].Octave)[0].levelsigma = (octaves[i-1].Octave)[SCALESPEROCTAVE].levelsigma;            (octaves[i].Octave)[0].absolute_sigma = (octaves[i-1].Octave)[SCALESPEROCTAVE].absolute_sigma;   printf( "0 scale and blur sigma : %f /n", ((octaves[i].Octave)[0].absolute_sigma) );  }  sigma = initial_sigma;        //建立本阶梯其他层的图像  for ( j =  1; j < SCALESPEROCTAVE + 3; j++)   {   dst = cvCreateMat(tempMat->rows, tempMat->cols, CV_32FC1);//用于存储高斯层   temp = cvCreateMat(tempMat->rows, tempMat->cols, CV_32FC1);//用于存储DOG层   // 2 passes of 1D on original   //   if(i!=0)   //   {   //       sigma1 = pow(k, j - 1) * ((octaves[i-1].Octave)[j-1].levelsigma);   //          sigma2 = pow(k, j) * ((octaves[i].Octave)[j-1].levelsigma);   //       sigma = sqrt(sigma2*sigma2 - sigma1*sigma1);   sigma_f= sqrt(k*k-1)*sigma;   //   }   //   else   //   {   //       sigma = sqrt(SIGMA * SIGMA - INITSIGMA * INITSIGMA * 4)*pow(k,j);   //   }              sigma = k*sigma;   absolute_sigma = sigma * (octaves[i].subsample);   printf("%d scale and Blur sigma: %f  /n", j, absolute_sigma);      (octaves[i].Octave)[j].levelsigma = sigma;            (octaves[i].Octave)[j].absolute_sigma = absolute_sigma;            //产生高斯层   int length=BlurImage((octaves[i].Octave)[j-1].Level, dst, sigma_f);//相应尺度            (octaves[i].Octave)[j].levelsigmalength = length;   (octaves[i].Octave)[j].Level=dst;            //产生DOG层            cvSub( ((octaves[i].Octave)[j]).Level, ((octaves[i].Octave)[j-1]).Level, temp, 0 );   //         cvAbsDiff( ((octaves[i].Octave)[j]).Level, ((octaves[i].Octave)[j-1]).Level, temp );            ((DOGoctaves[i].Octave)[j-1]).Level=temp;  }  // halve the image size for next iteration  tempMat  = halfSizeImage( ( (octaves[i].Octave)[SCALESPEROCTAVE].Level ) ); } return octaves;}  

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))&&  
  38.         (inf_val <= ImLevels(i,j,m  ,n-1))&&  
  39.         (inf_val <= ImLevels(i,j,m+1,n-1))&&  
  40.         (inf_val <= ImLevels(i,j,m-1,n  ))&&  
  41.         (inf_val <= ImLevels(i,j,m+1,n  ))&&  
  42.         (inf_val <= ImLevels(i,j,m-1,n+1))&&  
  43.         (inf_val <= ImLevels(i,j,m  ,n+1))&&  
  44.         (inf_val <= ImLevels(i,j,m+1,n+1))&&     //当前层8  
  45.           
  46.         (inf_val <= ImLevels(i,j+1,m-1,n-1))&&  
  47.         (inf_val <= ImLevels(i,j+1,m  ,n-1))&&  
  48.         (inf_val <= ImLevels(i,j+1,m+1,n-1))&&  
  49.         (inf_val <= ImLevels(i,j+1,m-1,n  ))&&  
  50.         (inf_val <= ImLevels(i,j+1,m  ,n  ))&&  
  51.         (inf_val <= ImLevels(i,j+1,m+1,n  ))&&  
  52.         (inf_val <= ImLevels(i,j+1,m-1,n+1))&&  
  53.         (inf_val <= ImLevels(i,j+1,m  ,n+1))&&  
  54.         (inf_val <= ImLevels(i,j+1,m+1,n+1))     //下一层大尺度9          
  55.         ) ||   
  56.         ( (inf_val >= ImLevels(i,j-1,m-1,n-1))&&  
  57.         (inf_val >= ImLevels(i,j-1,m  ,n-1))&&  
  58.         (inf_val >= ImLevels(i,j-1,m+1,n-1))&&  
  59.         (inf_val >= ImLevels(i,j-1,m-1,n  ))&&  
  60.         (inf_val >= ImLevels(i,j-1,m  ,n  ))&&  
  61.         (inf_val >= ImLevels(i,j-1,m+1,n  ))&&  
  62.         (inf_val >= ImLevels(i,j-1,m-1,n+1))&&  
  63.         (inf_val >= ImLevels(i,j-1,m  ,n+1))&&  
  64.         (inf_val >= ImLevels(i,j-1,m+1,n+1))&&  
  65.           
  66.         (inf_val >= ImLevels(i,j,m-1,n-1))&&  
  67.         (inf_val >= ImLevels(i,j,m  ,n-1))&&  
  68.         (inf_val >= ImLevels(i,j,m+1,n-1))&&  
  69.         (inf_val >= ImLevels(i,j,m-1,n  ))&&  
  70.         (inf_val >= ImLevels(i,j,m+1,n  ))&&  
  71.         (inf_val >= ImLevels(i,j,m-1,n+1))&&  
  72.         (inf_val >= ImLevels(i,j,m  ,n+1))&&  
  73.         (inf_val >= ImLevels(i,j,m+1,n+1))&&   
  74.           
  75.         (inf_val >= ImLevels(i,j+1,m-1,n-1))&&  
  76.         (inf_val >= ImLevels(i,j+1,m  ,n-1))&&  
  77.         (inf_val >= ImLevels(i,j+1,m+1,n-1))&&  
  78.         (inf_val >= ImLevels(i,j+1,m-1,n  ))&&  
  79.         (inf_val >= ImLevels(i,j+1,m  ,n  ))&&  
  80.         (inf_val >= ImLevels(i,j+1,m+1,n  ))&&  
  81.         (inf_val >= ImLevels(i,j+1,m-1,n+1))&&  
  82.         (inf_val >= ImLevels(i,j+1,m  ,n+1))&&  
  83.         (inf_val >= ImLevels(i,j+1,m+1,n+1))   
  84.         ) )      //2、满足26个中极值点  
  85.        {     
  86.         //此处可存储  
  87.         //然后必须具有明显的显著性,即必须大于CONTRAST_THRESHOLD=0.02  
  88.         if ( fabs(ImLevels(i,j,m,n))>= CONTRAST_THRESHOLD )  
  89.         {  
  90.          //最后显著处的特征点必须具有足够的曲率比,CURVATURE_THRESHOLD=10.0,首先计算Hessian矩阵  
  91.          // Compute the entries of the Hessian matrix at the extrema location.  
  92.          /* 
  93.          1   0   -1 
  94.          0   0   0 
  95.          -1   0   1         *0.25 
  96.          */  
  97.          // Compute the trace and the determinant of the Hessian.  
  98.          //Tr_H = Dxx + Dyy;  
  99.          //Det_H = Dxx*Dyy - Dxy^2;  
  100.          float Dxx,Dyy,Dxy,Tr_H,Det_H,curvature_ratio;  
  101.          Dxx = ImLevels(i,j,m,n-1) + ImLevels(i,j,m,n+1)-2.0*ImLevels(i,j,m,n);  
  102.          Dyy = ImLevels(i,j,m-1,n) + ImLevels(i,j,m+1,n)-2.0*ImLevels(i,j,m,n);  
  103.          Dxy = ImLevels(i,j,m-1,n-1) + ImLevels(i,j,m+1,n+1) - ImLevels(i,j,m+1,n-1) - ImLevels(i,j,m-1,n+1);  
  104.          Tr_H = Dxx + Dyy;  
  105.          Det_H = Dxx*Dyy - Dxy*Dxy;  
  106.          // Compute the ratio of the principal curvatures.  
  107.          curvature_ratio = (1.0*Tr_H*Tr_H)/Det_H;  
  108.          if ( (Det_H>=0.0) && (curvature_ratio <= curvature_threshold) )  //最后得到最具有显著性特征的特征点  
  109.          {  
  110.           //将其存储起来,以计算后面的特征描述字  
  111.           keypoint_count++;  
  112.           Keypoint k;  
  113.           /* Allocate memory for the keypoint. */  
  114.           k = (Keypoint) malloc(sizeof(struct KeypointSt));  
  115.           k->next = keypoints;  
  116.           keypoints = k;  
  117.           k->row = m*(GaussianPyr[i].subsample);  
  118.           k->col =n*(GaussianPyr[i].subsample);  
  119.           k->sy = m;    //行  
  120.           k->sx = n;    //列  
  121.           k->octave=i;  
  122.           k->level=j;  
  123.           k->scale = (GaussianPyr[i].Octave)[j].absolute_sigma;        
  124.          }//if >curvature_thresh  
  125.         }//if >contrast  
  126.        }//if inf value  
  127.      }//if non zero  
  128.      }//if >contrast  
  129.     }  //for concrete image level col  
  130.   }//for levels  
  131.  }//for octaves  
  132.  return keypoint_count;  
  133. }  
  134.   
  135. //在图像中,显示SIFT特征点的位置  
  136. void DisplayKeypointLocation(IplImage* image, ImageOctaves *GaussianPyr)  
  137. {  
  138.    
  139.     Keypoint p = keypoints; // p指向第一个结点  
  140.  while(p) // 没到表尾  
  141.  {     
  142.   cvLine( image, cvPoint((int)((p->col)-3),(int)(p->row)),   
  143.    cvPoint((int)((p->col)+3),(int)(p->row)), CV_RGB(255,255,0),  
  144.    1, 8, 0 );  
  145.         cvLine( image, cvPoint((int)(p->col),(int)((p->row)-3)),   
  146.    cvPoint((int)(p->col),(int)((p->row)+3)), CV_RGB(255,255,0),  
  147.    1, 8, 0 );  
  148.   //  cvCircle(image,cvPoint((uchar)(p->col),(uchar)(p->row)),  
  149.   //   (int)((GaussianPyr[p->octave].Octave)[p->level].absolute_sigma),  
  150.   //   CV_RGB(255,0,0),1,8,0);  
  151.   p=p->next;  
  152.  }   
  153. }  
  154.   
  155. // Compute the gradient direction and magnitude of the gaussian pyramid images  
  156. void ComputeGrad_DirecandMag(int numoctaves, ImageOctaves *GaussianPyr)  
  157. {  
  158.  // ImageOctaves *mag_thresh ;  
  159.     mag_pyr=(ImageOctaves*) malloc( numoctaves * sizeof(ImageOctaves) );  
  160.  grad_pyr=(ImageOctaves*) malloc( numoctaves * sizeof(ImageOctaves) );  
  161.  // float sigma=( (GaussianPyr[0].Octave)[SCALESPEROCTAVE+2].absolute_sigma ) / GaussianPyr[0].subsample;  
  162.  // int dim = (int) (max(3.0f, 2 * GAUSSKERN *sigma + 1.0f)*0.5+0.5);  
  163. #define ImLevels(OCTAVE,LEVEL,ROW,COL) ((float *)(GaussianPyr[(OCTAVE)].Octave[(LEVEL)].Level->data.fl + GaussianPyr[(OCTAVE)].Octave[(LEVEL)].Level->step/sizeof(float) *(ROW)))[(COL)]  
  164.  for (int i=0; i<numoctaves; i++)    
  165.  {          
  166.   mag_pyr[i].Octave= (ImageLevels*) malloc( (SCALESPEROCTAVE) * sizeof(ImageLevels) );  
  167.         grad_pyr[i].Octave= (ImageLevels*) malloc( (SCALESPEROCTAVE) * sizeof(ImageLevels) );  
  168.   for(int j=1;j<SCALESPEROCTAVE+1;j++)//取中间的scaleperoctave个层  
  169.   {    
  170.             CvMat *Mag = cvCreateMat(GaussianPyr[i].row, GaussianPyr[i].col, CV_32FC1);  
  171.    CvMat *Ori = cvCreateMat(GaussianPyr[i].row, GaussianPyr[i].col, CV_32FC1);  
  172.    CvMat *tempMat1 = cvCreateMat(GaussianPyr[i].row, GaussianPyr[i].col, CV_32FC1);  
  173.    CvMat *tempMat2 = cvCreateMat(GaussianPyr[i].row, GaussianPyr[i].col, CV_32FC1);  
  174.    cvZero(Mag);  
  175.    cvZero(Ori);  
  176.    cvZero(tempMat1);  
  177.    cvZero(tempMat2);   
  178. #define MAG(ROW,COL) ((float *)(Mag->data.fl + Mag->step/sizeof(float) *(ROW)))[(COL)]     
  179. #define ORI(ROW,COL) ((float *)(Ori->data.fl + Ori->step/sizeof(float) *(ROW)))[(COL)]    
  180. #define TEMPMAT1(ROW,COL) ((float *)(tempMat1->data.fl + tempMat1->step/sizeof(float) *(ROW)))[(COL)]  
  181. #define TEMPMAT2(ROW,COL) ((float *)(tempMat2->data.fl + tempMat2->step/sizeof(float) *(ROW)))[(COL)]  
  182.    for (int m=1;m<(GaussianPyr[i].row-1);m++)   
  183.     for(int n=1;n<(GaussianPyr[i].col-1);n++)  
  184.     {  
  185.      //计算幅值  
  186.      TEMPMAT1(m,n) = 0.5*( ImLevels(i,j,m,n+1)-ImLevels(i,j,m,n-1) );  //dx  
  187.                    &nb

    给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow
    这里写图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值