当前背景噪声的计算方法
执行一次数据采集,以进行FFT计算和相关目标检测及航迹处理的过程,称为一次完整的数据处理过程,相应的数据称为一帧.这里讨论动态计算每一帧中某一点的背景噪声的计算方法及执行效率.
参考下图进行解释说明.当前想要计算第9个点(关注数据点)附近的背景噪声,背景保护单元宽度为2(图中的第7-8, 10-11点),背景计算单元为5(图中的第2-6,12-16点).
第9个点的背景噪声值将由第2-6点,12-16点这左右对称的两组数据计算出来,例如取这两组数据之和的均值,或者取左右两组数据均值的较小值(或较大值).
背景保护单元内的数据将不用于计算被关注数据点的背景噪声,背景保护单元的大小受到产品的波形,配置参数,目标大小等多个因素的影响.
如果关注数据点较小,它左侧用于计算的背景单元数量不足指定的数据量时,仅依据它右侧的背景数据计算背景值;关注数据点较大,当它右侧用于计算的背景单元数量不足指定的数据量时,仅依据它左侧的背景数据计算背景值.
算法实现及改进
现有的实现方式
当计算某一个关注点的背景噪声时,分别求取它左侧和右侧的背景值的和,按照相关逻辑取得背景噪声值.例如想要计算第9个点的背景噪声,那么取一个变量,它等于第2~6点的数据值之和,取另一个变量,它等于第12~16点的数据值之和.然后这两个值之和除以10,即得到第9点的背景噪声值.
该方法的缺点是:每一个点的噪声值计算时,都需要在关注数据点的左右两侧分别做求和运算,求和的次数等于背景计算单元的宽度(例如这里等于5).一般我们需要按照顺序依次将所有的点作为关注数据点,设背景计算单元个数为BGCNT,数据总长度为DATAN,则总的求和次数大约为:
ADD_TIMES = 2×BGCNT×DATAN.
当BGCNT较大时(例如16/32),求和次数将按照线性递增.
改进的实现方式
系统维持两个变量,分别记录当前关注数据点的左侧背景噪声之和与右侧背景噪声之和.当向右移动关注数据点时,这两个背景噪声分别减去他们左侧已有的背景数据,增加右侧新的背景数据.相当于在数据排列的轴向上,指定的关注数据点两侧放置两个滑动窗口,这两个背景噪声和将依据窗口的滑动而增加或减少窗口内的边界噪声.
例如当前关注数据点为9,系统已经存有左侧窗口之和(2~6点数据噪声之和),和右侧窗口之和(12~16点数据噪声之和),现在想要改变关注数据点为10,那么它的左侧窗口之和将减去第2点的数据值,增加第7点的噪声值,它的右侧窗口之和将减去第12点的数据值,增加17点的数据值.这样就求得了第10点的左右噪声值.总的求和次数(含减法计算)大约为:
ADD_TIMES = 2×2×DATAN.
总的求和次数不会随背景单元个数而变化.
缺点:由于系统需要维护左右两个窗口的噪声值,所以不能随意指定关注数据点.一般的,按照顺序依次计算各个数据点的背景噪声,可完全满足现在的需求.
性能对比
使用以上两种方式分别对DATAN=512的浮点型数据(往往他们是原始AD数据经FFT处理之后的,这里是取随机数得到的)依次计算各个数据点的背景噪声,执行10000遍(在VS2010平台仿真).依据不同的背景单元个数,他们的耗时时长可绘制如下曲线:
由以上曲线可知,使用旧的实现方式,在背景单元个数小于4时,执行效率更高;大于等于4后,新的实现方式优势明显,且背景计算单元越多,优势约明显.
结论
一般的,背景单元个数达到或超过4个,采用新的实现方式,可提高执行效率,尤其在背景单元个数超过10个之后,新的实现方式优势巨大.当特殊情形下,我们设定的背景单元个数小于4个,那么可选择旧的实现方式.
附(代码)
1 /*---------------------------------------------------------------------------------------------------- 2 ----------------------------------------------------------------------------------------------------*/ 3 #define FFTN 512 4 int MC_bg_cnt_wid=6; //背景单元个数. 5 #define MC_bg_prot_wid 3 //背景保护单元个数. 6 float dbuf[FFTN]={0.0}; 7 8 typedef struct{ 9 int cursn; 10 float lsum;//left sum val; 11 float rsum;//right sum val; 12 }ST_BG; 13 ST_BG g_bg={0, 0.0, 0.0}; 14 15 /*---------------------------------------------------------------------------------------------------- 16 使用新的方法计算背景噪声. 17 ----------------------------------------------------------------------------------------------------*/ 18 float ComputeBg(int sn, float *datain) 19 { 20 int i, j, k, cursn, index; 21 float ret; 22 23 if(sn >= FFTN) 24 { return 0.0; // err! 25 } 26 if(0 == sn) 27 { 28 g_bg.cursn = 0; 29 g_bg.lsum = 0.0; 30 g_bg.rsum = 0.0; 31 32 for(i=1; i<=MC_bg_cnt_wid; i++) 33 { 34 g_bg.rsum += datain[MC_bg_prot_wid+i]; 35 } 36 } 37 38 while(g_bg.cursn < sn) 39 { 40 cursn = g_bg.cursn+1; 41 42 index = cursn-MC_bg_prot_wid-MC_bg_cnt_wid-1; 43 if(index>=0) 44 { g_bg.lsum -= datain[index]; 45 } 46 47 index = cursn-MC_bg_prot_wid-1; 48 if((index<FFTN)&&(index>=0)) 49 { g_bg.lsum += datain[index]; 50 } 51 52 index = cursn+MC_bg_prot_wid; 53 if(index < FFTN) 54 { g_bg.rsum -= datain[cursn+MC_bg_prot_wid]; 55 } 56 57 index = cursn+MC_bg_prot_wid+MC_bg_cnt_wid; 58 if(index < FFTN) 59 { g_bg.rsum += datain[index]; 60 } 61 g_bg.cursn ++; 62 } 63 64 if(sn < MC_bg_prot_wid+MC_bg_cnt_wid) 65 {//关注数据点较小,仅取右侧噪声. 66 ret = g_bg.rsum/MC_bg_cnt_wid; 67 } 68 else if(sn < FFTN-(MC_bg_prot_wid+MC_bg_cnt_wid)) 69 { 70 ret = (g_bg.lsum+g_bg.rsum)/(2*MC_bg_cnt_wid); 71 } 72 else if(sn < FFTN) 73 {//关注数据点较大,仅取左侧噪声. 74 ret = g_bg.lsum/MC_bg_cnt_wid; 75 } 76 else 77 { ret = 0.0; 78 } 79 return ret; 80 } 81 82 /*---------------------------------------------------------------------------------------------------- 83 使用旧的方式计算背景噪声. 84 ----------------------------------------------------------------------------------------------------*/ 85 float ComputeBg_old(int sn, float *datain) 86 { 87 int i, j, k; 88 float lsum=0.0, rsum=0.0; 89 float ret; 90 91 if(sn >= FFTN) 92 { 93 return 0.0; // err! 94 } 95 96 if(sn < MC_bg_prot_wid+MC_bg_cnt_wid) 97 {//仅计算右侧背景噪声. 98 for(i=0; i<MC_bg_cnt_wid; i++) 99 { 100 rsum += datain[sn+MC_bg_prot_wid+i+1]; 101 } 102 ret = g_bg.rsum/MC_bg_cnt_wid; 103 } 104 else if(sn < FFTN-(MC_bg_prot_wid+MC_bg_cnt_wid)) 105 { 106 for(i=0; i<MC_bg_cnt_wid; i++) 107 { 108 rsum += datain[sn+MC_bg_prot_wid+i+1]; 109 lsum += datain[sn-MC_bg_prot_wid-MC_bg_cnt_wid+i]; 110 } 111 ret = (lsum+rsum)/(2*MC_bg_cnt_wid); 112 } 113 else if(sn < FFTN) 114 {//仅计算左侧背景噪声. 115 for(i=0; i<MC_bg_cnt_wid; i++) 116 { 117 lsum += datain[sn-MC_bg_prot_wid-MC_bg_cnt_wid+i]; 118 } 119 ret = (lsum)/(MC_bg_cnt_wid); 120 } 121 else 122 { ret = 0.0; 123 } 124 return ret; 125 } 126 #define REDOTIMES 10000 //重复执行次数. 127 /*---------------------------------------------------------------------------------------------------- 128 ----------------------------------------------------------------------------------------------------*/ 129 void CTestvc1Dlg::OnBnClickedButton1() 130 { 131 int i, j, k=0; 132 float fv, fv2; 133 long timespan; 134 time_t time0,time1, time2; 135 136 UpdateData(true);//MFC工程更新输入的变量 137 MC_bg_cnt_wid = m_edit_bg_cnt;//用户通过MFC编辑框指定背景单元个数. 138 139 time0 = GetTickCount(); 140 srand(time0&0xffff); //随机数种子 141 for(i=0; i<FFTN; i++) 142 { 143 dbuf[i] = ((float)rand())/100.0;//获取随机数. 144 } 145 time0 = GetTickCount(); 146 for(j=0; j<REDOTIMES; j++) 147 { 148 for(i=0; i<FFTN; i++) 149 { 150 fv = ComputeBg(i, dbuf); //使用新方法计算背景噪声. 151 } 152 } 153 time1 = GetTickCount(); 154 for(j=0; j<REDOTIMES; j++) 155 { 156 for(i=0; i<FFTN; i++) 157 { 158 fv2 = ComputeBg_old(i, dbuf);//使用旧方法计算背景噪声. 159 } 160 } 161 time2 = GetTickCount(); 162 m_edit_new_time = (long)(time1-time0);//新方法耗时时长. 163 m_edit_old_time = (long)(time2-time1);//旧方法耗时时长. 164 fv = ((float)(time1-time0))/((float)(time2-time1)); 165 m_edit_n = (int)(fv*100);//新方法耗时相对于旧方法的百分比. 166 m_edit_cnt++; 167 UpdateData(false); 168 }