vpgl_radial_distortion.hxx
Go to the documentation of this file.
1 // This is core/vpgl/vpgl_radial_distortion.hxx
2 #ifndef vpgl_radial_distortion_hxx_
3 #define vpgl_radial_distortion_hxx_
4 //:
5 // \file
6 
7 #include <cmath>
8 #include <limits>
10 #include <vgl/vgl_homg_point_2d.h>
11 #include <vgl/vgl_point_2d.h>
12 
13 #ifdef _MSC_VER
14 # include <vcl_msvc_warnings.h>
15 #endif
16 
17 //: Distort a projected point on the image plane
18 // Calls the pure virtual radial distortion function
19 template <class T>
22 {
23  vgl_vector_2d<T> r = vgl_point_2d<T>(point) - center_;
24  T scale = distort_radius(r.length());
25  return vgl_homg_point_2d<T>(distorted_center_ + scale*r);
26 }
27 
28 
29 //: Return the original point that was distorted to this location (inverse of distort)
30 // \param init is an initial guess at the solution for the iterative solver
31 // if \p init is NULL then \p point is used as the initial guess
32 // calls the radial undistortion function
33 template <class T>
36  const vgl_homg_point_2d<T>* init ) const
37 {
38  vgl_vector_2d<T> r = vgl_point_2d<T>(point) - distorted_center_;
39  T radius = r.length();
40  T init_r = radius;
41  if (init)
42  init_r = (vgl_point_2d<T>(*init) - center_).length();
43  T scale = undistort_radius(radius, &init_r);
44  return vgl_homg_point_2d<T>(center_ + scale*r);
45 }
46 
47 
48 //: Return the inverse of the distort function
49 // \param init is an initial guess at the solution for the iterative solver
50 // if \p init is NULL then \p radius is used as the initial guess
51 template <class T>
52 T
53 vpgl_radial_distortion<T>::undistort_radius( T radius, const T* init) const
54 {
55  if (radius == T(0))
56  return T(1);
57 
58  T result = radius;
59  if (init)
60  result = *init;
61 
62  if (has_derivative_){
63  // uses the Newton Method for root finding
64  T e = std::numeric_limits<T>::infinity();
65  T eps = std::numeric_limits<T>::epsilon();
66  for (unsigned int i=0; i<100 && std::abs(e)>eps ; ++i){
67  T f_result = distort_radius(result);
68  e = radius - f_result*result;
69  result += e/(distort_radius_deriv(result)*result + f_result);
70  }
71  }
72  else{
73  // uses the Newton Method with finite differences for root finding
74  T e = std::numeric_limits<T>::infinity();
75  T eps = std::numeric_limits<T>::epsilon();
76  T df = T(0.001);
77  for (unsigned int i=0; i<100 && std::abs(e)>eps ; ++i){
78  T f_result = distort_radius(result);
79  T f_result_df = distort_radius(result-df);
80  e = radius - f_result*result;
81  result += e/((f_result - f_result_df)*result/df + f_result);
82  }
83  }
84 
85  return result/radius;
86 }
87 
88 // Code for easy instantiation.
89 #undef vpgl_RADIAL_DISTORTION_INSTANTIATE
90 #define vpgl_RADIAL_DISTORTION_INSTANTIATE(T) \
91 template class vpgl_radial_distortion<T >
92 
93 #endif // vpgl_radial_distortion_hxx_
vgl_homg_point_2d< T > distort(const vgl_homg_point_2d< T > &point) const override
Distort a projected point on the image plane.
vgl_homg_point_2d< T > undistort(const vgl_homg_point_2d< T > &point, const vgl_homg_point_2d< T > *init=nullptr) const override
Return the original point that was distorted to this location (inverse of distort).
double length() const
virtual T undistort_radius(T radius, const T *init=nullptr) const
Return the inverse of distort function.
An abstract base class for radial lens distortions.
double length(v const &a)