1.无畸变
相机内参包括相机矩阵参数和畸变系数。
相机内参矩阵为3*3的矩阵:M = [fx 0 ppx ; 0 fy ppy ; 0 0 1]
畸变系数:k1 k2 k3 p1 p2
首先看一下无畸变情况下,已知相机坐标系内的一个点[xc, yc, zc],通过内参矩阵求出该点在图像平面的投影点[u, v]。如下图,其中M矩阵边上相机的内参矩阵,x = xc / zc, y = yc / zc:
2.Brown-Conrady 畸变模型
当相机存在畸变的时候,需要根据畸变模型修正(x, y)的值为(x’ , y’), 然后使 u = x’ * fx + ppx, v = y’ * fy + ppy。畸变模型如下图,此处介绍的是Brown-Conrady 畸变模型:
下面给出相应的代码实现:
struct Intrinsics
{
float ppx;
float ppy;
float fx;
float fy;
float coeffs[5];
bool distortion;
};
void Project_Point_To_Pixel(float pixel[2], const struct Intrinsics * intrin, const float point[3])
{
float x = point[0] / point[2], y = point[1] / point[2];
if(intrin->distortion){
float r2 = x*x + y*y;
float f = 1 + intrin->coeffs[0]*r2 + intrin->coeffs[1]*r2*r2 + intrin->coeffs[4]*r2*r2*r2;
x *= f;
y *= f;
float dx = x + 2*intrin->coeffs[2]*x*y + intrin->coeffs[3]*(r2 + 2*x*x);
float dy = y + 2*intrin->coeffs[3]*x*y + intrin->coeffs[2]*(r2 + 2*y*y);
x = dx;
y = dy;
}
pixel[0] = x * intrin->fx + intrin->ppx;
pixel[1] = y * intrin->fy + intrin->ppy;
}
3. Opencv 里畸变图像矫正过程
有兴趣的读者可以查看opencv源码“modules/imagproc/undistort.cpp”, opencv图片矫正过程首先通过相机标定得到相机内参矩阵和畸变系数,然后对非畸变图像每个像素计算其在畸变图像中的像素位置,然后非畸变图像的像素值通过双线性插值来计算。函数cv::initUndistortRectifyMap就是非畸变图像每个像素计算其在畸变图像中的像素位置,查看源码就能看出来其畸变模型使用的是上文介绍的Brown-Conrady 畸变模型。
参考:http://wiki.opencv.org.cn/index.php/Cv照相机定标和三维重建
void cv::initUndistortRectifyMap( InputArray _cameraMatrix, InputArray _distCoeffs,
InputArray _matR, InputArray _newCameraMatrix,
Size size, int m1type, OutputArray _map1, OutputArray _map2 );