相机标定原理

标定的学习

相机标定原理

相机标定的意义:完成图像二维点和空间三维点互相转换

相机成像过程的简


相机成像可以近似为凸透镜成像,当物距远大于焦距时凸透镜成像可以看作为小孔成像,如上图。被拍摄物体和图像平面在小孔平面两侧,为了简化计算,通常将成像平面放置在光心(相机坐标系原点)前方(与场景同侧)


以上的相机成像过程可以简化为如下图。
在这个过程中我们需要将世界坐标转换到像素坐标系下,则需要以下几个过程
在不考虑相机畸变(镜头的凹凸问题)的情况下四个坐标的转换关系如下:
世界坐标系->相机坐标系->图像物理坐标系->图像像素坐标系
如下图
世界坐标系:XwYwZwX_w-Y_w-Z_w ,单位一般为mm
相机坐标系:XcYcZcX_c-Y_c-Z_c,光心为原点,镜头方向为ZZ方向 ,单位一般为mm
图像物理坐标系: xyx-y,图像中心为原点,单位一般为mmmm
图像像素坐标系: uvu-v,图像左上角为原点,单位一般为pixelpixel

每个单目相机模型从世界坐标系到图像像素坐标系的数学推导公式为:

Zc[uv1]=M2M1[XwYwZw1]Z_c \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} = M_2 M_1 \begin{bmatrix} X_w \\ Y_w \\ Z_w \\ 1 \end{bmatrix}

其中M1,M2M_1,M_2分别为外参矩阵与内参矩阵具体如下

世界坐标系->相机坐标系(刚体变换)

通过将世界坐标系旋转移动到相机坐标系,即如图


首先先将世界坐标系进行旋转将坐标的方向与相机坐标系的方向相同即

之后再将得到旋转后的坐标系移动到相机坐标系,从而达到世界坐标系到相机坐标系的转换

即(其中PcP_c是相机坐标系中点PwP_w是世界坐标系中点)

Pc=[R33t3101]PwP_c = \begin{bmatrix} R_{3*3} & t_{3*1} \\ 0 & 1 \end{bmatrix} P_w

其中

Pc=[XcYcZc1]=[R33t3101]Pw=[r11r12r13txr21r22r33tyr31r32r33tz0001][XwYwZw1]P_c = \begin{bmatrix} X_c \\ Y_c \\ Z_c \\ 1\end{bmatrix} = \begin{bmatrix} R_{3*3} & t_{3*1} \\ 0 & 1 \end{bmatrix} P_w = \begin{bmatrix} r_11 & r_12 & r_13 & t_x \\ r_21 & r_22 & r_33 & t_y \\ r_31 & r_32 & r_33 & t_z \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} X_w \\ Y_w \\ Z_w \\ 1\end{bmatrix}

该转换实际上就是我们所说的外参矩阵(描述了相机在世界坐标系中的位置和坐标即为位姿)
我们对此我们设为M1M_1即外参矩阵

M1=[R33t3101]M_1 = \begin{bmatrix} R_{3*3} & t_{3*1} \\ 0 & 1 \end{bmatrix}

相机坐标系->图像像素坐标系

相机坐标系 -> 图像坐标系(透射投影)


将三维世界中的点(相机坐标系下的(Xc,Yc,Zc)(X_c,Y_c,Z_c))通过透视投影映射到二维成像平面(图像物理坐标系下的(x,y)(x,y))。在这个过程中将会失去深度也就是ZZ的坐标,即3D>2D3D->2D,


其中z=fz=f为焦距,由上图可得出
xXc=yYc=fZc\dfrac{x}{X_c} = \dfrac{y}{Y_c} = \dfrac{f}{Z_c}

