第一部分,opencv 3.0 以后的接口:
主要解释的函数有:
1、单相机标定
①、 Rodrigues 罗德里格斯变换
②、projectPoints 计算世界坐标系中的点在相机相平面的投影点。
③、CalibrateCamera 单相机标定
④、calibrationMatrixValues 通过相机内参矩阵解析相机参数
2、双相机标定
主要是通过过优化来求解两个相机的位姿,优化的图模型为:
3、遗留问题:
_jacobian 参数需要深入了解。
void cv::reprojectImageTo3D(InputArray _disparity,
OutputArray __3dImage, InputArray _Qmat,
bool handleMissingValues, int dtype)
namespace cv
{
static void collectCalibrationData(InputArrayOfArrays objectPoints,
InputArrayOfArrays imagePoints1,
InputArrayOfArrays imagePoints2,
Mat& objPtMat, Mat& imgPtMat1, Mat* imgPtMat2,
Mat& npoints)
static Mat prepareCameraMatrix(Mat& cameraMatrix0, int rtype)
static Mat prepareDistCoeffs(Mat& distCoeffs0, int rtype, int outputSize = 14)
} // namespace cv
/*
* 功能: rodrigues 变换
* 参数:
* [in] _src 输入旋转矩阵,如果是3*3,则输出就3*1.若果输入时3*1,输出就3*3。
* [out] _dst 传递的参数可以不用声明矩阵的大小。
* [out] _jacobian 赋值为空即可。
* 返回值:
*
*
* 存在疑问:
* _jacobian 是用来干什么的。
*/
void cv::Rodrigues(InputArray _src, OutputArray _dst, OutputArray _jacobian)
void cv::matMulDeriv(InputArray _Amat, InputArray _Bmat,
OutputArray _dABdA, OutputArray _dABdB)
void cv::composeRT(InputArray _rvec1, InputArray _tvec1,
InputArray _rvec2, InputArray _tvec2,
OutputArray _rvec3, OutputArray _tvec3,
OutputArray _dr3dr1, OutputArray _dr3dt1,
OutputArray _dr3dr2, OutputArray _dr3dt2,
OutputArray _dt3dr1, OutputArray _dt3dt1,
OutputArray _dt3dr2, OutputArray _dt3dt2)
/*
* 功能: 计算世界坐标系到相机相平面的投影
* 参数:
* [in] _opoints 世界坐标系中的点坐标,一维数组,std::vector
* [in] _rvec 旋转向量(旋转轴+角度(模)),从世界坐标系到相机坐标系的变换
* [in] _tvec 平移向量,从世界坐标系到相机坐标系的变换
* [in] _cameraMatrix 相机内参,3*3矩阵,类型可以使64F也可以是32F,最好是64F
* [in] _distCoeffs n*1矩阵,根据畸变模型不同,n的取值不同
* [out] _ipoint 世界坐标系中点在图像上的投影坐标,类型为vector;
* [out] _jacobian 存在疑问???? ------此参数设置为空矩阵即可,对精度没有影响。
* [in] aspectRatio 如果为0,则相机矩阵中fx,fy输入什么就是什么,如果不为0,则fx需要重新赋值为fx = aspectRatio*fy
*
* 返回值:
*
*
* 存在疑问:
* _jacobian 是用来干什么的。
*/
void cv::projectPoints(InputArray _opoints,
InputArray _rvec,
InputArray _tvec,
InputArray _cameraMatrix,
InputArray _distCoeffs,
OutputArray _ipoints,
OutputArray _jacobian,
double aspectRatio)
{
Mat opoints = _opoints.getMat();
int npoints = opoints.checkVector(3), depth = opoints.depth();
CV_Assert(npoints >= 0 && (depth == CV_32F || depth == CV_64F));
CvMat dpdrot, dpdt, dpdf, dpdc, dpddist;
CvMat *pdpdrot = 0, *pdpdt = 0, *pdpdf = 0, *pdpdc = 0, *pdpddist = 0;
_ipoints.create(npoints, 1, CV_MAKETYPE(depth, 2), -1, true);
Mat imagePoints = _ipoints.getMat();
CvMat c_imagePoints(imagePoints);
CvMat c_objectPoints = opoints;
Mat cameraMatrix = _cameraMatrix.getMat();
Mat rvec = _rvec.getMat(), tvec = _tvec.getMat();
CvMat c_cameraMatrix = cameraMatrix;
CvMat c_rvec = rvec, c_tvec = tvec;
double dc0buf[5] = { 0 };
Mat dc0(5, 1, CV_64F, dc0buf);
Mat distCoeffs = _distCoeffs.getMat();
if (distCoeffs.empty())
distCoeffs = dc0;
CvMat c_distCoeffs = distCoeffs;
int ndistCoeffs = distCoeffs.rows + distCoeffs.cols - 1;
if (_jacobian.needed())
{
_jacobian.create(npoints * 2, 3 + 3 + 2 + 2 + ndistCoeffs, CV_64F);
Mat jacobian = _jacobian.getMat();
pdpdrot = &(dpdrot = jacobian.colRange(0, 3));
pdpdt = &(dpdt = jacobian.colRange(3, 6));
pdpdf = &(dpdf = jacobian.colRange(6, 8));
pdpdc = &(dpdc = jacobian.colRange(8, 10));
pdpddist = &(dpddist = jacobian.colRange(10, 10 + ndistCoeffs));
}
cvProjectPoints2(&c_objectPoints, &c_rvec, &c_tvec, &c_cameraMatrix, &c_distCoeffs,
&c_imagePoints, pdpdrot, pdpdt, pdpdf, pdpdc, pdpddist, aspectRatio);
}
cv::Mat cv::initCameraMatrix2D(InputArrayOfArrays objectPoints,
InputArrayOfArrays imagePoints,
Size imageSize, double aspectRatio)
double cv::calibrateCamera(InputArrayOfArrays _objectPoints,
InputArrayOfArrays _imagePoints,
Size imageSize, InputOutputArray _cameraMatrix, InputOutputArray _distCoeffs,
OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, int flags, TermCriteria criteria)
/*
* 功能: 单目相机标定--内参,畸变,外参
* 参数:
* [in] _objectPoints 二维数组std::vector>,也可以是std::vector>。外面一层的vector存储的是图像个数,里面vector存储的是世界坐标系中角点的坐标,一般z轴为0.
* -----当然也不排除z不为0的特殊情况,代码里对角点不在一个平面的情况也做了处理。尽量不要是角点不在一个平面上,否则单应矩阵肯定不准确,所以标定结果也一定不准确;
* [in] _imagePoints 二维数组std::vector>,也可以是std::vector>.外面一层的vector存储的是图像个数,里面vector存储的是图像坐标系中的坐标pixel。注意每组
* 图像的世界坐标系中的角点坐标与图像像坐标系中的角点坐标要一致;
* [in] imageSize 图像的size,主要用来初始化相机内参矩阵中的主点;
* [in/out] _cameraMatrix 当flags中设定了CALIB_USE_INTRINSIC_GUESS 标记,则会使内参矩阵中的主点(如果为0,则默认为图像中点)和焦距信息;设置此值后,不会进行张正友论文中的闭解形式的计算,直接进行极大似然估计。
* 当flags中设定了CALIB_FIX_ASPECT_RATIO 标记,则会使用内参矩阵红焦距fx/fy的比值,在以后的优化过程中fy为变量,fx只会随fy变。当没有设定当flags中设定了CALIB_USE_INTRINSIC_GUESS标记时,这种情况下内参矩阵其他值没有用。
* [in/out] _distCoeffs Output vector of distortion coefficients (k1,k2,p1,p2[,k3[,k4,k5,k6[,s1,s2,s3,s4[,τx,τy]]]]) of 4, 5, 8, 12 or 14 elements.这是opencv文档中的介绍,其实我发现输出的种类中没有4,有5,8,12,14.一般初始化赋值是全部输入为0即可。
* 输入:
* 如果输入中内含有值,如果被flags设置为不变,则优化过程中,不会对其改动。注意,此处如果flags中不包含CALIB_USE_INTRINSIC_GUESS,则畸变量优化之前全部置零。若设置CALIB_USE_INTRINSIC_GUESS则优化初始值用输入值。
* 输出:
* 当flags设置为CALIB_RATIONAL_MODEL 畸变模型时,k1,k2,p1,p2,k3,k4,k5,k6 共8个值有效,输出畸变矩阵的维度为(1,8)
* 当flags设置为CALIB_THIN_PRISM_MODEL 畸变模型时,k1,k2,p1,p2,k3,k4,k5,k6,s1,s2,s3,s4 共12值有效,输出畸变矩阵维度为(1,12)
* 当flags设置为CALIB_TILTED_MODEL 畸变模型时,k1,k2,p1,p2,k3,k4,k5,k6,s1,s2,s3,s4,τx,τy 共14值有效,输出畸变矩阵维度为(1,14)
* 如果不设值畸变模型,则k1,k2,p1,p2,k3, 共5个值有效,输出畸变矩阵维度为(1,5)
* 另外,当flags设置为CALIB_FIX_K1,CALIB_FIX_K2,CALIB_FIX_K3,CALIB_FIX_K4,CALIB_FIX_K5,CALIB_FIX_K6时,可以固定任意一个值,使其在优化过程中不变。
*
*
* [out] _rvecs 注意这是一个3*1的矩阵数组,表示旋转(可以用Rodriguez变换成矩阵方式),从世界坐标到相机坐标系m = A[R,t]M。初始化的时候可以使用std::vector 进行初始化。输出的个数是与图像个数一样的
* [out] _tvecs 表示方式如_rvecs一致,大小个数,以及初始化的方式一致。表示从世界坐标系到相机坐标系的平移。
* [out] stdDeviationsIntrinsics Output vector of standard deviations estimated for intrinsic parameters. Order of deviations values: (fx,fy,cx,cy,k1,k2,p1,p2,k3,k4,k5,k6,s1,s2,s3,s4,τx,τy) If one of parameters is not estimated, it's deviation is equals to zero.如果不使用可以赋值为空矩阵
* [out] stdDeviationsExtrinsics Output vector of standard deviations estimated for extrinsic parameters. Order of deviations values: (R1,T1,…,RM,TM) where M is number of pattern views, Ri,Ti are concatenated 1x3 vectors.
* [out] _perViewErrors 每幅图像的投影误差。创建一个mat矩阵放进去即可,输出的矩阵是(nimage * 1) 类型为CV_64F
* [in] flags 注意这个是可以多个flags组合使用的。
* CALIB_USE_INTRINSIC_GUESS: 一般不推荐使用。赋值这个标记位,代表输入的参数矩阵作为优化的初始值,而不是用张正友闭解形式的求解出内参矩阵,作为初始矩阵。
* CALIB_FIX_PRINCIPAL_POINT: 一般不推荐使用。赋值这个标记位,代表内参矩阵中的主点在在优化的过程中不变。
* CALIB_FIX_ASPECT_RATIO : 一般不推荐使用。赋值这个标记位,代表优化的时候有fy有效,fx会根据优化之前fx/fy的比值确定。
* CALIB_ZERO_TANGENT_DIST : 一般不推荐使用。赋值这个标记位,切向畸变被置为0.p1=p2 =0;
* CALIB_FIX_K1,CALIB_FIX_K2,CALIB_FIX_K3,CALIB_FIX_K4,CALIB_FIX_K5,CALIB_FIX_K6 一般不推荐使用:赋值这个标记位,优化中不对这些值进行改变
* CALIB_RATIONAL_MODEL : opencv中3个畸变模型之一,输出畸变个数为8
* CALIB_THIN_PRISM_MODEL : opencv中3个畸变模型之一,输出畸变个数为12
* CALIB_TILTED_MODEL : opencv中3个畸变模型之一,输出畸变个数为14
* CALIB_FIX_S1_S2_S3_S4 : 一般不推荐使用,这个是CALIB_THIN_PRISM_MODEL模型使用的变量。赋值此标记位,s1,s,s3,s4优化时固定不变;
* CALIB_FIX_TAUX_TAUY : 一般不推荐使用,这个是CALIB_TILTED_MODEL模型使用的变量。赋值此标记位,TAUX,TAUY优化时固定不变;
* 个人认为:这里flags主要用途,或者如果要提高标定精度,我认为主要是选择畸变模型,其他的对精度改善没有什么大的影响。
* 所以一般当相机为桶形畸变和枕形畸变,flags保持为0即可,不需要设置。
* [in] criteria 极大似然估计的目标函数在使用LM迭代优化算法时的迭代停止条件。
*
*
* 返回值:
* 返回值为重投影误差。
*
* 存在疑问:
* 内外参数返回的标准差计算的原理,貌似跟LM计算过程相关。
*/
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, TermCriteria criteria)
/*
* 功能: 根据相机内参矩阵,获得相机的信息,例如fov等
* 参数:
* [in] _cameraMatrix 标定后得到的相机矩阵
* [in] imageSize 图像的大小,以像素为单位
* [in] apertureWidth Sensor的宽度,物理尺寸mm,也可不为mm,输出也不是毫米
* [in] apertureHeight Sensor的高度,物理尺寸mm,也可不为mm,输出也不是毫米
* [out] fovx 输出的是角度
* [out] fovy 输出的是角度
* [out] focalLength 焦距的长度,单位与sensor高度的单位一致
* [out] principalPoint 主点位置,单位与sensor高度的单位一致
* [out] aspectRatio fy/fx
*
* 返回值:
*
*
*/
void cv::calibrationMatrixValues(InputArray _cameraMatrix, Size imageSize,
double apertureWidth, double apertureHeight,
double& fovx, double& fovy, double& focalLength,
Point2d& principalPoint, double& aspectRatio)
/*
* 功能: 双目相机标定
* 参数:
* [in] _objectPoints 标定板中的目标点
* [in] _imagePoints1 图像1(相机1)中的观测点,与标定板中的目标点对应;
* [in] _imagePoints2 图像2(相机2)中的观测点,与标定板中的目标点对应;
* [in/out] _cameraMatrix1 相机1的内参矩阵,最好输入一个标定好的内参;
* [in/out] _distCoeffs1 相机1的畸变矩阵,最好输入一个标定好的内参;
* [in/out] _cameraMatrix2 相机2的内参矩阵,最好输入一个标定好的内参;
* [in/out] _distCoeffs2 相机2的畸变矩阵,最好输入一个标定好的内参;
* [in] imageSize 输入图像的大小;
* [out] _Rmat 点从相机1到相机2的旋转矩阵变换;1-->2
* [out] _Tmat 点从相机1到相机2的平移变换; 1-->2
* [out] _Emat 本质矩阵
* [out] _Fmat 基础矩阵 x2' F x1 = 0 1-->2
* [in] flags 参考单相机标定
* [in] criteria 迭代优化停止条件
*
* 返回值:
* 重投影误差
*
*/
double cv::stereoCalibrate(InputArrayOfArrays _objectPoints,
InputArrayOfArrays _imagePoints1,
InputArrayOfArrays _imagePoints2,
InputOutputArray _cameraMatrix1, InputOutputArray _distCoeffs1,
InputOutputArray _cameraMatrix2, InputOutputArray _distCoeffs2,
Size imageSize, OutputArray _Rmat, OutputArray _Tmat,
OutputArray _Emat, OutputArray _Fmat, int flags,
TermCriteria criteria)
void cv::stereoRectify(InputArray _cameraMatrix1, InputArray _distCoeffs1,
InputArray _cameraMatrix2, InputArray _distCoeffs2,
Size imageSize, InputArray _Rmat, InputArray _Tmat,
OutputArray _Rmat1, OutputArray _Rmat2,
OutputArray _Pmat1, OutputArray _Pmat2,
OutputArray _Qmat, int flags,
double alpha, Size newImageSize,
Rect* validPixROI1, Rect* validPixROI2)
bool cv::stereoRectifyUncalibrated(InputArray _points1, InputArray _points2,
InputArray _Fmat, Size imgSize,
OutputArray _Hmat1, OutputArray _Hmat2, double threshold)
cv::Mat cv::getOptimalNewCameraMatrix(InputArray _cameraMatrix,
InputArray _distCoeffs,
Size imgSize, double alpha, Size newImgSize,
Rect* validPixROI, bool centerPrincipalPoint)
cv::Vec3d cv::RQDecomp3x3(InputArray _Mmat,
OutputArray _Rmat,
OutputArray _Qmat,
OutputArray _Qx,
OutputArray _Qy,
OutputArray _Qz)
void cv::decomposeProjectionMatrix(InputArray _projMatrix, OutputArray _cameraMatrix,
OutputArray _rotMatrix, OutputArray _transVect,
OutputArray _rotMatrixX, OutputArray _rotMatrixY,
OutputArray _rotMatrixZ, OutputArray _eulerAngles)
namespace cv
{
static void adjust3rdMatrix(InputArrayOfArrays _imgpt1_0,
InputArrayOfArrays _imgpt3_0,
const Mat& cameraMatrix1, const Mat& distCoeffs1,
const Mat& cameraMatrix3, const Mat& distCoeffs3,
const Mat& R1, const Mat& R3, const Mat& P1, Mat& P3)
}
float cv::rectify3Collinear(InputArray _cameraMatrix1, InputArray _distCoeffs1,
InputArray _cameraMatrix2, InputArray _distCoeffs2,
InputArray _cameraMatrix3, InputArray _distCoeffs3,
InputArrayOfArrays _imgpt1,
InputArrayOfArrays _imgpt3,
Size imageSize, InputArray _Rmat12, InputArray _Tmat12,
InputArray _Rmat13, InputArray _Tmat13,
OutputArray _Rmat1, OutputArray _Rmat2, OutputArray _Rmat3,
OutputArray _Pmat1, OutputArray _Pmat2, OutputArray _Pmat3,
OutputArray _Qmat,
double alpha, Size newImgSize,
Rect* roi1, Rect* roi2, int flags)
/* End of file. */