在下例中,关键字restrict的使用告知编译器func中指针a和b所指向的存储器范围不会交迭,这表明通过指针变量a和b对存储器的访问不会冲突,即对一个指针变量的写操作不会影响另外一个指针变量的读操作。
例:void func(int *restrict a,int *restrict b)
{
/*func’s code here*/
}
(4)program伪指令MUST_ITERATE
对于循环,应尽量使用MUST_ITERATE program,这条指令告知编译器准确的循环次数,消除冗余循环,有助于编译器实现最佳的循环(即软件流水和嵌套循环转化),也有助于减小代码尺寸。
在C和C++中MUST_ITERATE的语法:
#program MUST_ITERATE(min,max,multiple);
参数min和max是最小和最大执行次数,循环次数必须是multiple的整数倍。例如
#program MUST_ITERATE(5,25,5);表示循环执行次数5到25之间,并且为5的倍数;
#program MUST_ITERATE(10,10);表示循环执行次数为10。
(5)利用以上方法优化算法中的一个函数
float x1,y1,x2,y2;
void p(int *restrict pre,int *restrict now,int *restrict out)
{
int i;
#pragma MUST_ITERATE(256*256,256*256);
for(i=0;i<256*256;i++)
{
x1=(float)pre[2*i];
y1=(float)pre[2*i+1];
x2=(float)now[2*i];
y2=(float)now[2*i+1];
out[2*i]=(int)(1000.0*(x1*x2+y1*y2)*(_rsqrsp(1.0*(x1*x2-y1*y2)*(x1*x2-y1*y2)+1.0*(x1*y2+y1*x2)*(x1*y2+y1*x2))));
out[2*i+1]=(int)(1000.0*(y1*x2-x1*y2)*(_rsqrsp(1.0*(x1*x2-y1*y2)*(x1*x2-y1*y2)+1.0*(x1*y2+y1*x2)*(x1*y2+y1*x2))));
}
}
6 算法的运行结果
为了更好的看出配准的效果,我们编写了一个小程序,这个程序的功能是:通过计算出的偏移量,在前一幅图像的基础上,将后一幅图像偏移出的场景拼接到前一幅图像上,通过拼接处的拟合度来判断配准结果是否准确。
6.1 两幅图像进行配准的结果
以一个场景为目标,通过两个一模一样的摄像头采集出有一定位置平移的图像,采集多个场景,并以两副图像一组进行配准.
每组图像都给出两幅图像、图像的频谱图、拼接后的图像、偏移量矩阵的峰值以及它们的偏移量。
(1)一组浓密树叶的场景
峰值:0.100909 偏移量:(-27,28)
(2)树丛后的小路和围墙
峰值:0.130111 偏移量:(-30,28)
(3)开阔楼房
峰值:0.077882 偏移量:(-32,28)
(4)比较模糊的远景
峰值:0.027617 偏移量:(-36,28)
(5)有污点噪声的两幅图像
峰值:0.030447 偏移量:(115,16)
以上例子每组中的两幅图像都是由两个相同焦距不同光圈的传感器采集的,所以两幅图像的亮度存在一定差异,但是任然能准确的配准出来。根据原理不难发现,图像亮度的变化只是影响其频谱域的低频部分,高频部分记录信息,没有影响。所以明暗程度的变化也只影响到互功率谱的低频部分,当互功率谱进行逆变换时,峰值的位置不会变,变化的只是峰值大小。由此可见,明暗变化不影响配准的效果。
根据算法原理,理论上来讲,峰值应该为正无穷大,但是由于两幅图像是离散有界的,除了共同存在的平移场景外,其余部分全部算作噪声,并且传感器本身就存在一定的盲点,以及镜头上存在的一些污点,综合所有峰值便与理论值有了一定的差距,但是配准点的位置和原本冲激函数的峰值点的位置是基本一样的。如果不一样,那么就表示配准失败了。 基于DSP实现的移动场景的相位配准(11):http://www.751com.cn/wuli/lunwen_1614.html