摄像机模型与标定——标定函数

摄像机内参数,能够让我们将3D坐标转换为2D图像坐标。

说明:要理解下面的函数中参数的真实用法还需要阅读一下相机标定程序。

摄像机标定函数:

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表示矫正后的摄像机内参数。  
); 



你可能感兴趣的:(opencv,图像处理)