MATLAB:使用八点算法进行三维重建

时间:2014-10-31 18:49:34

标签: matlab computer-vision matlab-cvst 3d-reconstruction

我正在尝试从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.

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

此外,这是代码。如果这是正确的,请告诉我。

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

3 个答案:

答案 0 :(得分:1)

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

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

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

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

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

作为旁注(为提高效率),你应该做

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

您还希望强制执行基本矩阵具有rank-2的约束。计算F后,您可以执行以下操作:

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

在任何一种情况下,规范化并不是使算法工作的唯一关键。您希望将基本矩阵的估计包装在像RANSAC这样的稳健估计方案中。

这样的估计问题对非高斯噪声和异常值非常敏感。如果您有少量错误的对应关系或高错误的点,算法将会中断。

最后,In' triangulate'你想在均匀分割之前确保这些点不在无穷远处。

我建议使用“合成”代码来测试代码。数据。也就是说,生成自己的相机矩阵和对应关系。将它们送入具有不同噪声水平的估算程序。在零噪声的情况下,您应该获得精确的浮点精度解决方案。随着噪声的增加,估计误差会增加。

就目前的形式而言,在真实数据上运行此功能可能会效果不佳,除非你“强行对待”。使用RANSAC的算法,或其他一些强大的估计器。

祝你好运。

祝你好运。

答案 1 :(得分:0)

你有哪个版本的MATLAB?

计算机视觉系统工具箱中有一个名为estimateFundamentalMatrix的功能,它将为您提供基本矩阵。它可能会比你的代码给你更好的结果,因为它在引擎盖下使用RANSAC,这使得它对虚假匹配很有用。从版本R2014b开始,还有一个triangulate函数。

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

答案 2 :(得分:0)

如果您要问的是如何从基本的Matrix +对应点到密集模型,那么您仍然需要做很多工作。

相对摄像机位置(R,T)可以从基本矩阵计算,假设您知道内部摄像机参数(达到比例,旋转,平移)。要获得完整的密集矩阵,有几种方法可以实现。您可以尝试使用现有库(例如PMVS)。我查看OpenMVG,但我不确定matlab界面。

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

最后,你必须使用格式转换来从深度图到VRML(你可以看看meshlab)

抱歉,我的答案不是以Matlab为导向的。