Lauren Smith

November 9, 2010

CS342

 

Homography

 

For Assignment Three, we chose to implement part II:  Homography.  Homography is the relationship between two images of a translation.  In this instance, we have used homography to project an image onto a planar region.   The idea of this project is to select a two regions in a set of two images with user inputted mouse clicks.  Then, the selected region from image 1 will be inserted into the region created by the mouse clicks in image 2, with correct scaling and rotation.

 

The code compH is the piece to compute the homography between the images.  Building off of this, the homography.m file uses the calculated homography and translates the image from one to the next. The code works by first saving the regions defined by the user input.  By defining a meshgrid, we can separate the X and Y coordinates of each and create vectors. Using the inverse function, we use backwards mapping to fill in the region in the second image with a reshaped version of image one.

 

Results

 

Homography can be used to decorate bland home interiors.  Should we go with a Monet or a Van Gogh?

 

  

 

  

 

 

Homography can be used to transform your home into a beach house, without going anywhere!  Or perhaps you prefer urban living..?

 

   

 

Homography can even be used to create your own rules of the road.

 

  

 

Conclusion

 

This implementation of Homography is very effective for projecting images onto planes in a photo. As seen from the examples above, it works with any region with four vertices, from squares to rectangles, to projecting parallelograms and rhombuses on the walls in the final photos.  This code is also robust in that it allows for image rotation, as seen in the last image.  By clicking on the input points deliberately to align the top of the smiley face to the bottom of the street sign, it is even possible to project the image at a rotation.  The time complexity of this is very efficient as well, running very quickly for the images inputted.  An extension of this would be to allow multiple projections conveniently, (without saving the edited image and repeating it again).  This would be helpful for images like the window view, if the window had 3 panes of glass, we could substitute the image of the beach into all three.  Overall though, this code provides a very quick and effective way to manipulate the images, producing interesting results.

 

Code

 

homography.m

 

 

im2 = imread('speedlimit.jpg');

im1 = imread('smily.jpg');

im1 = im2double(im1);

im2 = im2double(im2);

figure(1);

imshow(im1);

hold on;

figure(2);

imshow(im2);

xx1 = []; yy1 = [];

xx2 = []; yy2 = [];

hold on;

 

% read in 4 user inputs

for n = 1: 4

    figure(1);

    [x1,y1] = ginput(1);

    plot(x1, y1, 'r.', 'markersize', 20);

    drawnow;

    xx1 = [xx1; x1];

    yy1 = [yy1; y1];

    figure(2);

    [x2,y2] = ginput(1);

    plot(x2, y2, 'r.', 'markersize', 20);

    drawnow; xx2 = [xx2; x2]; yy2 = [yy2; y2];

end

 

H = compH(xx1, yy1, xx2, yy2);

% get sizes

[h,W, d] = size(im2);

[x,y] = meshgrid(1:W, 1:h);

[b,a, d2] = size(im1);

% create vectors

x = x(:);

y = y(:);

% inverse

Z = inv(H)*[x'; y' ; ones(size(x'))];

% find u v

u = Z(1,:) ./ Z(3,:);

v = Z(2,:) ./ Z(3,:);

 

%reshape u and v

u = reshape(u,h,W);

v = reshape(v,h,W);

 

% pad the rest of the photo, if edge, stretch values further

u(u<1) = 1;

u(u>a) = a;

v(v<1) = 1;

v(v>b) = b;

% create meshgrid 2

[uu,vv] = meshgrid(1:a, 1:b);

%interp

J = interp2(uu,vv,im1(:,:,1),u,v, 'linear');

JG = interp2(uu,vv,im1(:,:,2),u,v,'linear');

JB = interp2(uu,vv,im1(:,:,3),u,v,'linear');

 

% create mask

mask = roipoly(im2, xx2,yy2);

 

im = im2(:,:,1).*(1-mask) + J.*mask;

imG = im2(:,:,2).*(1-mask) + JG.*mask;

imB = im2(:,:,3).*(1-mask) + JB.*mask;

imshow(cat(3, im, imG,imB));

 

 

compH.m

 

 

function H = compH(x1, y1, x2, y2)

% function compH finds the homography H

% (x1,y1) and (x2,y2) are matching points

ax = [-x1, -y1, -ones(size(x1)), zeros(size(x1)), zeros(size(x1)),zeros(size(x1)), x2.*x1, x2.*y1, x2];

ay = [zeros(size(x1)), zeros(size(x1)), zeros(size(x1)), -x1, -y1, -ones(size(x1)), y2.*x1, y2.*y1, y2];

A = [ax; ay];

[U,S,V] = svd(A);

H = reshape(V(:,9), 3, 3);

H = H';