00001
00002 #include "bgui3d_algo.h"
00003
00004
00005
00006 #include <vnl/algo/vnl_qr.h>
00007
00008
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
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
00029
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[] = {
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
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
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
00076 internal_calibration /= internal_calibration(2,2);
00077
00078 return true;
00079 }