内参、外参、畸变参数三种参数与相机的标定方法

转载:https://blog.csdn.net/yangdashi888/article/details/51356385
https://blog.csdn.net/Loser__Wang/article/details/51811347

1、 相机参数是三种不同的参数。

 相机的内参数是六个分别为:1/dx、1/dy、r、u0、v0、f。

opencv1里的说内参数是4个其为fx、fy、u0、v0。实际其fx=F*Sx,其中的F就是焦距上面的f,Sx是像素/没毫米即上面的dx,其是最后面图里的后两个矩阵进行先相乘,得出的,则把它看成整体,就相当于4个内参。其是把r等于零,实际上也是六个。

dx和dy表示:x方向和y方向的一个像素分别占多少长度单位,即一个像素代表的实际物理值的大小,其是实现图像物理坐标系与像素坐标系转换的关键。u0,v0表示图像的中心像素坐标和图像原点像素坐标之间相差的横向和纵向像素数

相机的外参数是6个:三个轴的旋转参数分别为(ω、δ、 θ),然后把每个轴的3*3旋转矩阵进行组合(即先矩阵之间相乘),得到集合三个轴旋转信息的R,其大小还是3*3;T的三个轴的平移参数(Tx、Ty、Tz)。R、T组合成成的3*4的矩阵,其是转换到标定纸坐标的关键。其中绕X轴旋转θ,则其如图:

   注意:在每个视场无论我们能提取多少个角点,我们只能得到四个有用的角点信息,这四个点可以产生8个方程,6个用于求外参,这样每个视场就还赚两个方程来求内参,则其在多一个视场即可求出4个内参。因为六个外参,这就是为什么要消耗三个点用于求外参。

内参、外参、畸变参数三种参数与相机的标定方法_第1张图片

 

畸变参数是:k1,k2,k3径向畸变系数,p1,p2是切向畸变系数。径向畸变发生在相机坐标系转图像物理坐标系的过程中。而切向畸变是发生在相机制作过程,其是由于感光元平面跟透镜不平行。其如下:

 

1.径向畸变:产生原因是光线在远离透镜中心的地方比靠近中心的地方更加弯曲径向畸变主要包含桶形畸变和枕形畸变两种。下面两幅图是这两种畸变的示意:

内参、外参、畸变参数三种参数与相机的标定方法_第2张图片

 

          它们在真实照片中是这样的:

内参、外参、畸变参数三种参数与相机的标定方法_第3张图片

 

           2.切向畸变:产生的原因透镜不完全平行于图像平面,这种现象发生于成像仪被粘贴在摄像机的时候。下面图片来自于《学习opencv》p413。

内参、外参、畸变参数三种参数与相机的标定方法_第4张图片

 

其中畸变的形象示意图是如下:

 

内参、外参、畸变参数三种参数与相机的标定方法_第5张图片

 

其总的转换关系:

内参、外参、畸变参数三种参数与相机的标定方法_第6张图片

下面是普通摄像头标定后的输出值,其如下:

内参、外参、畸变参数三种参数与相机的标定方法_第7张图片

其中的fx、fy是f/dx、f/dy得出来的值。其中的cx、cy一般不是正好是图像分辨率的一半,其是有偏差的,一般越好的摄像头则其越接近于分辨率的一半。上面例子使用的摄像头是一个普通的1280x720分辨率的摄像头,其偏差还是蛮大的。下面的数据是比较好的摄像头罗技720p的,其分辨率也是1280x720的分辨率。可以看出其更接近分辨率的一半。

内参、外参、畸变参数三种参数与相机的标定方法_第8张图片

 

2、相机的标定方法与意义:

(一)什么是摄像机标定

 

    在图像测量过程以及机器视觉应用中,为确定空间物体表面某点的三维几何位置与其在图像中对应点之间的相互关系,必须建立摄像机成像的几何模型,这些几何模型参数就是摄像机参数。在大多数条件下这些参数必须通过实验与计算才能得到,这个求解参数的过程就称之为摄像机标定。

 

(一)相机标定的意义

 

    无论是在图像测量或者机器视觉应用中,摄像机参数的标定都是非常关键的环节,其标定结果的精度及算法的稳定性直接影响摄像机工作产生结果的准确性。因此,做好摄像机标定是做好后续工作的前提,是提高标定精度是科研工作的重点所在。其标定的目的就是为了相机内参、外参、畸变参数。

  其标定方法大概有三种如下:

内参、外参、畸变参数三种参数与相机的标定方法_第9张图片

1.线性标定方法的大概数学公式是:

内参、外参、畸变参数三种参数与相机的标定方法_第10张图片

其求解过程如下:

内参、外参、畸变参数三种参数与相机的标定方法_第11张图片

注意:这种标定是没有考虑到相机畸变的非线性问题,意思是这种标定是

