contrib/oxl/mvl/PMatrixDecompCR.cxx
Go to the documentation of this file.
00001 // This is oxl/mvl/PMatrixDecompCR.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 //  \file
00007 
00008 #include "PMatrixDecompCR.h"
00009 
00010 
00011 #include <vcl_iostream.h>
00012 
00013 #include <vnl/vnl_matlab_print.h>
00014 #include <vnl/vnl_double_3.h>
00015 #include <vnl/algo/vnl_qr.h>
00016 
00017 #include <mvl/PMatrix.h>
00018 
00019 PMatrixDecompCR::PMatrixDecompCR(const PMatrix& P, bool scale_C)
00020 {
00021   compute(P.get_matrix(), scale_C);
00022 }
00023 
00024 PMatrixDecompCR::PMatrixDecompCR(const vnl_double_3x4& P, bool scale_C)
00025 {
00026   compute(P, scale_C);
00027 }
00028 
00029 void UtSolve(const vnl_double_3x3& T, vnl_double_3& x)
00030 {
00031   x[2] /= T(2,2);
00032   x[1] = (x[1] - T(1,2)*x[2])/T(1,1);
00033   x[0] = (x[0] - T(0,1)*x[1] - T(0,2)*x[2])/T(0,0);
00034 }
00035 
00036 //: Decompose P
00037 void PMatrixDecompCR::compute(const vnl_double_3x4& p, bool scale_C)
00038 {
00039   // P = [H t]
00040   //
00041   vnl_double_3x3 PermHtPerm;
00042 
00043   for (int i = 0; i < 3; ++i)
00044     for (int j = 0; j < 3; ++j)
00045       PermHtPerm(i,j) = p(2-j,2-i);
00046 
00047   vnl_qr<double> qr(PermHtPerm.as_ref()); // size 3x3
00048 
00049   vnl_double_3x3 Q = qr.Q();
00050   vnl_double_3x3 R = qr.R();
00051 
00052   // Ensure all diagonal components of C are positive.
00053   // Must insert a det(+1) or det(-1) mx between.
00054   int r0pos = R(0,0) > 0 ? 1 : 0;
00055   int r1pos = R(1,1) > 0 ? 1 : 0;
00056   int r2pos = R(2,2) > 0 ? 1 : 0;
00057   typedef double d3[3];
00058   d3 diags[] = {   // 1 2 3
00059     { -1,  1, -1}, // - + -
00060     {  1, -1, -1}, // - + +
00061     { -1, -1, -1}, // - - -
00062     {  1,  1, -1}, // - - +
00063     { -1, -1,  1}, // + + -
00064     {  1,  1,  1}, // + + +
00065     { -1,  1,  1}, // + - -
00066     {  1, -1,  1}, // + - +
00067   };
00068   int d = r0pos * 4 + r1pos * 2 + r2pos;
00069   double* diag = &diags[d][0];
00070 
00071   for (int i = 0; i < 3; ++i)
00072     for (int j = 0; j < 3; ++j) {
00073       C(j,i)  = diag[i] * R(2-i,2-j);
00074       Po(j,i) = diag[j] * Q(2-i,2-j);
00075     }
00076 
00077   // Compute t' = inv(C) t
00078   vnl_double_3 t;
00079   for (int i = 0; i < 3; ++i)
00080     t[i] = p(i,3);
00081   UtSolve(C, t);
00082 
00083   for (int i = 0; i < 3; ++i)
00084     Po(i,3) = t[i];
00085 
00086   if (((C * Po - p).fro_norm() > 1e-4) ||
00087       (C(0,0) < 0) ||
00088       (C(1,1) < 0) ||
00089       (C(2,2) < 0)) {
00090     vcl_cerr << "PMatrixDecompCR: AIEEE!\n";
00091     vnl_matlab_print(vcl_cerr, p, "p");
00092     vnl_matlab_print(vcl_cerr, C, "C");
00093     vnl_matlab_print(vcl_cerr, Po, "Po");
00094     vnl_matlab_print(vcl_cerr, C * Po - p, "C * Po - p");
00095   }
00096 
00097   // Make C(2,2) = 1
00098   if (scale_C)
00099     C *= 1.0/C(2,2);
00100 }