MATLAB实现双目校准

MATLAB实现双目图像校准

在网上见的大多数双目图像校准都是MATLAB与OpenCV结合来实现的,经过两个月断断续续的学习,总算用纯MATLAB实现的图像校准算法。下面对这一段时间的成果进行总结和防止以后重新学习。

不废话,直接开始吧。。。。。。

说到双目系统首先必须要说一下双目模型。
首先我们要先只要三个坐标系:图像坐标系、相机坐标系、世界坐标系。

可参考http://www.cnblogs.com/dverdon/p/5609124.html
其中相机坐标转换为图像坐标:这里写图片描述
其中u0、v0为图像平面的主点,dx、dy为相机的像元尺寸大小,u、v为图像坐标点、x、y为相机坐标点。
这里写图片描述
其中,Xc、Yc、Zc代表相机坐标系,X、Y、Z为世界坐标系。R为旋转矩阵,T为平移矩阵。
以上为理想状态下的双目视觉模型,但在实际中,相机的或多或少都存在畸变。因此在实际应用中要将畸变图像进行矫正。

世界坐标转换为相机坐标畸变矫正
相机的畸变模型公式:
可参考http://blog.csdn.net/wangxiaokun671903/article/details/37973365
http://blog.csdn.net/humanking7/article/details/45037239
上面两篇文章讲的很详细,我在这里就复制粘贴了。

综合以上内容,可以总结为一下内容(我很懒,就直接粘贴过来了)

该过程为世界坐标系转换为图像坐标系的过程
这里写图片描述

该过程为相机畸变处理过程这里写图片描述

以上对原理进行了简单介绍,网上资料比我讲的详细,我这里只是防止忘记,做一个备份。

下面开始相机标定过程:这里我直接参考http://blog.csdn.net/dreamharding/article/details/53700166
这里我将最终的标定结果贴出来
这里写图片描述

开始上代码:

公式法:

主要参考http://blog.csdn.net/wangxiaokun671903/article/details/38017055和工具箱代码

clc;clear;

I1 = rgb2gray(imread('右图片路径'));
I2 = rgb2gray(imread('左图片路径'));
[m,n] = size(I1);
I11 = zeros(m,n)+255;
[m,n] = size(I2);
I22 = zeros(m,n)+255;

A1 = [665.32773         0       345.54178;...
        0           660.17940   249.92143;...
        0               0           1];
D1 = [0.22386   -0.93591   0.00725   0.00018  0.00000];

A2 = [688.30717         0       315.31975;...
        0           683.13738   264.40537;...
        0               0           1];
D2 = [0.27153   -1.00396   0.01107   0.00364  0.00000 ];

fx1 = A1(1,1);
fy1 = A1(2,2);
cx1 = A1(1,3);
cy1 = A1(2,3);
k11 = D1(1);
k12 = D1(2);
p11 = D1(3);
p12 = D1(4);
k13 = D1(5);

fx2 = A2(1,1);
fy2 = A2(2,2);
cx2 = A2(1,3);
cy2 = A2(2,3);
k21 = D2(1);
k22 = D2(2);
p21 = D2(3);
p22 = D2(4);
k23 = D2(5);

fx = (fx1 + fx2)/2;
fy = (fy1 + fy2)/2;
cx = (cx1 + cx2)/2;
cy = (cy1 + cy2)/2;

T = [-39.78384   1.21230  -40.44029];

om = [-0.02302   -0.00735  0.00089];

% 以下部分为直接拷贝工具箱源码内容 start
r_r = rodrigues(-om/2);
r_l = r_r';
t = r_r * T;

% Rotate both cameras so as to bring the translation vector in alignment with the (1;0;0) axis:
if abs(t(1)) > abs(t(2)),
    type_stereo = 0;
    uu = [1;0;0]; % Horizontal epipolar lines
else
    type_stereo = 1;
    uu = [0;1;0]; % Vertical epipolar lines
end;
if dot(uu,t)<0,
    uu = -uu; % Swtich side of the vector 
end;
ww = cross(t,uu);
ww = ww/norm(ww);
ww = acos(abs(dot(t,uu))/(norm(t)*norm(uu)))*ww;
R = rodrigues(ww);


% Global rotations to be applied to both views:
R1 = R * r_r;
R2 = R * r_l;

T_new = R1*T;
% 以上部分为直接拷贝工具箱源码内容 end

