contrib/brl/bbas/bgui3d/bgui3d_algo.cxx
Go to the documentation of this file.
00001 // This is brl/bbas/bgui3d/bgui3d_algo.cxx
00002 #include "bgui3d_algo.h"
00003 //:
00004 // \file
00005 
00006 #include <vnl/algo/vnl_qr.h>
00007 
00008 //: decompose the camera into internal and external params
00009 bool
00010 bgui3d_decompose_camera( const vnl_double_3x4& camera,
00011                          vnl_double_3x3& internal_calibration,
00012                          vnl_double_3x3& rotation,
00013                          vnl_double_3&   translation )
00014 {
00015   // camera = [H t]
00016   //
00017   vnl_double_3x3 PermH;
00018 
00019   for (int i = 0; i < 3; ++i)
00020     for (int j = 0; j < 3; ++j)
00021       PermH(i,j) = camera(2-j,2-i);
00022 
00023   vnl_qr<double> qr(PermH.as_ref());
00024 
00025   vnl_double_3x3 Q = qr.Q();
00026   vnl_double_3x3 R = qr.R();
00027 
00028   // Ensure all diagonal components of C are positive.
00029   // Must insert a det(+1) or det(-1) mx between.
00030   int r0pos = R(0,0) > 0 ? 1 : 0;
00031   int r1pos = R(1,1) > 0 ? 1 : 0;
00032   int r2pos = R(2,2) > 0 ? 1 : 0;
00033   typedef double d3[3];
00034   d3 diags[] = {   // 1 2 3
00035     { -1, -1, -1}, // - - -
00036     {  1, -1, -1}, // + - -
00037     { -1,  1, -1}, // - + -
00038     {  1,  1, -1}, // + + -
00039     { -1, -1,  1}, // - - +
00040     {  1, -1,  1}, // + - +
00041     { -1,  1,  1}, // - + +
00042     {  1,  1,  1}, // + + +
00043   };
00044   int d = r0pos * 4 + r1pos * 2 + r2pos;
00045   double* diag = &diags[d][0];
00046 
00047   for (int i = 0; i < 3; ++i)
00048     for (int j = 0; j < 3; ++j) {
00049       internal_calibration(j,i) = diag[i] * R(2-i,2-j);
00050       rotation(j,i) = diag[j] * Q(2-i,2-j);
00051     }
00052 
00053   // Compute t' = inv(C) t
00054   vnl_double_3 t;
00055   for (int i = 0; i < 3; ++i)
00056     t[i] = camera(i,3);
00057 
00058   t[2] /= internal_calibration(2,2);
00059   t[1] = (t[1] - internal_calibration(1,2)*t[2])/internal_calibration(1,1);
00060   t[0] = (t[0] - internal_calibration(0,1)*t[1] - internal_calibration(0,2)*t[2])/internal_calibration(0,0);
00061 
00062   translation = t;
00063 
00064   // Recompose the matrix and compare
00065   vnl_double_3x4 Po;
00066   Po.set_columns(0,rotation.as_ref());
00067   Po.set_column(3,translation);
00068   if (((internal_calibration * Po - camera).fro_norm() > 1e-4) ||
00069       (internal_calibration(0,0) < 0) ||
00070       (internal_calibration(1,1) < 0) ||
00071       (internal_calibration(2,2) < 0)) {
00072     return false;
00073   }
00074 
00075   // Scale the internal calibration matrix such that the bottom right is 1
00076   internal_calibration /= internal_calibration(2,2);
00077 
00078   return true;
00079 }