图像解析力算法—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)
 
 

 
 
  1. unsigned long i, j;
  2. double dt, dt1, dt2;
  3. /* Compute the first difference on each line. Interpolate to find the
  4. centroid of the first derivatives. */
  5. //计算差分 计算矩心位置
  6. for (j = 0; j < size_y; j++) {
  7. dt = 0.0;
  8. dt1 = 0.0;
  9. for (i = 0; i < size_x -1; i++) {
  10. dt2 = farea[(j*( long)size_x)+(i+ 1)] - farea[(j*( long)size_x)+i];
  11. dt += dt2 * ( double)i;
  12. dt1 += dt2;
  13. }
  14. shifts[j] = dt / dt1;
  15. printf( "=========\n");
  16. printf( "%f\n", shifts[j]);
  17. }
  18. /* check again to be sure we aren't too close to an edge on the corners.
  19. If the black to white transition is closer than 2 pixels from either
  20. side of the data box, return an error of 5; the calling program will
  21. display an error message (the same one as if there were not a difference
  22. between the left and right sides of the box ) */
  23. if (shifts[size_y -1] < 2 || size_x - shifts[size_y -1] < 2) {
  24. fprintf( stderr, "** WARNING: Edge comes too close to the ROI corners.\n");
  25. // return 5;
  26. }
  27. //防止矩心过于靠近图像的边界
  28. if (shifts[ 0] < 2 || size_x - shifts[ 0] < 2){
  29. fprintf( stderr, "** WARNING: Edge comes too close to the ROI corners.\n");
  30. // return 5;
  31. }
  32. /* Reference rows to the vertical centre of the data box */
  33. j = size_y/ 2;
  34. dt = shifts[j];
  35. for (i = 0; i < size_y; i++) {
  36. temp[i] = ( double)i - ( double)j;
  37. shifts[i] -= dt;
  38. }
  39. *offset = dt;

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


 
 
  1. unsigned short fit(unsigned long ndata, double *x, double *y, double *b,
  2. double *a, double *R2, double *avar, double *bvar)
  3. {
  4. unsigned long i;
  5. double t,sxoss,syoss,sx= 0.0,sy= 0.0,st2= 0.0;
  6. double ss,sst,sigdat,chi2,siga,sigb;
  7. *b= 0.0;
  8. for ( i= 0; i < ndata; i++ ) {
  9. sx += x[i]; //x的叠加
  10. sy += y[i]; //y的叠加
  11. }
  12. //求平均值
  13. ss=( double)ndata;
  14. sxoss=sx/ss;
  15. syoss=sy/ss;
  16. for ( i= 0; i < ndata; i++ ) {
  17. t = x[i] - sxoss; //
  18. st2 += t*t; //方差
  19. *b += t * y[i];
  20. }
  21. *b /= st2; /* slope */ //斜率
  22. *a =(sy-sx*(*b))/ss; /* intercept */ //截距
  23. siga= sqrt(( 1.0+sx*sx/(ss*st2))/ss);
  24. sigb= sqrt( 1.0/st2);
  25. chi2= 0.0;
  26. sst= 0.0;
  27. for (i= 0; i < ndata; i++) {
  28. chi2 += SQR( y[i] - (*a) - (*b) * x[i]);
  29. sst += SQR( y[i] - syoss);
  30. }
  31. sigdat= sqrt(chi2/(ndata -2));
  32. siga *= sigdat;
  33. sigb *= sigdat;
  34. *R2 = 1.0 - chi2/sst; //拟合程度
  35. *avar = siga;
  36. *bvar = sigb;
  37. return 0;
  38. }

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


 
 
  1. unsigned short bin_to_regular_xgrid(unsigned short alpha,//alpha->指的是超取样的倍数
  2. double *edgex, double *Signal,
  3. double *AveEdge, long *counts,
  4. unsigned short size_x,
  5. unsigned short size_y)
  6. {
  7. long i, j, k,bin_number;
  8. long bin_len;
  9. int nzeros;
  10. bin_len = size_x * alpha; //扩大四倍
  11. for (i= 0; i<bin_len; i++) {
  12. AveEdge[i] = 0;
  13. counts[i] = 0;
  14. }
  15. for (i= 0; i<(size_x*( long)size_y); i++) {
  16. bin_number = ( long) floor(( double)alpha*edgex[i]); //向下取整
  17. if (bin_number >= 0) {
  18. if (bin_number <= (bin_len - 1) ) {
  19. AveEdge[bin_number] = AveEdge[bin_number] + Signal[i]; //把每一行的距离边缘x轴一样远的信号相加
  20. counts[bin_number] = (counts[bin_number])+ 1; //记录下对应位置有多少个信号相加
  21. }
  22. }
  23. }
  24. nzeros = 0;
  25. for (i= 0; i<bin_len; i++) {
  26. j = 0;
  27. k = 1;
  28. //感觉写的有点复杂
  29. if (counts[i] == 0) {
  30. nzeros++; //记录有多少个位置是空的,即没有信号
  31. //K的作用:因为这里的信号为0,找到后面第一个不为零的值,赋给当前这个零
  32. if (i == 0) {
  33. while (!j) { //当j==0时,表示此处的信号为0
  34. if (counts[i+k] != 0) { //第一行的元素
  35. AveEdge[i] = AveEdge[i+k]/(( double) counts[i+k]);
  36. j = 1; //充当flag。。。为啥不用布尔类型
  37. }
  38. else k++; //直到找到第一个不为零的数字才会停止
  39. }
  40. } else {
  41. while (!j && ((i-k) >= 0) ) { //j==0&&i-k>=0 j==0说明 counts[i]是0 i-k>0说明 k在i前面,找前面不为零的数值赋给AveEdge[i]
  42. if ( counts[i-k] != 0) {
  43. AveEdge[i] = AveEdge[i-k]; /* Don't divide by counts since it already happened in previous iteration */
  44. j = 1;
  45. }
  46. else k++;
  47. }
  48. if ( (i-k) < 0 ) { //k>i,其实联合上面那段,就是:此处的counts[i]累加次数为零,所以AveEdge[i]也就是0,所以要找到附近一个不为零的值赋给AveEdge[i]
  49. k = 1;
  50. while (!j) {
  51. if (counts[i+k] != 0) {
  52. AveEdge[i] = AveEdge[i+k]/(( double) counts[i+k]);
  53. j = 1;
  54. }
  55. else k++;
  56. }
  57. }
  58. }
  59. }
  60. else
  61. AveEdge[i] = (AveEdge[i])/ (( double) counts[i]); //如果此处不为零,直接就求个平均值
  62. }
  63. if (nzeros > 0) { //提示信息
  64. fprintf( stderr, "\nWARNING: %d Zero counts found during projection binning.\n", nzeros);
  65. fprintf( stderr, "The edge angle may be large, or you may need more lines of data.\n\n");
  66. }
  67. return nzeros;
  68. }

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

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值