相机内参与畸变模型

时间:2024-04-04 08:56:26

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 );