Created
February 13, 2014 15:23
-
-
Save milkersarac/8977031 to your computer and use it in GitHub Desktop.
sample image stitching from http://www.vlfeat.org/applications/sift-mosaic-code.html
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function mosaic = sift_mosaic(im1, im2) | |
% SIFT_MOSAIC Demonstrates matching two images using SIFT and RANSAC | |
% | |
% SIFT_MOSAIC demonstrates matching two images based on SIFT | |
% features and RANSAC and computing their mosaic. | |
% | |
% SIFT_MOSAIC by itself runs the algorithm on two standard test | |
% images. Use SIFT_MOSAIC(IM1,IM2) to compute the mosaic of two | |
% custom images IM1 and IM2. | |
% 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 | |
% -------------------------------------------------------------------- | |
[f1,d1] = vl_sift(im1g) ; | |
[f2,d2] = vl_sift(im2g) ; | |
[matches, scores] = vl_ubcmatch(d1,d2) ; | |
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 ; | |
for t = 1:100 | |
% estimate homograpyh | |
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) ; | |
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) < 6*6 ; | |
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 | |
% -------------------------------------------------------------------- | |
dh1 = max(size(im2,1)-size(im1,1),0) ; | |
dh2 = max(size(im1,1)-size(im2,1),0) ; | |
figure(1) ; clf ; | |
subplot(2,1,1) ; | |
imagesc([padarray(im1,dh1,'post') padarray(im2,dh2,'post')]) ; | |
o = size(im1,2) ; | |
line([f1(1,matches(1,:));f2(1,matches(2,:))+o], ... | |
[f1(2,matches(1,:));f2(2,matches(2,:))]) ; | |
title(sprintf('%d tentative matches', numMatches)) ; | |
axis image off ; | |
subplot(2,1,2) ; | |
imagesc([padarray(im1,dh1,'post') padarray(im2,dh2,'post')]) ; | |
o = size(im1,2) ; | |
line([f1(1,matches(1,ok));f2(1,matches(2,ok))+o], ... | |
[f1(2,matches(1,ok));f2(2,matches(2,ok))]) ; | |
title(sprintf('%d (%.2f%%) inliner matches out of %d', ... | |
sum(ok), ... | |
100*sum(ok)/numMatches, ... | |
numMatches)) ; | |
axis image off ; | |
drawnow ; | |
% -------------------------------------------------------------------- | |
% Mosaic | |
% -------------------------------------------------------------------- | |
box2 = [1 size(im2,2) size(im2,2) 1 ; | |
1 1 size(im2,1) size(im2,1) ; | |
1 1 1 1 ] ; | |
box2_ = inv(H) * box2 ; | |
box2_(1,:) = box2_(1,:) ./ box2_(3,:) ; | |
box2_(2,:) = box2_(2,:) ./ box2_(3,:) ; | |
ur = min([1 box2_(1,:)]):max([size(im1,2) box2_(1,:)]) ; | |
vr = min([1 box2_(2,:)]):max([size(im1,1) box2_(2,:)]) ; | |
[u,v] = meshgrid(ur,vr) ; | |
im1_ = vl_imwbackward(im2double(im1),u,v) ; | |
z_ = H(3,1) * u + H(3,2) * v + H(3,3) ; | |
u_ = (H(1,1) * u + H(1,2) * v + H(1,3)) ./ z_ ; | |
v_ = (H(2,1) * u + H(2,2) * v + H(2,3)) ./ z_ ; | |
im2_ = vl_imwbackward(im2double(im2),u_,v_) ; | |
mass = ~isnan(im1_) + ~isnan(im2_) ; | |
im1_(isnan(im1_)) = 0 ; | |
im2_(isnan(im2_)) = 0 ; | |
mosaic = (im1_ + im2_) ./ mass ; | |
figure(2) ; clf ; | |
imagesc(mosaic) ; axis image off ; | |
title('Mosaic') ; | |
if nargout == 0, clear mosaic ; end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment