0、两条路线
- 先单目标定再双目标定:
- findChessboardCorners:寻找棋盘图中棋盘角点
- find4QuadCornerSubpix:对粗提取的角点进行精确化
- cornerSubPix:在角点检测中精确化角点位置
- drawChessboardCorners:将发现到的所有角点绘制到所提供的图像上
- calibrateCamera:利用定标来计算摄像机的内参数和外参数
- projectPoints:通过得到的摄像机内外参数,对空间的三维点进行重新投影计算,得到新的投影点
- 利用标定结果对棋盘图进行矫正
(1). initUndistortRectifyMap用来计算畸变映射,remap把求得的映射应用到图像上
(2). 或者undistort一个函数搞定 - stereoCalibrate:双目摄像机标定,计算了两个摄像头进行立体像对之间的转换关系,根据左右相机的参数矩阵,生成两个相机之间的关系矩阵,以及基本和本质矩阵
- stereoRectify:作用是为每个摄像头计算立体校正的映射矩阵。所以其运行结果并不是直接将图片进行立体矫正,而是得出进行立体矫正所需要的映射矩阵
- 直接进行双目标定
- findChessboardCorners找到角点
- drawChessboardCorners画出角点
- stereoCalibrate直接计算左右相机内参矩阵、畸变量、R、T、E、F
- undistortPoints去畸变
- computeCorrespondEpilines
- stereoRectify
- initUndistortRectifyMap
- remap
路线2的精度会下降
一、单目标定
1.提取角点(findChessboardCorners)
从文件中读入图像,通过findChessboardCorners找到角点的图像坐标系坐标,这个函数采用Harris算法获得角点。
CV_EXPORTS_W bool findChessboardCorners(InputArray image,
Size patternSize,
OutputArray corners,
int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE );
参数说明:
- Image:输入的棋盘图,必须是8位的灰度或者彩色图像,类型为cv::Mat
- patternSize:棋盘图中每行和每列角点的个数,类型为cv::Size()
- corners:检测到的角点,类型为std::vector< cv::Point2f >。
- flags :不同的操作标记
- CALIB_CB_ADAPTIVE_THRESH:1,使用自适应阈值法把图像转换为黑白图,而不是使用一个固定的阈值。
- CALIB_CB_NORMALIZE_IMAGE:2,在利用固定阈值或自适应阈值法二值化图像之前,利用直方图均衡化图像。
- CALIB_CB_FILTER_QUADS:4,使用额外的标准(如轮廓面积,周长,正方形形状)来过滤掉在轮廓检索阶段提取的假四边形。
- CALIB_CB_FAST_CHECK:8,对图像运行一个快速检查机制以查找棋盘板的角点,如果没有找到角点则返回一个快捷提醒。当没有观察到棋盘时,可以极大地加快在退化条件下的调用。
bool ok = findChessboardCorners(imageInput, board_size, image_points, CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE);
2.对提取到的角点进行亚像素精确化(find4QuadCornerSubpix或cornerSubPix)
两种方法,可取其一
2.1 find4QuadCornerSubpix
bool cv::find4QuadCornerSubpix ( InputArray img,
InputOutputArray corners,
Size region_size
)
参数说明:
img:输入的Mat矩阵,最好是8位灰度图像,检测效率更高;
corners:初始的角点坐标向量,同时作为亚像素坐标位置的输出,所以需要是浮点型数据,一般用元素是Pointf2f/Point2d的向量来表示。
region_size:角点搜索窗口的尺寸,优化坐标时考虑的邻域范围。
find4QuadCornerSubpix(view_gray, image_points, Size(5, 5));
2.2 cornerSubPix
在角点检测中精确化角点位置,其函数原型如下:
void cornerSubPix( InputArray image,
InputOutputArray corners,
Size winSize,
Size zeroZone,
TermCriteria criteria);
函数参数说明如下:
image:输入图像
corners:输入角点的初始坐标以及精准化后的坐标用于输出。
winSize:搜索窗口边长的一半,例如如果winSize=Size(5,5),则一个大小为的搜索窗口将被使用。
zeroZone:搜索区域中间的dead region边长的一半,有时用于避免自相关矩阵的奇异性。如果值设为(-1,-1)则表示没有这个区域。
criteria:角点精准化迭代过程的终止条件。也就是当迭代次数超过criteria.maxCount,或者角点位置变化小于criteria.epsilon时,停止迭代过程。
cv::TermCriteria criteria = cv::TermCriteria(cv::TermCriteria::MAX_ITER + cv::TermCriteria::EPS, 100, 1e-5);
cv::cornerSubPix(view_gray, image_points, cv::Size(5, 5), cv::Size(-1, -1), criteria);
3.显示角点(drawChessboardCorners)
使用**drawChessboardCorners()**函数进行棋盘格绘制显示
void cv::drawChessboardCorners(
cv::InputOutputArray image, // 棋盘格图像(8UC3)即是输入也是输出
cv::Size patternSize, // 棋盘格内部角点的行、列数
cv::InputArray corners, // findChessboardCorners()输出的角点
bool patternWasFound // findChessboardCorners()的返回值
);
参数说明:
- image:棋盘格图像(8UC3),既是输入也是输出
- patternSize:棋盘格内部角点的行、列,和cv::findChessboardCorners()指定的相同
- corners:检测到的棋盘格角点
- patternWasFound :cv::findChessboardCorners()的返回值
drawChessboardCorners(imageInput, this->board_size, image_points, ok);
4.单目相机标定(calibrateCamera)
【OpenCV3学习笔记 】相机标定函数 calibrateCamera( ) 使用详解(附相机标定程序和数据)
求解出该相机的内参数和每一个视角的外参数。
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)
)
参数说明:
- objectPoints :世界坐标系中的点。在使用时,应该输入vector< vector< Point3f > >。
- imagePoints :其对应的图像点。和objectPoints一样,应该输入vector< vector< Point2f > >型的变量
- imageSize :图像的大小,在计算相机的内参数和畸变矩阵需要用到
- cameraMatrix :内参数矩阵。输入一个Mat cameraMatrix即可。
- distCoeffs :畸变矩阵。输入一个Mat distCoeffs即可。
- rvecs :旋转向量;应该输入一个Mat的vector,即vector< Mat > rvecs。因为每个vector< Point3f >会得到一个rvecs。
- tvecs :位移向量;和rvecs一样,也应该为vector< Mat >。
- 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参数被设置,保持为输入的值。
- 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_USE_INTRINSIC_GUESS参数,就从提供的畸变系数矩阵中得到。否则,设置为0。
- CV_CALIB_RATIONAL_MODEL(理想模型):启用畸变k4,k5,k6三个畸变参数。使标定函数使用有理模型,返回8个系数。如果没有设置,则只计算其它5个畸变参数。
- CALIB_THIN_PRISM_MODEL (薄棱镜畸变模型):启用畸变系数S1、S2、S3和S4。使标定函数使用薄棱柱模型并返回12个系数。如果不设置标志,则函数计算并返回只有5个失真系数。
- CALIB_FIX_S1_S2_S3_S4 :优化过程中不改变薄棱镜畸变系数S1、S2、S3、S4。如果cv_calib_use_intrinsic_guess设置,使用提供的畸变系数矩阵中的值。否则,设置为0。
- CALIB_TILTED_MODEL (倾斜模型):启用畸变系数tauX and tauY。标定函数使用倾斜传感器模型并返回14个系数。如果不设置标志,则函数计算并返回只有5个失真系数。
- CALIB_FIX_TAUX_TAUY :在优化过程中,倾斜传感器模型的系数不被改变。如果cv_calib_use_intrinsic_guess设置,从提供的畸变系数矩阵中得到。否则,设置为0。
- criteria: 迭代优化算法的终止准则
函数返回:重投影的总的均方根误差。
在相机标定之后,可以得到相机内参数矩阵与畸变系数cameraMatrix,distCoeffs