function [CamEST infoEST errEST CamOPT infoOPT errOPT]=...
	RealCamEstimation(T,CalibInfo,Points,OPT)
%ta*
% T: poses of real camera in relation to virtual grid. for N poses, this is
% a 4x4xN matrix. for pose n, T(:,:,n) is a transformation matrix obtained
% from Tc_n and Rc_n returned by Bouguet.
%
% CalibInfo.fc    Bouguet's fc      focal length in pixels
% CalibInfo.cc    Bouguet's cc      principal point coordinates
% CalibInfo.kc    Bouguet's kc      skew coefficient
% CalibInfo.alpha Bouguet's alpha_c distortion coeffs. vector
% 
% Points
%
% OPT: boolean; whether or not to optimise.
%
% *EST - results after first estimation.
%
% *OPT - results after optimisation.
% 
% Cam* - pose of real camera in relation to real grid.
% 
% info* -
%
% err* -

NV=size(T,3);
if NV<3
	error('Number of virtual views must be more than or equal to 3!');
end

if ~exist('CalibInfo','var');CalibInfo=[];end
if ~exist('Points','var');Points=[];end
if ~exist('OPT','var');OPT=0;end

%% Real camera position with NV virtual views of the object
%  For each order the first mirror pose is estimated then computed the
% real camera position.By last, the mean transformation of the real 
% camera displacement is computed and after the remaining mirror poses

auxORDER=1:NV;
Cam=zeros(4,4,NV);
A=zeros(3*(NV-1),4);
for NT=1:NV
	ORDER=circshift(auxORDER',(1-NT))';
	% estimate of N0,d0 using method 1 (ECCV 2010)
	[VcamEST,N0(:,NT),d0(NT),control(:,NT)]=EstimateN0d0(T(:,:,ORDER));
%ta* ORDER(1) is equal to NT
	Cam(:,:,NT)=inv(T(:,:,ORDER(1)))*VcamEST;
end

CamEST=MeanTransformation(Cam);

PIest=zeros(4,NV);
S=zeros(4,4,NV);
for N1=1:NV
	Vcam=T(:,:,N1)*CamEST;
	PIest(:,N1)=[Vcam(1:3,4)./norm(Vcam(1:3,4));-norm(Vcam(1:3,4))/2];
	S(:,:,N1)=ReflectTransf(PIest(1:3,N1),-PIest(4,N1));
end

infoEST.S=S;
infoEST.PI=PIest;
infoEST.control=control;
infoEST.auxPI=[N0;-d0];

%% Re-projection error
errEST=[];
if not(isempty(CalibInfo) || isempty(Points)) && nargout>2
	errEST=CompReprojectionError(CamEST,PIest,Points,CalibInfo);
end

%% Optimization
CamOPT=[];
infoOPT=[];
errOPT=[];
if OPT && nargout>3
	[CamOPT,PIopt,infoOPT]=OptimizeResult1Mirror(CamEST,PIest,Points,CalibInfo);
	infoOPT.PI=PIopt;
	errOPT=CompReprojectionError(CamOPT,PIopt,Points,CalibInfo);
end
