利用OpenCV3进行鱼眼镜头标定

来源:互联网 发布:stm32f4 嵌入式数据库 编辑:程序博客网 时间:2024/04/30 23:42


转自:http://www.cnblogs.com/kooo/articles/3987201.html

利用OpenCV3进行鱼眼镜头标定

  OpenCV3.0 alpha在8月21日发布,其中增加了鱼眼镜头模型,提供了标定、去畸变等一系列api,其实现方法参考了{Camera Calibration Toolbox for Matlab}。本文简单介绍了OpenCV 中实现的鱼眼镜头模型,给出调用demo的关键代码、注释和去畸变的结果。

鱼眼镜头模型

  鱼眼镜头的内参模型可以表示为,与普通镜头的内参一样,但畸变参数不同,为,含义如下:

  设(X,Y,Z)为一个三维坐标点,投影在图像上的二维坐标为(u,v),如果不考虑畸变,投影关系如下:

  

  R和t分别代表相机外参中的旋转矩阵和平移向量。

  当考虑鱼眼镜头的畸变后,投影关系转化为:

  

标定流程

  首先调用OpenCV的FindChessboardCorners()来寻找图像上的标定板的角点,再根据标定板的尺寸指定这些角点对应的三维点的三维坐标,再调用fisheye::calibrate()来进行标定,利用标定结果中的内参和畸变参数调用fisheye::undistortImage()对图像做去畸变操作。

代码片段

  

复制代码
tuple<Mat, Mat, double> calibrate_fisheye(const vector<Mat>& images, const Settings& s) {    /*寻找二维角点*/    auto corners = chessboard_corners(images, s);    /*计算二维角点对应的三维点坐标*/    auto object_points = vector<vector<Point3d>>(corners.size(), object_positions(s));    cv::Matx33d K;    cv::Vec4d D;int flag = 0;    flag |= cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC;    flag |= cv::fisheye::CALIB_CHECK_COND;    flag |= cv::fisheye::CALIB_FIX_SKEW;/*非常重要*/    double rms = fisheye::calibrate(object_points,         corners,         s.imageSize,        K, D,         cv::noArray(), cv::noArray(),         flag,         cv::TermCriteria(3, 20, 1e-6));    return make_tuple(Mat(K), Mat(D), rms);}
复制代码

  代码非常简单,和标定普通的镜头的区别在于:

  1. 角点坐标和和对应的三维点坐标为double类型,普通镜头为float类型,弄混后不能正确执行
  2. flag必须指定CALIB_FIX_SKEW,代表求解时假设内参中fx=fy,与鱼眼镜头标定论文中一致,没有这个假设的话是得不到结果的

结果

 

  测试了OpenCV的测试数据,34张图像进行标定,重投影误差均值为0.343542。

  左边为源图像,右边为去畸变结果:

未完成工作

  本来以为在畸变图像上找棋盘格角点会比一般的方法复杂一些,没想到利用FindChessboardCorners就可以成功找到,所以就暂时这样用了,对于畸变比较大的图像,或者手工标出角点,或者实现论文《Automatic Detection of Checkerboards on Blurred and Distorted Images》中自动提取棋盘格的方法。

参考:

http://docs.opencv.org/master/modules/calib3d/doc/calib3d.html

0 0