SLAM学习——相机模型(针孔+鱼眼)

2023-12-15 00:36

本文主要是介绍SLAM学习——相机模型(针孔+鱼眼),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

针孔相机模型

针孔相机模型是很常用,而且有效的模型,它描述了一束光线通过针孔之后,在针孔背面投影成像的关系,基于针孔的投影过程可以通过针孔和畸变两个模型来描述。
请添加图片描述
模型中有四个坐标系,分别为worldcameraimagepixel

  • world为世界坐标系,可以任意指定 x w x_w xw轴和 y w y_w yw轴,为上图P点所在坐标系。

  • camera为相机坐标系,原点位于小孔, z c z_c zc轴与光轴重合, x c x_c xc轴和 y c y_c yc轴平行投影面,为上图坐标系 X c Y c Z c X_cY_cZ_c XcYcZc

    • 归一化坐标系,原点位于 z c = 1 z_c=1 zc=1,x和y轴与相机坐标系一样。
  • image为图像坐标系,原点位于光轴和投影面的交点, x x x轴和 y y y轴平行投影面,为上图坐标系 x y xy xy,相对于camera相差一个缩放。

  • pixel为像素坐标系(opencv定义),从小孔向投影面方向看,投影面的左上角为原点, u v uv uv轴和投影面两边重合,该坐标系与图像坐标系处在同一平面,但原点不同,相对于image相差一个平移。

投影变换

正投影 (空间点->图像点)

**注意:**坐标变换过程使用的是齐次坐标

  • world->camera

    设点在world中的坐标为 P w = ( x w , y w , z w ) T P_w = (x_w,y_w,z_w)^T Pw=(xw,yw,zw)T,在camera中的坐标为 P c = ( x c , y c , z c ) T P_c = (x_c,y_c,z_c)^T Pc=(xc,yc,zc)T
    [ P c 1 ] = T w c [ P w 1 ] \begin{bmatrix} P_c\\1 \end{bmatrix}= T^c_w \begin{bmatrix} P_w\\1 \end{bmatrix} [Pc1]=Twc[Pw1]
    其中 T w c T^c_w Twc为外参,即世界坐标系相对于相机坐标系的变换。

  • camera->归一化相机系

    相机坐标系为 F s F_s Fs,设一平面位于相机坐标camera z = 1 z=1 z=1上,为归一化平面,其坐标系 C C C为归一化坐标系。
    请添加图片描述
    根据相似三角形,P点在归一化坐标系的坐标为
    P n = [ x c / z c y c / z c z c / z c ] = [ x n y n 1 ] P_n = \begin{bmatrix} x_c/z_c\\y_c/z_c\\z_c/z_c \end{bmatrix} =\begin{bmatrix} x_n\\y_n\\1 \end{bmatrix} Pn= xc/zcyc/zczc/zc = xnyn1

  • 归一化相机系->camera->pixel

请添加图片描述

设置图像坐标系上坐标为 P i P_i Pi,基于图中相似三角形(一般所得图像已经经过处理,完成翻转)可得点P在图像坐标系上坐标为:
x i f = x c z c = x n , y i f = y c z c = y n \frac{x_i}{f} = \frac{x_c}{z_c} = x_n, \frac{y_i}{f} = \frac{y_c}{z_c} = y_n fxi=zcxc=xn,fyi=zcyc=yn
α \alpha α β \beta β分别为x和y方向上的每米像素值,设图像中心偏移为 [ c x , c y ] [c_x,c_y] [cx,cy],设像素坐标 P u v = ( u , v , 1 ) T P_{uv} = (u,v,1)^T Puv=(u,v,1)T,则
u = α x i + c x = α f x n + c x , v = β y i + c y = β f y n + c y u = \alpha x_i+c_x = \alpha f x_n +c_x,v = \beta y_i+c_y = \beta f y_n +c_y u=αxi+cx=αfxn+cx,v=βyi+cy=βfyn+cy
f x = α f , f y = β f f_x = \alpha f, f_y = \beta f fx=αf,fy=βf,即
P u v = [ f x 0 c x 0 f y c y 0 0 1 ] P n = K P n P_{uv} = \begin{bmatrix} f_x&0&c_x\\0&f_y&c_y\\0&0&1 \end{bmatrix}P_n = K P_n Puv= fx000fy0cxcy1 Pn=KPn
其中K为内参数矩阵(Camera Intrinsics)。

