在前面的文章中,我们已经分析了SFR的算法原理与步骤,下面我们直接来分析源码,源码中主要的函数主要分为一下几个:
1、locate_centroids作用:定位每一行像素的矩心位置
C++
unsigned short locate_centroids(double *farea, double *temp,
double *shifts,unsigned short size_x, unsigned short size_y,double *offset)
C++
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函数的结果,利用最小二乘法进行拟合,得到一条拟合后的质心直线。
C++
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
C++
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,转载请注明出处!讨论可扫码加群:


