Opencv中的两种去畸变函数

Opencv中的两种去畸变函数

前言

参考 https://www.cnblogs.com/riddick/p/6711263.html 我们知道目前opencv在标定完后得到相机内参及畸变系数,要么通过cv::undistort()直接得到去畸变的图像,要么通过cv::getOptimalNewCameraMatrix()得到新的矩阵,再通过cv::initUndistortRectifyMap()得到x轴与y轴映射,最后通过cv::remap()将原图映射到新图。

两者的不同

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

getOptimalNewCameraMatrix(cv::InputArray _cameraMatrix,cv::InputArray _distCoeffs,cv::Size imgSize, double alpha, cv::Size newImgSize,cv::Rect* validPixROI, bool centerPrincipalPoint)

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。

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

alpha=1
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个点,进行去畸变转换得到新的点。
点转换
再从去畸变后的点中相互比较,得到外围矩阵oX0,oY0,oX1,oY1,及由原四个角点得到的内围矩阵,也就是outer与inner。

结束语

之所以会研究这部分代码,是因为在处理Ladybug相机时,它可以自动提供去畸变后的图片,例如
在这里插入图片描述
但是黑色边框却没有去掉,因为想偷懒尝试通过getOptimalNewCameraMatrix()将alpha设为0得到去黑边图像,但由于ladybug自身只提供相机内参而不提供畸变系数,当我设畸变系数为空时,内参并没有变化,出于好奇就稍深入研究了下源码。现在明白了当畸变系数为空时,inner与outer由于undistortpoint()大小相同,fx,fy,cx,cy当然就没有变化。
最后还是自己手动截取可视范围,保持fx,fy不变,根据新左上角重新计算cx,cy。得到新的去黑边后的图像以及对应的新相机内参。
[1]: https://www.cnblogs.com/riddick/p/6711263.html
[2]: https://docs.opencv.org/3.4.1/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值