因此worldpixel到关系为
P u v = K 3 × 3 T W C P w P_{uv}=K_{3 \times 3}T^C_WP_w Puv=K3×3TWCPw
其中隐含了一次齐次坐标到非齐次坐标的转换,具体坐标系变换流程为
世界坐标系 → 相机坐标系 ( 归一化处理 ) → 图像坐标系 → 像素坐标系 w o r l d → c a m r e a → i m a g e → p i x e l P w = ( x w , y w , z w , 1 ) T → P c = ( x c , y c , z c , 1 ) T [ P i = ( x i , y i , 1 ) T ] → P u v = ( u , v , 1 ) T 世界坐标系\rightarrow 相机坐标系( 归一化处理)\rightarrow 图像坐标系 \rightarrow 像素坐标系\\ world \rightarrow camrea \rightarrow image \rightarrow pixel\\ P_w = (x_w,y_w,z_w,1)^T\rightarrow P_c = (x_c,y_c,z_c,1)^T [P_i = (x_i,y_i,1)^T ]\rightarrow P_{uv} = (u,v,1)^T 世界坐标系相机坐标系(归一化处理)图像坐标系像素坐标系worldcamreaimagepixelPw=(xw,yw,zw,1)TPc=(xc,yc,zc,1)T[Pi=(xi,yi,1)T]Puv=(u,v,1)T

//Parameters vector corresponds to
//      [fx, fy, cx, cy]
// 归一化平面->pixel
Eigen::Vector2d Pinhole::project(const Eigen::Vector3d &v3D) {Eigen::Vector2d res;res[0] = mvParameters[0] * v3D[0] / v3D[2] + mvParameters[2];res[1] = mvParameters[1] * v3D[1] / v3D[2] + mvParameters[3];return res;
}

反投影(图像点->空间点)

设已知图像点在相机坐标系下的深度为Z
P w = T c w Z K − 1 P u v P_w = T^w_c Z K^{-1} P_{uv} Pw=TcwZK1Puv

//Parameters vector corresponds to
//      [fx, fy, cx, cy]
// pixel->归一化平面
cv::Point3f Pinhole::unproject(const cv::Point2f &p2D) {return cv::Point3f((p2D.x - mvParameters[2]) / mvParameters[0], (p2D.y - mvParameters[3]) / mvParameters[1],1.f);
}

畸变

