OpenCV相机标定
OpenCV相机标定
相机内参矩阵cameraMatrix
\[cameraMatrix = \begin{bmatrix}
f_x & 0 & c_x \\
0 & f_y & c_y \\
0 & 0 & 1
\end{bmatrix}
\]
相机畸变系数distCoeffs
畸变系数:径向畸变\((k_1,k_2,k_3)\), 切向畸变\((p_1,p_2)\)
\[distCoeffs = \begin{pmatrix}
k_1 & k_2 & p_1 & p_2 & k_3
\end{pmatrix}
\]
findChessboardCorners
棋盘格角点检测
#include <opencv2/calib3d.hpp>
bool cv::findChessboardCorners(
InputArray image,
Size patternSize,
OutputArray corners,
int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE
)
Python:
retval, corners = cv.findChessboardCorners(image, patternSize[, corners[, flags]])
image
:输入 棋盘格图像,必须是8位灰度或彩色图像(cv::Mat
)
patternSize
:输入 棋盘图内角点的行列数(注意:不是棋盘格的行列数,如棋盘格的行列数分别为4、8,而内部角点的行列数分别是3、7,因此这里应该指定为cv::Size(3, 7)
)(cv::Size
)corners
:输出 检测到的棋盘格角点(std::vector<cv::Point2f>
)flags
:输入 用于指定在检测棋盘格角点的过程中所应用的一种或多种过滤方法(int
):cv::CALIB_CB_ADAPTIVE_THRESH
:使用自适应阈值将图像转化成二值图像cv::CALIB_CB_NORMALIZE_IMAGE
:归一化图像灰度系数(用直方图均衡化或者自适应阈值)cv::CALIB_CB_FILTER_QUADS
:在轮廓提取阶段,使用附加条件排除错误的假设cv::CALIB_CV_FAST_CHECK
:快速检测
drawChessboardCorners
棋盘格角点的绘制
#include <opencv2/calib3d.hpp>
void cv::drawChessboardCorners(
InputOutputArray image,
Size patternSize,
InputArray corners,
bool patternWasFound
)
Python:
image = cv.drawChessboardCorners(image, patternSize, corners, patternWasFound)
image
:输入 棋盘格图像,必须是8位灰度或彩色图像(cv::Mat
)patternSize
:输入 棋盘图内角点的行列数(cv::Size
)corners
:输入findChessboardCorners
检测到的角点(std::vector<cv::Point2f>
)patternWasFound
:输入 标志位,用来指示定义的棋盘内角点是否被完整的探测到,true表示别完整的探测到,函数会用直线依次连接所有的内角点,作为一个整体,false表示有未被探测到的内角点,这时候函数会以(红色)圆圈标记处检测到的内角点;(bool
)
cornerSubPix
亚像素检测
#include <opencv2/imgproc.hpp>
void cv::cornerSubPix(
InputArray image,
InputOutputArray corners,
Size winSize,
Size zeroZone,
TermCriteria criteria
)
Python:
corners = cv.cornerSubPix(image, corners, winSize, zeroZone, criteria)
image
:输入 8位或浮点型单通道图像(cv::Mat
)corners
:输入输出 输入角点的初始坐标,输出更加精确的点(std::vector<cv::Point2f>
)winSize
:输入 大小为搜索窗口的一半,如果winSize=cv::Size(5,5),则搜索窗口为11*11(cv::Size
)zeroZone
:输入 死区的一半尺寸,死区为不对搜索区的中央位置做求和运算的区域。它是用来避免自相关矩阵出现某些可能的奇异性。当值为(-1,-1)时表示没有死区(cv::Size
)criteria
:输入 求角点的迭代过程的终止条件,可以为迭代次数和角点精度两者的组合(cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 30, 0.1)
)
经过重投影
projectPoints
,cornerSubPix
与find4QuadCornerSubpix
效果对比,find4QuadCornerSubpix
进行亚像素精确化的重投影结果不如cornerSubPix
参考文章
calibrateCamera
求解相机内参和外参
#include <opencv2/calib3d.hpp>
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)
)
Python:
retval, cameraMatrix, distCoeffs, rvecs, tvecs = cv.calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs[, rvecs[, tvecs[, flags[, criteria]]]])
objectPoints
:输入 世界坐标系中的三维点集。在使用时,应该是有多张图片同时进行标定,即应该输入一个三维坐标点的向量的向量(std::vector<std::vector<cv::Point3f>>
)。测量棋盘上单个黑白矩阵的实际大小,以初始化每一个内角点的世界坐标imagePoints
:输入 每一个3D内角点对应的图像坐标2D点(std::vector<std::vector<cv::Point2f>>
)imageSize
:输入 图像的像素尺寸大小,在计算相机的内参和畸变矩阵时需要使用到该参数(cv::Size
)cameraMatrix
:输出 相机内参矩阵(cv::Mat
)distCoeffs
:输出 相机畸变系数矩阵(cv::Mat
)rvecs
:输出 旋转向量(std::vector<cv::Vec3d>
)tvecs
:输出 平移向量(std::vector<cv::Vec3d>
)flags
:输入 标定时所采用的算法(int
),有如下几个参数: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_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、相机的5个畸变系数distCoeffs,另外每张图像都会生成属于自己的平移向量和旋转向量。
projectPoints
将世界坐标系中的3D坐标投影到像素坐标系中的2D坐标
可用于计算标定的误差
#include <opencv2/calib3d.hpp>
void cv::projectPoints(
InputArray objectPoints,
InputArray rvec,
InputArray tvec,
InputArray cameraMatrix,
InputArray distCoeffs,
OutputArray imagePoints,
OutputArray jacobian = noArray(),
double aspectRatio = 0
)
Python:
imagePoints, jacobian = cv.projectPoints(objectPoints, rvec, tvec, cameraMatrix, distCoeffs[, imagePoints[, jacobian[, aspectRatio]]])
objectPoints
:世界坐标系中的3D坐标(std::vector<cv::Point3f>
)rvec
:世界坐标系到相机坐标系的旋转向量(cv::Vec3d
)tvec
:世界坐标系到相机坐标系的平移向量(cv::Vec3d
)cameraMatrix
:相机内参矩阵(cv::Mat
)distCoeffs
:相机畸变系数矩阵(cv::Mat
)imagePoints
:3D坐标点在像素坐标系中估计的2D坐标(std::vectorcv::Point2f)jacobian
:可选输出的雅可比矩阵aspectRatio
:是否固定“宽高比”参数标志
initUndistortRectifyMap
计算畸变参数
#include <opencv2/calib3d.hpp>
void cv::initUndistortRectifyMap(
InputArray cameraMatrix,
InputArray distCoeffs,
InputArray R,
InputArray newCameraMatrix,
Size size,
int m1type,
OutputArray map1,
OutputArray map2
)
Python:
map1, map2 = cv.initUndistortRectifyMap(cameraMatrix, distCoeffs, R, newCameraMatrix, size, m1type[, map1[, map2]])
cameraMatrix
:输入 相机内参矩阵(cv::Mat
)distCoeffs
:输入 相机畸变系数矩阵(cv::Mat
)R
:输入 畸变矫正矩阵,在客观空间中的转换对象(cv::Mat::eye(cv::Size(3, 3), CV_32FC1)
)newCameraMatrix
:输入 新的3*3的浮点型矩矩阵(cv::Mat
)size
:输入 失真图像的大小(cv::Size
)m1type
:输入 第一个输出的map(CV_32FC1/CV_16SC2
)map1
:输出 x映射函数(cv::Mat
)map2
:输出 y映射函数(cv::Mat
)