for v=1:m %640
    for u=1:n  %480
        x = (v - cx1)/fx1;
        y = (u - cy)/fy1;
        pos=[x;y;1]; %3x1
        pos=inv(R1)*pos; %旋转相机坐标系,3x1
        x1=pos(1,:)/pos(3,:);%归一化
        y1=pos(2,:)/pos(3,:);
        r=x1^2+y1^2;
        x2 = x1*(1+k11*r+k12*r^2+k13*r^3) + 2*p11*x1*y1+p12*(r+2*x1^2);
        y2 = y1*(1+k11*r+k12*r^2+k13*r^3) + 2*p12*x1*y1+p11*(r+2*y1^2);
        x3 = x2*fx1 +cx1;
        y3 = y2*fy1 +cy;
        if (x3>1 && x3<=n && y3>1 && y3<=m)
            h=y3;
            w=x3;
            I11(v,u)=(floor(w+1)-w)*(floor(h+1)-h)*I1(floor(h),floor(w))+(floor(w+1)-w)*(h-floor(h))*I1(floor(h+1),floor(w))+(w-floor(w))*(floor(h+1)-h)*I1(floor(h),floor(w+1))+(w-floor(w))*(h-floor(h))*I1(floor(h+1),floor(w+1));
        end
        if mod(v,50) == 0
            I11(v,u) = 255;
        end
    end
end

for v=1:m %640
    for u=1:n  %480
        x = (v - cx2)/fx2;
        y = (u - cy)/fy2;
        pos=[x;y;1]; %3x1
        pos=inv(R2)*pos; %旋转相机坐标系,3x1
        x1=pos(1,:)/pos(3,:);%归一化
        y1=pos(2,:)/pos(3,:);
        r=x1^2+y1^2;
        x2 = x1*(1+k21*r+k22*r^2+k23*r^3) + 2*p21*x1*y1+p22*(r+2*x1^2);
        y2 = y1*(1+k21*r+k22*r^2+k23*r^3) + 2*p22*x1*y1+p21*(r+2*y1^2);
        x3 = x2*fx2 +cx2;
        y3 = y2*fy2 +cy;
        if (x3>1 && x3<=n && y3>1 && y3<=m)
            h=y3;
            w=x3;
            I22(v,u)=(floor(w+1)-w)*(floor(h+1)-h)*I1(floor(h),floor(w))+(floor(w+1)-w)*(h-floor(h))*I1(floor(h+1),floor(w))+(w-floor(w))*(floor(h+1)-h)*I1(floor(h),floor(w+1))+(w-floor(w))*(h-floor(h))*I1(floor(h+1),floor(w+1));
        end
        if mod(v,50) == 0           % 画线
            I22(v,u) = 255;
        end
    end
end

figure;imshow(I11,[]);
figure;imshow(I22,[]);

该过程是直接根据公式进行编写。执行效率很慢。

直接法:
主要参考工具箱代码
这里首先我们需要对工具箱源代码进行修改。

在工具箱中找到rectify_stereo_pair.m,添加如在代码。

save result_left ind_new_left ind_1_left ind_2_left ind_3_left ind_4_left a1_left a2_left a3_left a4_left ;
save result_right ind_new_right ind_1_right ind_2_right ind_3_right ind_4_right a1_right a2_right a3_right a4_right ;

添加如图:
这里写图片描述

点击Rectifu the calibration images
这里写图片描述

最终会多出两个文件这里写图片描述

这两个文件就是将原始图像直接转换为平行校准后图像。

clc;clear;
I = double(rgb2gray(imread('左图像路径')));
re = load('result_left.mat');
ind_new_left = re.ind_new_left;
a1_left = re.a1_left;
ind_1_left = re.ind_1_left;
a2_left = re.a2_left;
ind_2_left = re.ind_2_left;
a3_left = re.a3_left;
ind_3_left = re.ind_3_left;
a4_left = re.a4_left;
ind_4_left= re.ind_4_left;

Il = 255*ones(480,640);
Il(ind_new_left) = uint8(a1_left .* I(ind_1_left) + a2_left .* I(ind_2_left) + a3_left .* I(ind_3_left) + a4_left .* I(ind_4_left));

I = double(rgb2gray(imread('右图像路径')));
re = load('result_right.mat');
ind_new_right = re.ind_new_right;
a1_right = re.a1_right;
ind_1_right = re.ind_1_right;
a2_right = re.a2_right;
ind_2_right = re.ind_2_right;
a3_right = re.a3_right;
ind_3_right = re.ind_3_right;
a4_right = re.a4_right;
ind_4_right = re.ind_4_right;

