vpgl_ray_intersect.hxx
Go to the documentation of this file.
1 // This is core/vpgl/algo/vpgl_ray_intersect.hxx
2 #ifndef vpgl_ray_intersect_hxx_
3 #define vpgl_ray_intersect_hxx_
4 
5 #include <iostream>
6 #include <utility>
7 #include "vpgl_ray_intersect.h"
8 //:
9 // \file
12 #include <vnl/vnl_numeric_traits.h>
13 #include <vnl/vnl_vector.h>
14 #include <vnl/vnl_double_3.h>
15 #ifdef _MSC_VER
16 # include <vcl_msvc_warnings.h>
17 #endif
18 #include <vpgl/vpgl_camera.h>
19 
20 template<typename T>
22 {
23 public:
24  //: Constructor
25  vpgl_ray_intersect_lsqr(std::vector<const vpgl_camera<T>* > cams,
26  std::vector<vgl_point_2d<T> > image_pts,
27  unsigned num_residuals);
28 
29  //: Destructor
30  ~vpgl_ray_intersect_lsqr() override = default;
31 
32  //: The main function.
33  // Given the parameter vector x, compute the vector of residuals fx.
34  // fx has been sized appropriately before the call.
35  void f(vnl_vector<double> const& intersection_point,
36  vnl_vector<double>& image_errors) override;
37 
38 #if 0
39  //: Called after each LM iteration to print debugging etc.
40  virtual void trace(int iteration, vnl_vector<double> const& x, vnl_vector<double> const& fx);
41 #endif
42 
43 protected:
44  vpgl_ray_intersect_lsqr();//not valid
45  std::vector<const vpgl_camera<T>* > f_cameras_; //cameras
46  std::vector<vgl_point_2d<T> > f_image_pts_; //image points
47 };
48 
49 template<typename T>
51 vpgl_ray_intersect_lsqr(std::vector<const vpgl_camera<T>* > cams,
52  std::vector<vgl_point_2d<T> > image_pts,
53  unsigned num_residuals) :
54 vnl_least_squares_function(3, num_residuals,
55  vnl_least_squares_function::no_gradient ),
56 f_cameras_(std::move(cams)),
57 f_image_pts_(std::move(image_pts))
58 {}
59 
60 // Define virtual function for the LeastSquaresFunction class. Given
61 // a conjectured point (intersection_vert) in space, this determines the
62 // error vector formed by appending all <u - conjecture_u, v - conjecture_v>
63 // error tuples for each image. Here <u, v> is the actual image point, and
64 // <conjecture_u, conjecture_v> is the point corresponding to intersection_vert.
65 template<typename T>
66 void vpgl_ray_intersect_lsqr<T>::f(vnl_vector<double> const& intersection_point,
67  vnl_vector<double>& image_errors)
68 {
69  // Get the size of the error vector
70  std::size_t dim = static_cast<unsigned int>(image_errors.size() / 2);
71 
72  // Initialize huge error
74  for (unsigned i=0; i<image_errors.size(); i++)
75  image_errors.put(i, huge);
76 
77  // Compute the error in each image
78  double intersection_point_x = intersection_point[0];
79  double intersection_point_y = intersection_point[1];
80  double intersection_point_z = intersection_point[2];
81 #ifdef RAY_INT_DEBUG
82  std::cout << "Error Vector (" << intersection_point_x << ", "
83  << intersection_point_y << ", " << intersection_point_z << ") = ";
84 #endif
85 
86  for (unsigned image_no = 0; image_no < dim; image_no++)
87  {
88  // Get this camera and corresponding image point
89  const vpgl_camera<T>* cam = f_cameras_[image_no];
90  double image_u = f_image_pts_[image_no].x(),
91  image_v = f_image_pts_[image_no].y();
92  // Compute the image of the intersection vert through this camera
93  T cur_image_u, cur_image_v;
94  cam->project(intersection_point_x, intersection_point_y,
95  intersection_point_z, cur_image_u, cur_image_v);
96  // Compute and store the error with respect to actual image
97  image_errors.put(2*image_no,
98  (cur_image_u - image_u));
99  image_errors.put(2*image_no+1,
100  (cur_image_v - image_v));
101 #ifdef RAY_INT_DEBUG
102  std::cout << " x_err = " << cur_image_u << '-' << image_u << '='
103  << image_errors[2*image_no]
104  << " y_err = " << cur_image_v << '-' << image_v << '='
105  << image_errors[2*image_no+1];
106 #endif
107 
108 
109 #ifdef RAY_INT_DEBUG
110  std::cout << '\n';
111 #endif
112  }
113 }
114 
115 // Constructor.
116 template<typename T>
118 {}
119 
120 // A function to get the point closest to the rays coming out of image_pts
121 // in images, whose cameras (cams) are known. Point is stored in intersection.
122 // Returns true if successful, else false
123 template<typename T>
125 intersect(std::vector<const vpgl_camera<T>* > const& cams,
126  std::vector<vgl_point_2d<T> > const& image_pts,
127  vgl_point_3d<T> const& initial_intersection,
128  vgl_point_3d<T>& intersection)
129 {
130  // Make sure the dimension is at least 2
131  if (dim_ < 2)
132  {
133  std::cerr << "The dimension is too small. There must be at least 2 images"
134  << '\n';
135  return false;
136  }
137 
138  // Make sure there are correct number of cameras
139  if (cams.size() != dim_)
140  {
141  std::cerr << "Please provide correct number of cameras" << '\n';
142  return false;
143  }
144 
145  // Make sure there are correct number of image points
146  if (image_pts.size() != dim_)
147  {
148  std::cerr << "Please provide correct number of image points" << '\n';
149  return false;
150  }
151 
152  // cache the image points and camera points
153  f_cameras_ = cams;
154  f_image_pts_ = image_pts;
155 
156  // Create the Levenberg Marquardt minimizer
157  vpgl_ray_intersect_lsqr<T> lqf(cams, image_pts, 2*dim_);
158  vnl_levenberg_marquardt levmarq(lqf);
159 #ifdef RAY_INT_DEBUG
160  std::cout << "Created LevenbergMarquardt minimizer ... setting tolerances\n";
161  levmarq.set_verbose(true);
162 #endif
163  // Set the x-tolerance. When the length of the steps taken in X (variables)
164  // are no longer than this, the minimization terminates.
165  levmarq.set_x_tolerance(1e-10);
166 
167  // Set the epsilon-function. This is the step length for FD Jacobian.
168  levmarq.set_epsilon_function(1.0);
169 
170  // Set the f-tolerance. When the successive RMS errors are less than this,
171  // minimization terminates.
172  levmarq.set_f_tolerance(1e-10);
173 
174  // Set the maximum number of iterations
175  levmarq.set_max_function_evals(10000);
176  vnl_double_3 intersection_pt;
177  intersection_pt[0]=initial_intersection.x();
178  intersection_pt[1]=initial_intersection.y();
179  intersection_pt[2]=initial_intersection.z();
180 
181 #ifdef RAY_INT_DEBUG
182  std::cout << "Initialized the intersection point " << intersection_pt
183  << " ... minimizing\n";
184 #endif
185 
186  // Minimize the error and get the best intersection point
187  levmarq.minimize(intersection_pt);
188 
189  // Summarize the results
190 #ifdef RAY_INT_DEBUG
191  std::cout << "Min error of " << levmarq.get_end_error() << " at "
192  << '(' << intersection_pt[0] << ", " << intersection_pt[1]
193  << ", " << intersection_pt[2] << ")\n"
194  << "Iterations: " << levmarq.get_num_iterations() << " "
195  << "Evaluations: " << levmarq.get_num_evaluations() << '\n';
196  levmarq.diagnose_outcome();
197 #endif
198  // Assign the intersection
199  intersection.set(intersection_pt[0],
200  intersection_pt[1],
201  intersection_pt[2]);
202  // Return success
203  return true;
204 }
205 
206 #define VPGL_RAY_INTERSECT_INSTANTIATE(T) \
207 template class vpgl_ray_intersect<T >;
208 
209 
210 #endif // vpgl_ray_intersect_hxx_
void set_f_tolerance(double v)
vgl_homg_point_3d< Type > intersection(l const &l1, l const &l2)
int get_num_iterations() const
bool intersect(std::vector< const vpgl_camera< T > * > const &cams, std::vector< vgl_point_2d< T > > const &image_pts, vgl_point_3d< T > const &initial_intersection, vgl_point_3d< T > &intersection)
Intersect the rays. return false if intersection fails.
double get_end_error() const
int get_num_evaluations() const
size_t size() const
void set_verbose(bool verb)
void f(vnl_vector< double > const &intersection_point, vnl_vector< double > &image_errors) override
The main function.
virtual void trace(int iteration, vnl_vector< double > const &x, vnl_vector< double > const &fx)
void set_max_function_evals(int v)
void put(size_t i, double const &v)
A general camera class.
vpgl_ray_intersect(unsigned dim)
Find the 3-d point closest to the intersection of rays from >= 2 cameras.
std::vector< vgl_point_2d< T > > f_image_pts_
void set_epsilon_function(double v)
virtual void project(const T x, const T y, const T z, T &u, T &v) const =0
The generic camera interface. u represents image column, v image row.
void diagnose_outcome() const
std::vector< const vpgl_camera< T > * > f_cameras_
bool minimize(vnl_vector< double > &x)
~vpgl_ray_intersect_lsqr() override=default
Destructor.
void set_x_tolerance(double v)