MATLAB:使用八点算法进行 3D 重建

问题描述 投票:0回答:4

我正在尝试从 2 个图像实现 3D 重建。我遵循的步骤是,

1. Found corresponding points between 2 images using SURF.
2. Implemented eight point algo to find "Fundamental matrix"
3. Then, I implemented triangulation.

到目前为止我已经得到了基本矩阵和三角测量结果。我如何进一步进行 3D 重建?我对阅读互联网上提供的所有材料感到困惑。

另外,这是代码。让我知道这是否正确。

Ia=imread('1.jpg');
Ib=imread('2.jpg');
Ia=rgb2gray(Ia);
Ib=rgb2gray(Ib);
% My surf addition
% collect Interest Points from Each Image
blobs1 = detectSURFFeatures(Ia);
blobs2 = detectSURFFeatures(Ib);
figure;
imshow(Ia);
hold on;
plot(selectStrongest(blobs1, 36));
figure;
imshow(Ib);
hold on;
plot(selectStrongest(blobs2, 36));
title('Thirty strongest SURF features in I2');
[features1, validBlobs1] = extractFeatures(Ia, blobs1);
[features2, validBlobs2] = extractFeatures(Ib, blobs2);
indexPairs = matchFeatures(features1, features2);
matchedPoints1 = validBlobs1(indexPairs(:,1),:);
matchedPoints2 = validBlobs2(indexPairs(:,2),:);
figure;
showMatchedFeatures(Ia, Ib, matchedPoints1, matchedPoints2);
legend('Putatively matched points in I1', 'Putatively matched points in I2');

for i=1:matchedPoints1.Count
    xa(i,:)=matchedPoints1.Location(i);
    ya(i,:)=matchedPoints1.Location(i,2);
    xb(i,:)=matchedPoints2.Location(i);
    yb(i,:)=matchedPoints2.Location(i,2);
end

matchedPoints1.Count
figure(1) ; clf ;
imshow(cat(2, Ia, Ib)) ;
axis image off ;
hold on ;
xbb=xb+size(Ia,2);
set=[1:matchedPoints1.Count];
h = line([xa(set)' ; xbb(set)'], [ya(set)' ; yb(set)']) ;

pts1=[xa,ya];
pts2=[xb,yb];
pts11=pts1;pts11(:,3)=1;
pts11=pts11';
pts22=pts2;pts22(:,3)=1;pts22=pts22';

width=size(Ia,2);
height=size(Ib,1);
F=eightpoint(pts1,pts2,width,height);

[P1new,P2new]=compute2Pmatrix(F);
XP = triangulate(pts11, pts22,P2new);

eightpoint()

function [ F ] = eightpoint( pts1, pts2,width,height)

X = 1:width;
Y = 1:height;
[X, Y] = meshgrid(X, Y);
x0 = [mean(X(:)); mean(Y(:))];
X = X - x0(1);
Y = Y - x0(2);
denom = sqrt(mean(mean(X.^2+Y.^2)));
N = size(pts1, 1);

%Normalized data
T = sqrt(2)/denom*[1 0 -x0(1); 0 1 -x0(2); 0 0 denom/sqrt(2)];
norm_x = T*[pts1(:,1)'; pts1(:,2)'; ones(1, N)];
norm_x_ = T*[pts2(:,1)';pts2(:,2)'; ones(1, N)];
x1 = norm_x(1, :)';
y1= norm_x(2, :)';
x2 = norm_x_(1, :)';
y2 = norm_x_(2, :)';

A = [x1.*x2, y1.*x2, x2, ...
       x1.*y2, y1.*y2, y2, ...
       x1,       y1,     ones(N,1)];

% compute the SVD
[~, ~, V] = svd(A);
F = reshape(V(:,9), 3, 3)';
[FU, FS, FV] = svd(F);
FS(3,3) = 0; %rank 2 constrains
F = FU*FS*FV';

% rescale fundamental matrix
F = T' * F * T;