{x=fXcZcy=fYcZc\begin{cases} x = f\dfrac{X_c}{Z_c} \\ y = f\dfrac{Y_c}{Z_c} \end{cases}

=>Zc[xy1]=[f0000f000010][XcYcZc1] => Z_c\begin{bmatrix}x \\ y \\ 1\end{bmatrix} = \begin{bmatrix} f & 0 & 0 & 0 \\ 0 & f & 0 & 0 \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \begin{bmatrix} X_c \\ Y_c \\ Z_c \\1 \end{bmatrix}

图像坐标系 -> 图像像素坐标系(坐标变换)

图像坐标转到像素坐标即由mm>pixelmm->pixel
首先先梳理一下
图像坐标系(u0,v0)(u_0,v_0)为图像中心
像素坐标系(u,v)(u,v)为图像左上角

假设一个像素(pixelpixel)的长度与宽度设为dx,dydx,dy 单位为mmmm
那么(其中P(x,y)P(x,y)为图像坐标上任一点)

{u=xdx+u0b=ydy+v0=>[uv1]=[1dx0u001dyv0001][xy1]\begin{cases} u = \dfrac{x}{dx} + u_0 \\ b = \dfrac{y}{dy} +v_0 \end{cases} => \begin{bmatrix} u \\ v \\1 \end{bmatrix} = \begin{bmatrix} \dfrac{1}{dx} & 0 & u_0 \\ 0 & \dfrac{1}{dy} & v_0 \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\1 \end{bmatrix}

相机坐标系->图像像素坐标系

这个过程即为相机内参数矩阵变换公式,相机内参是描述相机内部几何和光学特性的一组参数,用于将三维相机坐标系中的点映射到二维图像像素坐标系。
由上述的“ 相机坐标系 -> 图像坐标系(透射投影)”和“图像坐标系 -> 图像像素坐标系(坐标变换)”相结合得到

Zc[xy1]=[f0000f000010][XcYcZc1]① Z_c\begin{bmatrix}x \\ y \\ 1\end{bmatrix} = \begin{bmatrix} f & 0 & 0 & 0 \\ 0 & f & 0 & 0 \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \begin{bmatrix} X_c \\ Y_c \\ Z_c \\1 \end{bmatrix}

[uv1]=[1dx0u001dyv0001][xy1]② \begin{bmatrix} u \\ v \\1 \end{bmatrix} = \begin{bmatrix} \dfrac{1}{dx} & 0 & u_0 \\ 0 & \dfrac{1}{dy} & v_0 \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\1 \end{bmatrix}

左右乘ZcZ_c后代入

Zc[uv1]=[1dx0u001dyv0001][f0000f000010][XcYcZc1]=[fx0u000fyv000010][XcYcZc1]=M2[XcYcZc1]Z_c \begin{bmatrix} u \\ v \\1 \end{bmatrix} = \begin{bmatrix} \dfrac{1}{dx} & 0 & u_0 \\ 0 & \dfrac{1}{dy} & v_0 \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} f & 0 & 0 & 0 \\ 0 & f & 0 & 0 \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \begin{bmatrix} X_c \\ Y_c \\ Z_c \\1 \end{bmatrix} = \begin{bmatrix} f_x & 0 & u_0 & 0\\ 0 & f_y & v_0 & 0\\ 0 & 0 & 1 & 0\\ \end{bmatrix} \begin{bmatrix} X_c \\ Y_c \\ Z_c \\1 \end{bmatrix} = M_2 \begin{bmatrix} X_c \\ Y_c \\ Z_c \\1 \end{bmatrix}

其中M2M_2为内参矩阵 即

M2=[fx0u000fyv000010]M_2 = \begin{bmatrix} f_x & 0 & u_0 & 0 \\ 0 & f_y & v_0 & 0\\ 0 & 0 & 1 & 0\\ \end{bmatrix}

世界坐标系->图像像素坐标系

由上述可知M1,M2M_1,M_2代入可得每个单目相机模型从世界坐标系到图像像素坐标系的数学推导公式为:

Zc[uv1]=M2M1[XwYwZw1]=[fx0u000fyv000010][R33t3101][XwYwZw1]Z_c \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} = M_2 M_1 \begin{bmatrix} X_w \\ Y_w \\ Z_w \\ 1 \end{bmatrix} = \begin{bmatrix} f_x & 0 & u_0 & 0 \\ 0 & f_y & v_0 & 0 \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \begin{bmatrix} R_{3*3} & t_{3*1} \\ 0 & 1 \end{bmatrix} \begin{bmatrix} X_w \\ Y_w \\ Z_w \\ 1 \end{bmatrix}

=[K330][R33t3101][XwYwZw1]=K33[R33t31][XwYwZw1]= \begin{bmatrix} K_{3*3} & 0 \end{bmatrix} \begin{bmatrix} R_{3*3} & t_{3*1} \\ 0 & 1 \end{bmatrix} \begin{bmatrix} X_w \\ Y_w \\ Z_w \\ 1 \end{bmatrix} = K_{3*3} \begin{bmatrix} R_{3*3} & t_{3*1} \end{bmatrix} \begin{bmatrix} X_w \\ Y_w \\ Z_w \\ 1 \end{bmatrix}

其中

K33=[fx0u00fyv0001] K_{3*3} = \begin{bmatrix} f_x & 0 & u_0 \\ 0 & f_y & v_0 \\ 0 & 0 & 1 \\ \end{bmatrix}

代码

世界坐标系转相机坐标系的函数

