Mitre_sfr代码注解(二) sfrproc函数

   笔者学识有限。 本博客旨在对mitre_sfr核心代码进行简单注解, 详细内容读者仁者见仁智者见智。

   bsfrproc函数是ISO12233附录A代码中的同名函数, 也是mitre_sfr中最核心的函数。因此对sfrproc函数的理解至关重要, 如果读者想对mitre_sfr功能进行自定义的移植, 最重要的就是对这个函数的移植与理解。

    sfrproc函数涵盖了ISO12233 Sect 6.3.2 中绝大部分的内容, 整个SFR计算的核心内容都在这个函数里面, 包含了下列步骤的主干(具体函数的注解见后续博文, 本文以核心函数注解为主, 其他main函数涉及的其他非主要部分函数, 且有必要注解的函数见后续再另行注解):

    1. 寻找sfr刀口的质心(locate_centroids函数)

    2. 拟合刀口划过的直线(fit函数)

    3. 刀口的超采样(ESF)(bin_to_regular_xgrid函数)

    4. ESF转换为LSF(calculate_derivative函数)

    5. 对LSF加汉明窗(apply_hamming_window函数)

    6. 计算SFR(ftwos函数)

short sfrProc (double **freq, double **sfr, 
	       int *len,
	       double *farea,
	       unsigned short size_x, int *nrows,
	       double *slope, int *numcycles, int *pcnt2, double *off, double *R2,
	       int version, int iterate, int user_angle)
{
  unsigned short i, j, col, err = 0;
  long pcnt;
  double dt, dt1, sfrc, tmp, tmp2;
  double *temp=NULL, *shifts=NULL, *edgex=NULL, *Signal=NULL;
  double *AveEdge=NULL, *AveTmp=NULL;
  long *counts=NULL;
  int nzero;
  unsigned short size_y;
  unsigned int bin_len;
  double avar, bvar, offset1, offset2, offset;
  double centroid;
  int start_row, center_row;
  double *farea_old;
  double cyclelimit;
  FILE *fp = NULL;

  size_y = *nrows;

  /* Verify input selection dimensions are EVEN */
  if (size_x%2 != 0) { 
    fprintf(stderr, "ROI width is not even.  Does this really matter???\n");
    return 1;
  }

  /* At least this many cycles required. */
  /* For special iterative versions of the code, it can go lower */
  if (iterate) cyclelimit = 1.0;
  else cyclelimit = 5.0;

  /* Allocate memory */
  shifts = (double *)malloc(size_y*sizeof(double));
  temp = (double *)malloc(size_y*sizeof(double));
  edgex = (double *)malloc(size_y*size_x*sizeof(double));
  Signal = (double *)malloc(size_y*size_x*sizeof(double));

  if( !user_angle ) {
	// 定位质心
    err = locate_centroids(farea, temp, shifts, size_x, size_y, &offset1); 
    if (err != 0)     { return 2; }

    /* Calculate the best fit line to the centroids */
    err = fit(size_y, temp, shifts, slope, &offset2, R2, &avar, &bvar);
    if (err != 0)     { return 3; }
    
    if (version)
      MTFPRINT4("\nLinear Fit:  R2 = %.3f SE_intercept = %.2f  SE_angle = %.3f\n",  
	      *R2, avar, atan(bvar)*(double)(180.0/M_PI))
  }

  /* Check slope is OK, and set size_y to be full multiple of cycles */
  // 检查刀口斜率, 以确保后面超采样的质量
  err = check_slope(*slope, &size_y, numcycles, cyclelimit, 1);

  /* Start image at new location, so that same row is center */
  // 调整ROI的行
  center_row = *nrows/2;
  start_row = center_row - size_y/2;
  farea_old = farea;
  farea = farea + start_row*size_x;
  /* On center row how much shift to get edge centered in row. */
  /* offset = 0.;  Original code effectively used this (no centering)*/
  // 计算刀口的偏移
  if(user_angle)
    offset = *off - size_x/2;
  else
    offset = offset1 + 0.5 + offset2  - size_x/2; // 为什么要加0.5?2019.03.26添加:因为dt是两个相邻点的关系, 所以dt的坐标应该加0.5

  *off = offset;
  if(version & ROUND || version & DER3)
    offset += 0.125;

  if (err != 0)     {   /* Slopes are bad.  But send back enough
			   data, so a diagnostic image has a chance. */
    *pcnt2 = 2*size_x;  /* Ignore derivative peak */
    return 4; 
  }

  /* reference the temp and shifts values to the new y centre */
  /* Instead of using the values in shifts, synthesize new ones based on 
     the best fit line. */
  // 基于拟合结果更新shifts
  col = size_y/2;
  for (i=0; i < size_y; i++) {
    shifts[i] = (*slope) * (double)(i-col) + offset;
  }

  /* Don't normalize the data.  It gets normalized during dft process */
  /* To normalize here, set dt = min and dt1 = max of farea data      */
  dt = 0.0;
  dt1 = 1.0;

  if (version & ESFFILE)
    fp = fopen("esf.txt","w");

  /* Calculate a long paired list of x values and signal values */
  pcnt = 0;
  for (j = 0; j < size_y; j++) 
  {
    for (i = 0; i < size_x; i++) 
	{
      edgex[pcnt] = (double)i - shifts[j]; // 计算每个点离刀口的距离
      Signal[pcnt] = ((farea[((j*(long)size_x)+i)]) - dt)/(dt1-dt);  // 归一化每个点的亮度
      if ((version & ESFFILE) && edgex[pcnt] < size_x/2 + 3 && edgex[pcnt] > size_x/2 - 3)
		fprintf(fp, "%f %f\n", edgex[pcnt], Signal[pcnt]);
      pcnt++;
    }
  }

  if (version & ESFFILE)
    fclose(fp);

  /* Allocate more memory */
  bin_len = (unsigned int)(ALPHA*size_x);
  AveEdge = (double *)malloc(bin_len*sizeof(double));
  AveTmp = (double *)malloc(bin_len*sizeof(double));
  counts = (long *)malloc(bin_len*sizeof(long));
 
  /* Project ESF data into supersampled bins */
  // 进行超采样, 生成长度为size_x*ALPHA(4)的单行图像(ESF), 保存在AveEdge中
  nzero = bin_to_regular_xgrid((unsigned short)ALPHA, edgex, Signal, 
			       AveEdge, counts, 
			       size_x, size_y); 
  free(counts);
  free(Signal);
  free(edgex);

  /* Compute LSF from ESF.  Not yet centered or windowed. */
  // 将ESF转换为差分图LSF, 并计算LSF的质心
  if ( (version&DER3) ) 
    calculate_derivative( bin_len, AveTmp, AveEdge, ¢roid, 1);
  else
    calculate_derivative( bin_len, AveTmp, AveEdge, ¢roid, 0);

  if (iterate == 0) {
    /* Copy ESF to output area */
    for ( i=0; i

 

你可能感兴趣的:(sfr,mitre_sfr,图像处理,数字图像处理,图像测试)