zoukankan      html  css  js  c++  java
  • 《学习OpenCV第18章》相机模型与标定整编

     

     

    一、相机模型

    针孔模型。在这个简单模型中,想象光线是从场景或一个很远的物体发射过来的,但只有一条光线从该场景中的任意特定点进入针孔。

    我们将这个图像进行抽象,就能够得到这样的结果:

    其中,f为像到针孔的距离,被称为“焦距”,Z为物到针孔的距离。这里我们讨论的都是理想情况下,光轴上的距离。

    那么,在该图中,我们可以通过相似三角形得到x/f = X/Z,或

     

    我们重新把针孔相机模型整理成另一种等价形式,使其数学形式更加简单

    主要的区别在于,负号被去掉了,因为在这种模型下,像是正向的。你们这个时候,我们可以这样来表示:

    实际上,芯片的中心通常不在光轴上,我们因此引入两个新的参数cxcy,对投影屏幕坐标中心可能的偏移(对光轴而言)进行建模。

    需要注意的是,这里的Xscreen/X= Sx(像素/长度),完整的公式为:

    其中,只有组合量fx = f· sxfy = f · sy可以直接计算出来而不必拆除相机去直接测量其部件。

    真实的针孔由于不能为快速曝光收集足够的光线,因此它不是一个得到图像的好方法。这也是为什么眼睛和相机都要使用透镜而不是仅仅用一个点来收集更多光线的原因。

     

     

    然而,对于快速生成图像的相机而言,必须利用大面积且弯曲特性,让足够多的光线能够聚焦到投影点上。为了实现这个目的,我们使用透镜。透镜可以聚焦足够多的光线到一个点上,使得图像生成更加迅速,但代价是引入了畸变。

    二、投影几何基础

     

    将物理世界中坐标为(Xi,Yi,Zi)的一系列物理点映射到投影平面上坐标为(xi, yi)的点的过程叫做投影变换。也就是

    采用了线代的方式来表示:

     

     

     

     

    其中:

     

    将乘数提取出来,可以发现w = Z,并且是用齐次坐标表示的,我们可以通过除以w (Z)来恢复我们之前的定义。

    三、透镜畸变(实验 我目前现有成像设备比较)(实验 OpenCV官方标定程序运行18-1 )

     

    理论上可以定义一个没有引入畸变的透镜。但实际中,不存在完美的透镜。主要因为制造上的原因,制造一个“球形”透镜要比制造一个数学上理想的透镜更容易。同时在机械方面,也很难将透镜和成像仪对齐。

    主要的两种畸变为径向畸变和切向畸变。径向畸变是由于透镜的形状造成的,

     

    而切向畸变则是由整个相机的组装过程造成的。

     

     

    四、标定

     

    既然我们已经知道了误差的由来,那么下面需要做的就是避免误差。

    对相机拍摄的一个特定物体的图像,我们可以用旋转和平移来描述物体相对于相机坐标系统的姿态。

    平面上的旋转,我们是这样来表示的

    对任何
    x = r cost, y = r sin t
    旋转之后变成
    x' = r cos(t+theta), y' = r sin(t+theta)

    根据三角公式中的和差公式

     

    展开
     

    注意这里的符号是反过来的。

    从以物体中心为原点的坐标系到以相机中心为原点的坐标系,相应的平移向量为

    一个点在物体(或世界)坐标系中坐标为,对应相机坐标系中的坐标

     

    五、标定板(实验 各种标定板附录Bccalib函数组 )

    原则上,任何适当表征的物体都可以用作标定物。一个实际的选择是平面上的规则图案。棋盘是最为常用的,而圆网格、随机图案等现在也逐渐流行起来。

    目前,甚至出现了这样的标定板,这也是微创新的结果

     

    标定的本质就是 以各种方向(左)手持棋盘得到棋盘图像,为完全求解这些图片在整个坐标系的位置(相对于相机)和相机内在参数提供足够的信息。

     

    关于标定函数的使用,在前面的课程中我提出了很多内容,可以参考。

     

    六、单应性

    如果只是考虑成像透镜本身的误差,那么前面的内容已经足够。下面,我们考虑的是物平面和像平面之间的关系。

    从一个平面到另一个屏幕的投影隐射成为单应性变化。

     

    那么我们可以将单应性简单表示为:

    ,是上s是缩放因子,是从H中独立出来的。

    它包含两个部分:用于定位观察的物体平面物理变换和使用相机内参矩阵的射影变换。

    其中,物理变换是与观察的图像屏幕相关的旋转矩阵R和平移矩阵t的影响之和。我们可以将它们组合到如下的矩阵中

     

    这里是一个3 × 4矩阵前三列包含R的九个元素,最后一列由具有三个分量的向量组成

     

                                                   

                                                                                                                                                                                                                                          

    七、Ransac方法系列

    这一类方法提供了明确目标下的有效优化方法。

    八、相机标定

    不仅需要说明的是可以操作的方法,更重要的是讲明白数学原理。

    我们需要了解,通过标定需掌握多少参数。首先,回顾我们的未知参数将是有启发性的; 也就是说,我们通过标定要求解多少个参数。 在OpenCV中,我们有四个相机内在参数(fxfycxcy)和五个(或更多个)畸变参数 ——由三个(或更多个)径向参数(k1k2k3[k4k5k6])和两个切向参数(p1p2)组成32通常将相机内在矩阵的参数和畸变参数的全部集合简单地称为固有参数或内在参数。在一些情况下,矩阵参数也被称为线性固有参数(因为它们共同定义线性变换),而畸变参数被称为非线性固有参数。内在参数控制实际物体与生成的图像之间的线性投影变换。因此,它们与外参矩阵合在一起,告诉我们该物体实际位于何处。

    畸变参数与点集在最终图像中畸变的二维几何学有关。原则上,已知图案的三个角点,产生六条信息,可能都需要用于求解我们的五个畸变参数。 因此,看起来只需要标定棋盘的一个视图就足够了。

    然而,由于内在参数和外参数之间存在耦合,所以一个视图是不够的。为了理解这一点,首先要注意的是外参数包括三个旋转参数(ψ,φ,θ)和三个平移参数(TxTyTz),每个棋盘视图共有六个外参数。由相机内在矩阵的四个参数和六个外参数共同构成十个需要求解的参数,在单个视图的情况下,每个额外的视图就会增加6个参数。

    假设有N个角点和K个棋盘图像(不同位置)。我们需要看到多少视图和角点才能有足够的约束条件来求解所有这些参数?

    l  K个棋盘图像提供2 · N · K个约束(出现因子2是因为图像上的每个点都具有xy两个坐标值)

    l  忽略每次的畸变参数,我们有4个内在参数和6·K个外参数(因为我们需要在K个视图中找到棋盘位置的6个参数)。

    l  求解的前提是2 · N · K ≥ 6 · K + 4(或等效为(N – 3) ·K ≥ 2)。

    无论我们在平面上发现多少角点,我们只得到四个有用的角点信息。对于每个棋盘视图,方程只能给我们四个角点信息。而实际上需要10个或更多视图,这种差异是因为内在参数对非常小的噪声具有非常高的灵敏度。

     

    收集并求解这些方程以找到畸变参数,之后重新估计内在参数和外参数。这些繁重的工作就是仅仅使用单个函数cv :: calibrateCamera()就能解决!3

    这看上去好极了,我们希望这也确实有用

    、标定函数

    一旦我们有几个图像的角点,我们可以调用cv :: calibrateCamera()。这个程序会做数字处理,并给我们提供我们想要的信息。具体来说,我们得到的结果是相机内在矩阵,畸变系数,旋转向量和平移向量。总算是最终到了这一步。

    double cv::calibrateCamera(
    cv::InputArrayOfArrays objectPoints, // K vecs (N pts each, object frame)      

    cv::InputArrayOfArrays imagePoints, // K vecs (N pts each, image frame)

    cv::Size imageSize, // Size of input images (pixels)                  
    cv::InputOutputArray cameraMatrix, // Resulting 3-by-3 camera matrix    
    cv::InputOutputArray distCoeffs, // Vector of 4, 5, or 8 coefficients        
    cv::OutputArrayOfArrays rvecs, // Vector of K rotation vectors          
    cv::OutputArrayOfArrays tvecs, // Vector of K translation vectors        
    int flags = 0, // Flags control calibration options              
    cv::TermCriteria criteria = cv::TermCriteria(         
                             cv::TermCriteria::COUNT | cv::TermCriteria::EPS,
                             30, // ...after this many iterations                            
                             DBL_EPSILON // ...at this total reprojection error

     

    第一个参数是objectPoints。它是向量的向量,每个向量包含特定图像的标定图案上的点的坐标。

    接下来是imagePoints参数。它也是向量的向量,并且包含每个图像中找到的每个点的位置。

    imageSize参数只是告诉cv:: calibrateCamera()提取imagePoints中的点的图像有多大(以像素为单位)。

    cameraMatrix 3 by 3 ,就是H了

    相机的内在参数返回到cameraMatrixdistCoeffs矩阵中。 前者将包含线性内在参数,应为3×3矩阵。 后者可以是4,58个元素。

    如果distCoeffs的长度为4,则返回的矩阵将包含系数(k1k2p1p2)。 如果长度为58,则元素分别为(k1k2p1p2k3)或(k1k2p1p2k3k4k5k6)。

    【这个函数已经足够复杂了,我想使用起来寻找到一种可用的方法也许比较简单。 】

    、矫正

    正如我们已经提到的,标定相机通常需要做两件事情:第一件是纠正畸变的影响,第二件是根据获得的图像重构三维场景。

    矫正是在数学上去掉透镜畸变,而校正是在数学上将两个(或更多)图像整齐排列

    这里应该有更棒的实现。

    这个过程比较复杂,我需要不断重构强化这块内容。到这里,也就完成了本章的内容。应该说,这里的混乱还是比较明显的,如果在我的素材中能够有效地去除这些混乱,就是成功。

     

     

     

     

     

     

     

     

     

     

     

     

     





  • 相关阅读:
    IDEA配置GIT
    夜游神安卓模拟器安装
    jira中使用eazyBI
    [Google Guava]学习--新集合类型Multimap
    [Google Guava]学习--新集合类型Multiset
    Java自己实现双向链表LinkList
    JVM学习之jstat使用方法
    Mycat+Mysql 插入数据报错 i[Err] 1064
    Windows配置mycat
    navicat cannot create file 文件名、目录名或卷标语法不正确 解决方法
  • 原文地址:https://www.cnblogs.com/jsxyhelu/p/10495447.html
Copyright © 2011-2022 走看看