图像の球面投影算法

本文转载至http://ms.csdn.net/share/8C5E2CDC87DCF73D4291595BD94A9642_1_IPHONE_APP.


关于图像的球面投影,是全景应用中比较常见的技术,而现有的一些资源大多写的不太好,比较晦涩。在经过一段时间的摸索之后,发现了这个博客写的相对可以,本文的实现也将其作为重要的参考,如果看过本文之后有什么不明白或者觉得不好的地方可以去看看。

    在展开本文之前,先来看看下面的两张图片:

图像の球面投影算法_第1张图片   图像の球面投影算法_第2张图片

    左边的图像被投影到球面上后,其正视图为右边的图像。而我们要研究的是,如何去投影的过程。

    可以想象,左边的图像是一张极薄的纱,将其蒙到一个大小正好的球面上(薄纱过中点的横轴正好覆盖球赤道的半周),然后正看过去会怎么样。我们将看到一个接近于上面右边图像的图像。为什么说接近而不说相同呢,因为大小是不一样的。左边图像的赤道如果刚刚好覆盖掉球的半个平面,则球的周长将为左边图像的宽度的两倍。假定左边图像的宽度为W,而球的半径为R,则有

    πR=W

    所以球的正视图的球直径应该为

    2R=2*W/π

    即球的正视图不会触碰到图像边缘,而为了我们看起来舒服一点,我们希望球的正视图刚刚好就触碰到图像边缘,是故球做完投影之后其正视图需要做一个等比例的放大,该放大系数为π/2。经过放大,我们就得到了右边的图像。之后,我们把放大系数设为k。

    下面我们正式进入图像投影的研究,还是遵循上面的设想,把左边图像设想成一张极薄的纱,然后将其蒙到一个大小正好的球面上。那么,左边图像的中点将是右边图像的中点,也就是球正面顶点的位置。

    接着,我们将图像的中心点记为点0,然后在左图像上随便取一个点即为点A,假设点A是落在过中点的横轴上的,很容易想象经过投影后A也将落在右图过中心点的赤道上。进一步想,左图绕中心旋转一个角度之后,原来不在过中点的横轴上的点可能变为其上的点,相应的该点的投影也会落在右图过中心点的赤道上。也就是说,图像上的任意一点经过投影之后,将落在原图与中心点连线的线上。接着我们沿着连线切下将得到下面的切面:

图像の球面投影算法_第3张图片

    这便是这篇文章推导的关键,其中最为关键的是弧长等于OA*k这句话(由上面的薄纱模型很容易得出该弧为左图中的OA经过弯曲而来,长度自然相同,而*k是因为图像经过了放大),有了上面这些条件,我们可以列出以下这些公式:

图像の球面投影算法_第4张图片

    推导到最后我们可以看到原图像坐标(X,Y)和投影后图像坐标(X',Y')的换算关系,其跟上面提到的博客最大不同的地方是将X,Y写在左边而X',Y'写在右边。在本人看来,这样才是合理的,因为后面我们需要去原图像找到对应的像素点取像素值,而映射后图像遍历时坐标是知道的,应该为已知条件。详细的可参考我之前写过的 C/C++ BMP(24位真彩色)图像处理(3)------图像の放大缩小(双线性插值)。

    OK,到这里推导过程就全部结束了,按照上面的公式便可完成图像的映射。经过本人的测试,如果每次直接这样算效率是比较低的,所以后来本人改由查表法来完成上面的工作,这份工程和可执行程序都已经打包在一起上传了(由于是X64编译的,需要电脑是64位操作系统才可以运行,如果是32位的则可通过修改工程解决,工程利用OpenCV进行解码,需要自行配置,否则无法运行),如果有兴趣的可以去下载。

你可能感兴趣的:(球面投影)