视觉(15)SFM的一个例子

这里采用的是Yi Ma , Stefano Soatto. An Invitation to 3-D Vision , From Images to Geometric Models 的算法



None.gif % //  Algorithm 8.1. also 11.7
None.gif
% //  Rank based factorization algorithm for multiview reconstruction  
None.gif
% //  using point features 
None.gif
% //  as described in Chapter 8, "An introduction to 3-D Vision"
None.gif
% //  by Y. Ma, S. Soatto, J. Kosecka, S. Sastry (MASKS)
None.gif
% //  Code distributed free for non-commercial use
None.gif
% //  Copyright (c) MASKS, 2003
None.gif

None.gif
% //  Generates multiple synthetic views of a house and computes the 
None.gif
% //  motion and structure, calibrated case, point features only
None.gif
% //  Jana Kosecka, George Mason University, 2002
None.gif
% //  ======================================================================
None.gif

None.gifclose all; clear;
None.gifFRAMES 
=   3 ;
None.gifPLOTS  
=   3 ;
None.gif
% //  transformation is expressed wrt to the camera frame
None.gif

None.gifZinit 
=   5 ;
None.gif
None.gif
% //  cube in the object frame
None.gif
 XW  =  [ 0   1   1   0   0   1   1   0   0.2   0.8   0.2   0.8  ;
None.gif       
0   0   1   1   0   0   1   1   1.5   1.5   1.5   1.5 ;
None.gif       
1   1   1   1   0   0   0   0   0.8   0.8   0.2   0.2  ;
None.gif       
1   1   1   1   1   1   1   1   1     1     1     1 ];
None.gif
None.gifNPOINTS 
=   12
None.gif
None.gifXC 
=  zeros( 4 ,NPOINTS,FRAMES);
None.gif
None.gif
% //  initial displacement摄像机的初始位置
None.gif
Rinit  =  rot_matrix([ 1   1   1 ], 0 ); 
None.gif
None.gifTinit 
=  [ Rinit( 1 ,:)  - 0.5  ;
None.gif          Rinit(
2 ,:)  - 0.5  ;
None.gif          Rinit(
3 ,:) Zinit;
None.gif          
0   0   0   1 ];
None.gif
% //  first camera coodinates 
None.gif
XC(:,:, 1 =  Tinit * XW;
None.gif
None.gif
% // 画出三维的结构 original motion and 3D structure
None.gif
figure; hold on;
None.gifplot3_struct(XC(
1 ,:, 1 ),XC( 2 ,:, 1 ),XC( 3 ,:, 1 ));
None.gifplot3(XC(
1 ,:, 1 ),XC( 2 ,:, 1 ),XC( 3 ,:, 1 ), ' * ' );
None.gifdraw_frame_scaled([diag([
1 , 1 , 1 ]), zeros( 3 , 1 )], 0.5 );
None.giftitle(
' original motion and 3D structure ' );
None.gifview(
220 , 20 );
None.gifgrid on; axis equal;
None.gif
% //  axis off;
None.gif
pause;
None.gif
None.gif
None.gif
% //  image coordinates 计算第一帧时的图像坐标
None.gif
xim(:,:, 1 =  project(XC(:,:, 1 ));
None.gif
None.gifZmax 
=  max(XC( 3 ,:, 1 ));
None.gifZmin 
=  min(XC( 3 ,:, 1 ));
None.gifrinc 
=    pi / 30 ;
None.gifrot_axis 
=  [ 1   0   0 0   - 1   0 ] ' ;
None.gif
trans_axis  =  [ 1   0   0 0   1   0 ] ' ;
None.gif

None.gifratio 
=   1 ;
None.gifrinc 
=   10 ;   % //  rotation increment 20 degrees
None.gif
Zmid  =  (Zmax + Zmin) / 2 ;
None.giftinc 
=   0.5 * ratio * Zmid * rinc * pi / 180 ;
None.gif
None.gifploting 
=   1 ;
None.gif
None.gif
for  i = 2 :FRAMES  % // 计算第i帧的图像坐标xim
None.gif
    theta  =  (i - 1 ) * rinc * pi / 180 ;
None.gif    r_axis 
=  rot_axis(:,i - 1 ) / norm(rot_axis(:,i - 1 ));
None.gif    t_axis 
=  trans_axis(:,i - 1 ) / norm(trans_axis(:,i - 1 ));
None.gif    trans 
=  (i - 1 ) * tinc * t_axis;
None.gif    R 
=  rot_matrix(r_axis,theta);
None.gif    
% //  translation represents origin of the camera frame
None.gif
     % //  in the world frame 
None.gif
    T(:,:,i)  =  ([ R trans;
None.gif                 
0   0   0   1 ]);
None.gif    
% //  all transformation with respect to the object frame
None.gif
    XC(:,:,i)  =  T(:,:,i) * XC(:,:, 1 );   % //  XW;
None.gif
    draw_frame_scaled(T( 1 : 3 ,:,i), 0.5 ); 
None.gif    xim(:,:,i) 
=  [XC( 1 ,:,i). / XC( 3 ,:,i); XC( 2 ,:,i). / XC( 3 ,:,i); dot.gif
None.gif                  ones(
1 ,NPOINTS)];
None.gifend;
None.gif
None.gif
for  j  =   2 :FRAMES
None.gif T_ini(:,j) 
=  T( 1 : 3 , 4 ,j);
None.gifend;
None.gif
None.gif
% //  noise can be added here
None.gif
for  i = 1 :FRAMES     
None.gif  xim_noisy(:,:,i) 
=  xim(:,:,i);
None.gifend   
None.gif
None.gif
% //  pause 以下为SFM算法
None.gif
% // ---------------------------------------------------------------------
None.gif
% //  compute initial \alpha's for each point using first two frames only 1)首先用八点算法计算初始的R0,T0(我感觉T0~即1,0帧之间的相对移动~和实际的应该相差常数倍,因此会导致恢复的结构和实际相差常数倍),然后估计lambda。。。
None.gif
[T0, R0]   =  essentialDiscrete(xim_noisy(:,:, 1 ),xim_noisy(:,:, 2 ));
None.gif
for  i  =   1 :NPOINTS
None.gif  alpha(:,i) 
=   - (skew(xim_noisy(:,i, 2 )) * T0) ' *dot.gif
None.gif
      (skew(xim_noisy(:,i, 2 )) * R0 * xim_noisy(:,i, 1 ))dot.gif
None.gif      
/ (norm(skew(xim_noisy(:,i, 2 )) * T0)) ^ 2 ;
None.gif  lambda(:,i) 
=   1 / alpha(:,i);
None.gifend
None.gif
None.gifscale 
=  norm(alpha(:, 1 ));      % //  set the global scale
None.gif
alpha  =  alpha / scale;           % //  normalize everything
None.gif
scale  =  norm(lambda(:, 1 ));      % //  set the global scale
None.gif
lambda  =  lambda / scale;          % //  normalize everything
None.gif

None.gif
% // ---------------------------------------------------------------------
None.gif
% //  Compute initial motion estimates for all frames
None.gif
% //  Here do 3 iterations - in real setting look at the change of scales
None.gif

None.gifiter 
=   1 ;
None.gif
while  (iter  <   5 );
None.gif  
for  j  =   2 :FRAMES
None.gif    P 
=  [];  % //   setup matrix P
None.gif
     for  i  =   1 :NPOINTS
None.gif      a 
=  [kron(skew(xim_noisy(:,i,j)),xim(:,i, 1 ) ' dot.gif
None.gif
       alpha(:,i) * skew(xim_noisy(:,i,j))];
None.gif      P 
=  [P; a];
None.gif    end;
None.gif    
% //  pause
None.gif
    [um, sm, vm]  =  svd(P);
None.gif    Ti 
=  vm( 10 : 12 , 12 );
None.gif    Ri 
=  transpose(reshape(vm( 1 : 9 , 12 ) ' ,3,3));
None.gif
    [uu,ss,vv]  =   svd(Ri);
None.gif    Rhat(:,:,j) 
=  sign(det(uu * vv ' ))*uu*vv ' ;
None.gif    Ti 
=  sign(det(uu * vv ' ))*Ti/((det(ss))^(1/3));
None.gif
    That(:,j)  =  Ti;
None.gif    True 
=  T( 1 : 3 , 4 ,j);
None.gif  end
None.gif
None.gif  
% //  recompute alpha's based on all views
None.gif
  lambda_prev  =  lambda;
None.gif  
for  i  =   1 :NPOINTS
None.gif    M 
=  [];   % //  setup matrix M
None.gif
     for  j = 2 :FRAMES        % //  set up Hl matrix for all m views
None.gif
      a  =  [ skew(xim(:,i,j)) * That(:,j) dot.gif
None.gif        skew(xim(:,i,j))
* Rhat(:,:,j) * xim(:,i, 1 )];
None.gif      M 
=  [M; a];
None.gif    end;
None.gif    a1 
=   - M(:, 1 ) ' *M(:,2)/norm(M(:,1))^2;
None.gif
    lambda(:,i)  =   1 / a1;
None.gif  end;
None.gif  scale 
=  norm(lambda(:, 1 ));    % //  set the global scale
None.gif
  lambda  =  lambda / scale;      % //  normalize everything
None.gif
  iter  =  iter  +   1
None.gifend 
% //  end while iter
None.gif

None.gif
% //  final structure with respect to the first frame
None.gif
XF  =  [lambda. * xim( 1 ,:, 1 );
None.gif      lambda.
* xim( 2 ,:, 1 );
None.gif      lambda.
* xim( 3 ,:, 1 )];
None.gif
None.giffigure; hold on;
None.gifplot3(XF(
1 ,:, 1 ),XF( 2 ,:, 1 ),XF( 3 ,:, 1 ), ' r* ' );
None.gifplot3_struct(XF(
1 ,:, 1 ), XF( 2 ,:, 1 ), XF( 3 ,:, 1 ));
None.giftitle(
' recovered structure ' );
None.gifview(
220 , 20 );
None.gifgrid on; axis equal;
None.gif
% //  axis off;
None.gif
pause;
None.gif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值