在不考虑相机畸变的情况下使用。

 

2.非线性标定方法:

当镜头畸变明显时必须引入畸变模型,将线性标定模型转化为非线性标定模型,

通过非线性优化的方法求解相机参数:

内参、外参、畸变参数三种参数与相机的标定方法_第12张图片

3.两步标定法:

 

   1.Tsai的经典两步法

       概念Tsai基于 RAC 约束(RadialAlignment Constrain)提出的两步法,在求解过程中将CCD(电耦合器件)阵列感光元的横向间距和纵向间距当作已知参数,求解的摄像机内部参数:有效焦距f;镜头径向畸变系数k1,k2;非确定性尺度因子xs ;图像中心或主点u0,v0。外部参数:世界坐标系与摄像机坐标系之间的旋转矩阵R与平移向量t。

 

     求解:首先利用最小二乘法求解超定线性方程组,求得模型外部参数;然后求解内部参数,如果摄像机无透镜畸变,可通过一个超定线性方程组解出,如果存在一个以二次多项式近似的径向畸变,则利用一个包含三个变量的目标函数进行优化搜索求解

 

  

 

1.相机坐标系:

相机坐标系是连接图像物理坐标系世界坐标系的桥梁,其中相机坐标的系的坐标原点是:镜头的光心---其也是相机坐标系里的投影中心。

内参、外参、畸变参数三种参数与相机的标定方法_第13张图片

 

 

 

参考文献:

像素坐标转换到标定纸坐标的过程

https://blog.csdn.net/Loser__Wang/article/details/51811347

摄像机标定

本文目的在于记录如何使用MATLAB做摄像机标定,并通过opencv进行校正后的显示。

首先关于校正的基本知识通过OpenCV官网的介绍即可简单了解:
http://docs.opencv.org/2.4/doc/tutorials/calib3d/camera_calibration/camera_calibration.html

对于摄像机我们所关心的主要参数为摄像机内参,以及几个畸变系数。上面的连接中后半部分也给了如何标定,然而OpenCV自带的标定程序稍显繁琐。因而在本文中我主推使用MATLAB的工具箱。下面让我们开始标定过程。

标定板

标定的最开始阶段最需要的肯定是标定板。两种方法,直接从opencv官网上能下载到:
http://docs.opencv.org/2.4/_downloads/pattern.png

方法二:逼格满满(MATLAB)

内参、外参、畸变参数三种参数与相机的标定方法_第14张图片

采集数据

那么有了棋盘格之后自然是需要进行照片了。不多说,直接上程序。按q键即可保存图像,尽量把镜头的各个角度都覆盖好。

#include "opencv2/opencv.hpp"
#include 
#include 

using namespace cv;
using namespace std;

int main()
{
    VideoCapture inputVideo(0);
    //inputVideo.set(CV_CAP_PROP_FRAME_WIDTH, 320);
    //inputVideo.set(CV_CAP_PROP_FRAME_HEIGHT, 240);
    if (!inputVideo.isOpened())
    {
        cout << "Could not open the input video " << endl;
        return -1;
    }
    Mat frame;
    string imgname;
    int f = 1;
    while (1) //Show the image captured in the window and repeat
    {
        inputVideo >> frame;              // read
        if (frame.empty()) break;         // check if at end
        imshow("Camera", frame);
        char key = waitKey(1);
        if (key == 27)break;
        if (key == 'q' || key == 'Q')
        {
            imgname = to_string(f++) + ".jpg";
            imwrite(imgname, frame);
        }
    }
    cout << "Finished writing" << endl;
    return 0;
}


保存大约15到20张即可。大家可以看到我的方法,直接对着实验室的屏幕拍摄的。这个阶段有个注意事项就是测量好屏幕上每个方格的大小,这个标定的时候会用到。
内参、外参、畸变参数三种参数与相机的标定方法_第15张图片

进行标定

直接而在MATLAB的Command Window里面输入cameraCalibrator即可调用标定应用。
这里写图片描述
内参、外参、畸变参数三种参数与相机的标定方法_第16张图片
首先先把之前照好的图像添加进去,这是出现:
内参、外参、畸变参数三种参数与相机的标定方法_第17张图片
这就是之前让你记录的标定板中每个方格的大小。
输入无误后就涉及到最关键的一步了(MATLAB的这个实在太方便了,都是傻瓜式操作),选择参数。

