基于opencv的手眼标定算法详解一-----------opencv之相机标定函数calibrateCamera()介绍

手眼标定问题描述

在机器人校准测量、机器人手眼协调以及机器人辅助测量等领域,都要求知道机器人执行器末端(抓取臂)坐标系和传感器(比如用来测量三维空间中目标位置和方向并固定在机器人手上的摄像机)坐标系之间的相互关系,确定这种转换关系在机器人领域就是通常所说的手眼标定。
将手眼标定系统如下图所示,其中为机器人执行器末端坐标系之间相对位置姿态的齐次变换矩阵;为摄像机坐标系之间相对位置姿态的齐次变换矩阵;为像机与机器人执行器末端之间的相对位置姿态齐次矩阵。

基于opencv的手眼标定算法详解一-----------opencv之相机标定函数calibrateCamera()介绍_第1张图片

opencv之相机标定函数calibrateCamera()介绍

简单理论介绍
opencv有函数可以进行径向或者切向畸变的矫正,首先说这两种畸变的样子:

基于opencv的手眼标定算法详解一-----------opencv之相机标定函数calibrateCamera()介绍_第2张图片
在现实中就是这样

基于opencv的手眼标定算法详解一-----------opencv之相机标定函数calibrateCamera()介绍_第3张图片
桶形畸变与枕型畸变都属于径向畸变。

切向畸变:
产生原因透镜不完全平行于图像平面,发生于成像仪粘贴在摄像机的时候,此现象是发生在相机制作过程中,由于感光平面跟透镜不平行。

对于切向畸变,opencv的矫正函数如下:

X(corrected) = X(1+ k1R ^ 2 + k2 R ^ 4 + k3* R ^ 6)
Y(corrected) = Y(1+ k1R ^ 2 + k2 R ^ 4 + k3* R ^ 6)

对于径向畸变(由于摄像机镜头与成像平面不完全平行),opencv的矫正函数如下:

X(corrected) = X + (2P1XY + P2(R^2 + 2X ^ 2))
Y(corrected) = Y + (2
P2XY + P1(R^2 + 2Y ^ 2))

总共加起来,opencv一共有5个畸变参数,形成一个矩阵就是:

(k1,k2,p1,p2,k3)

其次就是opencv函数中的参数与这几个参数联系起来:

double cv::calibrateCamera (

InputArrayOfArrays objectPoints,

InputArrayOfArrays imagePoints,

Size imageSize,

InputOutputArray cameraMatrix,

InputOutputArray distCoeffs,

OutputArrayOfArrays rvecs,

OutputArrayOfArrays tvecs,

OutputArray stdDeviationsIntrinsics,

OutputArray stdDeviationsExtrinsics,

OutputArray perViewErrors,

int flags = 0,

TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, DBL_EPSILON)

)

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)

)

参数详解:


相机标定中的有三个矩阵的含义如下:

  1. 外参数矩阵:告诉你现实世界点(世界坐标)怎样经过旋转平移,然后落到另一个现实世界(摄像机坐标)的坐标点上面。
  2. 内参数矩阵:告诉上诉的那个点在1的基础后,是如何经过摄像机的镜头,并通过针孔成像和电子转换而成为像素点的。
  3. 畸变矩阵:告诉为什么上面那个像素点并没有落到理论计算该落到的位置上面,并且产生了偏移与变形。

objectPoints:世界坐标系的点,在使用时输入vector格式

imagePoints:其对应的图像点,和objectPoints一样,应该输入vector的类型变量。

imageSize:图像的大小,在计算机的内参数和畸变矩阵中需要用到。

cameraMatrix:内参数矩阵,输入一个Mat cameraMatrix即可。

distCoeffs:畸变矩阵,输入一个Mat distCoeffs即可。

rvecs:旋转变量,应该输入一个Mat 类型的vector,即vector recs.因为每个vector会得到一个rvecs。

.tvecs:位移变量,和rvecs一样,也应该为vector tvecs.

stdDeviationsInstrinsics:内参数的输出变量,输出顺序为:
(fx,fy,cx,cy,k1,k2,p1,p2,k3,k4,k5,k6,s1,s2,s3,s4,Tx,Ty),如果算不出某一个值的话,其值默认为零。