end

triangulate()

function [ XP ] = triangulate( pts1,pts2,P2 )

n=size(pts1,2);
X=zeros(4,n);
for i=1:n
    A=[-1,0,pts1(1,i),0;
        0,-1,pts1(2,i),0;
        pts2(1,i)*P2(3,:)-P2(1,:);
        pts2(2,i)*P2(3,:)-P2(2,:)];
  [~,~,va] = svd(A);
  X(:,i) = va(:,4);
end
XP(:,:,1) = [X(1,:)./X(4,:);X(2,:)./X(4,:);X(3,:)./X(4,:); X(4,:)./X(4,:)];

end

function [ P1,P2 ] = compute2Pmatrix( F )

P1=[1,0,0,0;0,1,0,0;0,0,1,0];
[~, ~, V] = svd(F');
ep = V(:,3)/V(3,3);
P2 = [skew(ep)*F,ep];
end
matlab computer-vision matlab-cvst 3d-reconstruction
4个回答
1
投票

乍一看,它看起来是正确的。一些注意事项如下:

您在八点()中规范化代码并不理想。

最好针对涉及到的点做。每组点都有其缩放矩阵。那就是:

[pts1_n, T1] = normalize_pts(pts1);
[pts2_n, T2] = normalize-pts(pts2);

% ... code
% solution
F = T2' * F * T

作为旁注(为了效率)你应该这样做

[~,~,V] = svd(A, 0);

您还想强制执行基本矩阵的秩为 2 的约束。计算出 F 后,您可以执行以下操作:

[U,D,v] = svd(F);
F = U * diag([D(1,1),D(2,2), 0]) * V';

无论哪种情况,归一化都不是使算法发挥作用的唯一关键。您需要将基本矩阵的估计包装在 RANSAC 等稳健的估计方案中。

像这样的估计问题对非高斯噪声和异常值非常敏感。如果错误对应的数量较少,或者错误率较高的点,算法就会崩溃。

最后,在“三角测量”中,您要确保在齐次除法之前这些点不是无穷远。

我建议使用“合成”数据测试代码。即生成自己的相机矩阵和对应关系。将它们输入具有不同噪声级别的估计例程。在零噪声的情况下,您应该获得高达浮点精度的精确解。随着噪声的增加,您的估计误差也会增加。

以目前的形式,在真实数据上运行它可能效果不佳,除非您使用 RANSAC 或其他一些稳健的估计器“稳健”算法。

祝你好运。

祝你好运。


0
投票

您使用的是哪个版本的 MATLAB?

计算机视觉系统工具箱中有一个名为

estimateFundamentalMatrix
的函数,它可以为您提供基本矩阵。它可能会给你比你的代码更好的结果,因为它在底层使用 RANSAC,这使得它对虚假匹配具有鲁棒性。从 R2014b 版本开始,还有一个
triangulate
功能。

您得到的是稀疏 3D 重建。您可以绘制生成的 3D 点,并将相应像素的颜色映射到每个点。但是,对于您想要的,您必须将曲面或三角形网格拟合到这些点。不幸的是,我无法帮助你。


0
投票

如果你问的是如何从基本矩阵+对应点到密集模型,那么你还有很多工作要做。

假设您知道内部相机参数(缩放、旋转、平移),则可以根据基本矩阵计算相对相机位置(R,T)。要获得全稠密矩阵,有几种方法可以选择。您可以尝试使用现有的库(例如 PMVS)。我会研究 OpenMVG,但我不确定 matlab 接口。

另一种方法,您可以计算密集光流(许多可用于 matlab)。寻找极线 OF(它需要一个基本矩阵并将解限制在极线上)。然后您可以对每个像素进行三角测量以获得深度图。

最后,您必须进行格式转换,以从深度图转换为 VRML(您可以查看 meshlab)

抱歉,我的答案不是更面向 Matlab。


© www.soinside.com 2019 - 2024. All rights reserved.