版权声明:本文为博主原创文章,未经博主允许不得转载。
https://blog.csdn.net/xiaomifanhxx/article/details/79560693
    使用相机以前,首先要进行相机标定,其原因是我们通过标定知道相机的内外参、得到内外参矩阵后可对相机拍摄的照片进行矫正,可以得到畸变较小的图像。而
相机标定的输入就是相机所拍的多帧图片的角点坐标,以及标定板图像上所有角点的空间坐标(一般Z轴假设为Z=0)。相机标定后的输出就是相机的内外参数。

    针对张正友标定相机的标定流程:1、获得多帧图片的角点坐标 2、获取标定板图像上所有角点的空间坐标 3、进行相机标定 4、对标定结果进行评价
 5、再次利用标定板图像进行矫正 6、 图像坐标系转世界坐标系


    1、获得多帧图片的角点坐标

对标定图片连续拍照,选择10-20帧图片,然后对其提取角点信息。(在此需要注意标定图片需要清晰)

提取图片角点选用的函数为:findChessboardCorners函数提取角点

findChessboardCorners函数原型:


    


* //! finds checkerboard pattern of the specified size in the image
* CV_EXPORTS_W bool findChessboardCorners( InputArray image, Size patternSize,
* OutputArray corners,
* int flags=CALIB_CB_ADAPTIVE_THRESH+CALIB_CB_NORMALIZE_IMAGE );  参数解析:
①Image,传入拍摄的棋盘图Mat图像,必须是8位的灰度或者彩色图像;


  ②patternSize,每个棋盘图上内角点的行列数,一般情况下,行列数不要相同,便于后续标定程序识别标定板的方向;

 ③corners,用于存储检测到的内角点图像坐标位置,一般用元素是Point2f的向量来表示:vector<Point2f>
image_points_buf;

 ④flags:用于定义棋盘图上内角点查找的不同处理方式,有默认值。

    2、对每一帧图片进一步提取亚像素角点信息

为了提高标定精度,需要在初步提取的角点信息上进一步提取亚像素信息,降低相机标定偏差,常用的方法是cornerSubPix


cornerSubPix函数原型:


* CV_EXPORTS_W void cornerSubPix( InputArray image, InputOutputArray corners,
* Size winSize, Size zeroZone,
* TermCriteria criteria ); 参数解析:①Image,传入拍摄的棋盘图Mat图像,最好是8位灰度图像,检测效率更高;
  ②
corners,初始的角点坐标向量,同时作为亚像素坐标位置的输出,所以需要是浮点型数据,一般用元素是Pointf2f/Point2d的向量来表示:vector<Point2f/Point2d>
imagePointsBuf

 ③winSize,大小为搜索窗口的一半;

 ④
zeroZone,死区的一半尺寸,死区为不对搜索区的中央位置做求和运算的区域。它是用来避免自相关矩阵出现某些可能的奇异性。当值为(-1,-1)时表示没有死区;

⑤criteria,定义求角点的迭代过程的终止条件,可以为迭代次数和角点精度两者的组合;

    3、获取标定板图像上所有角点的空间坐标(即物体的实际坐标)

    以和步骤一相同的方法获取世界坐标系的三维坐标即objectPoints,其用向量来表示vector<vector<Point3f>>
object_points


    4、进行相机标定 


    

获取到棋盘标定图的内角点图像坐标以及标定板图像的空间坐标之后,就可以使用calibrateCamera函数进行标定,计算相机内参和外参系数,

calibrateCamera函数原型:


* 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>>
object_points。需要依据棋盘上单个黑白矩阵的大小,计算出(初始化)每一个内角点的世界坐标;
 ②imagePoints,为每一个内角点对应的图像坐标点。和objectPoints一样,应该输入vector<vector<Point2f>>
image_points_seq形式的变量;

③imageSize,为图像的像素尺寸大小,在计算相机的内参和畸变矩阵时需要使用到该参数;

