public void EstimatePose( Point[] points, out Matrix3x3 rotation, out Vector3 translation )
{
if ( points.Length != 4 )
{
throw new ArgumentException( "4 points must be be given for pose estimation." );
}
float Z0 = 0, scale = 1;
Vector3 X0 = new Vector3( points[0].X );
Vector3 Y0 = new Vector3( points[0].Y );
Vector3 XI = new Vector3( points[1].X, points[2].X, points[3].X );
Vector3 YI = new Vector3( points[1].Y, points[2].Y, points[3].Y );
int count = 0;
Vector3 iVector = new Vector3( );
Vector3 jVector = new Vector3( );
Vector3 kVector = new Vector3( );
Vector3 imageXs = new Vector3( );
Vector3 imageYs = new Vector3( );
Vector3 eps = new Vector3( 1 );
for ( ; count < 100; count++ )
{
// calculate new scale orthographic projection (SOP)
imageXs = XI * eps - X0;
imageYs = YI * eps - Y0;
// calculate I and J vectors
iVector = modelPseudoInverse * imageXs;
jVector = modelPseudoInverse * imageYs;
// convert them to unit vectors i and j
float iNorm = iVector.Normalize( );
float jNorm = jVector.Normalize( );
// scale of projection
scale = ( iNorm + jNorm ) / 2;
// calculate n vector k
kVector = Vector3.Cross( iVector, jVector );
// z-coordinate Z0 of the translation vector
Z0 = focalLength / scale;
// calculate new epsilon values
Vector3 oldEps = eps;
eps = ( modelVectors * kVector ) / Z0 + 1;
// check if it is time to stop
if ( ( eps - oldEps ).Abs( ).Max < stop_epsilon )
break;
}
// create rotation matrix
rotation = Matrix3x3.CreateFromRows( iVector, jVector, kVector );
// create translation vector
Vector3 temp = rotation * modelPoints[0];
translation = new Vector3(
points[0].X / scale - temp.X,
points[0].Y / scale - temp.Y,
focalLength / scale );
}
}