vgl_h_matrix_3d_compute_linear.cxx
Go to the documentation of this file.
1 // This is core/vgl/algo/vgl_h_matrix_3d_compute_linear.cxx
2 #include <iostream>
3 #include <cmath>
5 //:
6 // \file
7 
8 #ifdef _MSC_VER
9 # include <vcl_msvc_warnings.h>
10 #endif
11 #include <cassert>
13 #include <vnl/algo/vnl_svd.h>
14 
15 constexpr int TM_UNKNOWNS_COUNT = 16;
16 constexpr double DEGENERACY_THRESHOLD = 0.00001;
17 
18 
19 //: Compute a 3D-to-3D homography using linear least squares.
20 // Returns false if the calculation fails or there are fewer than five point
21 // matches in the list. The algorithm finds the nullvector of the $6 n \times 16$ design
22 // matrix:
23 
24 //:Assumes all corresponding points have equal weight
27  std::vector<vgl_homg_point_3d<double> > const& p2,
29 {
30  int n = p1.size();
31  //transform the point sets and fill the design matrix
32  vnl_matrix<double> D(n*6, TM_UNKNOWNS_COUNT);
33 
34  int row = 0;
35  for (int i = 0; i < n; i++) {
36  //double x1 = p1[i].x(), x2 = p1[i].y(), x3 = p1[i].z(), x4 = p1[i].w();
37  //double y1 = p2[i].x(), y2 = p2[i].y(), y3 = p2[i].z(), y4 = p2[i].w();
38  double x1 = p2[i].x(), x2 = p2[i].y(), x3 = p2[i].z(), x4 = p2[i].w();
39  double y1 = p1[i].x(), y2 = p1[i].y(), y3 = p1[i].z(), y4 = p1[i].w();
40 
41  D(row, 0) = -x2*y1; D(row, 1) = x1*y1; D(row, 2) = 0; D(row, 3) = 0;
42  D(row, 4) = -x2*y2; D(row, 5) = x1*y2; D(row, 6) = 0; D(row, 7) = 0;
43  D(row, 8) = -x2*y3; D(row, 9) = x1*y3; D(row, 10) = 0; D(row, 11) = 0;
44  D(row, 12) = -x2*y4; D(row, 13) = x1*y4; D(row, 14) = 0; D(row, 15) = 0;
45  ++row;
46  D(row, 0) = -x3*y1; D(row, 1) = 0; D(row, 2) = x1*y1; D(row, 3) = 0;
47  D(row, 4) = -x3*y2; D(row, 5) = 0; D(row, 6) = x1*y2; D(row, 7) = 0;
48  D(row, 8) = -x3*y3; D(row, 9) = 0; D(row, 10) = x1*y3; D(row, 11) = 0;
49  D(row, 12) = -x3*y4; D(row, 13) = 0; D(row, 14) = x1*y4; D(row, 15) = 0;
50  ++row;
51  D(row, 0) = -x4*y1; D(row, 1) = 0; D(row, 2) = 0; D(row, 3) = x1*y1;
52  D(row, 4) = -x4*y2; D(row, 5) = 0; D(row, 6) = 0; D(row, 7) = x1*y2;
53  D(row, 8) = -x4*y3; D(row, 9) = 0; D(row, 10) = 0; D(row, 11) = x1*y3;
54  D(row, 12) = -x4*y4; D(row, 13) = 0; D(row, 14) = 0; D(row, 15) = x1*y4;
55  ++row;
56  D(row, 0) = 0; D(row, 1) = -x4*y1; D(row, 2) = 0; D(row, 3) = x2*y1;
57  D(row, 4) = 0; D(row, 5) = -x4*y2; D(row, 6) = 0; D(row, 7) = x2*y2;
58  D(row, 8) = 0; D(row, 9) = -x4*y3; D(row, 10) = 0; D(row, 11) = x2*y3;
59  D(row, 12) = 0; D(row, 13) = -x4*y4; D(row, 14) = 0; D(row, 15) = x2*y4;
60  ++row;
61  D(row, 0) = 0; D(row, 1) = 0; D(row, 2) = -x4*y1; D(row, 3) = x3*y1;
62  D(row, 4) = 0; D(row, 5) = 0; D(row, 6) = -x4*y2; D(row, 7) = x3*y2;
63  D(row, 8) = 0; D(row, 9) = 0; D(row, 10) = -x4*y3; D(row, 11) = x3*y3;
64  D(row, 12) = 0; D(row, 13) = 0; D(row, 14) = -x4*y4; D(row, 15) = x3*y4;
65  ++row;
66  D(row, 0) = 0; D(row, 1) = -x3*y1; D(row, 2) = x2*y1; D(row, 3) = 0;
67  D(row, 4) = 0; D(row, 5) = -x3*y2; D(row, 6) = x2*y2; D(row, 7) = 0;
68  D(row, 8) = 0; D(row, 9) = -x3*y3; D(row, 10) = x2*y3; D(row, 11) = 0;
69  D(row, 12) = 0; D(row, 13) = -x3*y4; D(row, 14) = x2*y4; D(row, 15) = 0;
70  ++row;
71  }
72 
73  D.normalize_rows();
74  vnl_svd<double> svd(D);
75 
76  //
77  // FSM added :
78  //
79  if (svd.W(15)<DEGENERACY_THRESHOLD*svd.W(16)) {
80  std::cerr << "vgl_h_matrix_3d_compute_linear : design matrix has rank < 16\n"
81  << "vgl_h_matrix_3d_compute_linear : probably due to degenerate point configuration\n";
82  return false;
83  }
84  // form the matrix from the nullvector
85  H.set(svd.nullvector().data_block());
86  return true;
87 }
88 
90 compute_p(std::vector<vgl_homg_point_3d<double> > const& points1,
91  std::vector<vgl_homg_point_3d<double> > const& points2,
93 {
94  //number of points must be the same
95  assert(points1.size() == points2.size());
96  int n = points1.size();
97 
98  if (n * 3 < TM_UNKNOWNS_COUNT - 1) {
99  std::cerr << "vgl_h_matrix_3d_compute_linear: Need at least 5 matches.\n";
100  if (n == 0) std::cerr << "Could be std::vector setlength idiosyncrasies!\n";
101  return false;
102  }
103 
104  //compute the normalizing transforms
105  vgl_norm_trans_3d<double> tr1, tr2;
106  if (!tr1.compute_from_points(points1))
107  return false;
108  if (!tr2.compute_from_points(points2))
109  return false;
110  std::vector<vgl_homg_point_3d<double> > tpoints1, tpoints2;
111  for (int i = 0; i<n; i++)
112  {
113  tpoints1.push_back(tr1(points1[i]));
114  tpoints2.push_back(tr2(points2[i]));
115  }
116  vgl_h_matrix_3d<double> hh(tpoints1, tpoints2);
117  //vgl_h_matrix_3d<double> hh;
118  //if (!solve_linear_problem(tpoints1,tpoints2,hh))
119  //return false;
120 
121  //
122  // Next, hh has to be transformed back to the coordinate system of
123  // the original point sets, i.e.,
124  // p1' = tr1 p1 , p2' = tr2 p2
125  // hh was determined from the transform relation
126  // p2' = hh p1', thus
127  // (tr2 p2) = hh (tr1 p1)
128  // p2 = (tr2^-1 hh tr1) p1 = H p1
129  vgl_h_matrix_3d<double> tr2_inv = tr2.get_inverse();
130  H = tr2_inv*hh*tr1;
131  return true;
132 }
vgl_h_matrix_3d get_inverse() const
Return the inverse homography.
vgl_h_matrix_3d & set(unsigned int row_index, unsigned int col_index, T value)
Set an element of the 4x4 homography matrix.
Represents a homogeneous 3D point.
Definition: vgl_fwd.h:9
constexpr int TM_UNKNOWNS_COUNT
bool solve_linear_problem(std::vector< vgl_homg_point_3d< double > > const &p1, std::vector< vgl_homg_point_3d< double > > const &p2, vgl_h_matrix_3d< double > &H)
Assumes all corresponding points have equal weight.
bool compute_from_points(std::vector< vgl_homg_point_3d< T > > const &points)
compute the normalizing transform.
A class to hold a 3-d projective transformation matrix and to perform common operations using it e....
Definition: vgl_algo_fwd.h:12
bool compute_p(std::vector< vgl_homg_point_3d< double > > const &points1, std::vector< vgl_homg_point_3d< double > > const &points2, vgl_h_matrix_3d< double > &H) override
compute from matched points.
contains class vgl_h_matrix_3d_compute_linear
constexpr double DEGENERACY_THRESHOLD
The similarity transform that normalizes a 3-d point set.