VS2019+OpenCV4.5 鱼眼相机图像畸变矫正

  • 一、鱼眼相机概述

       鱼眼镜头是定焦镜头中的一种视野范围很大的镜头,它视角范围通常大于等于180度。鱼眼相机虽然能获得较大的视角范围,但是其拍摄的图像存在较大的畸变,为了后续任务的需要,往往需要对原始图像进行预处理,即进行图像的畸变矫正,获得没有畸变的图像。

       如下图所示,鱼眼相机在获得大视角范围的同时,产生的畸变也很大,真实场景中的直线经成像变成了曲线。

       日常生活中接触到的大多数相机都可以近似用针孔相机模型来近似,在针孔相机模型中,光线沿直线传播,在成像平面所成的像与真实物体具有相似性。像与物之间经过了透视变换,透视变换保证直线仍然成像为直线,但是不保证平行性,即平行的直线在图像上不再平行,而相交于无穷远处。

       针孔相机成像的特点带来了相应的缺陷,光线只能沿直线传播,这就使得镜头难以捕捉位于图像边缘的物体。如下图所示,越靠近边缘的物体经过直线传播后,在成像平面上的位置就会越远,而相机的底片尺寸有限,因此靠近边缘的物体无法成像。

       为了获得更大的视角范围,人们希望光线不经过直线传播,而是像光线从空气射入水中那样发生折射。如下图所示便是鱼眼相机的成像原理,光线的折射角小于入射角,并且入射角越大,折射角减小的程度也越大。这样就相当于把光线集中到了一个锥形空间内,在图像中表现为所有的画面都集中到一个圆圈之中,类似于鱼的眼睛,因此该相机得名“鱼眼相机”。

  • 二、鱼眼相机成像模型

       鱼眼相机采用最多的是等距投影模型,投影函数为r=f\theta,其中r为像高,f为焦距,θ为入射角。成像时,由于镜头畸变,实际的投影函数不会严格符合投影模型。考虑到畸变,实际的投影函数由下式给出(这里假设f=1):

r(\theta )=k_{0}\theta+k_{1}\theta^{3}+k_{2}\theta^{5}+k_{3}\theta^{7}+k_{4}\theta^{9}

       其中,k0约等于1,k1,k2,k3,k4称为畸变系数。

        如图所示,坐标系Oc-XcYcZc是相机坐标系,坐标系O-XY是物理图像坐标系。假设按照针孔相机的成像模型,世界坐标系中的一点P(x,y,z)经过直线投影到物理图像坐标系中的P_{0}(a,b)点。其中,光线的入射角为\theta。按照鱼眼相机的成像模型,出射角\theta _{d}应该小于入射角\theta,因此实际投影点应该为p^{'}(x^{'},y^{'})。不妨假设f=1,则P_{0}点坐标以及入射角如下:

\left\{\begin{matrix}a=\frac{x}{z} \\ b=\frac{y}{z} \\ r^{2}=a^{2}+b^{2} \\ \theta =arctan(r) \end{matrix}\right.

       由于畸变的存在,实际像点为P’,像点到图像中心的距离r被压缩为r_{d},结合鱼眼相机的投影函数得:

r_{d}=f(\theta _{d})=k_{0}\theta+k_{1}\theta^{3}+k_{2}\theta^{5}+k_{3}\theta^{7}+k_{4}\theta^{9}

由于f=1,且\theta _{d}的一次项系数约为1,因此OpenCV中使用的鱼眼相机模型为:

r_{d}=\theta _{d}=\theta+k_{1}\theta^{3}+k_{2}\theta^{5}+k_{3}\theta^{7}+k_{4}\theta^{9}

由相似三角形原理:

\frac{r_{d}}{r}=\frac{x^{'}}{a}=\frac{y^{'}}{b}=\frac{\theta _{d}}{r}

因此畸变后的点坐标p’为:

\left\{\begin{matrix}x^{'}=\frac{\theta _{d}}{r}a \\ y^{'}=\frac{\theta _{d}}{r}b \end{matrix}\right.

最后利用相机内参将物理图像坐标系转换为像素坐标系,得到p’点的像素坐标:

\left\{\begin{matrix}u=f_{x}x^{'}+c_{x} \\ v=f_{y}y^{'}+c_{y} \end{matrix}\right.

  • 三、基于OpenCV的鱼眼相机图像矫正

1.相机标定

       由鱼眼成像模型的知识可以知道,要矫正鱼眼相机图像需要获得相机内参及畸变系数。这两个参数可以通过相机标定获得。本文采用张正友标定法,拍摄了20张棋盘格图像,用于求解相机内参以及畸变系数。

2.图像矫正

       获得相机的内参及畸变系数之后,使用OpenCV的鱼眼图像矫正函数fisheye::undistortImage()进行畸变矫正。

void Undistort::UndistortImg(const double k, bool is_save, const string& path)
{
	//新的相机内参矩阵
	Mat new_intrinsic_mat;
	K.copyTo(new_intrinsic_mat);
	//调节视场大小,乘的系数越小视场越大
	new_intrinsic_mat.at<double>(0, 0) *= k;
	new_intrinsic_mat.at<double>(1, 1) *= k;

	cout << endl << "开始校正图像" << endl;
	for (int i = 0; i < test_images.size(); i++)
	{
		//调节校正图中心,建议置于校正图中心
		new_intrinsic_mat.at<double>(0, 2) = 0.5 * test_images[i].cols;
		new_intrinsic_mat.at<double>(1, 2) = 0.5 * test_images[i].rows;

		Mat undistort_img;
		fisheye::undistortImage(test_images[i], undistort_img, K, distortion_coeffs, new_intrinsic_mat);
		//保存图像
		if (is_save)
		{
			string filename = path + "/out" + format("%d", i + 1) + ".jpg";
			imwrite(filename, undistort_img);
		}
	}
	if (is_save)
		cout << endl << "校正结果已保存至:" << path << endl;
	cout << endl << "校正结束" << endl;
}

       fisheye::undistortImage()的第一个参数是待矫正的图像,第二个参数是矫正后的图像,第三个参数是相机内参,第四个参数是畸变系数,第五个参数是矫正后的相机内参,可以改变这个参数来调整矫正后图像的中心位置和视场大小。

3.矫正结果

原图1

 结果图1

 

 原图2

 结果图2

 原图3

结果图3

四、本文代码

(23条消息) fisheye_cali.zip-图像处理文档类资源-CSDN文库

五、参考文献

(23条消息) 鱼眼镜头的成像原理到畸变矫正(完整版)_Sual-CSDN博客

  • 6
    点赞
  • 82
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Shenhb0419

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值