function [H,Hnorm,inv_Hnorm] = compute_homography(m,M); %compute_homography % %[H,Hnorm,inv_Hnorm] = compute_homography(m,M) % %Computes the planar homography between the point coordinates on the plane (M) and the image %point coordinates (m). % %INPUT: m: homogeneous coordinates in the image plane (3xN matrix) % M: homogeneous coordinates in the plane in 3D (3xN matrix) % %OUTPUT: H: Homography matrix (3x3 homogeneous matrix) % Hnorm: Normalization matrix used on the points before homography computation % (useful for numerical stability is points in pixel coordinates) % inv_Hnorm: The inverse of Hnorm % %Definition: m ~ H*M where "~" means equal up to a non zero scalar factor. % %Method: First computes an initial guess for the homography through quasi-linear method. % Then, if the total number of points is larger than 4, optimize the solution by minimizing % the reprojection error (in the least squares sense). % % %Important functions called within that program: % %comp_distortion_oulu: Undistorts pixel coordinates. % %compute_homography.m: Computes the planar homography between points on the grid in 3D, and the image plane. % %project_points.m: Computes the 2D image projections of a set of 3D points, and also returns te Jacobian % matrix (derivative with respect to the intrinsic and extrinsic parameters). % This function is called within the minimization loop. Np = size(m,2); if size(m,1)<3, m = [m;ones(1,Np)]; end; if size(M,1)<3, M = [M;ones(1,Np)]; end; m = m ./ (ones(3,1)*m(3,:)); M = M ./ (ones(3,1)*M(3,:)); % Prenormalization of point coordinates (very important): % (Affine normalization) ax = m(1,:); ay = m(2,:); mxx = mean(ax); myy = mean(ay); ax = ax - mxx; ay = ay - myy; scxx = mean(abs(ax)); scyy = mean(abs(ay)); Hnorm = [1/scxx 0 -mxx/scxx;0 1/scyy -myy/scyy;0 0 1]; inv_Hnorm = [scxx 0 mxx ; 0 scyy myy; 0 0 1]; mn = Hnorm*m; % Compute the homography between m and mn: % Build the matrix: L = zeros(2*Np,9); L(1:2:2*Np,1:3) = M'; L(2:2:2*Np,4:6) = M'; L(1:2:2*Np,7:9) = -((ones(3,1)*mn(1,:)).* M)'; L(2:2:2*Np,7:9) = -((ones(3,1)*mn(2,:)).* M)'; if Np > 4, L = L'*L; end; [U,S,V] = svd(L); hh = V(:,9); hh = hh/hh(9); Hrem = reshape(hh,3,3)'; %Hrem = Hrem / Hrem(3,3); % Final homography: H = inv_Hnorm*Hrem; if 0, m2 = H*M; m2 = [m2(1,:)./m2(3,:) ; m2(2,:)./m2(3,:)]; merr = m(1:2,:) - m2; end; %keyboard; %%% Homography refinement if there are more than 4 points: if Np > 4, % Final refinement: hhv = reshape(H',9,1); hhv = hhv(1:8); for iter=1:10, mrep = H * M; J = zeros(2*Np,8); MMM = (M ./ (ones(3,1)*mrep(3,:))); J(1:2:2*Np,1:3) = -MMM'; J(2:2:2*Np,4:6) = -MMM'; mrep = mrep ./ (ones(3,1)*mrep(3,:)); m_err = m(1:2,:) - mrep(1:2,:); m_err = m_err(:); MMM2 = (ones(3,1)*mrep(1,:)) .* MMM; MMM3 = (ones(3,1)*mrep(2,:)) .* MMM; J(1:2:2*Np,7:8) = MMM2(1:2,:)'; J(2:2:2*Np,7:8) = MMM3(1:2,:)'; MMM = (M ./ (ones(3,1)*mrep(3,:)))'; hh_innov = inv(J'*J)*J'*m_err; hhv_up = hhv - hh_innov; H_up = reshape([hhv_up;1],3,3)'; %norm(m_err) %norm(hh_innov) hhv = hhv_up; H = H_up; end; end; if 0, m2 = H*M; m2 = [m2(1,:)./m2(3,:) ; m2(2,:)./m2(3,:)]; merr = m(1:2,:) - m2; end; return; %test of Jacobian mrep = H*M; mrep = mrep ./ (ones(3,1)*mrep(3,:)); m_err = mrep(1:2,:) - m(1:2,:); figure(8); plot(m_err(1,:),m_err(2,:),'r+'); std(m_err')