④cameraMatrix为相机的内参矩阵。输入一个Mat cameraMatrix即可,如Mat
cameraMatrix=Mat(3,3,CV_32FC1,Scalar::all(0));

⑤distCoeffs为畸变矩阵。输入一个Mat distCoeffs=Mat(1,5,CV_32FC1,Scalar::all(0));

⑥rvecs为旋转向量;应该输入一个Mat类型的vector,即vector<Mat>rvecs;

⑦tvecs为位移向量,和rvecs一样,应该为vector<Mat> tvecs;

⑧flags为标定时所采用的算法。有如下几个参数:


CV_CALIB_USE_INTRINSIC_GUESS:使用该参数时,在cameraMatrix矩阵中应该有fx,fy,u0,v0的估计值。否则的话,将初始化(u0,v0)图像的中心点,使用最小二乘估算出fx,fy。 

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_RATIONAL_MODEL:计算k4,k5,k6三个畸变参数。如果没有设置,则只计算其它5个畸变参数。

在使用该函数进行标定运算之前,需要对棋盘上每一个内角点的空间坐标系的位置坐标进行初始化,标定的结果是生成相机的内参矩阵cameraMatrix、相机的5个畸变系数distCoeffs,另外每张图像都会生成属于自己的平移向量和旋转向量。

    5、对标定结果进行评价

    
对标定结果进行评价的方法是通过得到的摄像机内外参数,对空间的三维点进行重新投影计算,得到空间三维点在图像上新的投影点的坐标,计算投影坐标和亚像素角点坐标之间的偏差,偏差越小,标定结果越好。


    对空间三维坐标点进行反向投影的函数是projectPoints,函数原型是:

    


* CV_EXPORTS_W void projectPoints( InputArray objectPoints,
* InputArray rvec, InputArray tvec,
* InputArray cameraMatrix, InputArray distCoeffs,
* OutputArray imagePoints,
* OutputArray jacobian=noArray(),
* double aspectRatio=0 );
    参数解析:①objectPoints,为相机坐标系中的三维点坐标;

②rvec为旋转向量,每一张图像都有自己的选择向量;


③tvec为位移向量,每一张图像都有自己的平移向量;

④cameraMatrix为求得的相机的内参数矩阵;


⑤distCoeffs为相机的畸变矩阵;

⑥imagePoints为每一个内角点对应的图像上的坐标点;

⑦jacobian是雅可比行列式;

⑧aspectRatio是跟相机传感器的感光单元有关的可选参数,如果设置为非0,则函数默认感光单元的dx/dy是固定的,会依此对雅可比矩阵进行调整;

    6、再次利用标定板图像进行矫正


    利用求得的相机的内参和外参数据,可以对图像进行畸变的矫正,使用undistort函数实现。


    undistort函数原型:


    


* CV_EXPORTS_W void undistort( InputArray src, OutputArray dst,
* InputArray cameraMatrix,
* InputArray distCoeffs,
* InputArray newCameraMatrix=noArray() );
    参数解析:①src,输入参数,代表畸变的原始图像;

②dst,矫正后的输出图像,跟输入图像具有相同的类型和大小;

③cameraMatrix为之前求得的相机的内参矩阵;

④distCoeffs为之前求得的相机畸变矩阵;

⑤newCameraMatrix,默认跟cameraMatrix保持一致;

    7、图像坐标系转世界坐标系


    图像坐标系转为世界坐标系采用的是透视变换,由张正友标定法单应性矩阵,再通过透视变换原理便可得到世界坐标系。

参考大佬博客:张正友标定:

http://blog.csdn.net/dcrmg/article/details/52939318

透视变换原理可参考如下博客:

http://blog.csdn.net/guduruyu/article/details/72518340


转载自:https://blog.csdn.net/xiaomifanhxx/article/details/79560693
<https://blog.csdn.net/xiaomifanhxx/article/details/79560693>