精华内容
下载资源
问答
  • 双目视觉三维重建

    2018-08-14 12:45:37
    一些双目三维重建的代码,有matlab和c++的,效果不错。
  • 很好的源码,思路清晰,利用双目实现的,大家有兴趣使用的可以直接下载,可以应用到比赛和论文内的,工具是matlab,代码也很好理解
  • 双目视觉三维重建

    2018-06-11 21:13:55
    双目视觉三维重建 双目视觉三维重建 双目视觉三维重建
  • 之后了解到三维重建原理 由两张图象的二维图像哥哥像素点的坐标,推导出咱们三维试图重德三维坐标系统中对应的xyz的坐标数值,并显示在Matlab三维图中。 那么像素点怎么找的呢,具体能找到多少个像素点呢,,鉴于...

    首先需要用到双目视觉平行系统原理
    在这里插入图片描述
    之后了解到三维重建原理
    在这里插入图片描述
    在这里插入图片描述
    由两张图象的二维图像哥哥像素点的坐标,推导出咱们三维试图重德三维坐标系统中对应的xyz的坐标数值,并显示在Matlab三维图中。
    那么像素点怎么找的呢,具体能找到多少个像素点呢,,鉴于现在自己本科那些薄弱的学识,用到的方法就是基元匹配,
    在这里插入图片描述
    使用MATLAB软件进行程序的编写与仿真,对左右摄像头采集到的图像进行特征点的匹配,构建图像的三维模型
    首先拍摄了一组人物图像,下面是原始图像
    在这里插入图片描述
    得到校正后的图像和上边的差不多,就不展示了
    对校正后的图像进行特征点的匹配,发现噪声过大,标注了150个明显特征点
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    去除掉多余背景特征点之后,得到较为清晰的三维图像
    在这里插入图片描述
    可以看出,这个人物所占的三维空间是很清楚的被展示出来的。

    Matlab代码

    %%  
    % 双目立体视觉  
    % 对比实验  
      
    %%  
    % 清空工作区  
    clc;  
    clear;  
    close all;  
      
    %%  
    % 导入图像数据  
    I1 = imread('viewleft.png');  
    I2 = imread('viewright.png');  
    figure  
    imshowpair(I1, I2, 'montage');   
    title('Original Images');  
    % 导入相机参数  
    load cameraParams.mat  
      
    %%  
    % 校正  
    I1 = undistortImage(I1, cameraParams);  
    I2 = undistortImage(I2, cameraParams);  
    figure   
    imshowpair(I1, I2, 'montage');  
    title('Undistorted Images');  
      
    %%  
    % 特征点提取  
    imagePoints1 = detectMinEigenFeatures(rgb2gray(I1), 'MinQuality', 0.1);  
      
    %%  
    % 可视化  
    figure  
    imshow(I1, 'InitialMagnification', 50);  
    title('150 Strongest Corners from the First Image');  
    hold on  
    plot(selectStrongest(imagePoints1, 150));  
      
    %%  
    % Create the point tracker  
    tracker = vision.PointTracker('MaxBidirectionalError', 1, 'NumPyramidLevels', 5);  
    imagePoints1 = imagePoints1.Location;  
    initialize(tracker, imagePoints1, I1);  
    % Track the points  
    [imagePoints2, validIdx] = step(tracker, I2);  
    matchedPoints1 = imagePoints1(validIdx, :);  
    matchedPoints2 = imagePoints2(validIdx, :);  
      
    %%  
    % 特征点匹配  
    figure  
    showMatchedFeatures(I1, I2, matchedPoints1, matchedPoints2);  
    title('Tracked Features');  
      
    %%  
    % F矩阵估计  
    [fMatrix, epipolarInliers] = estimateFundamentalMatrix(...  
      matchedPoints1, matchedPoints2, 'Method', 'MSAC', 'NumTrials', 10000);  
    % 极线  
    inlierPoints1 = matchedPoints1(epipolarInliers, :);  
    inlierPoints2 = matchedPoints2(epipolarInliers, :);  
    % 显示内点  
    figure  
    showMatchedFeatures(I1, I2, inlierPoints1, inlierPoints2);  
    title('Epipolar Inliers');  
      
    %%  
    % R和T(也可以用RANSAC算法)  
    R = [0.9455,-0.0096,0.3253;  
        0.0120,0.9999,-0.0053;  
        -0.3252,0.0090,0.9456];  
    t = [98.4069,0.1741,18.9018];  
      
    %%  
    % 稠密的特征点  
    imagePoints1 = detectMinEigenFeatures(rgb2gray(I1), 'MinQuality', 0.001);  
      
    %%  
    % Create the point tracker  创建一个跟踪点
    tracker = vision.PointTracker('MaxBidirectionalError', 1, 'NumPyramidLevels', 5);  
    % Initialize the point tracker  
    imagePoints1 = imagePoints1.Location;  
    initialize(tracker, imagePoints1, I1);  
    % Track the points  
    [imagePoints2, validIdx] = step(tracker, I2);  
    matchedPoints1 = imagePoints1(validIdx, :);  
    matchedPoints2 = imagePoints2(validIdx, :);  
      
    %%  
    % cameraMatrix  
    camMatrix1 = cameraMatrix(cameraParams, eye(3), [0 0 0]);  
    camMatrix2 = cameraMatrix(cameraParams, R', -t*R');  
      
    % 三维点云的计算  
    points3D = triangulate(matchedPoints1, matchedPoints2, camMatrix1, camMatrix2);  
      
    % 获取颜色信息  
    numPixels = size(I1, 1) * size(I1, 2);  
    allColors = reshape(I1, [numPixels, 3]);  
    colorIdx = sub2ind([size(I1, 1), size(I1, 2)], round(matchedPoints1(:,2)), ...  
        round(matchedPoints1(:, 1)));  
    color = allColors(colorIdx, :);  
      
    % 创建点云  
    ptCloud = pointCloud(points3D, 'Color', color);  
      
    %%  
    % 可视化  
    cameraSize = 0.3;  
    figure  
    plotCamera('Size', cameraSize, 'Color', 'r', 'Label', '1', 'Opacity', 0);  
    hold on  
    grid on  
    plotCamera('Location', t, 'Orientation', R, 'Size', cameraSize, ...  
        'Color', 'b', 'Label', '2', 'Opacity', 0);  
      
    % 点云的可视化  
    pcshow(ptCloud, 'VerticalAxis', 'y', 'VerticalAxisDir', 'down', ...  
        'MarkerSize', 45);  
      
    % Rotate and zoom the plot  
    camorbit(0, -30);  
    camzoom(1.5);  
      
    % Label the axes  
    xlabel('x-axis');  
    ylabel('y-axis');  
    zlabel('z-axis')  
    title('Up to Scale Reconstruction of the Scene');
    

    哈哈,顺便说一句,需要在文件中建立加上两张左右相机拍摄出的两张视差照片,并且矫正好,输入你们的相机的R T的参数,这样一个标准的三维重建图片就做好了
    我这次实验用的是
    在这里插入图片描述

    展开全文
  • 双目视觉三维重建框架

    万次阅读 多人点赞 2018-01-23 14:08:52
    玉米竭力用轻松具体的描述来讲述双目三维重建中的一些数学问题。希望这样的方式让大家以一个轻松的心态阅读玉米的《计算机视觉学习笔记》双目视觉数学架构系列博客。这个系列博客旨在捋顺一下已标定的双目视觉中的...

    一、图像坐标:我想和世界坐标谈谈(A)

    玉米竭力用轻松具体的描述来讲述双目三维重建中的一些数学问题。希望这样的方式让大家以一个轻松的心态阅读玉米的《计算机视觉学习笔记》双目视觉数学架构系列博客。这个系列博客旨在捋顺一下已标定的双目视觉中的数学主线。数学推导是有着几分枯燥的,但奇妙的计算机视觉世界是建立在严密的数学架构之上的。所以对数学框架的理解是理解双目视觉的必由之路。不过请大家放心,接下来玉米会以尽量有趣,尽量更接地气儿的方式,阐释一下自己对双目视觉数学或者说是投影几何的理解。

           先来张《计算机视觉:算法与应用》中的3D重建示例图镇楼!

             好吧,现在言归正传,来看看几何学上世界是怎样投影进摄相机里的吧!接下来让我们来看一下本系列博客的第一“搏”:

    图像坐标:我想和世界坐标谈谈(A)

    首先,我先解释一下这个题目吧。题目的字面意义是说:图像坐标系想和世界坐标系谈谈。这里面包含着两个问题:

             A、谈话对象:视觉系统的三大坐标系:世界坐标系,摄像机坐标系和图像坐标系。这是玉米在本文《我想和世界坐标谈谈 (A)》中想要和大家分享的内容。其中主要包含:三大坐标系的位置、作用和应用场景。

             B、谈话方式:两个不同的坐标系之间该如何沟通呢?玉米将在《我想和世界坐标谈谈(B)》中和大家分享一下刚体变换和透视                 投影变换。连起两个坐标系之间这不在一个参考系的“世界上最远的距离”。

    好吧,下面让我们来揭开三大坐标系的庐山真面目。

             上图是三个坐标的示意简图,通过它大家可以对三个坐标有一个直观的认识。下面来看看三个坐标系的骨子里藏了什么。

             世界坐标系(XW,YW,ZW):其是目标物体位置的参考系。除了无穷远,世界坐标可以根据运算方便与否自由放置。在双目视觉中世界坐标系主要有三个用途:1、标定时确定标定物的位置2、作为双目视觉的系统参考系,给出两个摄像机相对世界坐标系的关系,从而求出相机之间的相对关系3、作为重建得到三维坐标的容器,盛放重建后的物体的三维坐标。世界坐标系是将看见中物体纳入运算的第一站。

            摄像机坐标系(XC,YC,ZC):其是摄像机站在自己角度上衡量的物体的坐标系。摄像机坐标系的原点在摄像机的光心上,z轴与摄像机光轴平行。它是与拍摄物体发生联系的桥头堡,世界坐标系下的物体需先经历刚体变化转到摄像机坐标系(旋转和平移),然后再和图像坐标系发生关系。它是图像坐标与世界坐标之间发生关系的纽带,沟通了世界上最远的距离。哈哈

             图像坐标系(x,y)/(u,v)像素 :其是以摄像机拍摄的二维照片为基准建立的坐标系。用于指定物体在照片中的位置。玉米更倾向将(x,y)称为连续图像坐标或空间图像坐标,将(u,v)称为离散图像坐标系或者是像素图像坐标系(虽然这样的称呼未经考证,但更能传达二者的物理意义)。

              (x,y)坐标系的原点位于摄像机光轴与成像平面的焦点O’(u0,v0)上,单位为长度单位(米)。(u,v)坐标系的原点在图片的左上角(其实是存储器的首地址)如上图所示,单位为数量单位(个)。(x,y)主要用于表征物体从摄像机坐标系向图像坐标系的透视投影关系。而(u,v)则是实实在在的,我们能从摄像机中得到的真实信息。

    (x,y)与(u,v)存在如下转换关系:

              dx代表x轴方向一个像素的宽度,dy代表y轴方向上一个像素的宽度。dx、dy为摄像机的内参数。(u0,v0)称为图像平面的主点,也是摄像机的内参数。其实相当于对x轴和y轴的离散化。其可以运用齐次坐标,将上式写成矩阵形式,如下:

     

          (1)式运用了齐次坐标,初学者可能会感到有些迷惑。大家会问:怎样将普通坐标转换为齐次坐标呢?齐次坐标能带来什么好处呢?

             玉米在这里对齐次坐标做一个通俗的解释。此处只讲怎么将普通坐标改写为齐次坐标及为什么引入齐次坐标。这里只做一个通俗但不太严谨的表述。力求简单明了。针对齐次坐标的严谨的纯数学推导,可参见“周兴和版的《高等几何》---1.3拓广平面上的齐次坐标”。玉米曾详细读过《高等几何》这本书,但觉得离计算机视觉有点远,是讲纯数学的投影关系的,较为生涩难懂。

            齐次坐标可以理解为在原有坐标后面加一个“小尾巴”。将普通坐标转换为齐次坐标,通常就是在增加一个维度,这个维度上的数值为1。如图像坐标系(u,v)转换为(u,v,1)一样。对于无穷远点,小尾巴为0。注意,给零向量增加小尾巴,数学上无意义。

    那么,为什么计算机视觉在坐标运算时要加上这个“小尾巴”呢?

            玉米看来有两点原因:

             1、 将投影平面扩展到无穷远点。如对消隐点(vanishing point)的描述。

              2、 使得计算更加规整

             如式(1)如果用普通坐标来表达的话,会是下面的样子:

    这样的运算形式会给后与运算带来一定的麻烦,所以齐次坐标是一个更好的选择。

              齐次坐标还有一个重要的性质,伸缩不变性。即:设齐次坐标M,则αM=M。

    玉米才疏学浅,笔记中如有纰漏指出,希望大家不吝指出。玉米在这里拜谢啦!

    二、图像坐标:我想和世界坐标谈谈(B)

             玉米将在这篇博文中,对图像坐标与世界坐标的这场对话中涉及的第二个问题:谈话方式,进行总结。世界坐标是怎样变换进摄像机,投影成图像坐标的呢?

            玉米做了一个简单的图示,在这里做一个提纲。图中显示,世界坐标系通过刚体变换到达摄像机坐标系,然后摄像机坐标系通过透视投影变换到达图像坐标系。可以看出,世界坐标与图像坐标的关系建立在刚体变换和透视投影变换的基础上。为了奖励刚体变和透视投影变换沟通了“世界上最远的距离”,玉米在图上奖励了他们两朵小红花。哈哈

            首先,让我们来看一下刚体变换是如何将世界坐标系与图像坐标系联系起来的吧。这里,先对刚体变换做一个介绍:

            刚体变换(regidbody motion):三维空间中, 当物体不发生形变时,对一个几何物体作旋转, 平移运动,称之为刚体变换

    因为世界坐标系和摄像机坐标都是右手坐标系,所以其不会发生形变。我们想把世界坐标系下的坐标转换到摄像机坐标下的坐标,如下图所示,可以通过刚体变换的方式。空间中一个坐标系,总可以通过刚体变换转换到另外一个个坐标系的。转一转,走一走,就到另外一个坐标系下了。以前可能是面朝大海,经过平移旋转,最终可能只能面朝冰山了,哈哈

             下面让我来看一下,二者之间刚体变化的数学表达。

             其中,XC代表摄像机坐标系,X代表世界坐标系。R代表旋转,T代表平移。R、T与摄像机无关,所以称这两个参数为摄像机的外参数(extrinsic parameter)可以理解为两个坐标原点之间的距离,因其受x,y,z三个方向上的分量共同控制,所以其具有三个自由度。

             R则为分别绕XYZ三轴旋转的效果之和。如下面所示:

             R=r1*r2*r3.其由三个方向的θ控制,故具有三个自由度。

       好了,刚体变换就讲完了。大家应该都了解,世界坐标系到摄像机坐标系之间的转换过程了吧。

              接下来,让我们看看摄像机坐标下的坐标如何投影到图像坐标系下,最终变为照片中的一个像素。这其中包含两个过程:一是从摄像机坐标到“空间图像坐标”(x,y)所发生的透视投影;二是从“连续图像坐标”到“离散图像坐标”(u,v)。后者我们已经在第一篇博文中解释过。所以在这里,主要介绍一下透视投影。

    透视投影(perspective projection): 用中心投影法将形体投射到投影面上,从而获得的一种较为接近视觉效果的单面投影图。有一点像皮影戏。它符合人们心理习惯,即离视点近的物体大,离视点远的物体小,不平行于成像平面的平行线会相交于消隐点(vanish point)。

             啰嗦这么多,其实大家看看示意图,看看公式,秒懂。

             以图中B(XB,YB)点为例,在小孔成像摄像机模型下(几何分析的最常用模型)。这里的f为摄像机的焦距,其属于摄像机的内参数(intrinsic parameter)。其在成像平面上的投影点b(xb,yb)的坐标利用简单的相似三角形比例关系很容易求出:

             上面两式也阐明了摄像机坐标与图像坐标之间的透视投影关系。

    好吧,现在玉米已经把图像坐标与世界坐标之间的这场对话所需经历的三个波折的过程加以了解释。即:刚体变换、透视投影、(x,y)换(u,v)(ps.这个在上一篇博文中讲过)。接下来玉米用一张图把三个过程连接起来。实现从世界坐标(X,Y,Z)到(u,v)之间的转换。让图像坐标与世界坐标直接对话。

             下图中的转换关系,都是用齐次坐标表达的,大家会发现这样的表达非常整洁。

             其实这张图显示的过程还有一个名字:摄像机模型(camera model)。其实也就是摄像机的几何模型了。

             将三者相乘,可以把这三个过程和在一起,写成一个矩阵:

             P就是世界坐标到图像坐标的直接联系人,P就表示了一个投影相机,有下面公式:

             注意在表示齐次坐标时,需要在符号上面加个小帽子。除去齐次坐标控制位P23P具有11个自由度

    20141102170636562

            摄像机模型及其中涉及的坐标系等,是弄清3D重建几何框架的基础。可以把它们视为基本运算关系。后面对于三维重建几何框架的推导,都是要用到三个基本坐标系和摄像机模型的。

             到这里玉米就顺利搭建起了图像坐标与世界坐标间的这场对话。如有纰漏还请大家担待,并指正!

    三、致敬“张正友标定”

             此处“张正友标定”又称“张氏标定”,是指张正友教授于1998年提出的单平面棋盘格的摄像机标定方法。张氏标定法已经作为工具箱或封装好的函数被广泛应用。张氏标定的原文为“A Flexible New Technique forCamera Calibration”。此文中所提到的方法,为相机标定提供了很大便利,并且具有很高的精度。从此标定可以不需要特殊的标定物,只需要一张打印出来的棋盘格。So great! 这样的方法让人肃然起敬。所以玉米的这篇博客的题目是:致敬“张氏标定”。

             当然,此博的内容也是围绕着“张氏标定”进行的,在这里,玉米主要介绍一下,“张氏标定”的数学思路。因为标定在整个基于标定摄像机的三维重建的几何过程占有最重要最核心的地位。如下图:

             从图中明显可以看出,标定得到的内参、外参和畸变系数,是双目视觉进行图片矫正,摄像机校正和3D恢复的基础。没有好的标定,双目视觉系统就无法完成3D重建。

            既然标定对双目视觉如此重要,我们有必要对数学的深层含义多加理解。以张氏标定为例,让我们挖开工具箱,看看其数学本质吧。因为张教授的论文中对标定方法的讲述是循序渐进的,所以玉米在这里将按照张教授论文中的顺序,为大家讲述一下,张氏标定的脉络。

    1、标定平面到图像平面的单应性

            因为张氏标定是一种基于平面棋盘格的标定,所以想要搞懂张氏标定,首先应该从两个平面的单应性(homography)映射开始着手。

            单应性(homography):在计算机视觉中被定义为一个平面到另一个平面的投影映射。首先看一下,图像平面与标定物棋盘格平面的单应性。

            由上两篇博文中讲到的摄像机模型,肯容易得到:

             其中m的齐次坐标表示图像平面的像素坐标(u,v,1),M的齐次坐标表示世界坐标系的坐标点(X,Y,Z,1)。A[R t]即是上面一篇博客推出的P。R表示旋转矩阵、t表示平移矩阵、S表示尺度因子。A表示摄像机的内参数,具体表达式如下:

    α=f/dx,β=f/dy,因为像素不是规规矩矩的正方形,γ代表像素点在x,y方向上尺度的偏差。

             这里还有一个“梗儿”,就是S。它只是为了方便运算,对于齐次坐标,尺度因子不会改变坐标值的。

    因为标定物是平面,所以我们可以把世界坐标系构造在Z=0的平面上。然后进行单应性计算。令Z=0可以将上式转换为如下形式:

             既然,此变化属于单应性变化。那么我们可以给A[r1 r2 t]一个名字:单应性矩阵。并记H= A[r1 r2 t]。

             那么现在就有:

             大家可以分析一下,H是一个三3*3的矩阵,并且有一个元素是作为齐次坐标。因此,H有8个未知量待解。

    (x,y)作为标定物的坐标,可以由设计者人为控制,是已知量。(u,v)是像素坐标,我们可以直接通过摄像机获得。对于一组对应的(x,y)-à(u,v)我们可以获得两组方程。

            现在有8个未知量需要求解,所以我们至少需要八个方程。所以需要四个对应点。四点即可算出,图像平面到世界平面的单应性矩阵H。

            这也是张氏标定采用四个角点的棋盘格作为标定物的一个原因。

            在这里,我们可以将单应性矩阵写成三个列向量的形式,即:

    2、利用约束条件求解内参矩阵A

            从上面可知,应用4个点我们可以获得单应性矩阵H。但是,H是内参阵和外参阵的合体。我们想要最终分别获得内参和外参。所以需要想个办法,先把内参求出来。然后外参也就随之解出了。我们可以仔细的“观摩”一下下面的式子。

           从中可以得出下面两个约束条件,这两个约束条件都是围绕着旋转向量来的。

           1、r1,r2正交 得:r1r2=0。这个很容易理解,因为r1,r2分别是绕x,y轴旋转的。应用高中立体几何中的两垂直平面上(两个旋转向量分别位于y-z和x-z平面)直线的垂直关系即可轻松推出。

            2、旋转向量的模为1,即|r1|=|r2|=1。这个也很容易理解,因为旋转不改变尺度嘛。如果不信可以回到上一篇博客,找到个方向的旋转矩阵化行列式算一下。

            通过上面的式子可以将r1,r2代换为h1,h2与A的组合进行表达。即       r1=h1A-1,r2=h2A-1.根据两约束条件,可以得到下面两个式子:

            大家从上面两个式子是不是看出一点端倪了。式子中,h1,h2是通过单应性求解出来的那么未知量就仅仅剩下,内参矩阵A了。内参阵A包含5个参数:α,β,u0,v0,γ。那么如果我们想完全解出这五个未知量,则需要3个单应性矩阵。3个单应性矩阵在2个约束下可以产生6个方程。这样可以解出全部的五个内参了。大家想一下,我们怎样才能获得三个不同的单应性矩阵呢?答案就是,用三幅标定物平面的照片。我们可以通过改变摄像机与标定板间的相对位置来获得三张不同的照片。(当然也可以用两张照片,但这样的话就要舍弃掉一个内参了γ=0)

           到这里,大家应该就明白我们在张氏标定法时为什么要不断变换标定板的方位了吧。当然这只是一个原因。第二个原因,玉米会在讲极大似然时讲到。

           下面在对我们得到的方程做一些数学上的变化,这些变化都是简单的运算变化了,相信大家动动笔,一算就可以算出。这些变化都是为了运算方便的,所以也没什么物理意义。

    首先令:

            很容易发现B是一个对称阵,所以B的有效元素只剩下六个(因为有三对对称的元素是相等的,所以只要解得下面的6个元素就可以得到完整的B了),让这六个元素构成向量b。

            接下来在做一步纯数学化简:

            可以计算得:

             利用约束条件可以得到下面,方程组:

              这个方程组的本质和前面那两个用h和A组成的约束条件方程组是一样的。在此重复一遍解释:如果我们想完全解出这五个未知量,则需要3个单应性矩阵。3个单应性矩阵在2个约束下可以产生6个方程。这样可以解出全部的五个内参了。大家想一下,我们怎样才能获得三个不同的单应性矩阵呢?答案就是,用三幅标定物平面的照片。我们可以通过改变摄像机与标定板间的相对位置来获得三张不同的照片。(当然也可以用两张照片,但这样的话就要舍弃掉一个内参了γ=0)

           通过至少含一个棋盘格的三幅图像,应用上述公式我们就可以估算出B了。得到B后,我们通过cholesky分解 ,就可以轻松地得到摄像机的内参阵A。

    3、基于内参阵估算外参阵

           通过上面的运算,我们已经获得了摄像机的内参阵。那么对于外参阵,我们很容易通过下面的公式解得:

           对上面公式进行化简,可以得到:

            至此,玉米已经将张氏标定的主体数学框架已经讲完了。介于篇幅关系(怕太长大机会读的昏昏欲睡,哈哈)。但其实我们做了这么多推导,仅仅是为后面的极大似然参数估计提供初值。但当然这个初值也是不可或缺的,因为没有这个初值,就无法估计出更为准确的参数。玉米将张氏标定中用于提高标定精度的极大似然算法,放到下一篇博客中进行讲解。

    还是老话:玉米才疏学浅,讲解之中难免有纰漏,请大家谅解,并指正。

    四、极大似然参数估计

    此篇博文,玉米将和大家分享一下“张氏标定”除几何推导外的另外一大精髓:参数估计。

             张教授在大作“A Flexible New Technique for Camera Calibration”中的原话如下:” The above solution is obtained through minimizing an algebraic distancewhich is not physically meaningful. We can refine it through maximum likelihoodinference”.意思是:上面的几何推导仅仅是纯代数上的拟合,没有物理意义。下面让我们通过极大似然理论对得到的结果进行改善。

           顺着张教授的意思,玉米先在这里为大家从概念上讲述一下极大似然估计。

    极大似然估计是一种估计总体未知参数的方法。它主要用于点估计问题。所谓点估计是指用一个估计量的观测来估计未知参数的真值。说穿了就一句话:就是在参数空间中选取使得样本取得观测值的概率最大的参数。

           我们定义似然函数:

           总体分布为离散型的:(p是已知的分布律)

            总体分布为连续性的:(f为概率密度函数)

            极大似然法就是在的可取范围内,挑选出来的使L达到最大的未知参数的估计值

             如果在内:,那么就称为极大似然估计值。

    列了这么一大圈儿概念,估计大家看的都昏昏入睡了。玉米在这里用通俗点儿的方式解释一下极大似然估计:

            对很多实验,我们可以观察到样本,但影响样本的参数却是未知的。那我们就得对样本进行估计。既然我们要去估计,那么就想要估计的准。极大似然法就只在概率分布的观念下,指导我们估计的更准的方法。现实世界中,存在着一条普遍规律:与现实相差越远的概率越小。这就相当于人群中,非主流总是比主流要少一样,偏差大的总是占少数。所以,可能发生的概率越大就会越接近真实值。极大似然法就是应用这种思想,认为可能性最大的就是最优的估计值。即极大似然估计值就是最接近真实值的参数值。

    那么,极大似然为什么有这么一个别致的名字呢?什么是似然呢?是因为估计值不是随机变量,所以不能把它的可能性称为概率,那么数学家们就想了这样(likelihood)一个名字来代表可能性。

           极大似然法的一些概念上的问题玉米就讲到这里了。下面然玉米带这大家分析一个具体问题:张教授在张氏标定法中所用的极大似然估计。

           首先来看一下,为什么标定的内外参数可以用极大似然法进行估计:

           因为我们是假定图像上的角点是被噪声干扰的,且我们认为这些噪声是高斯噪声。那么对于噪声的幅度就是给观测值造成的误差。但高斯噪声的概率密度我们是已知的,所以我们可以用前面所述的极大似然估计的思想去“猜”真值。

           那么接下来我们就需要构造一个似然函数,然后寻找其最大值了。张教授在文章中直接略过推导,直接给出了公式:

    说当此式取得最小值时,就是参数的最大似然估计值。

           玉米在这里为大家讲一下自己的理解:

           设,角点附近的噪声服从高斯分布

           则:角点mij的样本值服从如下,概率密度函数:

           现在构造,似然函数:

            现在让L取得最大值,则可令下式最小:

            那么怎么令上面这个目标函数达到最小值呢,张氏标定法运用了可以用来解决多参数非线性系统优化问题的Levenberg-Marquardt算法。对于该方法,详细的介绍大家可以参照《The levenberg-marquardt algorithm, implementation andtheory》一文进行深入了解。这里给出下载本文的链接:

    http://link.springer.com/chapter/10.1007%2FBFb0067700

             那么张氏标定法在不考虑镜头畸变的情况下的,获取摄像机内外参数的数理推导过程。玉米就为大家讲到这里了。下面一篇博文,玉米会给大家分析一下,张氏标定法是怎样分析摄像机的非线性畸变的。

    还是老话:玉米才疏学浅,讲解之中难免有纰漏,请大家谅解,并指正。

    六、张正友标定法小结

          这一博文,是玉米后补上的。因为觉得前面用了三篇博文来描述张氏标定法,略显散乱。在这里总结一下,使条理清晰一点。另外关于张氏标定所得参数也还有两点需要澄清。下面这个总结,其实也是在“A Flexible New Technique forCamera Calibration”中出现的。

    一、张氏标定的过程:

           1.      打印一张棋盘格,把它贴在一个平面上,作为标定物。

           2.      通过调整标定物或摄像机的方向,为标定物拍摄一些不同方向的照片。

           3.      从照片中提取特征点(如角点)。

           4.      估算理想无畸变的情况下,五个内参和所有外参。

           5.      应用最小二乘法估算。实际存在径向畸变下的畸变系数。

           6.      极大似然法,优化估计,提升估计精度。

             通过这样的过程,我们就获得了具有高估计精度的五个内参,三个外参和两个畸变系数。利用这些信息,我们可以进行畸变矫正、图像校正和最终的三维信息恢复。

    二、以下是对于张氏标定求得的内参,需要注意的一点:

             通过张氏标定,我们并不能得到:焦距(f)和像素的物理尺寸(sx,sy)两个参数。因为我们在求解内参阵A时,求解出的是α和β。

    α=f/ sx,β= f/ sy 。分别代表焦距长度上,x轴和y轴像素的个数。

            虽然,没有求得焦距,但这并不影响,我们在三维坐标恢复时,进行三角运算。因为彼时,我们的计算中用到的也是α和β。

           大家可能会有疑问,既然我们无法得到焦距(f)和像素的物理尺寸(sx,sy)两个参数。那么在opencv中,调用的cvCalibrateCamera2时返回的参数中是包含焦距(f)的。Opencv的这个函数也是用了张氏标定法。为什么可以得到f呢?

           答案是这条opencv函数对内参阵做了简化,其认为γ=0即像素的物理尺寸(sx,sy)两个参数相等。然后统一约掉物理尺寸s。得到的B阵如下:

           这样我们就可以解出f了。

           张氏标定的精确度可达到0.5个像素,这样的指标已经可以满足绝大多数的应用了。所以如此简单的方法,得到了这么高的精度。这样的方法是值得人们膜拜的。在此,在次向张正友教授致敬!

           在此,玉米又对张氏标定法进行了一个总结。张氏标定的原理分析就到此为止了。但是它的作用还会延续到下面两篇博文中。

           玉米才疏学浅,文中如有纰漏,请大家批评指正。

    七、立体标定与立体校正

            这篇博文中,让玉米和大家一起了解一下,张氏标定是怎样过渡到立体标定的?在这里主要以双目立体视觉进行分析。对于双目立体视觉,我们有两个摄像头。它们就像人的一双眼睛一样,从不同的方向看世界。两只眼睛中的图像的视差,让我们对世界有了三维的认识。

            那么,想要知道视差,首先应该知道双目视觉系统中两个摄像头之间的相对位置关系。我们可以通过同时对两个摄像头进行标定,分别得到二者相对同一坐标系的旋转矩阵和平移矩阵。获得这两个矩阵的过程,就是立体标定的过程。也即是:从张氏标定走向立体标定!

           两摄像头之间的旋转矩阵和平移矩阵可以由下式求出:

           其中,R为两摄像头间的旋转矩阵,T为两摄像头间的平移矩阵。Rr为右摄像头经过张氏标定得到的相对标定物的旋转矩阵,Tr为右摄像头通过张氏标定得到的相对标定物的平移向量。Rl为左摄像头经过张氏标定得到的相对相同标定物的旋转矩阵,Tl为左摄像头经过张氏标定得到的相对相同标定物的平移向量。

          两个式子是可以通过数学代换推导来的。但玉米觉得对这样有明显物理意义并且空间过程简单的计算式。物理上的空间想象,比纯代数代换,要生动的多。并且有利于大家揣摩整个物理过程。

          在玉米眼里,这两个式子是这样的:

          对于R,首先用T把左摄像机坐标系平移到右摄像机坐标系上(即两坐标系远点重合)。然后在同一参考系下的两个旋转矩阵相乘,表示世界坐标先向右旋转到Rr ,再向左旋转Rl。那么两次旋转后得到的旋转,就是有摄像机旋转到左摄像机所需的旋转矩阵R。

          对于T,那就更容易理解了,先用R对左坐标系旋转一下,把左右两摄像机调成平行,然后直接平移向量相减,即得到。两摄像机之间的平移向量T。

          上面求得的R和T就是立体标定得到的参数了。

          那么运用的立体标定所得的参数了,下一步我们该做什么呢?答案是:立体校正。

          在介绍立体校正的具体方法之前,让我们来看一下,为什么要进行立体校正?

          因为当两个图像平面是完全共面行对准时,计算立体视差是最简单的。但是,在现实的双目立体视觉系统中,是不存在完全的共面行对准的两个摄像机图像平面的。所以我们要进行立体校正。立体校正的目的就是,把实际中非共面行对准的两幅图像,校正成共面行对准。如下面示意图所示。(共面行对准是指:两摄像机图像平面在同一平面上,且同一点投影到两个摄像机图像平面时,应该在两个像素坐标系的同一行)

    有了上述铺垫,下面让玉米给大家陈述一下基于立体标定所获参数的立体校正的数学原理,或者说是几何原理。但玉米在这里,主要和大家分享一下,如此校正的物理意义。

             立体校正应该分两步走:

             1、 将两个图像平面拉回同一平面。

             这一步,该怎么做呢?玉米相信,经过这么多铺垫,大家应该早就心里有数了。这一步很简单。可以这样:两个平面在方向上            之间不是相差一个旋转矩阵R吗,那么我们让两个相机个旋转一半,但需注意二者的旋转,应该是反向的。如下式所示:

             上面的这个公式是玉米根据物理意义自己总结的。r、r分别代表左摄像机和右摄像机为达到共面所需的旋转矩阵。rl、rr程度             相同,但旋转方向相反。左右相机分别经历了这样的旋转之后,二者就已经共面了。大家应该明白了吧?

              2、 旋转图像使得同行对准

             玉米在这里先为大家展示一个,校正成功的图吧。

                      大家可以像小学时候写看图说话作文一样,观察一下图中校正前和校正后左右两摄像机的图像到底发生了什么本质的变                化。

                      玉米的答案是:左右两图分别绕光轴作了旋转,旋转过后两摄像机的主点连线平行像素坐标的行线。

                      玉米的答案也是自己对行对准的理解,比较通俗。这与很多书上用极几何术语描述的有些不同,大家可以思考一下,玉米           说的有没有道理。

                       好,既然已经明确了,要达到行对准,图像所需发生的变化。那么就让我们用数学表达式来表达它们吧。

              玉米画了一个简单的示意图,画的丑大家不要见笑。

              红色的线表示的是校正后的行线,其是左右对准的。大家可以看到,从原图像的行线转到校正后图像的行线,左图像转动了α,右图像转动了θ。那么怎样来确定两个旋转角度呢?

               大家可以回忆一下,我们在本系列博文中的第二篇中讲述刚体变换时,把旋转矩阵按不同轴分解的方法。可以看做是沿光轴旋转,旋转目的是与主点连线平行。先以左图像为例:

              那么我们设旋转矩阵为Rh , 

              则Rh可以表示为以归一化T(平移向量):e1为旋转的指针,则随之e2为e1与光轴的叉积,e3为e2与e1的叉积:

              大家可以进一步算一下:

              我们发现,其实行对准就是绕e3方向,转了α。同样的,对右图就是转了θ。

              通过上面的推导,我们就把立体标定与立体校正中的数学思想理清楚了。其实,立体匹配是有很多种方法的,玉米在里只是介绍了立体校正的基本原理。其他方法中,有一些可以不依赖标定参数,如果大家想要对立体校正进行深入研究,大家可以搜索一些经典论文进行深入学习。如:A. Fusiello, E. Trucco, and A. Verri.写的 Acompact algorithm for rectification of stereo pairs.等等

             截止目前对于三维重建的所有准备工作,都已完成。几何框架也仅剩下最后一步:立体成像。(因为本系列博文只介绍双目视觉的几何架构,所以跳过匹配不谈)玉米在下一篇博文中将与大家分享一下,几何脉络的最终果实:立体成像。这也是我们对于双目视觉几何框架推导和理解的最终目标。

             玉米才疏学浅,文中如有纰漏,请大家批评指正!

    八、走向三维

            我们前面花了七篇博文做铺垫,我们所做的一切努力都是为了最后的这一击——立体成像。因为玉米的这个系列文章是对双目视觉几何框架的总结。此处跳过匹配,假设左右图像点的完美匹配的。只看在几何上,三维坐标是如何被还原的。相对来说,最后的这一步,比前面是要轻松许多的,因为我们前面已经做了大量的工作。这些工作使得最后的这一步,由不可能称为可能,由复杂变得简单,吧啦吧啦。好吧,闲话少说,让我们一起来见证这一时刻吧。

            此处我们按opencv中cvcalibratecamera2()函数得到的焦距f进行三维坐标的求解。

            请大家看下面示意图(莫怪,玉米的图一向画的丑):

            根据最简单的相似三角形关系,我们就可以求出,物点坐标(X,Y,Z)。

            首先,

             其中,s为像素的物理尺寸,d就是两个摄像机间的视差,d=(uL-uR)s。

            我们得到的这个三维坐标,相当于是在右摄像机的摄像机坐标系上的。

           那么重建就是透视投影的逆过程,我们可以把这个过程表示成矩阵形式。我们定义Q为反投影矩阵。那么依照上式:

            齐次坐标形式的三维坐标恢复,矩阵形式如下:

            至此,玉米的《计算机视觉学习笔记》双目视觉几何框架系列文章顺利收尾。希望这八篇博文对大家,尤其是计算机视觉的初学者有所帮助。

            在行文过程中,玉米引用了网络上的一些图片,但大多找不到出处,所以未给出引用表。如这些图片的主人,发现了自己的图片在这个博客上,请和玉米联系,玉米会将引用出处,重新给出!

           本系列博文中涉及的数学运算颇多,玉米才疏学浅,中间若有理解上的错误,恳请大家批评指正!

     原创地址:http://blog.csdn.net/onthewaysuccess/article/details/40709745

    展开全文
  • OpenCV+OpenGL 双目立体视觉三维重建代码以及文档 使用opencv进行立体匹配获取视差图,三角剖分 使用opengl进行纹理贴图 需要配置opengl,opencv,vs2015工程 博客地址: ...
  • 基于混合编程的双目视觉三维重建方法.pdf
  • 基于双目视觉三维重建

    热门讨论 2012-08-27 16:19:40
    基于双目视觉三维重建,包含了重建过程中的基本步骤: 1、稀疏点匹配与重建(无图像校正); 2、稀疏点匹配与重建; 3、密集点匹配
  • 基于matlab的双目结构光实现三维重建
  • 内容为整个三维重建描述方法,以及步骤过程,矩阵如何选择,如何标定等等
  • OpenCV实现SfM:双目三维重建

    千次下载 热门讨论 2015-09-02 14:29:19
    使用OpenCV3.0进行双目三维重建。 代码是用VS2013写的,OpenCV版本为3.0且包含扩展部分,如果不使用SIFT特征,可以修改源代码,然后使用官方未包含扩展部分的库。软件运行后会将三维重建的结果写入Viewer目录下的...
  • vs2015+opencv2.4.10实现的双目立体视觉三维重建c++代码。SGBM立体匹配
  • 基于双目视觉的深度计算和三维重建双目视觉opencv opengl三维重建,简单的三维重建系统,代码可正常运行
  • 基于双目视觉的深度计算和三维重建,代码我自己用过,绝对没问题
  • 三维重建 的matlab 代码 可以入门使用,希望对你有帮助
  • 计算三维重建的方法称为SfM(Structure from Motion).\ 假设计算机已经标定,计算重建的部分可以分为下面四个步骤:\ (1)、检测特征点,然后在两幅图间进行特征点匹配。\ (2)、有匹配算出基础矩阵。\ (3)、由...
  • 基于运动恢复的双目视觉三维重建系统设计与实现(一) 这是王欣 , 袁 坤 , 于晓 , 章明朝等人在2014年发表的一篇文章 , 我想实现用c++与opencv实现它 , 这篇文章可以在知网上下载<基于运动恢复的双目视觉三维重建...

    基于运动恢复的双目视觉三维重建系统设计与实现(一)

    这是王欣 , 袁 坤 , 于晓 , 章明朝等人在2014年发表的一篇文章 , 我想实现用c++与opencv实现它 , 这篇文章可以在知网上下载<基于运动恢复的双目视觉三维重建系统设计>.
    实现原理:
    在这里插入图片描述
    首先是利用双目视觉的原理 , 先计算视差并优化 , 得到深度值作为运动恢复结构算法SFM的初始化 , 接着把左右图像分开 , 单独进行sfm , 最后用双目一致性约束进行合并左右图像恢复的点云.

    一些原理就不介绍了 , 接下来的系列文章是代码实现 , 这里相当于立一个目标.

    展开全文
  • 双目立体视觉三维重建

    万次阅读 多人点赞 2018-07-22 17:15:08
    OpenCV+OpenGL 双目立体视觉三维重建 OpenCV 双目测距(双目标定、双目校正和立体匹配) 真实场景的双目立体匹配(Stereo Matching)获取深度图详解 图像获取 双目相机拍摄获取 左右目图像 双目标定 ...

    Overview

    双目立体视觉的整体流程包括:

    • 图像采集
    • 双目标定
    • 双目矫正
    • 立体匹配
    • 三维重建

    1. 图像采集

    双目相机采集 左右目图像

    2. 双目标定

    通过 双目标定工具 对双目相机进行标定,得到如下结果参数:

    内参外参
    相机矩阵 K 1 , K 2 K_1, K_2 K1,K2旋转矩阵 R R R
    畸变系数 D 1 , D 2 D_1, D_2 D1,D2平移向量 t t t

    《Learning OpenCV》中对于 Translation 和 Rotation 的图示是这样的:

    示例代码:

    cv::Matx33d K1, K2, R;
    cv::Vec3d T;
    cv::Vec4d D1, D2;
    
    int flag = 0;
    flag |= cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC;
    flag |= cv::fisheye::CALIB_CHECK_COND;
    flag |= cv::fisheye::CALIB_FIX_SKEW;
    
    cv::fisheye::stereoCalibrate(
            obj_points_, img_points_l_, img_points_r_,
            K1, D1, K2, D2, img_size_, R, T,
            flag, cv::TermCriteria(3, 12, 0));
    

    3. 双目矫正

    双目矫正 主要包括两方面:畸变矫正立体矫正

    利用 OpenCV的函数,主要分为

    • stereoRectify
    • initUndistortRectifyMap
    • remap

    stereoRectify

    根据双目标定的结果 K 1 , K 2 , D 1 , D 2 , R , t K_1, K_2, D_1, D_2, R, t K1,K2,D1,D2,R,t,利用 OpenCV函数 stereoRectify,计算得到如下参数

    • 左目 矫正矩阵(旋转矩阵) R 1 R_1 R1 (3x3)
    • 右目 矫正矩阵(旋转矩阵) R 2 R_2 R2 (3x3)
    • 左目 投影矩阵 P 1 P_1 P1 (3x4)
    • 右目 投影矩阵 P 2 P_2 P2 (3x4)
    • disparity-to-depth 映射矩阵 Q Q Q (4x4)

    其中,

    左右目投影矩阵(horizontal stereo, c x 1 ′ = c x 2 ′ {c_x}_1'={c_x}_2' cx1=cx2 if CV_CALIB_ZERO_DISPARITY is set)

    P 1 = [ f ′ 0 c x 1 ′ 0 0 f ′ c y ′ 0 0 0 1 0 ] P_1 = \begin{bmatrix} f' & 0 & {c_x}_1' & 0 \\ 0 & f' & c_y' & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix} P1=f000f0cx1cy1000

    P 2 = [ f ′ 0 c x 2 ′ t x ′ ⋅ f ′ 0 f ′ c y ′ 0 0 0 1 0 ] P_2 = \begin{bmatrix} f' & 0 & {c_x}_2' & t_x' \cdot f' \\ 0 & f' & c_y' & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix} P2=f000f0cx2cy1txf00

    where

    t x ′ = − B t_x' = -B tx=B

    disparity-to-depth 映射矩阵

    Q = [ 1 0 0 − c x 1 ′ 0 1 0 − c y ′ 0 0 0 f ′ 0 0 − 1 t x ′ c x 1 ′ − c x 2 ′ t x ′ ] Q = \begin{bmatrix} 1 & 0 & 0 & -{c_x}_1' \\ 0 & 1 & 0 & -c_y' \\ 0 & 0 & 0 & f' \\ 0 & 0 & -\frac{1}{t_x'} & \frac{ {c_x}_1'-{c_x}_2'}{t_x'} \end{bmatrix} Q=10000100000tx1cx1cyftxcx1cx2

    通过 P 2 P_2 P2 可计算出 基线 长度:

    baseline = B = − t x ′ = − P 2 ( 03 ) f ′ \begin{aligned} \text{baseline} = B = - t_x' = - \frac{ {P_2}_{(03)} }{f'} \end{aligned} baseline=B=tx=fP2(03)

    示例代码:

    cv::Mat R1, R2, P1, P2, Q;
    cv::fisheye::stereoRectify(
            K1, D1, K2, D2, img_size_, R, T,
            R1, R2, P1, P2, Q,
            CV_CALIB_ZERO_DISPARITY, img_size_, 0.0, 1.1);
    

    CameraInfo DKRP

    参考:sensor_msgs/CameraInfo Message

    • D: distortion parameters.

      • For “plumb_bob”, the 5 parameters are: (k1, k2, t1, t2, k3)
    • K: Intrinsic camera matrix for the raw (distorted) images.

      • Projects 3D points in the camera coordinate frame to 2D pixel coordinates using the focal lengths (fx, fy) and principal point (cx, cy).
        K = [ f x 0 c x 0 f y c y 0 0 1 ] \mathbf{K} = \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} K=fx000fy0cxcy1
    • R: Rectification matrix (stereo cameras only).

      • A rotation matrix aligning the camera coordinate system to the ideal stereo image plane so that epipolar lines in both stereo images are parallel.
      • For monocular cameras R = I \mathbf{R} = \mathbf{I} R=I
    • P: Projection/camera matrix.

      • For monocular cameras
        P = [ f x 0 c x 0 0 f y c y 0 0 0 1 0 ] \mathbf{P} = \begin{bmatrix} f_x & 0 & c_x & 0 \\ 0 & f_y & c_y & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix} P=fx000fy0cxcy1000
      • For a stereo pair, the fourth column [Tx Ty 0]’ is related to the position of the optical center of the second camera in the first camera’s frame. We assume Tz = 0 so both cameras are in the same stereo image plane.
        • The first camera
          P = [ f x ′ 0 c x ′ 0 0 f y ′ c y ′ 0 0 0 1 0 ] \mathbf{P} = \begin{bmatrix} f_x' & 0 & c_x' & 0 \\ 0 & f_y' & c_y' & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix} P=fx000fy0cxcy1000
        • The second camera
          P = [ f x ′ 0 c x ′ − f x ′ ⋅ B 0 f y ′ c y ′ 0 0 0 1 0 ] \mathbf{P} = \begin{bmatrix} f_x' & 0 & c_x' & -f_x' \cdot B \\ 0 & f_y' & c_y' & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix} P=fx000fy0cxcy1fxB00
      • Given a 3D point [ X Y Z ] ′ [X Y Z]' [XYZ], the projection ( x , y ) (x, y) (x,y) of the point onto the rectified image is given by:

      [ u v w ] = P ⋅ [ X Y Z 1 ] , { x = u w y = v w \begin{bmatrix} u \\ v \\ w \end{bmatrix} = \mathbf{P} \cdot \begin{bmatrix} X \\ Y \\ Z \\ 1 \end{bmatrix} , \quad \begin{cases} x = \frac{u}{w} \\ y = \frac{v}{w} \end{cases} uvw=PXYZ1,{x=wuy=wv

    initUndistortRectifyMap

    左右目 分别利用 OpenCV函数 initUndistortRectifyMap 计算 the undistortion and rectification transformation map,得到

    • 左目map: m a p 1 l , m a p 2 l map^l_1, map^l_2 map1l,map2l
    • 右目map: m a p 1 r , m a p 2 r map^r_1, map^r_2 map1r,map2r

    示例代码:

    cv::fisheye::initUndistortRectifyMap(K1, D1, R1, P1, img_size, CV_16SC2, rect_map_[0][0], rect_map_[0][1]);
    cv::fisheye::initUndistortRectifyMap(K2, D2, R2, P2, img_size, CV_16SC2, rect_map_[1][0], rect_map_[1][1]);
    

    Remap

    左右目 分别利用 OpenCV函数 remap 并根据 左右目map 对左右目图像进行 去畸变 和 立体矫正,得到 左右目矫正图像

    示例代码:

    cv::remap(img_l, img_rect_l, rect_map_[0][0], rect_map_[0][1], cv::INTER_LINEAR);
    cv::remap(img_r, img_rect_r, rect_map_[1][0], rect_map_[1][1], cv::INTER_LINEAR);
    

    4. 立体匹配

    根据双目矫正图像,通过 BM或SGM等立体匹配算法 对其进行立体匹配,计算 视差图

    视差计算

    通过 OpenCV函数 stereoBM (block matching algorithm),生成 视差图(Disparity Map) (CV_16S or CV_32F)

    disparity map from stereoBM of OpenCV :
    It has the same size as the input images. When disptype == CV_16S, the map is a 16-bit signed single-channel image, containing disparity values scaled by 16. To get the true disparity values from such fixed-point representation, you will need to divide each disp element by 16. If disptype == CV_32F, the disparity map will already contain the real disparity values on output.

    So if you’ve chosen disptype = CV_16S during computation, you can access a pixel at pixel-position (X,Y) by: short pixVal = disparity.at<short>(Y,X);, while the disparity value is float disparity = pixVal / 16.0f;; if you’ve chosen disptype = CV_32F during computation, you can access the disparity directly: float disparity = disparity.at<float>(Y,X);

    5. 三维重建

    (1)算法1:根据视差图,利用 f ′ f' f B B B 通过几何关系计算 深度值,并利用相机内参计算 三维坐标

    根据上图相似三角形关系,得

    Z B = Z − f B − d w ⟹ Z = B f d w \frac{Z}{B} = \frac{Z-f}{B-d_w} \quad \Longrightarrow \quad Z = \frac{Bf}{d_w} BZ=BdwZfZ=dwBf

    其中, f f f d w d_w dw 分别为 成像平面的焦距和视差,单位均为 物理单位,将其转换为 像素单位,上式写为

    Z = B f ′ d p Z = \frac{B f'}{d_p} Z=dpBf

    其中,

    d p = ( O r − u r ) + ( u l − O l ) = ( u l − u r ) + ( O r − O l ) d_p = (O_r - u_r) + (u_l - O_l) = (u_l - u_r) + (O_r - O_l) dp=(Orur)+(ulOl)=(ulur)+(OrOl)

    最终,深度计算公式如下,通过遍历图像可生成 深度图

    Z = depth = B ⋅ f ′ d p with d p = disp ( u , v ) + ( c x 2 ′ − c x 1 ′ ) Z = \text{depth} = \frac{B \cdot f'}{d_p} \quad \text{with} \quad d_p = \text{disp}(u,v) + ({c_x}_2' - {c_x}_1') Z=depth=dpBfwithdp=disp(u,v)+(cx2cx1)

    根据 小孔成像模型,已知 Z Z Z相机内参 可计算出 三维点坐标,从而可生成 三维点云

    { Z = depth = f ′ ⋅ B d p X = u − c x 1 ′ f ′ ⋅ Z Y = v − c y ′ f ′ ⋅ Z 或 { bd = B d p Z = depth = f ′ ⋅ bd X = ( u − c x 1 ′ ) ⋅ bd Y = ( u − c y ′ ) ⋅ bd \begin{aligned} \begin{cases} Z = \text{depth} = \frac{f' \cdot B}{d_p} \\ X = \frac{u-{c_x}_1'}{f'} \cdot Z \\ Y = \frac{v-{c_y}'}{f'} \cdot Z \end{cases} \end{aligned} \text{或} \begin{aligned} \begin{cases} \text{bd} = \frac{B}{d_p}\\ Z = \text{depth} = f' \cdot \text{bd} \\ X = (u-{c_x}_1') \cdot \text{bd} \\ Y = (u-{c_y}') \cdot \text{bd} \end{cases} \end{aligned} Z=depth=dpfBX=fucx1ZY=fvcyZbd=dpBZ=depth=fbdX=(ucx1)bdY=(ucy)bd

    其中, disp ( u , v ) \text{disp}(u,v) disp(u,v) 代表 视差图 坐标值

    (2)算法2:根据视差图,利用 Q Q Q 矩阵 计算 三维点坐标(reprojectImageTo3D

    [ X ′ Y ′ Z ′ W ] = Q ⋅ [ u v disp ( u , v ) 1 ] \begin{bmatrix} X' \\ Y' \\ Z' \\ W \end{bmatrix} = Q \cdot \begin{bmatrix} u \\ v \\ \text{disp}(u,v) \\ 1 \end{bmatrix} XYZW=Quvdisp(u,v)1

    最终,三维点坐标为

    [ X Y Z ] = [ X ′ W Y ′ W Z ′ W ] \begin{bmatrix} X \\ Y \\ Z \end{bmatrix} = \begin{bmatrix} \frac{X'}{W} \\[2ex] \frac{Y'}{W} \\[2ex] \frac{Z'}{W} \end{bmatrix} XYZ=WXWYWZ

    深度图 图像类型

    • 单位meter --> 32FC1
    • 单位millimeter --> 16UC1

    总结

    展开全文
  • 基于双目三维模型重建,模型比较简单,适合刚入门需要的
  • 双目视觉+结构光三维重建原理

    千次阅读 2020-05-24 13:18:50
    结构光三维重建原理   结构光三维重建系统是由一个相机和一个投影仪组成,关于结构光三维重建系统的理论有很多,其中有一个简单的模型是把投影仪看做相机来使用,从而得到物体的三维信息。接下来我将详细介绍这个...
  • python双目视觉标定及三维重建

    千次阅读 热门讨论 2021-04-10 15:07:16
    写在前面的话: 一个机器视觉的课程作业,是自行采集一组双目图像,完成立体视觉相关流程:包括相机标定(内参和外参)、畸变校正、基本矩阵估算、视差图计算(需要先进行图像矫正)、恢复并画出3D点坐标。...
  • 记录一下深度学习进行双目三维重建看过的网络 持续更新(时不时更新) 数据集: SceneFlow KITTI 与三维有关的数据集: TanksAndTemples 一大堆Github总结的数据集 Github大佬的笔记 -----------------------------...
  • 采用matlab和Vc混合编程实现了双目视觉三维重建

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,616
精华内容 1,446
关键字:

双目视觉三维重建