source: proiecte/pmake3d/make3d_original/Make3dSingleImageStanford_version0.1/third_party/kovesi/ransacfitfundmatrix.m @ 37

Last change on this file since 37 was 37, checked in by (none), 14 years ago

Added original make3d

  • Property svn:executable set to *
File size: 8.5 KB
Line 
1% RANSACFITFUNDMATRIX - fits fundamental matrix using RANSAC
2%
3% Usage:   [F, inliers, NewDist, fail] = ransacfitfundmatrix(defaultPara, x1, x2, t, Depth1, Depth2, dist, feedback, disp, FlagDist)
4%
5% Arguments:
6%          defaultPara - useful default parameters (like, camera intrinsic matrix)
7%          x1  - 2xN or 3xN set of homogeneous points.  If the data is
8%                2xN it is assumed the homogeneous scale factor is 1.
9%          x2  - 2xN or 3xN set of homogeneous points such that x1<->x2.
10%          t   - The distance threshold between data point and the model
11%                used to decide whether a point is an inlier or not.
12%                Note that point coordinates are normalised to that their
13%                mean distance from the origin is sqrt(2).  The value of
14%                t should be set relative to this, say in the range
15%                0.001 - 0.01 
16%          Depth1/2 - depth imformation to support more accurate ransac
17%          distrib  - initial distribution (default uniform dist)
18%          feedback  - An optional flag 0/1. If set to one the trial count and the
19%                 estimated total number of trials required is printed out at
20%                 each step.  Defaults to 0.
21%          disp  - if true, display the matches found when done.
22%
23%          FlagDist - if true, calculate the reprojection error
24%
25% Note that it is assumed that the matching of x1 and x2 are putative and it
26% is expected that a percentage of matches will be wrong.
27%
28% Returns:
29%          F       - The 3x3 fundamental matrix such that x2'Fx1 = 0.
30%          inliers - An array of indices of the elements of x1, x2 that were
31%                    the inliers for the best model.
32%          NewDist - New Distribution after Ransac (Outliers have zero distribution)
33%          fail    - true if Ransac fail to find any solution is not degenerated
34%
35% See Also: RANSAC, FUNDMATRIX
36
37% Copyright (c) 2004-2005 Peter Kovesi
38% School of Computer Science & Software Engineering
39% The University of Western Australia
40% http://www.csse.uwa.edu.au/
41%
42% Permission is hereby granted, free of charge, to any person obtaining a copy
43% of this software and associated documentation files (the "Software"), to deal
44% in the Software without restriction, subject to the following conditions:
45%
46% The above copyright notice and this permission notice shall be included in
47% all copies or substantial portions of the Software.
48%
49% The Software is provided "as is", without warranty of any kind.
50
51% February 2004  Original version
52% August   2005  Distance error function changed to match changes in RANSAC
53%
54% additional parameter distrib is a vector of non-negative numbers that
55% specifies a (not necessarily normalized) probability distribution over
56% the different possible matches - passed to the ransac function to be
57% used during the sampling procedure.
58% (added by Jeff Michels)
59% Additional NewDist estimated after Ransac is formed by using Depth
60% information
61% (added by Min Sun)
62
63function [F, inliers, NewDist, fail] = ransacfitfundmatrix(defaultPara, x1, x2, t, Depth1, Depth2, distrib, feedback, disp, FlagDist, s)
64% [F, inliers, fail] = ransacfitfundmatrix(x1, x2, t, feedback, distrib)
65
66    if ~all(size(x1)==size(x2))
67        error('Data sets x1 and x2 must have the same dimension');
68    end
69   
70    if nargin < 8
71        feedback = 0;
72        disp = 0;
73        FlagDist = 0;
74            s = 8;  % Number of points needed to fit a fundamental matrix. Note that
75                    % only 7 are needed but the function 'fundmatrix' only
76                    % implements the 8-point solution.
77    elseif nargin < 11
78            s = 8;  % Number of points needed to fit a fundamental matrix. Note that
79                    % only 7 are needed but the function 'fundmatrix' only
80                    % implements the 8-point solution.
81    end
82   
83    [rows,npts] = size(x1);
84    if rows~=2 & rows~=3
85        error('x1 and x2 must have 2 or 3 rows');
86    end
87   
88    if rows == 2    % Pad data with homogeneous scale factor of 1
89        x1 = [x1; ones(1,npts)];
90        x2 = [x2; ones(1,npts)];   
91    end
92   
93    % Normalise each set of points so that the origin is at centroid and
94    % mean distance from origin is sqrt(2).  normalise2dpts also ensures the
95    % scale parameter is 1.  Note that 'fundmatrix' will also call
96    % 'normalise2dpts' but the code in 'ransac' that calls the distance
97    % function will not - so it is best that we normalise beforehand.
98    [x1, T1] = normalise2dpts(x1);
99    [x2, T2] = normalise2dpts(x2);
100
101   
102    fittingfn = @fundmatrix;
103    distfn    = @funddist; % funciton handler below
104    degenfn   = @isdegenerate; % function handler below
105    % x1 and x2 are 'stacked' to create a 6xN array for ransac
106    [F, inliers, NewDist, fail] = ...
107        ransac(defaultPara, [x1; x2], [Depth1; Depth2], fittingfn, distfn, degenfn, s, t, distrib, [T1; T2], feedback, disp, FlagDist);
108
109    % Now do a final least squares fit on the data points considered to
110    % be inliers.
111    F = fundmatrix(x1(:,inliers), x2(:,inliers));
112   
113    % Denormalise
114    F = T2'*F*T1;
115   
116%--------------------------------------------------------------------------
117% Function to evaluate the first order approximation of the geometric error
118% (Sampson distance) of the fit of a fundamental matrix with respect to a
119% set of matched points as needed by RANSAC.  See: Hartley and Zisserman,
120% 'Multiple View Geometry in Computer Vision', page 270.
121%
122% Note that this code allows for F being a cell array of fundamental matrices of
123% which we have to pick the best one. (A 7 point solution can return up to 3
124% solutions)
125%
126% Min add to calculate ReProjection Error from Depth information (4/22, 2007)
127
128function [bestInliers, bestF, ReProjError] = funddist(F, x, t, defaultPara, Depth, T, FlagDist);
129%[bestInliers, bestF] = funddist(F, x, t);
130
131x1 = x(1:3,:);    % Extract x1 and x2 from x
132x2 = x(4:6,:);
133T1 = T(1:3,:);
134T2 = T(4:6,:);
135
136if iscell(F)  % We have several solutions each of which must be tested
137
138  nF = length(F);   % Number of solutions to test
139  bestF = F{1};     % Initial allocation of best solution
140  ninliers = 0;     % Number of inliers
141
142  for k = 1:nF
143        t
144    x2tFx1 = zeros(1,length(x1));
145    for n = 1:length(x1)
146      x2tFx1(n) = x2(:,n)'*F{k}*x1(:,n);
147    end
148
149    Fx1 = F{k}*x1;
150    Ftx2 = F{k}'*x2;
151
152    % Evaluate distances
153    d =  x2tFx1.^2 ./ ...
154      (Fx1(1,:).^2 + Fx1(2,:).^2 + Ftx2(1,:).^2 + Ftx2(2,:).^2);
155       
156    inliers = find(abs(d) < t);     % Indices of inlying points
157
158    if length(inliers) > ninliers   % Record best solution
159      ninliers = length(inliers);
160      bestF = F{k};
161      bestInliers = inliers;
162    end
163  end
164
165else     % We just have one solution
166  x2tFx1 = zeros(1,length(x1));
167  for n = 1:length(x1)
168    x2tFx1(n) = x2(:,n)'*F*x1(:,n);
169  end
170
171  Fx1 = F*x1;
172  Ftx2 = F'*x2;
173
174  % Evaluate distances
175  d =  x2tFx1.^2 ./ ...
176    (Fx1(1,:).^2 + Fx1(2,:).^2 + Ftx2(1,:).^2 + Ftx2(2,:).^2);
177  figure(1);hist(d(d<t));
178  bestInliers = find(abs(d) < t);     % Indices of inlying points
179  bestF = F;                          % Copy F directly to bestF
180
181end
182
183% calculate ReProError ------------------------------------------------
184if FlagDist
185        Depth1 = Depth(1,:);
186        Depth2 = Depth(2,:);
187    X1 = inv(defaultPara.InrinsicK1)*inv(T1)*x1.*repmat(Depth1,3,1);
188    X2 = inv(defaultPara.InrinsicK2)*inv(T2)*x2.*repmat(Depth2,3,1);
189    E = (defaultPara.InrinsicK2'*T2'*bestF*T1*defaultPara.InrinsicK1);   
190    [U S V] =svd(E);
191    Rz_pos = [ [0 -1 0];...
192               [1 0 0];...
193               [0 0 1]];
194    Rz_neg = Rz_pos';
195    T_hat1 = U*Rz_pos*diag([1 1 0])*U';
196    T1 = [-T_hat1(2,3);  T_hat1(1,3); -T_hat1(1,2)];
197    R1 = U*Rz_pos'*V';
198    T_hat2 = U*Rz_neg*diag([1 1 0])*U';
199    T2 = [-T_hat2(2,3);  T_hat2(1,3); -T_hat2(1,2)];
200    R2 = U*Rz_neg'*V';
201    X1_2_1 = R1*X1;
202    X1_2_2 = R2*X1;
203    ops = sdpsettings('solver','sedumi','verbose',1);
204    a = sdpvar(1,1);
205    b = sdpvar(1,1);
206    F = set(a>=0)+set(b>=0);
207    sol = solvesdp(F,norm(X1_2_1(:)*a + b*repmat(T1, size(X1,2),1)- X2(:),1),ops);
208    sol = solvesdp(F,norm(X1_2_2(:)*a + b*repmat(T2, size(X1,2),1)- X2(:),1),ops);
209    a = double(a);
210    b = double(b);
211    ReProjError = sum(abs(X2_1*a - X1),1) + sum(abs(X1_2*b - X2),1);
212    ReProjError(setdiff(1:size(ReProjError,2), bestInliers)) = Inf;
213else
214    ReProjError = [];
215end
216% ---------------------------------------------------------------------`
217
218%----------------------------------------------------------------------
219% (Degenerate!) function to determine if a set of matched points will result
220% in a degeneracy in the calculation of a fundamental matrix as needed by
221% RANSAC.  This function assumes this cannot happen...
222     
223function r = isdegenerate(x)
224    r = 0;   
225   
226
Note: See TracBrowser for help on using the repository browser.