相机模型

您所在的位置:网站首页 焦距在数学中怎么表示 相机模型

相机模型

2024-07-12 09:18| 来源: 网络整理| 查看: 265

问题:

1 广角/超广角与鱼眼摄像机,角度界限

2 畸变模型中radtan畸变模型与鱼眼畸变模型在小于150范围是否都时能适用.   (同数据,拟合模型不同,,参数结果不同,不欠拟合和过拟合就可)

3 FOV畸变模型与鱼眼畸变模型中体视投影的关系.

鱼眼相机模型 (fisheye camera model)

    模型介绍         等距投影         等立体角投影         正交投影         体视投影         线性投影     Kannala-Brandt 模型         去畸变过程         投影过程         反投影过程     雅可比计算

之前总结了一下针孔相机的模型,然后得到了比较积极的回复(其实是我到处求人关注的,虽然截至到目前才三个人),所以就再接再励,乘胜追击(也没得办法,夸下的海口,跪着也要做完),继续总结其他相机模型。

模型介绍

鱼眼相机相较于针孔相机来说,视野更广,但畸变也更加严重,因此普通的针孔模型已不适用。鱼眼镜头的基本构造如图所示,经过多个镜头的折射,最终到达成像单元上。文章中所有图片均来自于网络,非本人所绘。在这里插入图片描述 一般情况下,可以通过控制光线的路径来设计各种各样的镜头类型,根据投影方式的不同,可以将这些镜头分为等距投影、等立体角投影、正交投影、体视投影以及线性投影。

在这里插入图片描述

在这里插入图片描述

等距投影

r = f θ                                                         r=f*θ 等立体角投影

r = 2 f s i n ( θ /2 )                                      r=2*f*sin(θ/2​) 正交投影

r = f s i n ( θ )                                              r=f*sin(θ) 体视投影

r = 2 f t a n ( θ/ 2 )                                           r=2*f*tan(θ/2​) 线性投影

r = f t a n ( θ )                                         r=f*tan(θ)

Kannala-Brandt 模型

同针孔模型一样,鱼眼模型也有畸变,那么怎么来用数学鱼眼描述这种畸变呢?观察各种投影方式,发现他们都是一个关于入射角 θ 的奇函数,因此鱼眼镜头的畸变也是对 θ的畸变,KB模型用只包含奇次项的多项式来描述畸变过程,其具体形式如下所示

θ d = θ + k 1 θ 3 + k 2 θ 5 + k 3 θ 7 + k 4 θ 9              θd​=θ+k1​θ3+k2​θ5+k3​θ7+k4​θ9 opencv中使用的鱼眼相机畸变模型就是这个模型,该模型适用于大多数鱼眼相机。另外,也可以用这种模型来对普通的针孔相机模型进行标定,仔细观察,上述的线性投影实际就是普通的针孔投影模型。最后鱼眼相机的投影模型可以表示为 r = f θ d                                                                 r=fθd​   (kalibr工具, Equidistant模型,) 其中 r 表示图像中像素点到主点的距离。

去畸变过程

对于鱼眼相机的去畸变过程可以采用解析的方式,因为从上述畸变公式中可以看到,畸变模型是一个多项式,理论上是存在解析解的。但本人使用的方法和针孔模型中类似,通过优化的方法进行去即便,代码如下

    

template void undistort(const Eigen::MatrixBase &p_d,const Eigen::MatrixBase &p_ud) const { EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE_OR_DYNAMIC(Eigen::MatrixBase, 2) Eigen::MatrixBase &y_ud = const_cast(p_ud); Eigen::MatrixBase &y_d = const_cast(p_d); y_ud.derived().resize(2); y_d.derived().resize(2); struct MLFunctor{ MLFunctor( const Eigen::Vector2d &imagePoint, double k1, double k2, double k3, double k4 ) : imagePoint_(imagePoint), _k1(k1), _k2(k2), _k3(k3), _k4(k4) { } int operator( )( const Eigen::VectorXd &x, Eigen::VectorXd &fvec ) const{ double theta = x[0]; double phi = x[1]; double theta2 = theta * theta; double theta4 = theta2 * theta2; double theta6 = theta4 * theta2; double theta8 = theta4 * theta4; double thetad = theta * ( 1 + _k1 * theta2 + _k2 * theta4 + _k3 * theta6 + _k4 * theta8); fvec[0] = thetad; fvec[1] = phi; fvec = fvec - imagePoint_; return 0; } int df( const Eigen::VectorXd &x, Eigen::MatrixXd &fjac ) const { double theta = x[0]; double theta2 = theta * theta; double theta4 = theta2 * theta2; double theta6 = theta4 * theta2; double theta8 = theta4 * theta4; fjac(0, 0) = 9 * _k4 * theta8 + 7 * _k3 * theta6 + 5 * _k2 * theta4 + 3 * _k1 * theta2 + 1; fjac(0, 1) = 0; fjac(1, 0) = 0; fjac(1, 1) = 1; return 0; } int values() const { return 2; } int inputs() const { return 2; } Eigen::Vector2d imagePoint_; double _k1; double _k2; double _k3; double _k4; }; Eigen::Vector2d target = y_d; MLFunctor func( target, m_k1, m_k2, m_k3, m_k4 ); Eigen::LevenbergMarquardt< MLFunctor > lm(func); double theta = y_d[0]; double phi = y_d[1]; Eigen::VectorXd res = Eigen::Vector2d(theta, phi); lm.minimize(res); y_ud = res; } 投影过程

