视觉slam14讲——第5讲 相机与图像

本系列文章是记录学习高翔所著《视觉slam14讲》的内容总结,文中的主要文字和代码、图片都是引用自课本和高翔博士的博客。代码运行效果是在自己电脑上实际运行得出。手动记录主要是为了深入理解

文章目录

  • 第5讲 相机与图像
    • 1 相机模型
      • 1.1 针孔相机模型
      • 1.2 畸变
      • 1.3 双目相机模型
      • 1.4 RGBD相机模型
    • 2 图像的存储和访问
      • 2.1 图像的存储
      • 2.2 图像的通道
      • 2.3 opencv图像像素的遍历

第5讲 相机与图像

1 相机模型

相机模型是用来描述将三维世界坐标系中的坐标点映射到二维图像平面的过程
使用针孔和畸变两个模型来描述整个投影过程。

1.1 针孔相机模型

视觉slam14讲——第5讲 相机与图像_第1张图片

(1) 相机坐标系内中物理坐标点 P c ~ = [ X , Y , Z ] T \tilde{P_c}=[X,Y,Z]^T Pc~=[X,Y,Z]T,
(2) 成像平面内成像坐标点 P ′ = [ X ′ , Y ′ , Z ′ ] T P^{'}=[X^{'},Y^{'},Z^{'}]^T P=[X,Y,Z]T, 焦距为 f f f,
通过对称成像平面和归一化成像平面得到二者关系为
X ′ = f X Z Y ′ = f Y Z X^{'}=f\frac{X}{Z} \\ Y^{'}=f\frac{Y}{Z} X=fZXY=fZY
(3) 像素坐标系内像素坐标为 [ u , v ] T [u,v]^T [u,v]T,像素坐标系和成像平面相差了一个缩放( u 轴 缩 放 α 倍 , v 轴 缩 放 β 倍 u轴缩放\alpha 倍,v轴缩放\beta 倍 uαvβ)和一个原点的平移 [ c x , c y ] T [c_x,c_y]^T [cx,cy]T
p ′ p^{'} p和像素坐标 [ u , v ] T [u,v]^T [u,v]T关系为
u = α X ′ + c x v = β Y ′ + c y u=\alpha X^{'}+c_x \\ v=\beta Y^{'}+c_y u=αX+cxv=βY+cy
代入上式得到像素坐标和相机坐标系内点的关系
u = f x X Z + c x v = f y Y Z + c y u=f_x\frac{X}{Z}+c_x \\ v=f_y\frac{Y}{Z}+c_y u=fxZX+cxv=fyZY+cy
其中, f x = α f , f y = β f f_x=\alpha f, f_y=\beta f fx=αf,fy=βf
齐次化写成矩阵形式,
[ u v 1 ] = 1 Z [ f x 0 c x 0 f y c y 0 0 1 ] [ X Y Z ] = 1 Z K P c ~ \begin{bmatrix} u\\ v\\ 1 \end{bmatrix}=\frac{1}{Z} \begin{bmatrix} f_x & 0 & c_x\\ 0 & f_y & c_y\\ 0&0&1 \end{bmatrix}\begin{bmatrix} X\\ Y\\ Z \end{bmatrix}=\frac{1}{Z}K\tilde{P_c} uv1=Z1fx000fy0cxcy1XYZ=Z1KPc~按照传统习惯将 Z Z Z挪到左侧,表达的就是相机坐标系中点和像素坐标系中像素的关系
Z [ u v 1 ] = [ f x 0 c x 0 f y c y 0 0 1 ] [ X Y Z ] = K P c ~ Z\begin{bmatrix} u\\ v\\ 1 \end{bmatrix}= \begin{bmatrix} f_x & 0 & c_x\\ 0 & f_y & c_y\\ 0&0&1 \end{bmatrix}\begin{bmatrix} X\\ Y\\ Z \end{bmatrix}=K\tilde{P_c} Zuv1=fx000fy0cxcy1XYZ=KPc~
把中间量 K K K称作相机内参。 K = [ f x 0 c x 0 f y c y 0 0 1 ] K=\begin{bmatrix} f_x & 0 & c_x\\ 0 & f_y & c_y\\ 0&0&1 \end{bmatrix} K=fx000fy0cxcy1
相机坐标 P P P是由它的世界坐标 P w P_w Pw变换而来,相机位姿由 R , t R,t R,t决定。那么有下式成立,
Z P u v = Z [ u v 1 ] = K ( R P w + t ) = K ( T P w ) ( 1 : 3 ) ZP_{uv}=Z\begin{bmatrix} u\\ v\\ 1 \end{bmatrix}=K(RP_w+t)=K(TP_{w})_{(1:3)} ZPuv=Zuv1=K(RPw+t)=K(TPw)(1:3)
最后一个式子里面隐含着一次齐次坐标到非齐次坐标的转换( T P w TP_w TPw的最后一维是1),也就是 P c ~ = K ( R P w + t ) = ( T P w ) ( 1 : 3 ) = [ X Y Z ] \tilde{P_c}=K(RP_w+t)=(TP_{w})_{(1:3)}=\begin{bmatrix} X\\ Y\\ Z \end{bmatrix} Pc~=K(RPw+t)=(TPw)(1:3)=XYZ
两边除以 Z Z Z, 所以, P u v = 1 Z K ( T P w ) ( 1 : 3 ) = 1 Z K P c ~ = K [ X Z Y Z 1 ] = K P c P_{uv}=\frac{1}{Z}K(TP_{w})_{(1:3)}=\frac{1}{Z}K\tilde{P_c}=K\begin{bmatrix} \frac{X}{Z}\\ \frac{Y}{Z}\\ 1 \end{bmatrix}=KP_c Puv=Z1K(TPw)(1:3)=Z1KPc~=KZXZY1=KPc
其中 P c = [ X Z Y Z 1 ] P_c=\begin{bmatrix} \frac{X}{Z}\\ \frac{Y}{Z}\\ 1 \end{bmatrix} Pc=ZXZY1称为归一化坐标,二维的齐次坐标,它位于相机前方 z = 1 z=1 z=1的平面上,叫做归一化平面
其实到现在才理解了什么是归一化平面,这个平面其实是相机坐标系下的一个平面,利用3d点除以z得到的平面。

变换过程总结:
世界坐标系下点 P w → R , t 或 者 T P c ~ = R P w + t = [ X Y Z ] → 投 影 到 归 一 化 平 面 P c = [ X Z Y Z 1 ] → 经 过 相 机 内 参 P u v = K P c P_w\xrightarrow{R,t或者T}\tilde{P_c}=RP_w+t=\begin{bmatrix} X\\ Y\\ Z \end{bmatrix}\xrightarrow{投影到归一化平面}P_c=\begin{bmatrix} \frac{X}{Z}\\ \frac{Y}{Z}\\ 1 \end{bmatrix}\xrightarrow{经过相机内参}P_{uv}=KP_c PwR,tT Pc~=RPw+t=XYZ Pc=ZXZY1 Puv=KPc

1.2 畸变

  • 径向畸变
    透镜的形状引起,有桶形失真和枕形失真。
  • 切向畸变
    相机组装过程不能使透镜和成像平面严格平行引起

一般使用的去畸变处理方法:先对整张图像去畸变,得到去畸变后的图像,然后讨论图像上点的空间位置。

1.3 双目相机模型

视觉slam14讲——第5讲 相机与图像_第2张图片

根据三角形相似得到
z − f z = b − u L + u R b \frac{z-f}{z}=\frac{b-u_L+u_R}{b} zzf=bbuL+uR
整理得到
z = f b d , d = u L − u R z=\frac{fb}{d}, d=u_L-u_R z=dfb,d=uLuR

1.4 RGBD相机模型

原理

  • 红外结构光
  • 飞行时间法

2 图像的存储和访问

视觉slam14讲——第5讲 相机与图像_第3张图片

2.1 图像的存储

例如一张宽度为640像素,高度为480像素的灰度图(0~255)表示为

//unsigned char image[h][w];
unsigned char image[480][640];

像素坐标原点位于图像的左上角,X轴向右。Y轴向下,Z轴向前(里)。

  • 数组的行 → \xrightarrow{\quad} 图像的高度 → \xrightarrow{\quad} Y Y Y
  • 数组的列 → \xrightarrow{\quad} 图像的宽度 → X \xrightarrow{\quad}X X
unsigned char pixel = image[y][x]

2.2 图像的通道

  • 灰度图使用一个unsigned char来表示8位数据(0~255)。
  • 彩色图像需要用到通道的概念。常见的彩色图像使用三个通道来表示,每个通道由8位整数来表示,这样的话一个像素占用24位空间。
  • 通道的顺序在opencv中是BGR的顺序,如果还想表达图像的透明度,可以使用RGBA四个通道。

2.3 opencv图像像素的遍历

先定位到某一行,在到某一列,再到某一个通道,最后是某一个像素。

cv::Mat image = cv::read("lena.png");
for (size_t y=0; y(y);
        unsigned char data_ptr = &row_ptr[x*image.channels()];
        
        for(int c=0; c!=image.channels();c++)
        {
            unsigned char data = data_ptr[c];
        }
    }
}

你可能感兴趣的:(视觉slam14讲)