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

4

我正在尝试从两张图像中实现3D重建。我所遵循的步骤如下:

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

我现在已经得到了基本矩阵和三角化的结果。接下来我该如何进一步获得三维重建呢?网上提供的所有材料都让我感到困惑。

此外,这是一段代码。请告诉我它是否正确。

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

2
计算机视觉工具箱中有一些不错的演示:http://www.mathworks.com/help/vision/examples/stereo-calibration-and-scene-reconstruction.html,http://www.mathworks.com/help/vision/examples/sparse-3-d-reconstruction-from-two-views.html - Amro
你有什么问题吗?triangulate是一个函数,它可以在给定图像A和图像B中的一个点以及它们之间的关系后,为您提供一个3D点。 - Ander Biguri
我已经得到了3D点,但是我不知道如何使用这些点生成带纹理的3D模型,以便最终可以看到重建的3D模型。 - user3830162
3个回答

1

从快速查看来看,它看起来是正确的。以下是一些注释:

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

最好在涉及的点上完成。每组点都将有其缩放矩阵。也就是说:

[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
如果你问的是如何从基础矩阵+对应点到密集模型,那么你还有很多工作要做。
相对摄像机位置(R,T)可以从基础矩阵中计算出来,假设你知道内部摄像机参数(缩放、旋转、平移)。要得到完整的密集矩阵,有几种方法可供选择。你可以尝试使用现有的库(PMVS 例如)。我会研究OpenMVG,但我不确定它是否有Matlab接口。
另一种方法是计算密集光流(许多Matlab可用)。寻找一个极线光流(它需要一个基础矩阵,并将解决方案限制在极线上)。然后你可以三角化每个像素来获得深度图。
最后,你必须进行格式转换,从深度图到VRML(你可以看看meshlab)。
抱歉我的回答不太针对Matlab。

0
你用的是哪个版本的MATLAB?
在计算机视觉系统工具箱中有一个名为estimateFundamentalMatrix的函数,它将给出基础矩阵。它可能比你的代码产生更好的结果,因为它在后台使用了RANSAC,使其对虚假匹配具有鲁棒性。从R2014b版本开始还有一个triangulate函数。
你得到的是稀疏3D重建。你可以绘制生成的3D点,并将相应像素的颜色映射到每个点上。但是,对于你想要的东西,你需要将表面或三角网格拟合到这些点。不幸的是,我不能帮你解决这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接