分享

投影与三维视觉——矫正映射

 Y忍冬草 2016-11-01

/****************************************************************

转自:http://www./article/p-656561.html

***************************************************************/

从上一篇文章,我们知道cvStereoRectify()函数只是计算了校正需要的参数,并没有完成图像上实际的校正。

在本节将介绍两个函数:

cvInitUndistortRectifyMap()函数来计算左右视图的校正查找映射表mapx,mapy。

cvRemap()函数利用查找映射表和插值算法实现将输入图像的重投影,从而得到校正后图像。

为了理解下面的话,我们将书上图附上:


图12-11:立体校正。对左右摄像机而言,(a)原始图像(b)非畸变化(c)校正(d)最后裁切成两幅图像间的重叠区域。校正实际上是右(c)到(a)的反过程。

对任何图像到图像的映射函数,由于目标位置是浮点型的缘故,正向映射(即根据原始图像上的点计算其到目标图像上的点),不会命中目标图像对应的像素位置。

为了理解上面的话,我们引入OpenCV中cvRemap函数中的解释:

例如,我们可以说像素的位于(20,17)位置,当这些整数位置映射到新的图像中,可能会有一些差异——源图像中像素中的像素位置是整形的而目标图像是浮点型的,就必须将其四舍五入到最相近的整型,因为可能映射后的位置完全就是没有像素的(联想一下通过拉伸图像扩大两倍,其他的每个目标像素将是空白)。这个问题一般被称为正向投影问题。为了解决这些四舍五入和目标差异的问题,实际上我们可以反过来解决:通过目标图像中的每一个像素去问:“哪个像素需要来填充这个目标像素?“这些源像素的位置几乎都是小数(非整数),所以必须对这些像素进行插值以得到目标位置的正确值。


因此我们采用逆向映射:对目标图像上的每一个整形的像素位置,首先查找出其对应源图像上的浮点位置,然后利用周围源像素的每个整形值插值出新的值来


计算这样映射关系的实现函数cvInitUndistortRectifyMap()被调用两次,即分别求解左右原始图像到校正图像之间的映射查找表,声明如下:

1void cvInitUndistortRectifyMap(
2const CvMat* M,
3const CvMat* distCoeffs,
4const CvMat* Rrect,
5const CvMat* Mrect,
6CvArr* mapx,
7CvArr* mapy
8);
1、M,是3×3的摄像机内参数矩阵,校正前的。

2、disCoeffs,是5×1的摄像机畸变系数。

3、Rrect,是cvStereoRecify()函数输出的Rl或者Rr

4、Mrect是3×3的校正后的摄像机内参数矩阵,该矩阵是cvStereoRectify()计算得到投影矩阵P的前三列。

5、mapx,mapy,是函数返回的输出查找映射表。

(个人对查找表的理解:我们知道查找表的大小和目标图像一样,那么我们对于目标图像的每一个位置如(12,8),那么mapx和mapy存储着位于该处(即在mapx和mapy矩阵中也是(12,8)位置处)的源图像对应的x和y坐标位置,此时的在源图像中的坐标为浮点型,我们利用插值算法求解出该位置的像素值,然后将该像素值给目标图像的(12,8)位置的像素,要像正确理解,还需要深入的了解算法的操作流程,这里理解不免有误)。

利用计算得到查找映射表重投影图像的cvRemap()函数声明如下:

1void cvRemap(
2const CvArr* src,
3CvArr* dst,
4const CvArr* mapx,
5const CvArr* mapy,
6int flags = CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS,
7CvScalar fillval = cvScalarAll(0)
8);

cvRemap函数将一幅图像中一个位置的像素平滑的重映射到另一个位置。

1、src源图像

2、dst目标图像,源图像和目标图像必须大小和通道一致,数据类型可以任意。

3、mapx,mapy,为单通道,通常为IPL_DEPTH_32F浮点型数据,和源图像、目标图像有同样的大小,指明具体像素重新分别的位置。

4、flags,插值方法,默认采用双线性插值。

插值方法:

CV_INTER_NN 最邻近插值

CV_INTER_LINEAR 双线性插值(默认)

CV_INTER_AREA  像素区域重新采样

CV_INTER_CUBIC 双三次插值


CV_WARP_FILL_OUTLIERS,其效果是可以用最后一个变量fillval设置的值填充目标图像的像素,而这些像素在原始输入图像中没有任意像素与之对应。



如果使用cvStereoRectifyUncalibrated()函数,即不使用摄像机内参数来校正视觉时,关于讲解请看Learning OpenCV中文版 475页倒数第二段以及阅读OpenCV自带的stereo_calib.cpp程序来详细了解具体的操作

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多