Ir = 255*ones(480,640);
Ir(ind_new_left) = uint8(a1_left .* I(ind_1_left) + a2_left .* I(ind_2_left) + a3_left .* I(ind_3_left) + a4_left .* I(ind_4_left));

for i = 1:480
    for j = 1:640
        if mod(i,20)==0
            Il(i,j) = 255;
            Ir(i,j) = 255;
        end
    end
end

figure;imshow(Il,[]);
figure;imshow(Ir,[]);

该方法可以提高算法的执行效率。
今天先写到这里,下一步利用C++来实现双目校准过程。

### 回答1: 双目立体匹配是实现三维视觉的基础技术之一,而MATLAB作为一种强大的数学计算和可视化工具,可以用于实现双目立体匹配算法。 首先,需要对左右摄像机采集到的图像进行预处理,包括灰度化、去噪、增强等操作。然后,可以通过计算左右图像对应像素之间的距离或相似度来实现匹配。其中,常用的匹配算法包括基于区域的SAD、SSD、NCC等方法和基于特征点的SIFT、SURF等方法。 下面以基于SAD算法的立体匹配为例进行说明。SAD算法是一种简单有效的匹配方法,它计算左右图像中同一像素之间的差值的绝对值之和来评估它们的相似度。具体实现过程如下: 1. 设置一个匹配窗口大小,例如5x5。 2. 对左图的每个像素,在右图上沿着同一行扫描匹配窗口,计算窗口内像素值差的绝对值之和,称为SAD值。 3. 对于每个像素,找到右图中SAD值最小的像素,并将它的位置作为匹配点。 4. 重复以上步骤,对于右图的每个像素,都可以找到左图对应的匹配点。 5. 根据匹配点之间的距离计算三维坐标,从而得到立体视觉效果。 MATLAB提供了丰富的图像处理和计算函数,可以轻松实现双目立体匹配算法。各种算法的具体应用可以参考MATLAB官方文档和相关论文,也可以借助MATLAB社区的开源代码进行实现。 ### 回答2: 双目立体匹配是计算机视觉中的重要技术之一,可以用来获取景深信息或者进行三维重构。Matlab是一个强大的科学计算软件,也提供了许多图像处理和计算机视觉工具箱,因此可以用Matlab实现双目立体匹配算法双目立体匹配的基本步骤包括:特征提取、匹配代价计算、代价聚合、视差计算等。其中,特征提取是关键步骤,通常采用SIFT、SURF等算法提取关键点和特征描述子。 在Matlab中,可以使用Computer Vision toolbox中的函数来进行特征提取和匹配。如SURF特征提取函数“detectSURFFeatures”和匹配函数“matchFeatures”。 接下来,需要计算匹配代价,常用的代价函数有SSD、SAD和NCC等。在Matlab中,可以使用内置函数“normxcorr2”来计算NCC代价。此外,还需要进行代价聚合,这里使用了动态规划算法或者Belief Propagation等方法来求解视差图。 最终,根据视差值计算深度等信息即可。需要注意的是,在进行双目立体匹配时,必须对左右图像进行校准,确保左右摄像机的光学中心和旋转矩阵已知。 总之,通过Matlab实现双目立体匹配算法可以快速实现目标检测、三维重构等视觉应用。虽然也有其他的工具可以实现,但Matlab提供了更多的高级算法和工具,可以快速构建和测试双目立体匹配算法。 ### 回答3: 双目立体匹配算法是数字图像处理中非常重要的一个领域,其可以解决立体成像中的深度测量问题。Matlab作为一款优秀的数学软件,可以很好地实现这种算法。 首先,双目立体匹配算法需要用到两个摄像头,将同一场景捕捉到的图像进行采集,使其产生一定的视差。接着,对于双目图像进行预处理,如图像去噪,平滑处理等。 然后在Matlab实现视差计算的算法。这里可以采用灰度共生矩阵、SAD(Sum of Absolute Differences)等算法来计算视差。最后,对匹配结果进行处理,如消除错误匹配点、处理孔洞、插值等,得到最终的深度图。 实现双目立体匹配算法需要掌握Matlab图像处理工具箱中函数的使用,如图像滤波函数、图像分割函数、特征提取函数等。同时需要理解立体匹配原理和相关算法,并能进行代码编写和调试。 总之,通过Matlab实现双目立体匹配算法能够使我们更好地理解该算法的原理,加深对计算机视觉领域的认识,并且提高图像处理的技能水平。
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值