opencv 鱼眼相机模型原理及去畸变方法

opencv 鱼眼相机模型原理及去畸变方法

1. 官方文档地址

[官方文档地址点击这里](OpenCV: Fisheye camera model)

2. 命名空间

cv::fisheye

3. 详细描述鱼眼模型

P P P为世界参照系中坐标 X X X的三维点(存储在矩阵 X X X中)。摄像机参照系中 P P P的坐标向量为:
X c = R X + T Xc=RX+T Xc=RX+T
其中 R R R为旋转向量 o r or or对应的旋转矩阵( T T T为平移矩阵): R = r o d r i g u e s ( o m ) R = rodrigues(om) R=rodrigues(om);称 x , y , z x, y, z x,y,z X c Xc Xc的3个坐标:
x = X c 1 y = X c 2 z = X c 3 x=Xc_1\\ y=Xc_2\\ z=Xc_3\\ x=Xc1y=Xc2z=Xc3
P P P的针孔投影坐标(归一化坐标)为 [ a ; b ] [a;b] [a;b]:
a = x / z b = y / z r 2 = a 2 + b 2 θ = a t a n ( r ) a=x/z \\ b=y/z \\ r^2= a^2+b^2 \\ \theta=atan(r) a=x/zb=y/zr2=a2+b2θ=atan(r)

鱼眼畸变:
θ d = θ ( 1 + k 1 θ 2 + k 2 θ 4 + k 3 θ 6 + k 4 θ 8 ) \theta_d=\theta(1+k_1\theta^2+k_2\theta^4+k_3\theta^6+k_4\theta^8) θd=θ(1+k1θ2+k2θ4+k3θ6+k4θ8)
畸变点坐标为 [ x ′ ; y ′ ] [x';y'] [x;y]
x ′ = ( θ d / r ) a y ′ = ( θ d / r ) b x'=(\theta_d/r)a\\ y'=(\theta_d/r)b x=(θd/r)ay=(θd/r)b
最后转换成像素坐标(重投影):最终像素坐标向量 [ u ; v ] [u;v] [u;v]:

u = f x ( x ′ + α y ′ ) + c x v = f y y ′ + c y u=f_x(x'+\alpha y')+c_x \\ v=f_y y'+c_y u=fx(x+αy)+cxv=fyy+cy
最后再最近邻插值即可去畸变。

4. 代码

#include 

// 文件路径,如果不对,请调整
std::string input_file = "../fisheye.jpg";

int main(int argc, char **argv) {
  // 本程序实现鱼眼的等距投影去畸变模型
  // 畸变参数(本例设为零)
  double k1 = 0, k2 = 0, k3 = 0, k4 = 0;

  // 内参
  double fx = 689.21, fy = 690.48, cx = 1295.56, cy = 942.17;

  cv::Mat image = cv::imread(input_file);
  int rows = image.rows, cols = image.cols;
  cv::Mat image_undistort = cv::Mat(rows, cols, CV_8UC3); // 去畸变以后的图

  // 计算去畸变后图像的内容
  for (int v = 0; v < rows; v++)
    for (int u = 0; u < cols; u++) {

      double u_distorted = 0, v_distorted = 0;
      // 按照公式,计算点(u,v)对应到畸变图像中的坐标(u_distorted,v_distorted) (~6 lines)

      // start your code here
      //归一化平面
      double x = (u - cx)/fx;
      double y = (v - cy)/fy;

      //引入畸变
      double r = sqrt(x*x + y*y);
      double theta = atan(r);
      double theta_d = theta + k1*pow(theta, 3) + k2*pow(theta, 5) + k3*pow(theta, 7) + k4*pow(theta, 9);
      double x_distorted = theta_d*x/r;
      double y_distorted = theta_d*y/r;
      
      //重新投影到像素坐标
      u_distorted = (0.01*y_distorted+x_distorted)*fx + cx;
      v_distorted = y_distorted*fy + cy;
      // end your code here

      // 赋值 (最近邻插值)去畸变
      if (u_distorted >= 0 && v_distorted >= 0 && u_distorted < cols &&
          v_distorted < rows) {
        image_undistort.at<cv::Vec3b>(v, u) =
            image.at<cv::Vec3b>((int)v_distorted, (int)u_distorted);
      } else {
        image_undistort.at<cv::Vec3b>(v, u) = 0;
      }
    }

  // 画图去畸变后图像
  cv::imshow("image undistorted", image_undistort);
  cv::imwrite("fisheye_undist.jpg", image_undistort);
  cv::waitKey();

  return 0;
}

5.其它

其它的鱼眼模型的函数等请见opencv官方文档。

你可能感兴趣的:(SLAM,opencv,计算机视觉,人工智能)