反投影过程

   

雅可比计算

多数情况下,都用BA算法来计算相机的内外参,这就需要知道雅可比矩阵,即投影误差对各待优化变量的偏导数组成的矩阵。所谓的投影误差,实际检测到点与投影到图像上的点之间的误差

                       e r r = p m − p                                     err=pm​−p 其中 pm​表示检测到的角点。为了避免手撕公式,我使用了matlab直接来推导出结果,并且在推导公式时,没有考虑畸变项,因为公式太长了,懒得敲。 代码:

syms fx fy x y z cx cy k1 k2 k3 k4 R = sqrt(x^2 + y^2 + z^2); xc = x / R; yc = y / R; zc = z / R; theta = acos(z); %thetad = theta + k1 * theta^3 + k2 * theta^5 + k3 * theta^7 + k4 * theta^9; thetad = theta; r = sqrt(xc^2 + yc^2); u = fx * (thetad * xc) / r + cx; v = fy * (thetad * yc) / r + cy; alphaE_alphaK = - [diff(u, fx), diff(u, fy), diff(u, cx), diff(u, cy); diff(v, fx), diff(v, fy), diff(v, cx), diff(v, cy)] alphaE_alphaP = -[diff(u, x), diff(u, y), diff(u, z); diff(v, x), diff(v, y), diff(v, z)] alphaP_alphaR = [1, 0, 0, 0, z, -y; 0, 1, 0, -z, 0, x; 0, 0, 1, y, -x, 0] alphaE_alphaP * alphaP_alphaR

假设相机坐标系下归一化到球面的3D点坐标坐标为Ps​=(xs​,ys​,zs​)

 1.   误差项关于内参的偏导数

在这里插入图片描述     其中

2.误差项关于相机坐标系下点Ps​的偏导在这里插入图片描述 其中

3.误差项在李代数上的扰动模型     根据链式法则可得

其中, ∂ P c/∂ δ ξ​​的推导后续会有专门篇幅进行总结,在这个先用起来再说。

其中。 ———————————————— 原文链接:https://blog.csdn.net/weixin_43304707/article/details/113261307

鱼眼相机标定以及OpenCV实现

在另一篇文章中我已经写过有关普通相机模型及其OpenCV标定实现,这篇文章将主要关注鱼眼相机模型及其OpenCV标定实现。 先看一张鱼眼相机拍摄出来的结果:

从图中可以看出很明显的畸变。对鱼眼相机标定,有时候也可以用普通相机的标定方法对其进行标定,但是却不能保证去畸变后的效果是最好的。因此对于Gopro等鱼眼镜头拍摄出来的图像去畸变,最好的方法就是采用鱼眼相机标定方法进行标定。 鱼眼相机模型

鱼眼相机的内参模型依然可以表示为:  

这与普通镜头的成像模型没有区别。两者之间的区别主要体现在畸变系数,鱼眼相机的畸变系数为{ k1,k2,k3,k4},畸变系数不同,就导致鱼眼相机的投影关系也发生了变化,主要变化发生在考虑畸变情况下的投影关系转化: 设(X,Y,Z)为空间中一个三维点,它在成像平面内的成像坐标为(u,v),在考虑畸变的情况下,

OpenCV实现鱼眼相机标定

利用opencv实现鱼眼相机的标定和普通相机标定的标定流程基本一致,具体流程如下:

    1. 检测角点     cv::findChessboardCorners(InputArray image, Size patternSize, OutputArray corners, int     flags=CALIB_CB_ADAPTIVE_THRESH+CALIB_CB_NORMALIZE_IMAGE}     获得棋盘标定板的角点位置,使用     cornerSubPix(InputArray image, InputOutputArray corners, Size winSize, Size zeroZone,     TermCriteria criteria)获取角点更精细的检测结果     2. 初始化标定板上角点的三维坐标     3. 开始标定     double fisheye::calibrate(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints,     const Size& image_size, InputOutputArray K, InputOutputArray D,     OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, int flags=0,     TermCriteria criteria=TermCriteria(TermCriteria::COUNT + TermCriteria::     EPS, 100, DBL_EPSILON))     注意:K,D 分别表示内参矩阵和畸变系数向量,在定义时要定义为double型,这里推荐使用Matx33d和Vec4d数据类型,更为方便简单。objectPoints,imagePoints可以是float型,也可以是double型,但是再stereorectify中需要时double型。flags的可选项有很多,其中需要注意的是必须要指定CALIB_FIX_SKEW,代表求解时假设内参中fx=fy

    .     4.评定误差(可选项)

以上就是鱼眼相机标定的基本流程,部分代码片段如下: 

for (int i = 0; i != image_count; i++) { cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3