vgl_h_matrix_3d_compute_affine.cxx
Go to the documentation of this file.
1 // This is core/vgl/algo/vgl_h_matrix_3d_compute_affine.cxx
2 #include <iostream>
3 #include <cmath>
4 #include <iomanip>
6 //:
7 // \file
8 
9 #include <cassert>
11 #include <vnl/algo/vnl_svd.h>
12 #ifdef _MSC_VER
13 # include <vcl_msvc_warnings.h>
14 #endif
15 
16 constexpr int TM_UNKNOWNS_COUNT = 9;
17 constexpr double DEGENERACY_THRESHOLD = 0.00001;
18 
19 
20 //: Compute a 3D-to-3D affine transformation without translation 3 x 3 matrix
21 // Note: requires all finite points.
22 // The algorithm finds the nullvector of the $3 n \times 9$ design matrix.
23 
24 //:Assumes all corresponding points have equal weight
27  std::vector<vgl_homg_point_3d<double> > const& p2,
28  vnl_matrix<double>& M)
29 {
30  int n = static_cast<int>(p1.size());
31  //fill the design matrix
32  vnl_matrix<double> D(n*3, TM_UNKNOWNS_COUNT, 0.0);
33  vnl_matrix<double> b(n*3, 1);
34 
35  int row = 0;
36  for (int i = 0; i < n; i++) {
37  vgl_homg_point_3d<double> hp1 = p1[i], hp2 = p2[i];
38  hp1.rescale_w(); hp2.rescale_w();
39  double X1 = hp1.x(), X2 = hp1.y(), X3 = hp1.z();
40  double x1 = hp2.x(), x2 = hp2.y(), x3 = hp2.z();
41 #if 0
42  std::cout << "X(" << X1 << ' ' << X2 << ' ' << X3 << '\n';
43  std::cout << "x(" << x1 << ' ' << x2 << ' ' << x3 << '\n';
44 #endif
45  D(row, 0) = X1; D(row, 1) = X2; D(row, 2) = X3; b(row,0) = x1;
46  D(row+1, 3) = X1; D(row+1, 4) = X2; D(row+1, 5) = X3; b(row+1,0) = x2;
47  D(row+2, 6) = X1; D(row+2, 7) = X2; D(row+2, 8) = X3; b(row+2,0) = x3;
48  row+=3;
49  }
50 #if 0
51  std::cout << '{';
52  for(int r = 0; r<(3*n); ++r){
53  std::cout << '{';
54  for(int c = 0; c<9; ++c)
55  std::cout << D[r][c] << ',';
56  std::cout << "},";
57  }
58  std::cout << '}';
59  std::cout << '{';
60  for(int r = 0; r<(3*n); ++r)
61  std::cout << b[r][0] << ',';
62  std::cout << "}\n";
63 #endif
64  vnl_svd<double> svd(D);
65  std::cout << svd.W() << '\n';
66  if (svd.W(8)<DEGENERACY_THRESHOLD*svd.W(7)) {
67  std::cerr << "vgl_h_matrix_3d_compute_linear : design matrix has rank < 9\n"
68  << "vgl_h_matrix_3d_compute_linear : probably due to degenerate point configuration\n";
69  return false;
70  }
71  M = svd.solve(b);
72  return true;
73 }
74 
76 compute_p(std::vector<vgl_homg_point_3d<double> > const& points1,
77  std::vector<vgl_homg_point_3d<double> > const& points2,
79 {
80  //number of points must be the same
81  assert(points1.size() == points2.size());
82  int n = static_cast<int>(points1.size());
83 
84  if (n * 3 < TM_UNKNOWNS_COUNT+3) {
85  std::cerr << "vgl_h_matrix_3d_compute_affine: Need at least 4 matches.\n";
86  if (n == 0) std::cerr << "Could be std::vector setlength idiosyncrasies!\n";
87  return false;
88  }
89  //compute the normalizing transforms
91  if (!tr1.compute_from_points(points1))
92  return false;
93  if (!tr2.compute_from_points(points2))
94  return false;
95  std::vector<vgl_homg_point_3d<double> > tpoints1, tpoints2;
96  for (int i = 0; i<n; i++)
97  {
98  tpoints1.push_back(tr1(points1[i]));
99  tpoints2.push_back(tr2(points2[i]));
100  }
101  vnl_matrix<double> M;
102  if (!solve_linear_problem(tpoints1,tpoints2,M))
103  return false;
104  // form the h_matrix
105  vnl_matrix_fixed<double, 4, 4> m;
106  m.fill(0.0);
107  m[0][0]=M[0][0]; m[0][1]=M[1][0]; m[0][2] = M[2][0];
108  m[1][0]=M[3][0]; m[1][1]=M[4][0]; m[1][2] = M[5][0];
109  m[2][0]=M[6][0]; m[2][1]=M[7][0]; m[2][2] = M[8][0];
110  m[3][3] = 1.0;
111 #if 0
112  for(unsigned r = 0; r<4; ++r)
113  std::cout << std::setprecision(2) << m[r][0] << ' ' << m[r][1] << ' '<< m[r][2] << ' '<< m[r][3] << '\n';
114  std::cout << '\n';
115 #endif
117  //
118  // Next, hh has to be transformed back to the coordinate system of
119  // the original point sets, i.e.,
120  // p1' = tr1 p1 , p2' = tr2 p2
121  // hh was determined from the transform relation
122  // p2' = hh p1', thus
123  // (tr2 p2) = hh (tr1 p1)
124  // p2 = (tr2^-1 hh tr1) p1 = H p1
125  vgl_h_matrix_3d<double> tr2_inv = tr2.get_inverse();
126  H = tr2_inv*hh*tr1;
127  return true;
128 }
vgl_h_matrix_3d get_inverse() const
Return the inverse homography.
bool rescale_w(Type new_w=Type(1))
constexpr double DEGENERACY_THRESHOLD
bool solve_linear_problem(std::vector< vgl_homg_point_3d< double > > const &p1, std::vector< vgl_homg_point_3d< double > > const &p2, vnl_matrix< double > &M)
Assumes all corresponding points have equal weight.
Represents a homogeneous 3D point.
Definition: vgl_fwd.h:9
contains class vgl_h_matrix_3d_compute_affine
bool compute_from_points(std::vector< vgl_homg_point_3d< T > > const &points)
compute the normalizing transform.
constexpr int TM_UNKNOWNS_COUNT
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.
The similarity transform that normalizes a 3-d point set.