% Load images
% C: \Users\DELL\Desktop\Assignment2
jakobs_a = imread( 'C:\Users\DELL\Desktop\A ssignment2\jakobs_a.jpg' ) ;
jakobs_b = imread( 'C:\Users\DELL\Desktop\A ssignment2\jakobs_b.jpg' ) ;
jakobs_c = imread( 'C:\Users\DELL\Desktop\A ssignment2\jakobs_c.jpg' ) ;
% Display images for reference
figure;
subplot( 1 , 3 , 1 ) ; imshow( jakobs_a) ; title( 'jakobs_a.jpg' ) ;
subplot( 1 , 3 , 2 ) ; imshow( jakobs_b) ; title( 'jakobs_b.jpg' ) ;
subplot( 1 , 3 , 3 ) ; imshow( jakobs_c) ; title( 'jakobs_c.jpg' ) ;
% Select 4 corresponding points between Image 1 and Image 2
figure; imshow( jakobs_a) ; title( 'Select 4 points in Image 1' ) ;
[ x1, y1] = ginput( 4 ) ;
figure; imshow( jakobs_b) ; title( 'Select 4 points in Image 2' ) ;
[ x2, y2] = ginput( 4 ) ;
% Store points as homogeneous coordinates
points1 = [ x1 y1 ones( 4 , 1 ) ] ;
points2 = [ x2 y2 ones( 4 , 1 ) ] ;
function H = computeHomography( points1, points2)
% Number of points
num_points = size( points1, 1 ) ;
% Build the matrix A for which A * h = 0
A = zeros( 2 * num_points, 9 ) ;
for i = 1 : num_points
x = points1( i, 1 ) ;
y = points1( i, 2 ) ;
xp = points2( i, 1 ) ;
yp = points2( i, 2 ) ;
A( 2 * i - 1 , : ) = [ - x, - y, - 1 , 0 , 0 , 0 , x * xp, y * xp, xp] ;
A( 2 * i, : ) = [ 0 , 0 , 0 , - x, - y, - 1 , x * yp, y * yp, yp] ;
end
% Perform SVD on A
[ ~, ~, V] = svd( A) ;
% The homography matrix is the last column of V, reshaped to 3x3
H = reshape( V( :, 9 ) , [ 3 , 3 ] ) ';
end
% Compute homography from Image 1 to Image 2
H12 = computeHomography(points1, points2);
function i = geokor (H, f, g)
% ====================
[h1 w1 d] = size(f); f = double(f); % Image dimensions
[h2 w2 d] = size(g); g = double(g);
% Transformation of image corners to determine the resulting size
cp = norm2(H * [1 1 w1 w1; 1 h1 1 h1; 1 1 1 1]);
Xpr = min([cp(1, :) 0]) : max([cp(1, :) w2]); % min x : max x
Ypr = min([cp(2, :) 0]) : max([cp(2, :) h2]); % min y : max y
[Xp, Yp] = ndgrid(Xpr, Ypr);
[wp hp] = size(Xp); % = size(Yp)
X = norm2(H \ [Xp(:) Yp(:) ones(wp*hp, 1)]' ) ; % Indirect transformation
xI = reshape( X( 1 , : ) , wp, hp) '; % Resampling of intensity values
yI = reshape(X(2, :), wp, hp)' ;
f2 = zeros( hp, wp) ; i = f2;
for k = 1 : d
f2( 1 : h1, 1 : w1, k) = f( :, :, k) ;
i( :, :, k) = interp2( f2( :, :, k) , xI, yI) ; % bilinear interpolation
end
% Copy the original image g in the rectified image f
off = - round( [ min( [ cp( 1 , : ) 0 ] ) min( [ cp( 2 , : ) 0 ] ) ] ) ;
Index = find( sum( g, 3 ) > 9 ) ;
for k = 1 : d
iPart = i( 1 + off( 2 ) : h2+ off( 2 ) , 1 + off( 1 ) : w2+ off( 1 ) , k) ;
fChannel = g( :, :, k) ;
iPart( Index) = fChannel( Index) ;
i( 1 + off( 2 ) : h2+ off( 2 ) , 1 + off( 1 ) : w2+ off( 1 ) , k) = iPart;
end
i( ~isfinite( i) ) = 0 ;
i = uint8 ( i) ;
end
function n = norm2( x)
for i = 1 : 3
n( i,: ) = x( i,: ) ./ x( 3 ,: ) ;
end
end
i = geokor( H12, jakobs_a, jakobs_b) ; % Transform image f using H and combine with g
% figure;
imshow( i) ; title( 'Select 4 points in attached image 1 and 2' ) ;
[ x3, y3] = ginput( 4 ) ;
imshow( img3) ; title( 'Select 4 points in attached image 3' ) ;
[ x4, y4] = ginput( 4 ) ;
points12 = [ x3 y3 ones( 4 , 1 ) ] ;
points4 = [ x4 y4 ones( 4 , 1 ) ] ;
H23 = computeHomography( points12, points4) ;
finalResult = geokor( H23, i, jakobs_c) ;
imshow( finalResult) ;
JSBMb2FkIGltYWdlcwolQzpcVXNlcnNcREVMTFxEZXNrdG9wXEFzc2lnbm1lbnQyCmpha29ic19hID0gaW1yZWFkKCdDOlxVc2Vyc1xERUxMXERlc2t0b3BcQXNzaWdubWVudDJcamFrb2JzX2EuanBnJyk7Cmpha29ic19iID0gaW1yZWFkKCdDOlxVc2Vyc1xERUxMXERlc2t0b3BcQXNzaWdubWVudDJcamFrb2JzX2IuanBnJyk7Cmpha29ic19jID0gaW1yZWFkKCdDOlxVc2Vyc1xERUxMXERlc2t0b3BcQXNzaWdubWVudDJcamFrb2JzX2MuanBnJyk7CgogCiUgRGlzcGxheSBpbWFnZXMgZm9yIHJlZmVyZW5jZQpmaWd1cmU7CnN1YnBsb3QoMSwgMywgMSk7IGltc2hvdyhqYWtvYnNfYSk7IHRpdGxlKCdqYWtvYnNfYS5qcGcnKTsKc3VicGxvdCgxLCAzLCAyKTsgaW1zaG93KGpha29ic19iKTsgdGl0bGUoJ2pha29ic19iLmpwZycpOwpzdWJwbG90KDEsIDMsIDMpOyBpbXNob3coamFrb2JzX2MpOyB0aXRsZSgnamFrb2JzX2MuanBnJyk7CgolIFNlbGVjdCA0IGNvcnJlc3BvbmRpbmcgcG9pbnRzIGJldHdlZW4gSW1hZ2UgMSBhbmQgSW1hZ2UgMgpmaWd1cmU7IGltc2hvdyhqYWtvYnNfYSk7IHRpdGxlKCdTZWxlY3QgNCBwb2ludHMgaW4gSW1hZ2UgMScpOwpbeDEsIHkxXSA9IGdpbnB1dCg0KTsKIApmaWd1cmU7IGltc2hvdyhqYWtvYnNfYik7IHRpdGxlKCdTZWxlY3QgNCBwb2ludHMgaW4gSW1hZ2UgMicpOwpbeDIsIHkyXSA9IGdpbnB1dCg0KTsKIAolIFN0b3JlIHBvaW50cyBhcyBob21vZ2VuZW91cyBjb29yZGluYXRlcwpwb2ludHMxID0gW3gxIHkxIG9uZXMoNCwgMSldOwpwb2ludHMyID0gW3gyIHkyIG9uZXMoNCwgMSldOwoKCmZ1bmN0aW9uIEggPSBjb21wdXRlSG9tb2dyYXBoeShwb2ludHMxLCBwb2ludHMyKQogICAgJSBOdW1iZXIgb2YgcG9pbnRzCiAgICBudW1fcG9pbnRzID0gc2l6ZShwb2ludHMxLCAxKTsKIAogICAgJSBCdWlsZCB0aGUgbWF0cml4IEEgZm9yIHdoaWNoIEEgKiBoID0gMAogICAgQSA9IHplcm9zKDIgKiBudW1fcG9pbnRzLCA5KTsKICAgIGZvciBpID0gMTpudW1fcG9pbnRzCiAgICAgICAgeCA9IHBvaW50czEoaSwgMSk7CiAgICAgICAgeSA9IHBvaW50czEoaSwgMik7CiAgICAgICAgeHAgPSBwb2ludHMyKGksIDEpOwogICAgICAgIHlwID0gcG9pbnRzMihpLCAyKTsKIAogICAgICAgIEEoMiAqIGkgLSAxLCA6KSA9IFsteCwgLXksIC0xLCAwLCAwLCAwLCB4ICogeHAsIHkgKiB4cCwgeHBdOwogICAgICAgIEEoMiAqIGksIDopICAgICA9IFswLCAwLCAwLCAteCwgLXksIC0xLCB4ICogeXAsIHkgKiB5cCwgeXBdOwogICAgZW5kCiAKICAgICUgUGVyZm9ybSBTVkQgb24gQQogICAgW34sIH4sIFZdID0gc3ZkKEEpOwogCiAgICAlIFRoZSBob21vZ3JhcGh5IG1hdHJpeCBpcyB0aGUgbGFzdCBjb2x1bW4gb2YgViwgcmVzaGFwZWQgdG8gM3gzCiAgICBIID0gcmVzaGFwZShWKDosIDkpLCBbMywgM10pJzsKZW5kCiAKIAolIENvbXB1dGUgaG9tb2dyYXBoeSBmcm9tIEltYWdlIDEgdG8gSW1hZ2UgMgpIMTIgPSBjb21wdXRlSG9tb2dyYXBoeShwb2ludHMxLCBwb2ludHMyKTsKIAogCgpmdW5jdGlvbiBpID0gZ2Vva29yIChILCBmLCBnKQolICAgICAgICA9PT09PT09PT09PT09PT09PT09PQoJW2gxIHcxIGRdID0gc2l6ZShmKTsgZiA9IGRvdWJsZShmKTsgICAgICAgICAgICAgICAgICAgICAlIEltYWdlIGRpbWVuc2lvbnMKCVtoMiB3MiBkXSA9IHNpemUoZyk7IGcgPSBkb3VibGUoZyk7CgogICAgICAgICAlIFRyYW5zZm9ybWF0aW9uIG9mIGltYWdlIGNvcm5lcnMgdG8gZGV0ZXJtaW5lIHRoZSByZXN1bHRpbmcgc2l6ZQoJY3AgPSBub3JtMihIICogWzEgMSB3MSB3MTsgMSBoMSAxIGgxOyAxIDEgMSAxXSk7CglYcHIgPSBtaW4oW2NwKDEsIDopIDBdKSA6IG1heChbY3AoMSwgOikgdzJdKTsgICAgICAgICAgICAgICUgbWluIHggOiBtYXggeAoJWXByID0gbWluKFtjcCgyLCA6KSAwXSkgOiBtYXgoW2NwKDIsIDopIGgyXSk7ICAgICAgICAgICAgICAlIG1pbiB5IDogbWF4IHkKCVtYcCwgWXBdID0gbmRncmlkKFhwciwgWXByKTsKCVt3cCBocF0gPSBzaXplKFhwKTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJSA9IHNpemUoWXApCglYID0gbm9ybTIoSCBcIFtYcCg6KSBZcCg6KSBvbmVzKHdwKmhwLCAxKV0nKTsgICAgJSBJbmRpcmVjdCB0cmFuc2Zvcm1hdGlvbgoJCgl4SSA9IHJlc2hhcGUoWCgxLCA6KSwgd3AsIGhwKSc7ICAgICAgICAgICAlIFJlc2FtcGxpbmcgb2YgaW50ZW5zaXR5IHZhbHVlcyAKCXlJID0gcmVzaGFwZShYKDIsIDopLCB3cCwgaHApJzsKCWYyID0gemVyb3MoaHAsIHdwKTsgaSA9IGYyOwoJZm9yIGsgPSAxIDogZAoJCWYyKDE6aDEsIDE6dzEsIGspID0gZig6LCA6LCBrKTsKCQlpKDosIDosIGspID0gaW50ZXJwMihmMig6LCA6LCBrKSwgeEksIHlJKTsgICAgJSBiaWxpbmVhciBpbnRlcnBvbGF0aW9uICAgICAgICAgICAKCWVuZAogICAgICAgICAgICAgICAgICAgICAgJSBDb3B5IHRoZSBvcmlnaW5hbCBpbWFnZSBnIGluIHRoZSByZWN0aWZpZWQgaW1hZ2UgZgoJb2ZmID0gLXJvdW5kKFttaW4oW2NwKDEsIDopIDBdKSBtaW4oW2NwKDIsIDopIDBdKV0pOwoJSW5kZXggPSBmaW5kKHN1bShnLCAzKSA+IDkpOyAKCWZvciBrID0gMSA6IGQKICAgIAkJaVBhcnQgPSBpKDErb2ZmKDIpIDogaDIrb2ZmKDIpLCAxK29mZigxKSA6IHcyK29mZigxKSwgayk7CiAgICAJCWZDaGFubmVsID0gZyg6LCA6LCBrKTsKICAgIAkJaVBhcnQoSW5kZXgpID0gZkNoYW5uZWwoSW5kZXgpOwogICAgCQlpKDErb2ZmKDIpIDogaDIrb2ZmKDIpLCAxK29mZigxKSA6IHcyK29mZigxKSwgaykgPSBpUGFydDsKCWVuZAoJaSh+aXNmaW5pdGUoaSkpID0gMDsKCWkgPSB1aW50OChpKTsKCmVuZAoKZnVuY3Rpb24gbiA9IG5vcm0yKHgpCglmb3IgaSA9IDEgOiAzCgkJbihpLDopID0geChpLDopIC4vIHgoMyw6KTsJCgllbmQKCmVuZAoKCgppID0gZ2Vva29yKEgxMiwgamFrb2JzX2EsIGpha29ic19iKTsgICAgICUgVHJhbnNmb3JtIGltYWdlIGYgdXNpbmcgSCBhbmQgY29tYmluZSB3aXRoIGcKJSBmaWd1cmU7IAoKaW1zaG93KGkpO3RpdGxlKCdTZWxlY3QgNCBwb2ludHMgaW4gYXR0YWNoZWQgaW1hZ2UgMSBhbmQgMicpOwpbeDMsIHkzXSA9IGdpbnB1dCg0KTsKaW1zaG93KGltZzMpOyB0aXRsZSgnU2VsZWN0IDQgcG9pbnRzIGluIGF0dGFjaGVkIGltYWdlIDMnKTsKW3g0LCB5NF0gPSBnaW5wdXQoNCk7CnBvaW50czEyID0gW3gzIHkzIG9uZXMoNCwgMSldOwpwb2ludHM0ID0gW3g0IHk0IG9uZXMoNCwgMSldOwpIMjMgPSBjb21wdXRlSG9tb2dyYXBoeShwb2ludHMxMiwgcG9pbnRzNCk7CgpmaW5hbFJlc3VsdCA9IGdlb2tvcihIMjMsIGksIGpha29ic19jKTsgCmltc2hvdyhmaW5hbFJlc3VsdCk7