Mitre_sfr代码注解(一)main函数

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

  本人最近有幸拜读mitre_sfr代码, 对代码进行了简单的注解。介于学习的时候在网上没搜到类似的文章,所以特开立这个主题, 希望对后面学习mitre_sfr或想了解SFR算法的同学有所帮助。

    另外, 本人是计科生, 对信号与系统知识了解有限, 读代码的时候也有一些不甚了解之处, 在代码注解中进行了标注, 希望相关领域大神在浏览的时候能顺便帮我解惑, 在此不甚感激。

    拜读mitre_sfr代码时发现mitre_sfr的源码和ISO12233附录A中的代码出奇的一致, 相似性达到至少90%, 说明mitre_sfr作者对IOS的作者出于崇高的敬意。

    废话少说, 贴代码。

    看代码先看主干, 我先贴main函数。 Mitre_sfr的main函数对核心算法和主干涉及不多, 仅涉及sfr计算的预处理和sfr计算结果输出的一些处理, 建议大家快速阅读即可。

  下一篇我将先贴出mitre_sfr最核心的函数sfrProc的源码和注解。 其他次要代码及注解在后续文章贴出, 希望大家体谅。

int main(int argc, char **argv)
{
  char problem_string[82];
  unsigned char rotation;
  int i;
  double *farea;
  double slope, scale, b;
  int size_x, size_y;
  int len, err, bin_len;
  int rgt_side, left_side;
  int center;
  int numcycles=0;
  double *Freq=NULL;
  double *disp=NULL;
  double *ref_lut;
  double off, R2;
  int center_x, center_y, new_x, new_y;
  int lowest_val, highest_val, grey_level, first, last;
  int piv_err;

  TIFF* tif = NULL;

#if !defined(MSDOS)
  char *fnamep;
  fnamep = dirname(argv[0]);
  if (argc==1 && fnamep != NULL && fnamep[0] == '/') {
    printf ("Changed to directory of executable:  %s\n\n", fnamep);
    chdir((const char *)fnamep);
  }
#else
  atexit(wait_to_exit);
#endif

  /* Once-only initializations */
  g_scan_image_file_id = 0;
  g_problem_count = 0;                /* # of problems in our problem report */
  g_IQS_problem_count = 0;

  get_switches(argc, argv, image_filename, data_filename);              

  /* always append output to this file */
  if ((g_mtfout = fopen(MTFOUTNAME,"a")) == NULL) {
    fprintf(stderr,"Can't open %s\n",MTFOUTNAME);
    exit(1);
  }

  /* command line args */
  get_args(image_filename,data_filename,&tif); // 获取源文件名并读取文件头, 获取ROI位置, 如果需要读取计算角度的两个点位
 
  /* print the user entered data (corner coords, etc.) in the output */
  /* 时间, 版本号, 以及get_args函数里面获取到的信息*/
  print_header(image_filename,data_filename);

  g_target_res = 500;
  if (abs((int)g_ppi - g_target_res) > 10) {
    sprintf(problem_string,
	    "Resolution outside the %d-%d ppi PIV spec range\n",
	    g_target_res-10,g_target_res+10);
    put_problem(problem_string, IQS);
    put_problem("\n", IQS);
  }

  // 从ROI 4个角落各读取4个像素点, 用于判断刀口方向, 并确认ROI区域的合法性
  input_area(tif, &rotation, 
	     g_test_pattern_yul, g_test_pattern_ylr, 
	     g_test_pattern_xul, g_test_pattern_xlr);

  /* read the image in - we store it internally in a standard way */
  // 读取ROI图像, 如果并将水平刀口转换为垂直刀口
  read_in_image(tif,rotation,image_filename,&size_x,&size_y);

  /* get reflectance */
  // 创建反射查找表, 将图像灰阶映射在0~1范围内
  ref_lut = read_in_ref_lut(data_filename, &lowest_val, &highest_val);

  // 将原图ROI映射到反射ROI
  len = size_x*size_y;
  farea = (double *)malloc(len*sizeof(double));
  for(i=0; i highest_val) {
      MTFPRINT("ERROR: OECF range does not cover the entire image\n")
      MTFPRINT2("       Greylevel %d found in image, but not OECF\n", grey_level)
      exit(-1);
    }
    farea[i] = (double)ref_lut[grey_level];
  }

  if(g_autorefine) {   
    find_area(farea, (unsigned short)size_x, (unsigned short)size_y, &new_x, &new_y, ¢er_x, ¢er_y, g_extended);
    if (new_x != size_x || new_y != size_y ||
	center_x != size_x/2  || center_y != size_y/2) {
      center_x += (g_test_pattern_xlr + g_test_pattern_xul)/2 - size_x/2;
      center_y += (g_test_pattern_ylr + g_test_pattern_yul)/2 - size_y/2;
      g_test_pattern_xul = center_x - new_x/2;
      g_test_pattern_yul = center_y - new_y/2;
      g_test_pattern_xlr = g_test_pattern_xul + new_x;
      g_test_pattern_ylr = g_test_pattern_yul + new_y;
      read_in_image(tif,rotation,image_filename,&size_x,&size_y);
      len = size_x*size_y;
      for(i=0; i= size_x-2 ) {
      MTFPRINT("** ERROR: User specified edge does not work with ROI **\n");
      if (off-fslope < 2)
	MTFPRINT3("Edge Angle = %.3f  degrees    located %d pixels before ROI\n",
              (atan(slope)*(double)(180.0/M_PI)), (int)rint(off))  
      else
	MTFPRINT3("Edge Angle = %.3f  degrees    located %d pixels after ROI\n",
              (atan(slope)*(double)(180.0/M_PI)), (int)rint(off-size_x))  
      if (g_debug) {
	MTFPRINT("See location of edge points in diagnostic image\n")
	write_debug_image(g_debug_array,g_debug_fullwidth, g_debug_fullheight);
      }
      exit(-1);
    }
  }  

  // 计算ROI中超出取值范围[0, 255]外的像素比例
  // 前面像素映射的时候已经逐点确认过是否所有像素在oecf范围内, 感觉这个函数没什么实际作用
  clipping (0, 255, 0.02, g_image_array, len);

  /* calculate the sfr on this area */
  err = sfrProc(&Freq, &disp, &bin_len, farea, (unsigned short)size_x, &size_y, &slope, &numcycles,¢er,&off, &R2, g_version, 0, g_userangle);

  /* Add messages to problem report */
  slope_bounds( slope, size_y, numcycles, 5.0, problem_string);

  if(g_debug) {
    draw_lines(g_debug_array, slope, rotation, center, size_y, off, size_x);
    write_debug_image(g_debug_array,g_debug_fullwidth, g_debug_fullheight);
  }

  if (!g_userangle)
    MTFPRINT2("R2 of linear edge fit = %.3f\n", R2)
  else 
    MTFPRINT("User input edge location: No R2 available\n")
  MTFPRINT4("Edge Angle = %.3f  degrees  \nCycle Length = %.3f  \t#Cycles = %d\n",
              (atan(slope)*(double)(180.0/M_PI)), fabs(1.0/slope), numcycles )  

  left_side = size_x/2+off;  rgt_side = size_x/2-off;
  if (left_side > bin_len/4) left_side = bin_len/4;
  if (rgt_side > bin_len/4) rgt_side = bin_len/4;

  MTFPRINT2("SFR computed using ~%d pixels on left or top side of the edge,\n", left_side)
  MTFPRINT2("               and ~%d pixels on right or bottom side of the edge,\n", rgt_side)
  MTFPRINT("              all within the ROI\n")
  if (rotation == RIGHT)
    MTFPRINT3("    over %d rows, centered at row %d\n", size_y, (g_test_pattern_yul + g_test_pattern_ylr)/2 )
  else
    MTFPRINT3("    over %d cols, centered at col %d\n", size_y, (g_test_pattern_xul + g_test_pattern_xlr)/2 )

  if (center/4 < 16) {
    MTFPRINT("\nERROR: Too few pixels across the edge for valid SFR computation\n\n")
    exit(-1);
  }
  if ( left_side < 20 || rgt_side < 20) 
    MTFPRINT("Warning: Low width across the edge. SFR values may be suspect.\n")

  /* log any problems we encountered into output */
  if (g_reversepolarity)
    MTFPRINT("\nNOTE: Original image polarity was reversed by user request.\n")

  if (err) {
    MTFPRINT ("** ERROR in computation. SFR values unknown **\n\n")
      exit(-1);
  }

  scale = g_ppi/MM_PER_INCH;
  MTFPRINT("\n\ncy/mm         \t SFR  ")
  if(rotation == RIGHT)
    MTFPRINT("\t  Vert ")
  else
    MTFPRINT("\t  Horz ")
  if(farea[4*size_x-1] - farea[0] > 0) 
    MTFPRINT("black-to-white** edge\n(obj.plane)\n")
  else
    MTFPRINT("white-to-black** edge\n(obj.plane)\n")

  piv_err=0;
  for( i=0; i 0.5)
      MTFPRINT("\t#\n")    /* Mark frequencies above Nyquist */
    else {
      double lower = 1.02829 - 1.67473e-1*f + 1.06255e-2*f*f - 2.80874e-4*f*f*f;
      double upper = 1.12;
      if ((f<=10 && f >= 0.998) && (sfr < lower || sfr > upper)) {
	     if (g_nocompare)
	       MTFPRINT("\n")
	     else {
		   piv_err = 1;
	       MTFPRINT("\t*\n")    /* Mark out of PIV spec values */
	    }
        sprintf(problem_string,
                "Computed SFR at %.3f cy/mm is outside PIV spec range of %.3f - %.2f\n",
		  f,lower,upper);
        put_problem(problem_string, IQS);
      }
      else MTFPRINT("\n")
    }
  }

  MTFPRINT("\n#  Frequencies above Nyquist\n") 
  if (piv_err)
    MTFPRINT("\n*  SFR is outside PIV spec.  See problem report for details.\n")
  first = reverse_lut(ref_lut, farea[0], lowest_val, highest_val); 
  last = reverse_lut(ref_lut, farea[4*size_x-1], lowest_val, highest_val); 
  if (rotation == RIGHT) {
    MTFPRINT2("** Edge type based on leftside gray level (%d)\n", first)
    MTFPRINT2("    and rightside gray level (%d)\n", last)
  }
  else {
    MTFPRINT2("** Edge type based on top gray level (%d)\n", first)
    MTFPRINT2("    and bottom gray level (%d)\n", last)
  }
  MTFPRINT("    If type isn't correct, use 'f' option to adjust polarity\n\n")

  print_problems();

  if (g_extended){
    int offset, begin, end;
    int j, cnt;
    double threshold,max_edge,current;

    /* Derivatives below this value is considered insignificant for printing */
    max_edge = fabs(farea[4*size_x+bin_len]);
    threshold = max_edge / 25.0;

    /* Find 5 contiguous insignificant values first occur before center */
    offset = center - bin_len;
    j = bin_len;    cnt = 0;
    while (cnt < 5 && j>=0) {
      current = fabs(farea[4*size_x+j]);
      if ( current < threshold ) cnt ++;
      else cnt = 0;
      if (current > max_edge) max_edge = current;
      j--;
    }
    if (j<0) j=0;
    begin = j + offset;

    /* Find 5 contiguous insignificant values first occur after center */
    j = bin_len;    cnt = 0;
    while (cnt < 5 && j max_edge) max_edge = current;
      j++;
    }
    if (j==2*bin_len) j=2*bin_len-1;
    end = j + offset;

    if ( farea[4*size_x+bin_len] < 0 ) max_edge *= -1;


    MTFPRINT("\n\nPixel+ \t\t LSF_w \t\t AvgESF")
    if (g_version&4)
	MTFPRINT(" \t \n")
    else
	MTFPRINT("(with -0.125 offset)\n")

    for( i=begin, j=begin-offset; i<0; j++, i++)
	MTFPRINT3("% .2f \t\t% f\n", (i-center)/4.0,  farea[4*size_x + j]/max_edge)

    for( ; i

 

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