OpenCV:鱼眼相机去畸变=图像去畸变+点去畸变

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV:鱼眼相机去畸变=图像去畸变+点去畸变相关的知识,希望对你有一定的参考价值。

参考技术A 官网: https://docs.opencv.org/3.4/db/d58/group__calib3d__fisheye.html

(5)undistortPoints是点去畸变函数

去畸变点的坐标为(725,514)和去畸变图像中一致.

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

  • 一、鱼眼相机概述

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

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

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

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

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

  • 二、鱼眼相机成像模型

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

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

        如图所示,坐标系Oc-XcYcZc是相机坐标系,坐标系O-XY是物理图像坐标系。假设按照针孔相机的成像模型,世界坐标系中的一点经过直线投影到物理图像坐标系中的点。其中,光线的入射角为。按照鱼眼相机的成像模型,出射角应该小于入射角,因此实际投影点应该为。不妨假设f=1,则点坐标以及入射角如下:

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

由于,且的一次项系数约为1,因此OpenCV中使用的鱼眼相机模型为:

由相似三角形原理:

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

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

  • 三、基于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博客

以上是关于OpenCV:鱼眼相机去畸变=图像去畸变+点去畸变的主要内容,如果未能解决你的问题,请参考以下文章

相机标定中的一些知识点(小孔模型、鱼眼模型、畸变、泰勒展开)

opencv鱼眼图像畸变校正——标定校正

图像视觉 --鱼眼摄像头标定和图像畸变矫正

Python OpenCV 单目相机标定坐标转换相关代码(包括鱼眼相机)

如何利用opencv计算图像畸变系数,并进行校正与摄像机标定?

相机模型与去畸变方法详解