OpenCV 相机标定 (Python版)

相机标定 + 相机畸变矫正 (基于OpenCV + Matlab + Python)

  • 前言
  • 一、标定前准备:采集相机原画面
  • 二、开始标定:计算相机内参与畸变
  • 三、标定代码: Python 版本
  • 四、矫正效果对比
  • 总结


前言


  此博客记录了利用 matlab 中 cameraCalibrator 工具箱进行相机标定求取相机参数,并利用 OpenCV 对相机畸变进行矫正。


一、标定前准备:采集相机原画面


  1. 生成 “棋盘式” 标定板,可以用 matlab 生成,代码参考如下:

image = (checkerboard(300,4,5)>0.5);
figure, imshow(image);
imwrite(image,'F:\\image\\abc.png');


  2. 将标定板用 A4 纸打印好或者找块屏幕显示都行,然后要测量标定板实物上实际黑白正方形的边长,后面会用到。

  3. 采集镜头各个角度大概 15~20 张图片,参考如下。
OpenCV 相机标定 (Python版)_第1张图片

二、开始标定:计算相机内参与畸变


   1.在MATLAB的命令行窗口输入 cameraCalibrator 打开标定工具。

在这里插入图片描述

   标定窗口如图所示:

OpenCV 相机标定 (Python版)_第2张图片

   2.选择 “Add Images” 将上述准备好的图片全部导入

在这里插入图片描述

   然后出现如下界面,输入刚才测量的标定板正方形黑白块的边长后点击确定。

OpenCV 相机标定 (Python版)_第3张图片

   3.点击 “Options” 选项,进行如下设置(使用两参数,选择错切和桶形畸变。)
   注:具体原理参见OpenCV官网介绍:
http://docs.opencv.org/2.4/doc/tutorials/calib3d/camera_calibration/camera_calibration.html

OpenCV 相机标定 (Python版)_第4张图片
   对于不会科学上网的朋友可以参考以下理论解释,简单说就是对于相机的畸变从 “径向” 和 “切向” 两个方向去考虑,总共有 5 个参数,三个径向畸变(k1, k2, k3)和两个切向畸变(p1, p2),考虑到 k3 对矫正影响较大,容易产生扭曲,故仅采用 k1, k2 两参数,即令 k3 = 0。

OpenCV 相机标定 (Python版)_第5张图片

   4.点击 “Calibrate” 开始标定。

在这里插入图片描述
   标定结束后点击 “Export Camera Parameters” 导出参数。

OpenCV 相机标定 (Python版)_第6张图片
   保存成功后,打开变量,即可看到保存的参数值。

在这里插入图片描述
OpenCV 相机标定 (Python版)_第7张图片

三、标定代码: Python 版本


   标定出的参数中:

   RadialDistortion 对应k1,k2(k3 默认为 0)。
  TangentialDistortion 对应p1,p2。
  IntrinsicMatrix 对应内参,注意其与 OpenCV 中的转置关系,参考下图对比,实际代码编写时需注意!OpenCV 相机标定 (Python版)_第8张图片

在这里插入图片描述

   Python 对应畸变矫正代码(参数一 一对应),以函数形式给出,输入待矫正图形变量,返回矫正好的图形变量。

OpenCV 相机标定 (Python版)_第9张图片

在这里插入图片描述

在这里插入图片描述

# 摄像头畸变矫正函数,输入待矫正的图形变量
def undistort(frame):
    fx = 7.867891195067076e+02
    cx = 6.823648074697487e+02
    fy = 8.454139535337483e+02
    cy = 5.185634497802844e+02
    k1, k2, p1, p2, k3 = -0.327782591286664, 0.104488486639823, -9.519326514054385e-04, 2.433441734520703e-04, 0.0

    # 相机坐标系到像素坐标系的转换矩阵
    k = np.array([
        [fx, -0.766489481509873, cx],
        [0, fy, cy],
        [0, 0, 1]
    ])
    # 畸变系数
    d = np.array([
        k1, k2, p1, p2, k3
    ])
    height, weight = frame.shape[:2]
    mapx, mapy = cv2.initUndistortRectifyMap(k, d, None, k, (weight, height), 5)
    
	# 返回矫正好的图形变量
    return cv2.remap(frame, mapx, mapy, cv2.INTER_LINEAR)

四、矫正效果对比


   矫正前
OpenCV 相机标定 (Python版)_第10张图片
   矫正后,可以看出矫正后画面明显变小。
OpenCV 相机标定 (Python版)_第11张图片


总结

  此博客为相机标定求取内参畸变,并对其进行矫正,采用的是 120° 超广角的镜头,镜头畸变较大,效果对比明显。不过现在主流的工业镜头畸变都比较低,求取相机参数主要还是为了测算,本博客后续将整理 OpenCV 中 solvePnP 测距的实现方法。

你可能感兴趣的:(OpenCV,项目复盘,RoboMaster,opencv,python,matlab)