-
Notifications
You must be signed in to change notification settings - Fork 2
/
sift_match.m
140 lines (117 loc) · 4.04 KB
/
sift_match.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
function matchResult = sift_match(im1, im2, varargin)
% SIFT_MATCH Match two images using SIFT and RANSAC
%
% SIFT_MATCH demonstrates matching two images based on SIFT
% features and RANSAC.
%
% SIFT_MATCH by itself runs the algorithm on two standard test
% images. Use SIFT_MATCH(IM1,IM2) to compute the matches of two
% custom images IM1 and IM2.
%
% SIFT_MATCH can also run on two pre-computed sets of features.
% Use SIFT_MATCH(IM1, IM2, FEAT1, FEAT2), where FEAT1.f and FEAT1.d
% represent the SIFT frames and descriptors of the first image.
%
% SIFT_MATCH returns MATCHRESULT, where
% -- MATCHRESULT.RATIO_TEST reports the number of correspondences
% after the distance ratio test
% -- MATCHRESULT.RANSAC reports the number of correspondences
% after the distance ratio test + RANSAC with a homography
% -- MATCHRESULT.MODEL contains the best homography found
% -- MATCHRESULTS.MATCHES contains the indices of the matching
% features in the two images
% AUTORIGHTS
if nargin == 0
im1 = imread(fullfile(vl_root, 'data', 'river1.jpg')) ;
im2 = imread(fullfile(vl_root, 'data', 'river2.jpg')) ;
end
% make single
im1 = im2single(im1) ;
im2 = im2single(im2) ;
% make grayscale
if size(im1,3) > 1, im1g = rgb2gray(im1) ; else im1g = im1 ; end
if size(im2,3) > 1, im2g = rgb2gray(im2) ; else im2g = im2 ; end
% --------------------------------------------------------------------
% SIFT matches
% --------------------------------------------------------------------
if length(varargin) >= 2
set1 = varargin{1};
set2 = varargin{2};
f1 = set1.f;
d1 = set1.d;
f2 = set2.f;
d2 = set2.d;
else
[f1,d1] = vl_sift(im1g) ;
[f2,d2] = vl_sift(im2g) ;
end
% Perform distance ratio test
[matches, scores] = vl_ubcmatch(d1,d2) ;
% Remove many-to-one matches
[uniqueRow2, IA, IC] = unique(matches(2,:));
uniqueRow1 = matches(1,IA);
matches = [uniqueRow1; uniqueRow2];
numMatches = size(matches,2) ;
X1 = f1(1:2,matches(1,:)) ; X1(3,:) = 1 ;
X2 = f2(1:2,matches(2,:)) ; X2(3,:) = 1 ;
% --------------------------------------------------------------------
% RANSAC with homography model
% --------------------------------------------------------------------
clear H score ok ;
radius = 6;
for t = 1:10
% estimate homography
subset = vl_colsubset(1:numMatches, 4) ;
A = [] ;
for i = subset
A = cat(1, A, kron(X1(:,i)', vl_hat(X2(:,i)))) ;
end
[U,S,V] = svd(A) ;
if numel(V) == 0
V = zeros(9,9);
end
H{t} = reshape(V(:,9),3,3) ;
% score homography
X2_ = H{t} * X1 ;
du = X2_(1,:)./X2_(3,:) - X2(1,:)./X2(3,:) ;
dv = X2_(2,:)./X2_(3,:) - X2(2,:)./X2(3,:) ;
ok{t} = (du.*du + dv.*dv) < radius*radius ;
score(t) = sum(ok{t}) ;
end
[score, best] = max(score) ;
H = H{best} ;
ok = ok{best} ;
% --------------------------------------------------------------------
% Optional refinement
% --------------------------------------------------------------------
function err = residual(H)
u = H(1) * X1(1,ok) + H(4) * X1(2,ok) + H(7) ;
v = H(2) * X1(1,ok) + H(5) * X1(2,ok) + H(8) ;
d = H(3) * X1(1,ok) + H(6) * X1(2,ok) + 1 ;
du = X2(1,ok) - u ./ d ;
dv = X2(2,ok) - v ./ d ;
err = sum(du.*du + dv.*dv) ;
end
if exist('fminsearch') == 2
H = H / H(3,3) ;
opts = optimset('Display', 'none', 'TolFun', 1e-8, 'TolX', 1e-8) ;
H(1:8) = fminsearch(@residual, H(1:8)', opts) ;
else
% warning('Refinement disabled as fminsearch was not found.') ;
end
% --------------------------------------------------------------------
% Show matches
% --------------------------------------------------------------------
warning off;
dh1 = max(size(im2,1)-size(im1,1),0) ;
dh2 = max(size(im1,1)-size(im2,1),0) ;
matchResult.ratio_test = size(matches,2);
matchResult.ransac = sum(ok);
matchResult.model = H;
matchResult.matches = matches(:,ok);
matchResult.f1 = f1;
matchResult.f2 = f2;
matchResult.d1 = d1;
matchResult.d2 = d2;
warning on;
end