本程序的执行界面如下图所示,只需要输入标定板影像路径,即可全自动完成相机的标定,得出相机的焦距和畸变系数。
图 1. 相机标定程序运行界面
下面首先简略介绍相机标定的原理,然后简略介绍OpenCV的实现思路,最后详细介绍带UI的相机标定程序的开发方法。
一,相机标定的原理
(参考《学习OpenCV(中文版)》(清华大学出版社))
要通过拍摄的二维相片信息回复相片中物体的三维信息,就必须明确物方点三维坐标(X,Y,Z)与其在相片上的坐标(x,y)之间的几何关系。物方坐标和像方坐标的几何关系由相机的成像模型确定。普通相机的成像模型都是小孔成像,其数学模型为中心投影,表达式为:
相机标定的目标是求出内参数fx,fy,cx,cy,即焦距(主距)和像主点偏移量,下面我们来分析如何求得这四个内参数。
由以上公式可以看出,每拍摄一张图像,就有6个外参数未知量(三个角度和三个偏移量,注意W矩阵中的R0-R8的独立参数只有三个角度),以及4个内参数未知量,同时每拍摄一张图像,对于图像上每个像点就会产生2个方程(展开以上公式很容易得到)。
以棋盘作为标定板进行试验,假设棋盘有K个角点,一共拍摄N幅图像,那么将会有2NK个方程,6N+4个未知量,想要求解4个内参数,则只需2NK>=6N+4,于是,当N=1且K=5时即可完成标定。然而因为棋盘上无论有多少个点,真正独立的只有4个,因为其他点可以通过线性变换得出。因此将K固定为4,那么可得出能完成标定的要求是N>=2,即至少拍摄两幅棋盘。考虑到误差问题,一般需要10幅以上7*8个角点的棋盘图像才能完成高质量的标定。
此外,实际的相机的透镜成像并非完全的小孔成像,而是存在畸变的,主要是径向畸变和切向畸变,在数学上通过二阶多项式来模拟。在原来的方程q=sMWQ的基础上,增加一个畸变改正系数矩阵即可得到带畸变纠正的标定模型。这样做会带来另外4个内参数(2个径向畸变系数和2个切向畸变系数),但是可以通过增加拍摄图像数目来增加方程进而完成解算。
二,OpenCV对相机标定的实现思路
OpenCV提供了cvCalibrateCamera2函数用以完成相机标定,以下是函数说明(来自百度百科)
void cvCalibrateCamera2( const CvMat* object_points, const CvMat* image_points, const CvMat* point_counts, CvSize image_size, CvMat* intrinsic_matrix, CvMat* distortion_coeffs, CvMat* rotation_vectors=NULL, CvMat* translation_vectors=NULL, int flags=0 );
-
object_points
-
定标点的世界坐标,为3xN或者Nx3的矩阵,这里N是所有视图中点的总数。
-
image_points
-
定标点的图像坐标,为2xN或者Nx2的矩阵,这里N是所有视图中点的总数。