00001
00002 #include "vgl_h_matrix_3d_compute_linear.h"
00003
00004
00005
00006 #include <vcl_iostream.h>
00007 #include <vcl_cmath.h>
00008 #include <vcl_cassert.h>
00009 #include <vgl/algo/vgl_norm_trans_3d.h>
00010 #include <vnl/algo/vnl_svd.h>
00011
00012 const int TM_UNKNOWNS_COUNT = 16;
00013 const double DEGENERACY_THRESHOLD = 0.00001;
00014
00015
00016
00017
00018
00019
00020
00021
00022 bool vgl_h_matrix_3d_compute_linear::
00023 solve_linear_problem(vcl_vector<vgl_homg_point_3d<double> > const& p1,
00024 vcl_vector<vgl_homg_point_3d<double> > const& p2,
00025 vgl_h_matrix_3d<double>& H)
00026 {
00027 int n = p1.size();
00028
00029 vnl_matrix<double> D(n*6, TM_UNKNOWNS_COUNT);
00030
00031 int row = 0;
00032 for (int i = 0; i < n; i++) {
00033
00034
00035 double x1 = p2[i].x(), x2 = p2[i].y(), x3 = p2[i].z(), x4 = p2[i].w();
00036 double y1 = p1[i].x(), y2 = p1[i].y(), y3 = p1[i].z(), y4 = p1[i].w();
00037
00038 D(row, 0) = -x2*y1; D(row, 1) = x1*y1; D(row, 2) = 0; D(row, 3) = 0;
00039 D(row, 4) = -x2*y2; D(row, 5) = x1*y2; D(row, 6) = 0; D(row, 7) = 0;
00040 D(row, 8) = -x2*y3; D(row, 9) = x1*y3; D(row, 10) = 0; D(row, 11) = 0;
00041 D(row, 12) = -x2*y4; D(row, 13) = x1*y4; D(row, 14) = 0; D(row, 15) = 0;
00042 ++row;
00043 D(row, 0) = -x3*y1; D(row, 1) = 0; D(row, 2) = x1*y1; D(row, 3) = 0;
00044 D(row, 4) = -x3*y2; D(row, 5) = 0; D(row, 6) = x1*y2; D(row, 7) = 0;
00045 D(row, 8) = -x3*y3; D(row, 9) = 0; D(row, 10) = x1*y3; D(row, 11) = 0;
00046 D(row, 12) = -x3*y4; D(row, 13) = 0; D(row, 14) = x1*y4; D(row, 15) = 0;
00047 ++row;
00048 D(row, 0) = -x4*y1; D(row, 1) = 0; D(row, 2) = 0; D(row, 3) = x1*y1;
00049 D(row, 4) = -x4*y2; D(row, 5) = 0; D(row, 6) = 0; D(row, 7) = x1*y2;
00050 D(row, 8) = -x4*y3; D(row, 9) = 0; D(row, 10) = 0; D(row, 11) = x1*y3;
00051 D(row, 12) = -x4*y4; D(row, 13) = 0; D(row, 14) = 0; D(row, 15) = x1*y4;
00052 ++row;
00053 D(row, 0) = 0; D(row, 1) = -x4*y1; D(row, 2) = 0; D(row, 3) = x2*y1;
00054 D(row, 4) = 0; D(row, 5) = -x4*y2; D(row, 6) = 0; D(row, 7) = x2*y2;
00055 D(row, 8) = 0; D(row, 9) = -x4*y3; D(row, 10) = 0; D(row, 11) = x2*y3;
00056 D(row, 12) = 0; D(row, 13) = -x4*y4; D(row, 14) = 0; D(row, 15) = x2*y4;
00057 ++row;
00058 D(row, 0) = 0; D(row, 1) = 0; D(row, 2) = -x4*y1; D(row, 3) = x3*y1;
00059 D(row, 4) = 0; D(row, 5) = 0; D(row, 6) = -x4*y2; D(row, 7) = x3*y2;
00060 D(row, 8) = 0; D(row, 9) = 0; D(row, 10) = -x4*y3; D(row, 11) = x3*y3;
00061 D(row, 12) = 0; D(row, 13) = 0; D(row, 14) = -x4*y4; D(row, 15) = x3*y4;
00062 ++row;
00063 D(row, 0) = 0; D(row, 1) = -x3*y1; D(row, 2) = x2*y1; D(row, 3) = 0;
00064 D(row, 4) = 0; D(row, 5) = -x3*y2; D(row, 6) = x2*y2; D(row, 7) = 0;
00065 D(row, 8) = 0; D(row, 9) = -x3*y3; D(row, 10) = x2*y3; D(row, 11) = 0;
00066 D(row, 12) = 0; D(row, 13) = -x3*y4; D(row, 14) = x2*y4; D(row, 15) = 0;
00067 ++row;
00068 }
00069
00070 D.normalize_rows();
00071 vnl_svd<double> svd(D);
00072
00073
00074
00075
00076 if (svd.W(15)<DEGENERACY_THRESHOLD*svd.W(16)) {
00077 vcl_cerr << "vgl_h_matrix_3d_compute_linear : design matrix has rank < 16\n"
00078 << "vgl_h_matrix_3d_compute_linear : probably due to degenerate point configuration\n";
00079 return false;
00080 }
00081
00082 H.set(svd.nullvector().data_block());
00083 return true;
00084 }
00085
00086 bool vgl_h_matrix_3d_compute_linear::
00087 compute_p(vcl_vector<vgl_homg_point_3d<double> > const& points1,
00088 vcl_vector<vgl_homg_point_3d<double> > const& points2,
00089 vgl_h_matrix_3d<double>& H)
00090 {
00091
00092 assert(points1.size() == points2.size());
00093 int n = points1.size();
00094
00095 if (n * 3 < TM_UNKNOWNS_COUNT - 1) {
00096 vcl_cerr << "vgl_h_matrix_3d_compute_linear: Need at least 5 matches.\n";
00097 if (n == 0) vcl_cerr << "Could be vcl_vector setlength idiosyncrasies!\n";
00098 return false;
00099 }
00100
00101
00102 vgl_norm_trans_3d<double> tr1, tr2;
00103 if (!tr1.compute_from_points(points1))
00104 return false;
00105 if (!tr2.compute_from_points(points2))
00106 return false;
00107 vcl_vector<vgl_homg_point_3d<double> > tpoints1, tpoints2;
00108 for (int i = 0; i<n; i++)
00109 {
00110 tpoints1.push_back(tr1(points1[i]));
00111 tpoints2.push_back(tr2(points2[i]));
00112 }
00113 vgl_h_matrix_3d<double> hh(tpoints1, tpoints2);
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 vgl_h_matrix_3d<double> tr2_inv = tr2.get_inverse();
00127 H = tr2_inv*hh*tr1;
00128 return true;
00129 }
00130
00131
00132