OpenCV相机标定calibrateCamera坐标系详解

时间:2024-05-20 16:00:58

OpenCV中,可以使用calibrateCamera函数,通过多个视角的2D/3D对应,求解出该相机的内参数和每一个视角的外参数。


使用C++接口时的输入参数如下:

CV_EXPORTS_W double calibrateCamera( InputArrayOfArrays objectPoints,
                                     InputArrayOfArrays imagePoints,
                                     Size imageSize,
                                     CV_OUT InputOutputArray cameraMatrix,
                                     CV_OUT InputOutputArray distCoeffs,
                                     OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs,
                                     int flags=0, TermCriteria criteria = TermCriteria(
                                         TermCriteria::COUNT+TermCriteria::EPS, 30, DBL_EPSILON) );


objectPoints - 每一个视角中,关键点的世界坐标系。可以使用vector < vector <Point3f> >类型,第一层vector表示每一个视角,第二层vector表示每一个点。

如果使用opencv自带的棋盘格,可以直接传入交叉点(不包括边角)的实际坐标,以物理世界尺度(例如毫米)为单位。

写坐标时,要保证z轴为0,按照先x变化,后y变化,从小到大的顺序来写。如果网格尺寸为5厘米,写作:(0,0,0),(5,0,0), (10,0,0)...(0,5,0), (5,5,0), (10,5,0),...

如下图例子,x方向是8个交叉点,y方向3个较差点。

OpenCV相机标定calibrateCamera坐标系详解


imagePoints - 每一个视角中,关键点的图像坐标系。可以使用vector < vector <Point2f> >类型。

这个值可以通过findChessboardCorners函数从图像中获得。注意:传入findChessboardCorners函数的patternSize参数,要和objectPoints中的行列数统一。


imageSize - 图像尺寸。

flags - 参数。决定是否使用初始值,扭曲参数个数等。


输出参数如下:

OpenCV相机标定calibrateCamera坐标系详解

cameraMatrix - 3*3的摄像机内矩阵。

distCoeffs - 4*1(具体尺寸取决于flags)。对图像坐标系进行进一步扭曲。

这两个参数是内参数,可以把摄像机坐标系转换成图像坐标系。


rvecs - 每一个视图的旋转向量。vector<Mat>类型,每个vec为3*1,可以用Rodrigues函数转换为3*3的旋转矩阵。

tvecs - 每一个视图的平移向量。vector<Mat>类型,每个vec为3*1。

这两个参数是外参数,每一个视图不同,可以把世界坐标系转换成摄像机坐标系。


CV_CALIB_USE_INTRINSIC_GUESS:使用该参数时,在cameraMatrix矩阵中应该有fx,fy,cx,cy的估计值。否则的话,将初始化(cx,cy)图像的中心点,使用最小二乘估算出fxfy如果内参数矩阵和畸变居中已知的时候,应该标定模块中的solvePnP()函数计算外参数矩阵。

CV_CALIB_FIX_PRINCIPAL_POINT:在进行优化时会固定光轴点。当CV_CALIB_USE_INTRINSIC_GUESS参数被设置,光轴点将保持在中心或者某个输入的值。

CV_CALIB_FIX_ASPECT_RATIO:固定fx/fy的比值,只将fy作为可变量,进行优化计算。当CV_CALIB_USE_INTRINSIC_GUESS没有被设置,fxfy将会被忽略。只有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:计算k4k5k6三个畸变参数。如果没有设置,则只计算其它5个畸变参数。




* 在2.10文档中,写的是from the model coordinate space (in which object points are specificed) to the world coordinate space。提到model容易引起歧义。


看到这里,问题来了:这个世界坐标系是什么样的?

在objectPoints中,我们实际只设定了每个交叉点的间隔,具体xyz指向哪里却没有给出。

这时候,需要使用drawChessboardCorners函数,把检测到的2D点在原图上显示出来:

OpenCV相机标定calibrateCamera坐标系详解

这个函数按照先变化x,而后变化y的方式依次画点。先画的行为红色,逐渐变为蓝色。

回顾我们写objectPoints时的方式,可以推断出世界坐标的方向:图中x轴正方向向左,y轴正方向远离镜头,根据右手螺旋,z轴正方向向下。

总结来说,calibrateCamera函数给出的世界坐标方向,是由obejctPoints的设定顺序,以及findChessboardCorners的检测顺序共同决定的。

但是,findChessboardCorners先检测那个角点并不确定。前例从右下角开始,以下就从左上角开始:

OpenCV相机标定calibrateCamera坐标系详解


另一种常见用法是:先用calibrateCamera标定好摄像机内参,而后使用solvePnP函数只求解外参。solvePnP函数的参数意义和calibrateCamera类似。