一般使用的去畸变处理方法:先对整张图像去畸变,得到去畸变后的图像,然后讨论图像上点的空间位置。
{ x c o r r e c t e d = x ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) + 2 p 1 x y + p 2 ( r 2 + 2 x 2 ) y c o r r e c t e d = y ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) + p 1 ( r 2 + 2 y 2 ) + 2 p 2 x y \begin{cases} x_{corrected} =x(1+k_1r^2+k_2r^4+k_3r^6)+2p_1xy+p_2(r^2+2x^2) \\ y_{corrected} =y(1+k_1r^2+k_2r^4+k_3r^6)+p_1(r^2+2y^2)+2p_2xy \end{cases} {xcorrected=x(1+k1r2+k2r4+k3r6)+2p1xy+p2(r2+2x2)ycorrected=y(1+k1r2+k2r4+k3r6)+p1(r2+2y2)+2p2xy
上式为对归一化平面上的点进行径向畸变和切向畸变纠正,其中k1、k2、k3为径向畸变,p1、p2为切向畸变,根据需求可以调整使用的参数,不一定要五个全用上。

径向畸变

径向畸变(桶形畸变和枕形畸变)产生原因:光线在远离透镜中心的地方偏折更大,矫正公式:
{ x c o r r e c t e d = x ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) y c o r r e c t e d = y ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) \begin{cases} x_{corrected} =x(1+k_1r^2+k_2r^4+k_3r^6) \\ y_{corrected} =y(1+k_1r^2+k_2r^4+k_3r^6) \end{cases} {xcorrected=x(1+k1r2+k2r4+k3r6)ycorrected=y(1+k1r2+k2r4+k3r6)
请添加图片描述
请添加图片描述

切向畸变

切向畸变产生原因:相机组装过程不能使透镜和成像平面严格平行引起,矫正公式:
{ x c o r r e c t e d = x + 2 p 1 x y + p 2 ( r 2 + 2 x 2 ) y c o r r e c t e d = y + p 1 ( r 2 + 2 y 2 ) + 2 p 2 x y \begin{cases} x_{corrected} =x+2p_1xy+p_2(r^2+2x^2) \\ y_{corrected} =y+p_1(r^2+2y^2)+2p_2xy \end{cases} {xcorrected=x+2p1xy+p2(r2+2x2)ycorrected=y+p1(r2+2y2)+2p2xy
请添加图片描述

小结

综上,16个单目相机的参数:

  • 10个内部参数(内参,只与相机有关):

    • 5个内部矩阵参数K: f , d x , d y , u 0 , v 0 f,d_x,d_y,u_0,v_0 f,dx,dy,u0,v0(也可视作4个参数 f x , f y , u 0 , v 0 f_x,f_y,u_0,v_0 fx,fy,u0,v0
    • 5个畸变参数D: k 1 , k 2 , k 3 , p 1 , p 2 k_1,k_2,k_3,p_1,p_2 k1,k2,k3,p1,p2
  • 6个外部参数(外参,描述目标点的世界坐标到像素坐标的投影关系):

    • 3个旋转参数R
    • 3个平移参数t

鱼眼相机模型

请添加图片描述
鱼眼相机与针孔相机原理不同,采用非相似成像,在成像过程中引入畸变,通过对直径空间的压缩,突破成像视角的局限,从而达到广角成像,所以鱼眼镜头是一种极端得广角镜头,通常焦距小于等于16mm并且视角接近或等于180°(在工程上视角超过140°的镜头即统称为鱼眼镜头)。

鱼眼相机成像模型近似为单位球面投影模型,一般将鱼眼相机成像过程分解成两步:

  1. 先将三维空间点线性的投影到虚拟单位球面上

  2. 随后将单位球面上的点投影到图像平面上,这个过程是非线性的

由于鱼眼相机所成影像存在畸变,其中径向畸变非常严重,因此其畸变模型主要考虑径向畸变。
请添加图片描述
鱼眼相机的投影函数是为了尽可能将庞大的场景投影到有限的图像平面所设计的。根据投影函数的不同,鱼眼相机的设计模型大致分为

  • 等距投影
    r d = f θ r_d = f \theta rd=fθ

  • 等立体角投影
    r d = 2 f sin ⁡ ( θ 2 ) r_d = 2 f \sin(\frac{\theta}{2}) rd=2fsin(2θ)

  • 正交投影
    r d = 2 f sin ⁡ ( θ ) r_d = 2 f \sin(\theta) rd=2fsin(θ)

  • 体视投影
    r d = 2 f tan ⁡ ( θ ) r_d = 2 f \tan(\theta) rd=2ftan(θ)

相机的成像模型实际上表征的是成像的像高与入射角之间的映射关系。
请添加图片描述

通用鱼眼相机模型-Kannala-Brandt

Kannala-Brandt模型主要用于第二步,单位球面上的点投影到图像平面,该步骤为非线性,不同投影可以统一为
r d = f θ d r_d =f\theta _d rd=fθd
因sin,tan的泰勒展开都是奇次项形式,取前5项可得
θ d = k 0 θ + k 1 θ 3 + k 2 θ 5 + k 3 θ 7 + k 4 θ 9 \theta_d= k_0\theta + k_1 \theta^3 + k_2 \theta^5 + k_3 \theta^7 + k_4 \theta^9 θd=k0θ+k1θ3+k2θ5+k3θ7+k4θ9

正投影(空间点->图像点)

  • 世界系->归一化相机系

    设外参为 T w c T^c_w Twc
    [ X c Y c Z c ] = R [ X w Y w Z w ] + t x c = X c Z c , y c = Y c Z c \left[ \begin{array}{c} X_c \\ Y_c \\ Z_c \end{array} \right]=R \left[\begin{array}{c} X_w \\ Y_w \\ Z_w \end{array}\right]+t\\ x_c = \frac{X_c}{Z_c},\ y_c=\frac{Y_c}{Z_c} XcYcZc =R XwYwZw +txc=ZcXc, yc=ZcYc

  • 归一化相机系->虚拟单位球面

r 2 = x c 2 + y c 2 θ = a r c t a n ( r ) θ d = k 0 θ + k 1 θ 3 + k 2 θ 5 + k 3 θ 7 + k 4 θ 9 x d = θ d r x c , y d = θ d r y c r^2 = x^2_c + y^2_c\\ \theta = arctan(r)\\ \theta _d = k_0\theta + k_1 \theta^3 + k_2 \theta^5 + k_3 \theta^7 + k_4 \theta^9\\ x_d=\frac{\theta_d}{r}x_c, \ y_d=\frac{\theta_d}{r}y_c r2=xc2+yc2θ=arctan(r)θd=k0θ+k1θ3+k2θ5+k3θ7+k4θ9xd=rθdxc, yd=rθdyc

  • 虚拟单位球面->图像系
    u = f x x d + c x , v = f y y d + c y u=f_xx_d+c_x, \ v=f_yy_d+c_y u=fxxd+cx, v=fyyd+cy
    变换后为拉伸变形图像。

    // Parameters vector corresponds to
    // [fx, fy, cx, cy, k0, k1, k2, k3]    
    // 相机系->图像系
    Eigen::Vector2f KannalaBrandt8::project(const Eigen::Vector3f &v3D) {const float x2_plus_y2 = v3D[0] * v3D[0] + v3D[1] * v3D[1];const float theta = atan2f(sqrtf(x2_plus_y2), v3D[2]);const float psi = atan2f(v3D[1], v3D[0]);const float theta2 = theta * theta;const float theta3 = theta * theta2;const float theta5 = theta3 * theta2;const float theta7 = theta5 * theta2;const float theta9 = theta7 * theta2;const float r = theta + mvParameters[4] * theta3 + mvParameters[5] * theta5+ mvParameters[6] * theta7 + mvParameters[7] * theta9;Eigen::Vector2f res;res[0] = mvParameters[0] * r * cos(psi) + mvParameters[2];res[1] = mvParameters[1] * r * sin(psi) + mvParameters[3];return res;
    }
    

反投影(图像点->空间点)

  • 图像系->虚拟单位球面

    x d = u − c x f X , y d = v − c y f y x_d = \frac{u-c_x}{f_X},y_d = \frac{v-c_y}{f_y} xd=fXucx,yd=fyvcy

  • 虚拟单位球面->归一化相机系->相机系
    θ d = x d 2 + y d 2 \theta _d = \sqrt{x_d^2+y_d^2} θd=xd2+yd2
    使用牛頓法 (Newton’s method)求解 θ \theta θ
    θ = N e w t o n ( θ d . k 1 , k 2 , k 3 , k 4 ) \theta = Newton(\theta_d.k_1,k_2,k_3,k_4) θ=Newton(θd.k1,k2,k3,k4)

    x c = tan ⁡ θ θ d ∗ x d , y c = tan ⁡ θ θ d ∗ y d x_c =\frac{\tan{\theta}}{\theta_d} * x_d, y_c =\frac{\tan{\theta}}{\theta_d} * y_d xc=θdtanθxd,yc=θdtanθyd

    设相机系下深度为Z
    P c = [ X c Y c Z c ] = Z [ x c y c 1 ] P_c = \left[ \begin{array}{c} X_c \\ Y_c \\ Z_c \end{array} \right] = Z \left[ \begin{array}{c} x_c \\ y_c \\ 1 \end{array} \right] Pc= XcYcZc =Z xcyc1

  • 相机系->世界系
    P w = T c w P c P_w = T^w_c P_c Pw=TcwPc

    // Parameters vector corresponds to
    // [fx, fy, cx, cy, k0, k1, k2, k3]
    // 图像系->归一化相机系
    cv::Point3f KannalaBrandt8::unproject(const cv::Point2f &p2D) {//Use Newthon method to solve for theta with good precision (err ~ e-6)cv::Point2f pw((p2D.x - mvParameters[2]) / mvParameters[0], (p2D.y - mvParameters[3]) / mvParameters[1]);float scale = 1.f;float theta_d = sqrtf(pw.x * pw.x + pw.y * pw.y);theta_d = fminf(fmaxf(-CV_PI / 2.f, theta_d), CV_PI / 2.f);if (theta_d > 1e-8) {//Compensate distortion iterativelyfloat theta = theta_d;for (int j = 0; j < 10; j++) {float theta2 = theta * theta, theta4 = theta2 * theta2, theta6 = theta4 * theta2, theta8 =theta4 * theta4;float k0_theta2 = mvParameters[4] * theta2, k1_theta4 = mvParameters[5] * theta4;float k2_theta6 = mvParameters[6] * theta6, k3_theta8 = mvParameters[7] * theta8;float theta_fix = (theta * (1 + k0_theta2 + k1_theta4 + k2_theta6 + k3_theta8) - theta_d) /(1 + 3 * k0_theta2 + 5 * k1_theta4 + 7 * k2_theta6 + 9 * k3_theta8);theta = theta - theta_fix;if (fabsf(theta_fix) < precision)break;}//scale = theta - theta_d;scale = std::tan(theta) / theta_d;}return cv::Point3f(pw.x * scale, pw.y * scale, 1.f);
    }
    

参考

toolToEffectorimage coordinate to world coordinate opencv

Computing x,y coordinate (3D) from image point

双目视觉之相机标定

camera_calibration_and_3d

3x4 Projection Matrix

Configure Monocular Fisheye Camera

Fisheye Calibration Basics

一文详解分析鱼眼相机投影成像模型和畸变模型

鱼眼镜头模型

K.B.鱼眼相机模型的投影与反投影

相机成像畸变模型与鱼眼相机模型

opencv去畸变的方法图像去畸变vs点畸变

opencv鱼眼相机畸变校正 python 鱼眼相机模型推导

这篇关于SLAM学习——相机模型(针孔+鱼眼)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/494471

相关文章

Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)

《Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)》:本文主要介绍Python基于火山引擎豆包大模型搭建QQ机器人详细的相关资料,包括开通模型、配置APIKEY鉴权和SD... 目录豆包大模型概述开通模型付费安装 SDK 环境配置 API KEY 鉴权Ark 模型接口Prompt

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

Retrieval-based-Voice-Conversion-WebUI模型构建指南

一、模型介绍 Retrieval-based-Voice-Conversion-WebUI(简称 RVC)模型是一个基于 VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech)的简单易用的语音转换框架。 具有以下特点 简单易用:RVC 模型通过简单易用的网页界面,使得用户无需深入了