Matlab rectify仿真,rectify3.m · zigzag2015/machinevision-toolbox-matlab - Gitee.com

仲阳朔
2023-12-01

% Copyright (C) 1993-2011, by Peter I. Corke

%

% This file is part of The Machine Vision Toolbox for Matlab (MVTB).

%

% MVTB is free software: you can redistribute it and/or modify

% it under the terms of the GNU Lesser General Public License as published by

% the Free Software Foundation, either version 3 of the License, or

% (at your option) any later version.

%

% MVTB is distributed in the hope that it will be useful,

% but WITHOUT ANY WARRANTY; without even the implied warranty of

% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

% GNU Lesser General Public License for more details.

%

% You should have received a copy of the GNU Leser General Public License

% along with MVTB. If not, see .

function [Img1_new, Img2_new, H12,H21,F12] = rectify(F, m, Img1, Img2)

F12 = F';

[rows,cols,depth] = size(Img1);

% Get homographies.

x1 = e2h( m.xy(:,1:2)' );

x2 = e2h( m.xy(:,3:4)' );

[H12,H21,bSwap] = rectify_homographies( F12, x1, x2, rows, cols );

[w1,off1] = homwarp(H12, Img1, 'full');

[w2,off2] = homwarp(H21, Img2, 'full');

% fix the vertical alignment of the images by padding

dy = off1(2) - off2(2);

if dy < 0

w1 = ipad(w1, 'b', -dy);

w2 = ipad(w2, 't', -dy);

else

w1 = ipad(w1, 't', dy);

w2 = ipad(w2, 'b', dy);

end

[w1,w2] = itrim(w1, w2);

if nargout == 0

stview(w1, w2)

else

Img1_new = w1;

Img2_new = w2;

end

%-----------------------------------------------------------------------------

function [H1,H2,bSwap] = rectify_homographies( F, x1, x2, rows, cols )

% F: a fundamental matrix

% x1 and x2: corresponding points such that x1_i' * F * x2_i = 0

% Initialize

H1 = [];

H2 = [];

bSwap = 0;

% Center of image

cy = round( rows/2 );

cx = round( cols/2 );

% Fix F to be rank 2 to numerical accuracy

[U,D,V] = svd( F );

D(3,3) = 0;

F = U*D*V';

% Get epipole. e12 is the epipole in image 1 for camera 2.

e12 = null( F' ); % Epipole in image 1 for camera 2

e21 = null( F ); % Epipole in image 2 for camera 1

% Put epipoles in front of camera

if e12 < 0, e12 = -e12; end;

if e21 < 0, e21 = -e21; end;

% Make sure the epipoles are inside the images

check_epipoles_in_image( e12, e21, rows, cols );

% Check that image 1 is to the left of image 2

% if e12(1)/e12(3) < cx

% fprintf( 1, 'Swapping left and right images...\n' );

% tmp = e12;

% e12 = e21;

% e21 = tmp;

% F = F';

% bSwap = 1;

% end;

% Now we have

% F' * e12 = 0,

% F * e21 = 0,

% Let's get the rectifying homography Hprime for image 1 first

Hprime = map_to_infinity( e12, cx, cy );

e12_new = Hprime * e12;

% Normalize Hprime so that Hprime*eprime = (1,0,0)'

Hprime = Hprime / e12_new(1);

e12_new = Hprime * e12;

fprintf( 1, 'Epipole 1/2 mapped to infinity: (%g, %g, %g)\n', e12_new );

% Get canonical camera matrices for F12 and compute H0, one possible

% rectification homography for image 2

[P,Pprime] = get_canonical_cameras( F );

M = Pprime(:,1:3);

H0 = Hprime * M;

% Test that F12 is a valid F for P,Pprime

test_p_f( P, Pprime, F );

% Now we need to find H so that the epipolar lines match

% each other, i.e., inv(H)' * l = inv(Hprime)' * lprime

% and the disparity is minimized, i.e.,

% min \sum_i d(H x_i, Hprime xprime_i)^2

% Transform data initially according to Hprime (img 1) and H0 (img 2)

x1hat = Hprime * x1;

x1hat = x1hat ./ repmat( x1hat(3,:), 3, 1 );

x2hat = H0 * x2;

x2hat = x2hat ./ repmat( x2hat(3,:), 3, 1 );

rmse_x = sqrt( mean( (x1hat(1,:) - x2hat(1,:) ).^2 ));

rmse_y = sqrt( mean( (x1hat(2,:) - x2hat(2,:) ).^2 ));

fprintf( 1, 'Before Ha, RMSE for corresponding points in Y: %g X: %g\n', ...

rmse_y, rmse_x );

% Estimate [ a b c ; 0 1 0 ; 0 0 1 ] aligning H, Hprime

n = size(x1,2);

A = [ x2hat(1,:)', x2hat(2,:)', ones(n,1) ];

b = x1hat(1,:)';

abc = A\b;

HA = [ abc' ; 0 1 0 ; 0 0 1 ];

H = HA*H0;

x2hat = H * x2;

x2hat = x2hat ./ repmat( x2hat(3,:), 3, 1 );

rmse_x = sqrt( mean(( x1hat(1,:) - x2hat(1,:) ).^2 ));

rmse_y = sqrt( mean(( x1hat(2,:) - x2hat(2,:) ).^2 ));

fprintf( 1, 'After Ha, RMSE for corresponding points in Y: %g X: %g\n', ...

rmse_y, rmse_x );

% Return the homographies as appropriate

if bSwap

H1 = H;

H2 = Hprime;

else

H1 = Hprime;

H2 = H;

end;

%-----------------------------------------------------------------------------

function check_epipoles_in_image( e1, e2, rows, cols )

% Check whether given epipoles are in the image or not

if abs( e1(3) ) < 1e-6 & abs( e2(3) ) < 1e-6, return; end;

e1 = e1 / e1(3);

e2 = e2 / e2(3);

if ( e1(1) <= cols & e1(1) >= 1 & e1(2) <= rows & e1(2) >= 1 ) | ...

( e2(1) <= cols & e2(1) >= 1 & e2(2) <= rows & e2(2) >= 1 )

err_msg = sprintf( 'epipole (%g,%g) or (%g,%g) is inside image', ...

e1(1:2), e2(1:2) );

error( [ err_msg, ' -- homography does not work in this case!' ] );

end;

%-----------------------------------------------------------------------------

function [P,Pprime] = get_canonical_cameras( F )

% Get the "canonical" cameras for given fundamental matrix

% according to Hartley and Zisserman (2004), p256, Result 9.14

% But ensure that the left 3x3 submatrix of Pprime is nonsingular

% using Result 9.15, that the general form is

% [ skewsym( e12 ) * F + e12 * v', k * e12 ] where v is an arbitrary

% 3-vector and k is an arbitrary scalar

P = [ 1 0 0 0

0 1 0 0

0 0 1 0 ];

e12 = null( F' );

M = skew( e12 ) * F + e12 * [1 1 1];

Pprime = [ M, e12 ];

%-----------------------------------------------------------------------------

function test_p_f( P, Pprime, F )

% Test that camera matrices Pprime and P are consistent with

% fundamental matrix F

% Meaning (Pprime*X)' * F * (P*X) = 0, for all X in 3space

% Get the epipole in camera 1 for camera 2

C2 = null( P );

eprime = Pprime * C2;

% Construct F from Pprime, P, and eprime

Fhat = skew( eprime ) * Pprime * pinv( P );

% Check that it's close to F

alpha = Fhat(:)\F(:);

if norm( alpha*Fhat-F ) > 1e-10

fprintf( 1, 'Warning: supplied camera matrices are inconsistent with F\n' );

else

fprintf( 1, 'Supplied camera matrices OK\n' );

end;

%-----------------------------------------------------------------------------

function H = map_to_infinity( x, cx, cy )

% Given a point and the desired origin (point of minimum projective

% distortion), compute a homograph H = G*R*T taking the point to the

% origin, rotating it to align with the X axis, then mapping it to

% infinity.

% First map cx,cy to the origin

T = [ 1 0 -cx

0 1 -cy

0 0 1 ];

x = T * x;

% Now rotate the translated x to align with the X axis.

cur_angle = atan2( x(2), x(1) );

R = [ cos( -cur_angle ), -sin( -cur_angle ), 0

sin( -cur_angle ), cos( -cur_angle ), 0

0, 0, 1 ];

x = R * x;

% Now the transformation G mapping x to infinity

if abs( x(3)/norm(x) ) < 1e-6

% It's already at infinity

G = eye(3)

else

f = x(1)/x(3);

G = [ 1 0 0

0 1 0

-1/f 0 1 ];

end;

H = G*R*T;

一键复制

编辑

Web IDE

原始数据

按行查看

历史

 类似资料: