立体匹配中图像重叠分块的实现方法

本文分三部分:

1. 图像直接分块的问题;

2. 图像重叠分块的实现原理介绍;

3. 立体匹配中的图像重叠分块的方法介绍;

1. 图像直接分块的问题

由于内存的限制或为了实现并行处理,对图像进行分块处理是必要的。如果仅仅对图像进行分块处理,然后把处理的图像块进行简单的拼接,容易导致界边处缝的问题(如下图所示)。所以,需要在图像分块时使得相邻图像块有一定的重叠,然后选择最优的处理结果填充重叠区域,从而消除接边缝。

   

图 1. 左图为直接分块处理结果,右图为重叠分块处理结果

2. 图像重叠分块的实现原理介绍


图 2. 图像分块原理示意图

如上图所示,图像重叠分块时,有三个Block,三个Position和一个Principle:

三个Block是:起始Block,中间Block和边缘Block;

三个Position是:Block在原始图像的读取和写入位置,处理结果有效内容在Block自身的位置;

一个 Principle是:各个Block处理结果的有效部分应该保持保持无缝连接;

基于以上思路,我们列出图像分块时的几个关键参数:

图像纵向块数:m_Tile = (height-BLOCKOVERLAP_Y-1)/(BLOCKHEIGHT-2*BLOCKOVERLAP_Y)+1

图像横向块数:nTile = (width-BLOCKOVERLAP_X-1)/(BLOCKWIDTH-2*BLOCKOVERLAP_X)+1

其中,width和height为原始图像的宽高,BLOCKWIDTH和BLOCKHEIGHT为图像块的宽高,BLOCKOVERLAP_X和BLOCKOVERLAP_Y为图像块横向和纵向的重叠尺寸。因为横向和纵向的公式是完全类似的,为了简便起见,下面我们用size,BLOCK,OVERLAP来相应代替上面的三个量。

图像重叠分块参数表

i_Read i_Write i_Offset
1st 0 0 0
Middle i*(BLOCK-2*OVERLAP) i_Read+OVERLAP OVERLAP
Last size-BLOCK (i+1)*BLOCK-(2*i-1)*OVERLAP-size (i+1)*BLOCK-(2*i-1)*OVERLAP-size

上面的表中还有一项i_Offset表示的是Block处理结果的有效内容的起始位置,在写入图像时,要从Block的此位置开始读取内容并写入原始图像从i_Write开始的内存中。

3. 立体匹配中的图像重叠分块的方法介绍

立体匹配中使用分块处理的方法和一般的图像处理的分块方法不同,因为Block之间的对应需要一个初始的视差来驱动,否则可能导致图像块之间没有很好的重叠(如图3所示)。


图 3. 无初始视差驱动的航空影像分块处理

所以,如果有初始视差图来驱动,就可以很好地实现影像分块,而且这时不仅可以解除内存限制或者实现并行处理,还可以减小每个图像块的视差搜索范围,因此最终还有可能减少误匹配率。

基于此方法,立体匹配的分块处理方法框架如下:

	int mTile = (height-BLOCKOVERLAP_Y-1)/(BLOCKHEIGHT-2*BLOCKOVERLAP_Y)+1;
	int nTile = (width-BLOCKOVERLAP_X-1)/(BLOCKWIDTH-2*BLOCKOVERLAP_X)+1;

	for (int m=0;m<mTile;m++)
	{

		int m_index= m*(BLOCKHEIGHT-2*BLOCKOVERLAP_Y);
		int m_offset = BLOCKOVERLAP_Y;
		int m_write = m_index+BLOCKOVERLAP_Y;
		if (m==0)
		{
			m_offset = 0;
			m_write = 0;
		}
		else if (m == mTile-1)
		{
			m_index = height-BLOCKHEIGHT;
			m_offset = (m+1)*BLOCKHEIGHT-(2*m-1)*BLOCKOVERLAP_Y-height;
			m_write = m*BLOCKHEIGHT-(2*m-1)*BLOCKOVERLAP_Y;
		}

		for (int n=0;n<nTile;n++)
		{
			int n_index = n*(BLOCKWIDTH-2*BLOCKOVERLAP_X);
			int n_offset=BLOCKOVERLAP_X;
			int n_write = n_index+BLOCKOVERLAP_X;

			if (n==0)
			{
				n_offset = 0;
				n_write = 0;
			}
			else if (n == nTile-1)
			{
				n_index = width-BLOCKWIDTH;
				n_offset = (n+1)*BLOCKWIDTH-(2*n-1)*BLOCKOVERLAP_X-width;
				n_write = n*BLOCKWIDTH-(2*n-1)*BLOCKOVERLAP_X;
			}
			CopyImgData(n_index,m_index,width,height,0,0,BLOCKWIDTH,BLOCKHEIGHT);
			//计算整体视差平移量
			int AvgBlockDisp = 0;
			int num_disp = BLOCKWIDTH*BLOCKHEIGHT;
			for (int i=0;i<num_disp;i++)
			{

				AvgBlockDisp += dm->disparity[i];

			}
			AvgBlockDisp /= num_disp;
			int n_index_refer = n_index+AvgBlockDisp;

			CopyImgData(bufl_block,bufl,n_index_refer,m_index,width,height,0,0,BLOCKWIDTH,BLOCKHEIGHT);
			CopyImgData(bufr_block,bufr,n_index,m_index,width,height,0,0,BLOCKWIDTH,BLOCKHEIGHT);

			Match();

			//还原到原始视差范围
			for (int i=0;i<BLOCKHEIGHT;i++)
			{
				for (int j=0;j<BLOCKWIDTH;j++)
				{ 
					dm->disparity[i*BLOCKWIDTH+j] += AvgBlockDisp;
				}
			}
			//写入到内存
			CopyImgData(n_offset,m_offset,BLOCKWIDTH,BLOCKHEIGHT,n_write,m_write,width,height);
			CopyImgData(n_offset,m_offset,BLOCKWIDTH,BLOCKHEIGHT,n_write,m_write,width,height);
		}
	}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章