成像模型都假设相机遵循线性投影模型,其中世界中的直线即图像中的直线。(这是将线性矩阵运算应用于齐次坐标的自然结果。)不幸的是,许多广角镜头具有明显的径向畸变,这表现为直线投影中的可见曲率。(有关镜头光学和色差)除非考虑到这种失真,否则不可能创建高度准确的照片级逼真重建。例如,在未考虑径向失真的情况下构建的图像马赛克通常会由于像素混合之前相应特征的配准错误而表现出模糊。
幸运的是,在实践中补偿径向失真并不是那么困难。 对于大多数镜头,一个简单的四次失真模型可以产生良好的效果。 令
为透视分割后但在焦距
缩放和图像中心
移动之前获得的像素坐标,即

径向畸变模型表明,观察到的图像中的坐标偏离图像中心(桶形畸变)或远离(枕形畸变),位移量与它们的径向距离成正比(图 2a-b)。最简单的径向畸变模型使用低阶多项式,例如,

其中
和
和
称为径向畸变参数。该模型还包括一个用于解释镜头偏心的切向分量,由 Brown (1966) 在摄影测量文献中首次提出,因此是 有时称为布朗或布朗-康拉迪模型。 然而,失真的切向分量通常被忽略,因为它们会导致估计不太稳定。
在径向失真步骤之后,可以使用计算最终像素坐标

可以使用多种技术来估计给定镜头的径向畸变参数。
有时,上述简化模型无法足够准确地模拟复杂镜头产生的真实失真(尤其是在非常广角时)。 更完整的分析模型还包括切向畸变和偏心畸变(Slama 1980)。
鱼眼镜头(图 2c)需要一个不同于传统径向畸变多项式模型的模型。 鱼眼镜头的行为,第一个近似值,作为远离光轴角度的等距离投影仪,


由于距中心的距离(像素)和视角之间大多是线性映射,因此此类镜头有时被称为 f-theta 镜头,这很可能是流行的 RICOH THETA 360° 相机得名的地方。 Xiong 和 Turkowski (1997) 描述了如何通过添加额外的二次校正来扩展该模型,以及如何从一组重叠的鱼眼图像中估计未知参数(投影中心、缩放因子 s 等) 使用直接(基于强度)非线性最小化算法。
对于更大、更不规则的失真,可能需要使用样条的参数失真模型(Goshtasby 1989)。 如果镜头没有单个投影中心,则可能需要分别对与每个像素对应的 3D 线(与方向相反)建模(Gremban、Thorpe 和 Kanade 1988;Champleboux、Lavall´ee 等人 1992a ;Grossberg 和 Nayar 2001;Sturm 和 Ramalingam 2004;Tardif、Sturm 等人 2009)。 我们将在后面讨论如何校准镜头畸变。

与简单的径向失真模型相关的一个微妙问题经常被忽略。 我们在透视投影和最终传感器阵列投影步骤之间引入了非线性。 因此,一般来说,我们不能对任意
矩阵 K 进行旋转后乘以将其转化为上三角形式并将其吸收到全局旋转中。 然而,这种情况并不像最初看起来那么糟糕。 如果我们将径向和其他失真校正到保留直线的精度,我们基本上已经将传感器转换回线性成像器,并且之前的分解仍然适用。
使用 OpenCV 消除失真
消除因镜头引起的失真的三个主要步骤
1、执行相机标定并获取相机的内在参数。内在参数还包括相机畸变参数。
估计相机参数(相机校准)相关参考
2、使用getOptimalNewCameraMatrix()方法得到优化相机矩阵以控制未失真图像中不需要的像素的百分比。
参考下图,在右图中,我们看到边缘附近有一些黑色像素。这些是由于图像的不失真而发生的。有时这些黑色像素在最终的未失真图像中是不需要的。因此getOptimalNewCameraMatrix () 方法返回一个精确的相机矩阵和 ROI(感兴趣区域),可用于裁剪图像以排除所有黑色像素。要消除的不需要像素的百分比由参数 alpha 控制,该参数作为参数传递给getOptimalNewCameraMatrix () 方法。

3、使用优化的相机矩阵减少图像失真。
pyhon参考代码
# Refining the camera matrix using parameters obtained by calibration newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w,h), 1, (w,h)) # Method 1 to undistort the image dst = cv2.undistort(img, mtx, dist, None, newcameramtx) # Method 2 to undistort the image mapx,mapy=cv2.initUndistortRectifyMap(mtx,dist,None,newcameramtx,(w,h),5) dst = cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR) # Displaying the undistorted image cv2.imshow("undistorted image",dst) cv2.waitKey(0)
c++参考代码
cv::Mat dst, map1, map2,new_camera_matrix; cv::Size imageSize(cv::Size(image.cols,image.rows)); // Refining the camera matrix using parameters obtained by calibration new_camera_matrix = cv::getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, imageSize, 0); // Method 1 to undistort the image cv::undistort( frame, dst, new_camera_matrix, distCoeffs, new_camera_matrix ); // Method 2 to undistort the image cv::initUndistortRectifyMap(cameraMatrix, distCoeffs, cv::Mat(),cv::getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, imageSize, 0),imageSize, CV_16SC2, map1, map2); cv::remap(frame, dst, map1, map2, cv::INTER_LINEAR); //Displaying the undistorted image cv::imshow("undistorted image",dst); cv::waitKey(0);
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/221363.html原文链接:https://javaforall.net
