contrib/gel/mrc/vpgl/vpgl_radial_distortion.txx
Go to the documentation of this file.
00001 // This is gel/mrc/vpgl/vpgl_radial_distortion.txx
00002 #ifndef vpgl_radial_distortion_txx_
00003 #define vpgl_radial_distortion_txx_
00004 //:
00005 // \file
00006 
00007 #include "vpgl_radial_distortion.h"
00008 #include <vgl/vgl_homg_point_2d.h>
00009 #include <vgl/vgl_point_2d.h>
00010 
00011 #include <vcl_cmath.h>
00012 // not used? #include <vcl_iostream.h>
00013 #include <vcl_limits.h>
00014 
00015 //: Distort a projected point on the image plane
00016 //  Calls the pure virtual radial distortion function
00017 template <class T>
00018 vgl_homg_point_2d<T>
00019 vpgl_radial_distortion<T>::distort( const vgl_homg_point_2d<T>& point ) const
00020 {
00021   vgl_vector_2d<T> r = vgl_point_2d<T>(point) - center_;
00022   T scale = distort_radius(r.length());
00023   return vgl_homg_point_2d<T>(distorted_center_ + scale*r);
00024 }
00025 
00026 
00027 //: Return the original point that was distorted to this location (inverse of distort)
00028 // \param init is an initial guess at the solution for the iterative solver
00029 // if \p init is NULL then \p point is used as the initial guess
00030 // calls the radial undistortion function
00031 template <class T>
00032 vgl_homg_point_2d<T>
00033 vpgl_radial_distortion<T>::undistort( const vgl_homg_point_2d<T>& point,
00034                                        const vgl_homg_point_2d<T>* init ) const
00035 {
00036   vgl_vector_2d<T> r = vgl_point_2d<T>(point) - distorted_center_;
00037   T radius = r.length();
00038   T init_r = radius;
00039   if (init)
00040     init_r = (vgl_point_2d<T>(*init) - center_).length();
00041   T scale = undistort_radius(radius, &init_r);
00042   return vgl_homg_point_2d<T>(center_ + scale*r);
00043 }
00044 
00045 
00046 //: Return the inverse of the distort function
00047 // \param init is an initial guess at the solution for the iterative solver
00048 // if \p init is NULL then \p radius is used as the initial guess
00049 template <class T>
00050 T
00051 vpgl_radial_distortion<T>::undistort_radius( T radius, const T* init) const
00052 {
00053   if (radius == T(0))
00054     return T(1);
00055 
00056   T result = radius;
00057   if (init)
00058     result = *init;
00059 
00060   if (has_derivative_){
00061     // uses the Newton Method for root finding
00062     T e = vcl_numeric_limits<T>::infinity();
00063     T eps = vcl_numeric_limits<T>::epsilon();
00064     for (unsigned int i=0; i<100 && vcl_abs(e)>eps ; ++i){
00065       T f_result = distort_radius(result);
00066       e = radius - f_result*result;
00067       result += e/(distort_radius_deriv(result)*result + f_result);
00068     }
00069   }
00070   else{
00071     // uses the Newton Method with finite differences for root finding
00072     T e = vcl_numeric_limits<T>::infinity();
00073     T eps = vcl_numeric_limits<T>::epsilon();
00074     T df = T(0.001);
00075     for (unsigned int i=0; i<100 && vcl_abs(e)>eps ; ++i){
00076       T f_result = distort_radius(result);
00077       T f_result_df = distort_radius(result-df);
00078       e = radius - f_result*result;
00079       result += e/((f_result - f_result_df)*result/df + f_result);
00080     }
00081   }
00082 
00083   return result/radius;
00084 }
00085 
00086 // Code for easy instantiation.
00087 #undef vpgl_RADIAL_DISTORTION_INSTANTIATE
00088 #define vpgl_RADIAL_DISTORTION_INSTANTIATE(T) \
00089 template class vpgl_radial_distortion<T >
00090 
00091 #endif // vpgl_radial_distortion_txx_