这个函数可以计算出后续所需的内参和外参
内参:用于后续的投影(如 projectPoints)或去畸变(如 undistort)。
外参:若需要将其他世界坐标系中的点转换到相机坐标系,需使用对应的 rvec 和 tvec
在opencv中上述的操作都封装成一个函数即"calibratecamera"

double cv::calibrateCamera	(	
InputArrayOfArrays 	objectPoints,
InputArrayOfArrays 	imagePoints,
Size 	imageSize,
InputOutputArray 	cameraMatrix,
InputOutputArray 	distCoeffs,
OutputArrayOfArrays 	rvecs,
OutputArrayOfArrays 	tvecs,
int 	flags = 0,
TermCriteria 	criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, DBL_EPSILON) 
)	
参数名 是否为赋值 功能
objectPoints 输入为世界坐标系中的点
imagePoints 输入对应的图像坐标系的点
imageSize 图像的大小,在计算相机的内参数和畸变矩阵需要用到
cameraMatrix 赋予计算后的内参矩阵
distCoeffs 输出畸变系数
rvecs 旋转向量,即外参矩阵的R
tvecs 位移向量,即外参矩阵的t
flags 标定时采用的参数
flag对应参数
CV_CALIB_USE_INTRINSIC_GUESS:使用该参数时,在cameraMatrix矩阵中应该有fx,fy,cx,cy的估计值。否则的话,将初始化(cx,cy)图像的中心点,使用最小二乘估算出fx,fy。如果内参数矩阵和畸变居中已知的时候,应该标定模块中的solvePnP()函数计算外参数矩阵。
CV_CALIB_FIX_PRINCIPAL_POINT:在进行优化时会固定光轴点。当CV_CALIB_USE_INTRINSIC_GUESS参数被设置,光轴点将保持在中心或者某个输入的值。
CV_CALIB_FIX_ASPECT_RATIO:固定fx/fy的比值,只将fy作为可变量,进行优化计算。当CV_CALIB_USE_INTRINSIC_GUESS没有被设置,fx和fy将会被忽略。只有fx/fy的比值在计算中会被用到。
CV_CALIB_ZERO_TANGENT_DIST:设定切向畸变参数(p1,p2)为零。
CV_CALIB_FIX_K1,...,CV_CALIB_FIX_K6:对应的径向畸变在优化中保持不变。如果设置了CV_CALIB_USE_INTRINSIC_GUESS参数,
CV_CALIB_RATIONAL_MODEL:计算k4,k5,k6三个畸变参数。如果没有设置,则只计算其它5个畸变参数。

相机坐标系到像素坐标系函数

将三维坐标系中的点转换为图像坐标系中的点,需结合相机内参(焦距、畸变参数等)和外参(旋转、平移向量)。

void cv::projectPoints(
    InputArray objectPoints, // 输入的三维点坐标,可以是一个包含三维点的数组或矩阵
    InputArray rvec, // 相机的旋转向量(旋转矩阵的旋转向量形式)
    InputArray tvec, // 相机的平移向量
    InputArray cameraMatrix, // 相机的内参数矩阵
    InputArray distCoeffs, // 相机的畸变参数
    OutputArray imagePoints, // 输出的二维图像坐标,可以是一个包含二维点的数组或矩阵
    OutputArray jacobian = noArray() // 输出的雅可比矩阵(可选参数)
)
objectPoints:输入的三维点坐标,可以是一个包含三维点的数组或矩阵。每个三维点都表示为一个 cv::Point3f 或 cv::Point3d 对象。
rvec:相机的旋转向量,通常由旋转矩阵转换而来。可以使用 cv::Rodrigues() 函数将旋转矩阵转换为旋转向量。旋转向量表示相机的旋转姿态。
tvec:相机的平移向量,表示相机位置相对于世界坐标系的平移。通常以 cv::Mat 对象的形式提供。
cameraMatrix:相机的内参数矩阵,也称为相机矩阵。它包含相机的焦距、主点坐标和畸变参数等信息。通常以 cv::Mat 对象的形式提供。
distCoeffs:相机的畸变参数,用于校正图像中的畸变。通常以 cv::Mat 对象的形式提供。
imagePoints:输出的二维图像坐标,用于存储投影后的二维点坐标。可以是一个包含二维点的数组或矩阵。每个二维点都表示为一个 cv::Point2f 或 cv::Point2d 对象。
jacobian(可选参数):输出的雅可比矩阵,用于表示投影函数相对于输入参数的导数。如果不需要该信息,可以忽略此参数。

参考

知乎大佬
b站三维重建之旅
蒋师兄笔记

赞赏