绝对差立体匹配算法的实现
Implementation of Absolute Differences Stereo Matching Algorithm
美好的一天!
我正在尝试学习如何手动实施立体匹配算法。我基本上从最基本的开始 - 绝对差异。
我在网上找到了一些介绍如何操作的幻灯片。基本上,据我了解,我应该通过某个 distance/disparity 计算左图像中的像素与右图像中的相同像素 "shifted" 之间的差异。然后在这些差异中,我 select 最小,这对我来说很有意义,因为具有最低差异的像素意味着它很可能是左图中的相同像素。
我已经在 MATLAB 中制作了原型。这是代码:
im_left = imread('tsu_left.png');
im_right = imread('tsu_right.png');
height = size(im_left, 1);
width = size(im_left, 2);
disparity_max = 16;
ad_costs = zeros(height, width,disparity_max);
for disparity = 1:disparity_max
for row = 1:height
for col = 1:width
%Left to right matching
col_disp = col - disparity;
if col_disp < 1
ad_costs(row, col, disparity) = 0;
else
%Average RGB
left_pixel = (im_left(row, col, 1) + im_left(row, col, 2) + im_left(row, col, 3))/3;
right_pixel = (im_right(row, col_disp, 1) + im_right(row, col_disp, 2) + im_right(row, col_disp, 3))/3;
%Subtract averages
ad_costs(row, col, disparity) = abs(left_pixel - right_pixel);
end
end
end
end
min_costs = zeros(height, width);
for disparity = 1:disparity_max
for row = 1:height
for col = 1:width
%The minimum disparity is chosen
min_costs(row, col) = min(ad_costs(row, col, :));
end
end
end
请注意,我还没有实现对某个 window 中的差异求和的变体,从而导致绝对差异之和。我只考虑每个像素、每个视差的差异。我在网上找到的讲义幻灯片说它应该是这样的(最右图):
https://dl.dropboxusercontent.com/u/92715312/lec.PNG
但是,上面代码(使用 imshow(min_costs))的结果是这样的:
https://dl.dropboxusercontent.com/u/92715312/res.PNG
我不明白为什么输出如此不同。我是否遗漏了一些微不足道的步骤,或者我对算法工作原理的理解有误?我也在用筑波图片
这很可能是 imshow 问题。函数 imshow 除外图像在 [0, 255] 范围内(如果它是 uint8)或 [0.0, 1.0](如果是浮点数)。
尝试:
imshow(min_cost, []);
注意,第二个参数为空数组。这告诉 Matlab 计算缩放比例。
或者,使用:
imagesc(min_cost); axis image off;
编辑:
带有一些像素差异测量的香草校正立体相当简单。请看下面的代码:
function [D, C_min, C] = stereo_sad(I1, I2, min_d, max_d, w_radius)
% function [D, C_min, C] = stereo_sad(I1, I2, min_d, max_d, w_radius)
%
% INPUT
% I1 the left stereo image
% I2 the right stereo image
% min_d minimum disparity
% max_d maximum disparity
% w_radius the radius of the window to do the AD aggeration
%
% OUTPUT
% D disparity values
% C_min cost associated with the minimum disparity at pixel (i,j)
% C the cost volume for AD
%
if nargin < 5, w_radius = 4; end % 9x9 window
if nargin < 4, max_d = 64; end
if nargin < 3, min_d = 0; end
% aggregation filter (window size to aggerate the AD cost)
kernel = ones(w_radius*2+1);
kernel = kernel ./ numel(kernel); % normalize it
% grayscale is sufficient for stereo matching
% the green channel is actually a good approximation of the grayscale, we
% could instad do I1 = I1(:,:,2);
if size(I1,3) > 1, I1 = rgb2gray(I1); end
if size(I2,3) > 1, I2 = rgb2gray(I2); end
% conver to double/single
I1 = double(I1);
I2 = double(I2);
% the range of disparity values from min_d to max_d inclusive
d_vals = min_d : max_d;
num_d = length(d_vals);
C = NaN(size(I1,1), size(I1,2), num_d); % the cost volume
% the main loop
for i = 1 : length(d_vals);
d = d_vals(i);
I2_s = imtranslate(I2, [d 0]);
C(:,:,i) = abs(I1 - I2_s); % you could also have SD here (I1-I2_s).^2
C(:,:,i) = imfilter(C(:,:,i), kernel);
end
[C_min, D] = min(C, [], 3);
D = D + min_d;
end
给运行代码
I1 = imread( ... 你的左图
I2 = imread( ... 你的右图)
D = stereo_sad(I1, I2, 0, 96, 4);
图片c(D);轴图像关闭;彩条
你会得到像下面这样的视差图
步骤是:
- 在每个差异处移动右图像
- 计算移动后的图像和
左图(或其他一些度量,如 SSD)
- 用矩形取平均值window,这是一个"box"过滤器
- 以每像素 "volume" 的成本存储平均值
- 差异位于每像素成本量的最小值处。
Disparity 会在索引中变成最小值
可以使用内置的 Matlab 工具完成这些操作,以生成易于阅读的代码。
希望对您有所帮助。
我认为你应该在最小化步骤之后做一个过滤器
美好的一天!
我正在尝试学习如何手动实施立体匹配算法。我基本上从最基本的开始 - 绝对差异。
我在网上找到了一些介绍如何操作的幻灯片。基本上,据我了解,我应该通过某个 distance/disparity 计算左图像中的像素与右图像中的相同像素 "shifted" 之间的差异。然后在这些差异中,我 select 最小,这对我来说很有意义,因为具有最低差异的像素意味着它很可能是左图中的相同像素。
我已经在 MATLAB 中制作了原型。这是代码:
im_left = imread('tsu_left.png');
im_right = imread('tsu_right.png');
height = size(im_left, 1);
width = size(im_left, 2);
disparity_max = 16;
ad_costs = zeros(height, width,disparity_max);
for disparity = 1:disparity_max
for row = 1:height
for col = 1:width
%Left to right matching
col_disp = col - disparity;
if col_disp < 1
ad_costs(row, col, disparity) = 0;
else
%Average RGB
left_pixel = (im_left(row, col, 1) + im_left(row, col, 2) + im_left(row, col, 3))/3;
right_pixel = (im_right(row, col_disp, 1) + im_right(row, col_disp, 2) + im_right(row, col_disp, 3))/3;
%Subtract averages
ad_costs(row, col, disparity) = abs(left_pixel - right_pixel);
end
end
end
end
min_costs = zeros(height, width);
for disparity = 1:disparity_max
for row = 1:height
for col = 1:width
%The minimum disparity is chosen
min_costs(row, col) = min(ad_costs(row, col, :));
end
end
end
请注意,我还没有实现对某个 window 中的差异求和的变体,从而导致绝对差异之和。我只考虑每个像素、每个视差的差异。我在网上找到的讲义幻灯片说它应该是这样的(最右图):
https://dl.dropboxusercontent.com/u/92715312/lec.PNG
但是,上面代码(使用 imshow(min_costs))的结果是这样的:
https://dl.dropboxusercontent.com/u/92715312/res.PNG
我不明白为什么输出如此不同。我是否遗漏了一些微不足道的步骤,或者我对算法工作原理的理解有误?我也在用筑波图片
这很可能是 imshow 问题。函数 imshow 除外图像在 [0, 255] 范围内(如果它是 uint8)或 [0.0, 1.0](如果是浮点数)。
尝试:
imshow(min_cost, []);
注意,第二个参数为空数组。这告诉 Matlab 计算缩放比例。
或者,使用:
imagesc(min_cost); axis image off;
编辑:
带有一些像素差异测量的香草校正立体相当简单。请看下面的代码:
function [D, C_min, C] = stereo_sad(I1, I2, min_d, max_d, w_radius)
% function [D, C_min, C] = stereo_sad(I1, I2, min_d, max_d, w_radius)
%
% INPUT
% I1 the left stereo image
% I2 the right stereo image
% min_d minimum disparity
% max_d maximum disparity
% w_radius the radius of the window to do the AD aggeration
%
% OUTPUT
% D disparity values
% C_min cost associated with the minimum disparity at pixel (i,j)
% C the cost volume for AD
%
if nargin < 5, w_radius = 4; end % 9x9 window
if nargin < 4, max_d = 64; end
if nargin < 3, min_d = 0; end
% aggregation filter (window size to aggerate the AD cost)
kernel = ones(w_radius*2+1);
kernel = kernel ./ numel(kernel); % normalize it
% grayscale is sufficient for stereo matching
% the green channel is actually a good approximation of the grayscale, we
% could instad do I1 = I1(:,:,2);
if size(I1,3) > 1, I1 = rgb2gray(I1); end
if size(I2,3) > 1, I2 = rgb2gray(I2); end
% conver to double/single
I1 = double(I1);
I2 = double(I2);
% the range of disparity values from min_d to max_d inclusive
d_vals = min_d : max_d;
num_d = length(d_vals);
C = NaN(size(I1,1), size(I1,2), num_d); % the cost volume
% the main loop
for i = 1 : length(d_vals);
d = d_vals(i);
I2_s = imtranslate(I2, [d 0]);
C(:,:,i) = abs(I1 - I2_s); % you could also have SD here (I1-I2_s).^2
C(:,:,i) = imfilter(C(:,:,i), kernel);
end
[C_min, D] = min(C, [], 3);
D = D + min_d;
end
给运行代码
I1 = imread( ... 你的左图 I2 = imread( ... 你的右图) D = stereo_sad(I1, I2, 0, 96, 4); 图片c(D);轴图像关闭;彩条
你会得到像下面这样的视差图
步骤是:
- 在每个差异处移动右图像
- 计算移动后的图像和 左图(或其他一些度量,如 SSD)
- 用矩形取平均值window,这是一个"box"过滤器
- 以每像素 "volume" 的成本存储平均值
- 差异位于每像素成本量的最小值处。 Disparity 会在索引中变成最小值
可以使用内置的 Matlab 工具完成这些操作,以生成易于阅读的代码。
希望对您有所帮助。
我认为你应该在最小化步骤之后做一个过滤器