stdDeviationsExtrinsics:外参数的输出向量,输出顺序:(R1,T1,…,RM,TM),M为标定图片的个数,Ri,Ti是1*3的向量。

perViewErrors:每个标定图片的重投影均方根误差的输出向量。

criteria:迭代优化算法的终止准则。

flags:标定函数所采用的模型,可输入如下某个或者某几个参数:

CV_CALIB_USE_INTRINSIC_GUESS:使用该参数时,将包含有效的fx,fy,cx,cy的估计值的内参矩阵cameraMatrix,作为初始值输入,然后函数对其做进一步的优化,如果不使用这个参数,将图像的中心点初始化光轴点坐标(cx,cy),使用最小二乘估算出fx,fy。如果已知内部参数(内部矩阵和畸变系数),就不需要使用这个函数来估计外参,可以使用solvePnP()函数来计算外参矩阵。

CV_CALIB_FIX_PRINCIPAL_POINT:在进行优化时会固定光轴点,光轴点将保持为图像的中心点,当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参数,就从提供的畸变系数矩阵中得到,否则设置为0.

CV_CALIB_RATIONAL_MODEL(理想模型):启用畸变k4,k5,k6三个畸变参数,使标定函数使用理想模型,返回8个系数,如果没有设置,则只计算其他5个畸变参数。

CALIB_THIN_PRISM_MODEL(薄棱镜畸变模型):启用畸变系数S1,S2,S3,S4。如果CV_CALIB_USE_INTRINSIC_GUESS设置,使用提供的畸变系数矩阵中的值,否则,设置为0.

CALIB_FIX_S1_S2_S3_S4:优化过程中不改变薄棱镜畸变系数S1,S2,S3,S4如果CV_CALIB_USE_INTRINSIC_GUESS设置,使用提供的畸变系数矩阵中的值,否则设置为0.

CALIB_TILTED_MODEL(倾斜模型):启用畸变系数Tx,Ty。标定函数使用倾斜传感器模型并返回14个系数,如果不设置标志,则函数计算并返回只有5个失真系数。

CALIB_FIX_TAUX_TAUY:在优化过程中,倾斜传感器模型的系数不被改变,如果CV_CALIB_USE_INTRINSIC_GUESS设置,从提供的畸变系数矩阵中得到,否则,设置为0。

函数返回:

重投影的总的均方根误差。

函数的作用:

其实现的功能:从校准图案的多个视图中发现相机的内部与外部参数。

在每个视图中,必须指定三维物体点及其相应的二维投影的坐标。这可以通过使用已知几何形状和易于检测特征点的对象来实现。这样的对象称为标定或校准模式,而且opencv有对棋盘格标定的内置支持,目前。固有参数的初始化只实现平面校准模式(对象点的z坐标,也必须全部为0)。只要提供初始相机内参矩阵cameraMatrix,也可以用于三维标定。

在算法执行以下步骤:

计算初始的内在参数(只能用于平面校准模式的选项)或从输入参数中读取他们,畸变系数开始都为0,除非有CV_CALIB_FIX_K指定。

估计初始相机的姿态,就像内在参数已知一样,这是通过使用solvePnP,运行的全局Levenberg-Marquardt优化算法来最小化投影误差,投影误差等于所提取到的图像上的特征点坐标和三维点,根据使用相机的参数和姿态计算得到图像上的投影坐标的距离的综合。

calibrateCamera()坐标系

在calibrateCmaera()的输入参数,第一个参数为objectPoints—每一个视角中,关键点的世界坐标系,可以用vector

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

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

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

基于opencv的手眼标定算法详解一-----------opencv之相机标定函数calibrateCamera()介绍_第4张图片
至于该函数传入的第二个参数:imgPoints–每一个视角中,特征点的图像的坐标,可以使用vector类型,这个值可以通过findChessboardCorners函数从图像中获得,

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

这时候需要drawChessboardCorners函数,把检测到的2D点在原图上面显示出来,
基于opencv的手眼标定算法详解一-----------opencv之相机标定函数calibrateCamera()介绍_第5张图片
这个函数按照先变化x,而后变化y的方式一次画点,先画的行为为红色,逐渐变成蓝色。

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

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

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

你可能感兴趣的:(opencv,opencv之手眼标定系列)