matlab畸变校正代码_Opencv中的两种去畸变函数

728ce3b362ff58d1821a1e6692891d5e.png
  • 前言

参考 OpenCV畸变校正原理以及损失有效像素原理分析 - 一度逍遥 - 博客园 我们知道目前opencv在标定完后得到相机内参及畸变系数,要么通过cv::undistort()直接得到去畸变的图像,要么通过cv::getOptimalNewCameraMatrix()得到新的矩阵,再通过cv::initUndistortRectifyMap()得到x轴与y轴映射,最后通过cv::remap()将原图映射到新图。

  • 两者的不同

在说两者不同之前,我们先介绍下getOptimalNewCameraMatrix()函数。

getOptimalNewCameraMatrix

alpha之前的参数自不必说,alpha之后的参数都可以视为默认。关键就在alpha的含义。

 icvGetRectangles(cameraMatrix, distCoeffs, 0, 0, imgSize, inner, outer);
    
 // Projection mapping inner rectangle to viewport
 double fx0 = (newImgSize.width) / inner.width;
 double fy0 = (newImgSize.height) / inner.height;
 double cx0 = -fx0 * inner.x;
 double cy0 = -fy0 * inner.y;
    
 // Projection mapping outer rectangle to viewport
 double fx1 = (newImgSize.width) / outer.width;
 double fy1 = (newImgSize.height) / outer.height;
 double cx1 = -fx1 * outer.x;
 double cy1 = -fy1 * outer.y;
    
 // Interpolate between the two optimal projections
 M[0][0] = fx0*(1 - alpha) + fx1*alpha;
 M[1][1] = fy0*(1 - alpha) + fy1*alpha;
 M[0][2] = cx0*(1 - alpha) + cx1*alpha;
 M[1][2] = cy0*(1 - alpha) + cy1*alpha;

在getOptimalNewCameraMatrix()函数中,有上述一段代码,意思是从内参/畸变系数中得到两个inner和outer矩阵,当alpha为0时,取inner即内矩阵,用内矩阵大小作为新的图像大小,重新得到fx,fy,cx,cy,因此新的内参矩阵诞生了. 当alpha为1时,取outer即外矩阵。当alpha介于0~1时,则按照比例重新计算fx,fy,cx,cy。

事实上,内矩阵等同于不含任何黑色边框的图幅大小,而外矩阵等同于原图大小。

e6f99bcda784789b1ea0161e575dad0e.png
alpha=1

59841c50f585fa213de64952c3baba01.png
alpha=0

继续深究,那么它的inner和outer又是怎么来的呢?

  • inner和outer的来源

inner和outer又是怎么来的,和原来的内参与畸变又有什么关系呢? 在icvGetRectangles()函数中有这样一段代码

for (y = k = 0; y < N; y++) //opencv 默认为 9
    for (x = 0; x < N; x++)
	pts[k++] = cvPoint2D32f((float)x*imgSize.width / (N - 1),(float)y*imgSize.height / (N - 1));
cvUndistortPoints2(_pts, _pts, cameraMatrix, distCoeffs, R, newCameraMatrix);
float iX0 = -FLT_MAX, iX1 = FLT_MAX, iY0 = -FLT_MAX, iY1 = FLT_MAX;
float oX0 = FLT_MAX, oX1 = -FLT_MAX, oY0 = FLT_MAX, oY1 = -FLT_MAX;
// find the inscribed rectangle.
// the code will likely not work with extreme rotation matrices (R) (>45%)
for (y = k = 0; y < N; y++)
    for (x = 0; x < N; x++)
    {
    	CvPoint2D32f p = pts[k++];
    	oX0 = MIN(oX0, p.x);
    	oX1 = MAX(oX1, p.x);
    	oY0 = MIN(oY0, p.y);
    	oY1 = MAX(oY1, p.y);
    
    	if (x == 0)
    		iX0 = MAX(iX0, p.x);
    	if (x == N - 1)
    		iX1 = MIN(iX1, p.x);
    	if (y == 0)
    		iY0 = MAX(iY0, p.y);
    	if (y == N - 1)
    		iY1 = MIN(iY1, p.y);
    }
 inner = cv::Rect_<float>(iX0, iY0, iX1 - iX0, iY1 - iY0);
 outer = cv::Rect_<float>(oX0, oY0, oX1 - oX0, oY1 - oY0);

这段代码的含义是指,按照输入图像的大小,生成长宽分别按照 imgSize.width / 8的间隔和 imgSize.height / 8 间隔的9*9个点。

再对这81个点,进行去畸变转换得到新的点。

b425a791881d53311b22c48a3942e960.png
81个点的转换(部分)

再从去畸变后的点中相互比较,得到外围矩阵oX0,oY0,oX1,oY1,及由原四个角点得到的内围矩阵,也就是outer与inner。

  • 结束语

之所以会研究这部分代码,是因为在处理Ladybug相机时,它可以自动提供去畸变后的图片,例如

5f26e867ab54ad130397e9ff3533fc02.png
ladybug某个镜头的图像

但是黑色边框却没有去掉,因为想偷懒尝试通过getOptimalNewCameraMatrix()将alpha设为0得到去黑边图像,但由于ladybug自身只提供相机内参而不提供畸变系数,当我设畸变系数为空时,内参并没有变化,出于好奇就稍深入研究了下源码。现在明白了当畸变系数为空时,inner与outer由于undistortpoint()大小相同,fx,fy,cx,cy当然就没有变化。

最后还是自己手动截取可视范围,保持fx,fy不变,根据新左上角重新计算cx,cy。得到新的去黑边后的图像以及对应的新相机内参。

[1]: OpenCV畸变校正原理以及损失有效像素原理分析 - 一度逍遥 - 博客园

[2]: OpenCV: OpenCV modules

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值