图像解析力算法—SFR(Spatial Frequency Response)源码分析(一)

在前面的文章中,我们已经分析了SFR的算法原理与步骤,下面我们直接来分析源码,源码中主要的函数主要分为一下几个:

1、locate_centroids作用:定位每一行像素的矩心位置

unsigned short locate_centroids(double *farea, double *temp, 
double *shifts,unsigned short size_x, unsigned short size_y,double *offset)
 unsigned long i, j;
  double dt, dt1, dt2;
 
  /* Compute the first difference on each line. Interpolate to find the 
     centroid of the first derivatives. */
  //计算差分  计算矩心位置
  for (j = 0; j < size_y; j++) {
    dt = 0.0;
    dt1 = 0.0;
    for (i = 0; i < size_x-1; i++) {
      dt2 = farea[(j*(long)size_x)+(i+1)] - farea[(j*(long)size_x)+i]; 
      dt += dt2 * (double)i;
      dt1 += dt2;
    }
	shifts[j] = dt / dt1;
	printf("=========\n");
	printf("%f\n", shifts[j]);
  }
 
  /* check again to be sure we aren't too close to an edge on the corners. 
     If the black to white transition is closer than 2 pixels from either 
     side of the data box, return an error of 5; the calling program will 
     display an error message (the same one as if there were not a difference 
     between the left and right sides of the box ) */
  if (shifts[size_y-1] < 2  || size_x - shifts[size_y-1] < 2) {
    fprintf(stderr,"** WARNING: Edge comes too close to the ROI corners.\n");
   // return 5;
  }
//防止矩心过于靠近图像的边界
  if (shifts[0] < 2 || size_x - shifts[0] < 2){
    fprintf(stderr,"** WARNING: Edge comes too close to the ROI corners.\n");
  //  return 5;
  }
 
  /* Reference rows to the vertical centre of the data box */
  j = size_y/2;
  dt = shifts[j];
  for (i = 0; i < size_y; i++) {
    temp[i] = (double)i - (double)j;
    shifts[i] -= dt;
  }
  *offset = dt;

2、fit函数:根据上面locate_centroid函数的结果,利用最小二乘法进行拟合,得到一条拟合后的质心直线。

unsigned short fit(unsigned long ndata, double *x, double *y, double *b, 
		   double *a, double *R2, double *avar, double *bvar)
{
  unsigned long i;
  double t,sxoss,syoss,sx=0.0,sy=0.0,st2=0.0;
  double ss,sst,sigdat,chi2,siga,sigb;
 
  *b=0.0;
  for ( i=0; i < ndata; i++ ) {
    sx += x[i];//x的叠加
    sy += y[i];//y的叠加
  }
  //求平均值
  ss=(double)ndata;
  sxoss=sx/ss;   
  syoss=sy/ss;
  for ( i=0; i < ndata; i++ ) {
    t = x[i] - sxoss;  //
    st2 += t*t; //方差
    *b += t * y[i];  
  }
  *b /= st2;         /* slope  *///斜率
  *a =(sy-sx*(*b))/ss; /* intercept *///截距
  siga=sqrt((1.0+sx*sx/(ss*st2))/ss);
  sigb=sqrt(1.0/st2);
  chi2=0.0;
  sst=0.0;
  for (i=0; i < ndata; i++) {
    chi2 += SQR( y[i] - (*a) - (*b) * x[i]); 
    sst += SQR( y[i] - syoss); 
  }
  sigdat=sqrt(chi2/(ndata-2));
  siga *= sigdat;
  sigb *= sigdat;
  *R2 = 1.0 - chi2/sst;//拟合程度
  *avar = siga;
  *bvar = sigb;
  return 0;
}

3、bin_to_regular_xgrid的作用:进行四倍的超采样得到ESF

unsigned short bin_to_regular_xgrid(unsigned short alpha,//alpha->指的是超取样的倍数
				    double *edgex, double *Signal, 
				    double *AveEdge, long *counts,
				    unsigned short size_x,
				    unsigned short size_y)
{
  long i, j, k,bin_number;
  long bin_len;
  int nzeros;
 
  bin_len = size_x * alpha;  //扩大四倍
 
  for (i=0; i<bin_len; i++) {
    AveEdge[i] = 0;
    counts[i] = 0;
  }
  for (i=0; i<(size_x*(long)size_y); i++) {
    bin_number = (long)floor((double)alpha*edgex[i]);//向下取整
    if (bin_number >= 0) {
      if (bin_number <= (bin_len - 1) ) {
        AveEdge[bin_number] = AveEdge[bin_number] + Signal[i];//把每一行的距离边缘x轴一样远的信号相加
        counts[bin_number] = (counts[bin_number])+1;//记录下对应位置有多少个信号相加
      }
    }
  }
 
  nzeros = 0;
  for (i=0; i<bin_len; i++) {
    j = 0;
    k = 1;
    //感觉写的有点复杂
    if (counts[i] == 0) {
      nzeros++; //记录有多少个位置是空的,即没有信号
      //K的作用:因为这里的信号为0,找到后面第一个不为零的值,赋给当前这个零
      if (i == 0) {
        while (!j) { //当j==0时,表示此处的信号为0
          if (counts[i+k] != 0) {//第一行的元素
	    AveEdge[i] = AveEdge[i+k]/((double) counts[i+k]);
            j = 1;//充当flag。。。为啥不用布尔类型
	  }
          else k++;//直到找到第一个不为零的数字才会停止
	}
      } else {
        while (!j && ((i-k) >= 0) ) { //j==0&&i-k>=0  j==0说明 counts[i]是0  i-k>0说明  k在i前面,找前面不为零的数值赋给AveEdge[i]
          if ( counts[i-k] != 0) {
	    AveEdge[i] = AveEdge[i-k];   /* Don't divide by counts since it already happened in previous iteration */
	    j = 1;
	  } 
	  else k++;
	}
        if ( (i-k) < 0 ) {//k>i,其实联合上面那段,就是:此处的counts[i]累加次数为零,所以AveEdge[i]也就是0,所以要找到附近一个不为零的值赋给AveEdge[i]
	  k = 1;
	  while (!j) {
	    if (counts[i+k] != 0) {
	      AveEdge[i] = AveEdge[i+k]/((double) counts[i+k]);
	      j = 1;
	    } 
	    else k++;
	  }
	}
      }
    } 
    else 
      AveEdge[i] = (AveEdge[i])/ ((double) counts[i]);//如果此处不为零,直接就求个平均值
  }
 
  if (nzeros > 0) {//提示信息
    fprintf(stderr, "\nWARNING: %d Zero counts found during projection binning.\n", nzeros);
    fprintf(stderr, "The edge angle may be large, or you may need more lines of data.\n\n");
  }
  return nzeros;
}

好了,今天先写到这,接下来有空会把接下来几个函数补上。



本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864