为什么说他关键呢,因为如果你仔细阅读了OpenCV的说明之后你会大概明白畸变参数,总共有五个,径向畸变3个(k1,k2,k3)和切向畸变2个(p1,p2)。
径向畸变:
这里写图片描述
切向畸变:
这里写图片描述
以及在OpenCV中的畸变系数的排列(这点一定要注意k1,k2,p1,p2,k3),千万不要以为k是连着的。
这里写图片描述
并且通过实验表明,三个参数的时候由于k3所对应的非线性较为剧烈。估计的不好,容易产生极大的扭曲,所以我们在MATLAB中选择使用两参数,并且选择错切和桶形畸变。
这里写图片描述
点击开始后等待一段时间即可完成标定。并且MATLAB给出的可视化还是很不错的,可以对比校正前后的样子。
内参、外参、畸变参数三种参数与相机的标定方法_第18张图片
点击show Undistorted即可看到无畸变的图像。
内参、外参、畸变参数三种参数与相机的标定方法_第19张图片
到这为止,你已经完成了标定过程。选择导出参数,即可把参数进行保存。
这里写图片描述
保存后可以退出标定应用,在MATLAB主界面中将保存的Mat文件打开。
内参、外参、畸变参数三种参数与相机的标定方法_第20张图片
第二行就是参数
内参、外参、畸变参数三种参数与相机的标定方法_第21张图片
里面的RadialDistortion对应k1,k2,k3设置为0了。
TangentialDistortion对应p1,p2。
IntrinsicMatrix对应内参,注意这个和OpenCV中是转置的关系,注意不要搞错。
这里写图片描述
对应
这里写图片描述

OpenCV中查看标定的结果

直接上代码。

#include "opencv2/opencv.hpp"
#include 

using namespace cv;
using namespace std;

int main()
{
    VideoCapture inputVideo(0);
    if (!inputVideo.isOpened())
    {
        cout << "Could not open the input video: " << endl;
        return -1;
    }
    Mat frame;
    Mat frameCalibration;

    inputVideo >> frame;
    Mat cameraMatrix = Mat::eye(3, 3, CV_64F);
    cameraMatrix.at<double>(0, 0) = 4.450537506243416e+02;
    cameraMatrix.at<double>(0, 1) = 0.192095145445498;
    cameraMatrix.at<double>(0, 2) = 3.271489590204837e+02;
    cameraMatrix.at<double>(1, 1) = 4.473690628394497e+02;
    cameraMatrix.at<double>(1, 2) = 2.442734958206504e+02;

    Mat distCoeffs = Mat::zeros(5, 1, CV_64F);
    distCoeffs.at<double>(0, 0) = -0.320311439187776;
    distCoeffs.at<double>(1, 0) = 0.117708464407889;
    distCoeffs.at<double>(2, 0) = -0.00548954846049678;
    distCoeffs.at<double>(3, 0) = 0.00141925006352090;
    distCoeffs.at<double>(4, 0) = 0;

    Mat view, rview, map1, map2;
    Size imageSize;
    imageSize = frame.size();
    initUndistortRectifyMap(cameraMatrix, distCoeffs, Mat(),
        getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, imageSize, 0),
        imageSize, CV_16SC2, map1, map2);


    while (1) //Show the image captured in the window and repeat
    {
        inputVideo >> frame;              // read
        if (frame.empty()) break;         // check if at end
        remap(frame, frameCalibration, map1, map2, INTER_LINEAR);
        imshow("Origianl", frame);
        imshow("Calibration", frameCalibration);
        char key = waitKey(1);
        if (key == 27 || key == 'q' || key == 'Q')break;
    }
    return 0;
}

相信此时你的镜头的畸变也得到了修复。
内参、外参、畸变参数三种参数与相机的标定方法_第22张图片
内参、外参、畸变参数三种参数与相机的标定方法_第23张图片

还有就是之前讨论的为什么选2系数而不是3系数。因为。。。。。。。
下面是三系数的修正结果,惨不忍睹啊。
内参、外参、畸变参数三种参数与相机的标定方法_第24张图片

立体标定 想要让双目视觉系统知道视差,首先应该知道双目视觉系统中两个摄像头之间的相对位置关系。。任意两个坐标系之间的相对位置关系,都可以通过两个矩阵来描述:旋转矩阵R和平移矩阵T。 我们可以同时对两个摄像头进行标定,分别得到二者相对同一坐标系的旋转矩阵和平移矩阵,然后就可以获得两个摄像头之间的相对位置关系,这就是双目标定! --------------------- 立体校正 为了使立体匹配步骤更加容易并且更加精准,立体校正是必须的,基于对极几何立体校正将左右两幅图像调整为完全的行对准,当两幅图像是完全的行对准时,计算立体视差是最简单的。立体校正的目的是对两台摄像头的图像平面重投影,是的它们精准落在同一个平面上,而且图像的行也完全地对准到前向平行的结构上。 本征矩阵的意义就是将两个相机拍摄的同一点的两个相机坐标系下的坐标联系起来,而基础矩阵就是将同一点在两个像平面坐标系下的坐标联系起来。 关于本征矩阵和基础矩阵的东西,想知道详情的可以自行阅读《学习opencv》。 ---------------------

你可能感兴趣的:(内参、外参、畸变参数三种参数与相机的标定方法)