相机标定

坐标系

世界坐标系 $(x_w,y_w,z_w)$

相机坐标系 $(x_c,y_c,z_c)$

图像坐标系 $(x,y)$

$x_p=f\frac{x_c}{z_c},y_p=f\frac{y_c}{z_c}$

像素坐标系 $(u,v)$

$u=\frac{x_c}{d_x}+u_0,v=\frac{y_c}{d_y}+v_0$

坐标系转换

1 世界坐标系到相机坐标系(旋转矩阵)

2 相机坐标系到图像坐标系(透视投影矩阵 3X4矩阵)

3 图像坐标系到像素坐标系(K 内参矩阵)

张正友标定法

在不考虑透镜畸变情况下求解内参和外参

相机内参: fx,fy,u0,v0(,r=K12) ​

相机外参:$T_x,T_y,T_z,\omega,\delta,\theta$

单应性矩阵:单应性矩阵用于表示投射图像间的透视变换,变换图像的视图

单应性:从一个平面到另一个平面的投影映射,例如

定义标定板平面为世界坐标系中 Z=0 的平面

其中,$s$为尺度因数(使得单应性定义到该尺度的比例),$H=K\begin{bmatrix}r_1 & r_2 & t\end{bmatrix}$为成像平面和标定平面之间的单应矩阵(由变换和相机内参两部分组成,$r_1,r_2,t$ 分别为旋转矩阵的前两个列向量和平移向量),$\begin{bmatrix}R&t\end{bmatrix}$是一个3X4的矩阵(前3X3是旋转矩阵,后3X1是一个平移向量t)

图像平面(src)的点集与目标平面(dst)上的点集 间的关系(由单应性矩阵确定):

记:$H=\begin{bmatrix}h_1&h_2&h_3\end{bmatrix}$

求内参矩阵

(1)(2)可推导出两等式,

通过两张不同位置的图片,可以标定后求解出相机内参矩阵K(四个未知数四个方程)

求外参矩阵

在求得内参矩阵后,则可以估算外参矩阵:

考虑畸变,求解畸变系数

径向畸变处理

参数最优化

非线性最小二乘法,极大似然估计


1
2
3
4
5
// image creator
if(!((i+j)%2))
rectangle(ChessImage, Point(Start.x+i*SingleSize, Start.y+j*SingleSize),
Point(Start.x+(i+1)*SingleSize-1, Start.y+(j+1)*SingleSize-1),
Scalar(0, 0, 0), -1);
1
2
3
4
5
// image capture
VideoCapture capture;
Mat frame;
capture.open( [filename] )
while(true) capture >> frame
1
2
3
// opencv/samples/cpp/calibration.cpp
cv::findChessboardCorners() //绘制交点
cv::calibrationCamera() //校准
1
2
3
4
5
6
// cv::undistort() //校正畸变
double x = (u - cx)/fx, y = (v - cy)/fy;
// X/Z , Y/Z -> 归一化坐标 (X/Z Y/Z 1)-> 映射到二维 -> (x y) -> 写成极坐标形式 (r theta)
double r = sqrt(x*x + y*y); // 极坐标 长度
double u_distort = fx * x * (1 + k1*pow(r, 2) + k2*pow(r, 4) + k3*pow(r, 6) ) + 2*p1*x*y + p2*(pow(r, 2) + 2*pow(x, 2) ) + cx;
double v_distort = fy * y * (1 + k1*pow(r, 2) + k2*pow(r, 4) + k3*pow(r, 6) ) + p1*(pow(r, 2) + 2*pow(y, 2) ) + 2*p2*x*y + cy;

畸变方程

Undistort Sample

1
2
./imagelist_creator imagelist.yaml [path].jpg
./calibration -w=[num] -h=[num] [-op] [-oe] [...] imagelist.yaml
1
2
3
# out_camera_data.yml
camera_matrix: //相机内参
distortion_coefficients: //畸变系数

参考:

  • 1 视觉SLAM十四讲:从理论到实践(第2版)