function [A,R,t]=art(P,fsign)
%ART Factorize camera matrix into intrinsic and extrinsic matrices
%
% [A,R,t] = art(P,fsign) factorize the projection matrix P
% as P=A*[R;t] and enforce the sign of the focal lenght to be fsign.
% By defaukt fsign=1.
% Author: A. Fusiello, 1999
%
% fsign tells the position of the image plane wrt the focal plane. If it is
% negative the image plane is behind the focal plane.
% by default assume POSITIVE focal lenght
if nargin == 1
fsign = 1;
end
s = P(1:3,4);
Q = inv(P(1:3, 1:3));
[U,B] = qr(Q);
% fix the sign of B(3,3). This can possibly change the sign of the resulting matrix,
% which is defined up to a scale factor, however.
sig = sign(B(3,3));
B=B*sig;
s=s*sig;
% if the sign of the focal lenght is not the required one,
% change it, and change the rotation accordingly.
if fsign*B(1,1) < 0
E= [-1 0 0
0 1 0
0 0 1];
B = E*B;
U = U*E;
end
if fsign*B(2,2) < 0
E= [1 0 0
0 -1 0
0 0 1];
B = E*B;
U = U*E;
end
% if U is not a rotation, fix the sign. This can possibly change the sign
% of the resulting matrix, which is defined up to a scale factor, however.
if det(U)< 0
U = -U;
s= - s;
end
% sanity check
if (norm(Q-U*B)>1e-10) & (norm(Q+U*B)>1e-10)
error(‘Something wrong with the QR factorization.‘); end
R = U‘;
t = B*s;
A = inv(B);
A = A ./A(3,3);
% sanity check
if det(R) < 0 error(‘R is not a rotation matrix‘); end
if A(3,3) < 0 error(‘Wrong sign of A(3,3)‘); end
% this guarantee that the result *is* a factorization of the given P, up to a scale factor
W = A*[R,t];
if (rank([P(:), W(:)]) ~= 1 )
error(‘Something wrong with the ART factorization.‘); end