摄像机标定函数:
void cvCalibrateCamera2(
CvMat* object_points,
CvMat* image_points,
int* point_counts,
CvSize image_size,
CvMat* intrinsic_matrix,
CvMat* distortion_coeffs,
CvMat* rotation_vectors = NULL,
CvMat* translation_vectors = NULL,
int flags = 0
);
1、object_points,是一个N×3的矩阵,如果对于每一个棋盘,我们有k个角点,并且我们通过旋转棋盘,得到棋盘的M的视场图,那么此时N=k×M。
在使用棋盘的场合,我们另点z的坐标值为0,而x,y坐标用里面来度量,选用英寸单位,那么所有参数计算的结果也是用英寸表示。类似地,如果设置所有x坐标为0(而不是z坐标),那么意味着与摄像机相关的棋盘位置将主要在x方向上而不是在z方向上。棋盘上的正方形定义了一个单位,即如果正方形的边长为90mm,那么物体和摄像机坐标单位应该是mm/90。最简单的方式是我们定义棋盘的每一个方块为一个单位。
2、image_points,是一个N×2的矩阵。包含object_points所提供的所有点的坐标。即算法在图像中寻找到的角点的坐标。
3、point_counts,每个图像上角点的个数,以M×1矩阵形式提供,M是视场的数目
4、image_size,图像的大小,以像素为衡量单位。
5、intrinsic_matrix,摄像机内参数矩阵3×3大小。可以作为输入变量(此时会影响计算的结果),可以作为输出变量(本来主要就是为了求解该参数),内参数矩阵完全定义了理想摄像机模型的摄像机行为。
6、distortion_matrix,畸变系数,为5×1大小的矢量,可以作为输入变量,可以作为输出变量(同上),畸变系数的记录顺序是:k1,k2,p1,p2,k3;
7、rotation_vectors,大小为M×3,M为视场的个数。旋转矢量的讲解参考上一篇文章。可以通过cvRodrigues2()将旋转矢量转换为旋转矩阵。
8、translation_vectors,大小为M×3矩阵。
函数中的标志位:
1、CV_CALIB_USE_INTRINSIC_GUESS cvCalibrateCamera2()计算内参数矩阵的时候,通常不需要额外的信息。具体来说,参数cx和cy(图像中心)的初始值可以直接从变量image_size中得到(即(H-1)/2,(W-1)/2)),如果设置了该变量那么instrinsic_matrix假设包含正确的值,并被用作初始猜测,为cvCalibrateCamera2()做优化时所用。
2、CV_CALIB_USE_PRINCIPAL_POINT 可以和CV_CALIB_USE_INTRINSIC_GUESS 一起使用。如果仅设置了该标志位,那么设置图像的中心作为主点。如果一起使用,则设置主点位置为intrinsic_matrix矩阵提供的初始值。(这也是为什么,instrinsic_matrix不仅可以作为输出,也可以作为输入的原因了)
3、CV_CALIB_FIX_ASPECT_RATIO 如果设置了该标志位,那么在调用标定程序时,优化过程只同时改变fx和fy,而固定intrinsic_matrix的其他值(如果 CV_CALIB_USE_INTRINSIC_GUESS也没有被设置,则intrinsic_matrix中的fx和fy可以为任何值,但比例相关)。
4、CV_CALIB_FIX_FOCAL_LENGTH 该标志位在优化的时候,直接使用intrinsic_matrix传递过来的fx和fy。
5、CV_CALIB_FIX_K1,CV_CALIB_FIX_K2,CV_CALIB_FIX_K3 固定径向畸变k1,k2,k3。径向畸变参数可以通过组合这些标志设置为任意值。一般地最后一个参数应设置为0,初始使用鱼眼透镜。
6、CV_CALIB_ZERO_TANGENT_DIST 该标志在标定高级摄像机的时候比较重要,因为精确制作将导致很小的径向畸变。试图将参数拟合0会导致噪声干扰和数值不稳定。通过设置该标志可以关闭切向畸变参数p1和p2的拟合,即设置两个参数为0。
只计算外参数
函数cvFindExtrinsicCameraParam2()只计算外参数,接口如下:
void cvFindExtrinsicCameraParams2(
const CvMat* object_points,
const CvMat* image_points,
const CvMat* intrinsic_matrix,
const CvMat* distortion_coeffs,
CvMat* rotation_vector,
CvMat* translation_vector
);
函数的形参和标定函数是一样的,只是内参数矩阵和畸变系数是直接提供,而非计算得到的。
矫正
标定摄像机通常想做两件事情:
1)矫正畸变效应
2)根据获得的图像重构三维场景
“矫正”是数学上去掉透镜畸变
“校正”是数学上将图像排列整齐。
OpenCV提供了直接使用的校正算法,下面两个方法均能完成矫正:
1)直接一次性调用函数cvUndistort2()完成。
2)通过函数cvInitUndistortMap()和cvRemap()来更有效的处理,通常适合处理视频,或从同一个摄像机得到多个图像的应用。(其实很好理解的,我们利用一帧图像计算畸变映射,将后面的图像帧均利用该映射,并且计算畸变映射是一个耗时的操作)。
cvInitUndistortMap()函数计算畸变映射。
cvRemap()表示在任意图像上应用该映射。
// Undistort images
void cvInitUndistortMap(
const CvMat* intrinsic_matrix,//内参数矩阵
const CvMat* distortion_coeffs,//畸变系数
cvArr* mapx,//32位单通道矩阵
cvArr* mapy
);
void cvRemap(
const CvArr* src,
CvArr *dst,
const CvArr *mapx,
const CvArr *mapy,
int flags=CV INTER LINEAR+CV WARP FILL OUTLIERS,
CvScalar fillval=cvScalarAll(0) );
void cvUndistort2(
const CvArr* src,
CvArr* dst,
const cvMat* intrinsic_matrix,
const cvMat* distortion_coeffs
);
// Undistort a list of 2D points only
void cvUndistortPoints( //函数的功能:将一些列来至于原始图像的2维点坐标并且计算相应的矫正点坐标。
const CvMat* _src,
CvMat* dst,
const CvMat* intrinsic_matrix,
const CvMat* distortion_coeffs,
const CvMat* R = 0,//R表示两个摄像机之间的旋转矩阵
const CvMat* Mr = 0; //Mr表示矫正后的摄像机内参数。
);