OpenCV畸变校正原理以及损失有效像素原理分析

原博客地址:相机畸变校正

上一篇博客简要介绍了一下常用的张正友标定法的流程,其中获取了摄像机的内参矩阵K,和畸变系数D。

1.在普通相机cv模型中,畸变系数主要有下面几个:(k1; k2; p1; p2[; k3[; k4; k5; k6]] ,其中最常用的是前面四个,k1,k2为径向畸变系数,p1,p2为切向畸变系数。

2.在fisheye模型中,畸变系数主要有下面几个(k1,k2,k3,k4).

 

因为cv和fisheye的镜头畸变模型不一样,所以畸变系数也会有所不同,具体在畸变校正时的公式也不同,具体公式请参见opencv2.0和3.0的官方文档。OpenCV中对畸变图像进行畸变校正主要用的函数有UndistortImage()函数,以及initUndistortRectifyMap()结合remap()函数。其实UndistortImage()就是initUndistortRectifyMap()和remap()的简单组合,效果是一样的。

 

但是有一点是:当你有很多畸变图像需要较正时,用UndistortImage()函数的缺点就暴露了。因为畸变坐标映射矩阵mapx和mapy只需要计算一次就足够了,而重复调用UndistortImage()只会重复计算mapx和mapy,严重影响程序效率。因此当有多张图片要畸变校正时,建议使用一次initUndistortRectifyMap(),获取畸变坐标映射矩阵mapx和mapy后,作为remap函数的输入,多次调用remap函数进行畸变校正。

 

今天要说的第二点就是做过畸变校正的同学都知道,畸变校正后的图像会损失很多像素,这是为什么呢?接下来就以常见的桶形畸变为例分析一下:由于我目前手头的相机畸变程度并不明显(之前用广角镜头的时候畸变程度相当明显)。因此就从网上找一些图片作为例子以便说明,这里引用一下图片来源

http://www.developersite.org/904-45591-%E6%A0%87%E5%AE%9A。

畸变原图如下:

 

畸变校正后的图如下:

 

相信大家已经可以看到了,由于桶形畸变的特征是,远离图像中心的地方成像放大率小,因此越远离图像中心的位置畸程度越明显,像点越向内移动。畸变校正后,原本挤在一起的像素点们被校正到原来的位置,就得到上面的图像。同时由于四周的像素被拉伸,会造成四周出现模糊的情况。

得到上述图像后很自然想到的是把四周的黑色区域裁掉,只留下中间的图像区域。如下图(红色框):

 

那么问题来了,这样做的话输出图像的长宽比和输入图像的长宽比就不一致了。因此opencv畸变校正函数内部做法是:在保证长宽比不变的情况下,对上面的图像取中间的ROI区域出来,类似进行“裁剪”操作,那么就会得到损失更多像素的输出图像啦,如下图(蓝色框)!

好了,说到这里,我们就把代码中的罪魁祸首找出来吧!先看一下initUndistortRectifyMap()函数的原型,如下图左,默认情况下,我们通常不会求取新的CameraMatrix,这样代码中会默认使用标定得到的CameraMatrix。而这个摄像机矩阵是在理想情况下没有考虑畸变得到的,所以并不准确,重要的是fx和fy的值会比考虑畸变情况下的偏大,会损失很多有效像素。我们可以通过这个函数getOptimalNewCameraMatrix ()求取一个新的摄像机内参矩阵,函数原型如下图右,注意函数上面的备注” Return the new camera matrix based on the free scaling parameter“,通过这个函数可以自行调整缩放比例。

       

 

 

在getOptimalNewCameraMatrix ()函数中,其中的一个输入参数为alpha∈(0,1),alpha的意义见上图,调节alpha的值能够控制得到的新矩阵中的fx和fy的大小,当alpha=1的时候,原图像中的所有像素能够得到保留,也就出现了上面校正后图像中的那些黑色的空洞区域。【注:cv模型中为alpha,fisheye模型中为balance,意义是一样的】

那么alpha是怎么样改变 f 值的,主要是getOptimalNewCameraMatrix ()中又调用了一个函数undistortPoints(),这个函数会在畸变图像中选取上下左右四个点进行畸变校正,具体请看源码。下面图片中我圈出的代码就在这个函数里面,里面具体的f1,f2,f3,f4的意思就与取的上下左右四个点有关,可以去看源代码,当然不明白了也可以问我。总之是在fmin和fmax之间进行插值计算 f,而通常balance(alpha)默认为0,f=fmax,焦距越大,视场越小,损失的有效像素越多。

 

感谢原作者解决了我的问题!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值