contrib/gel/mrc/vpgl/algo/vpgl_lens_warp_mapper.h
Go to the documentation of this file.
00001 // This is gel/mrc/vpgl/algo/vpgl_lens_warp_mapper.h
00002 #ifndef vpgl_lens_warp_mapper_h_
00003 #define vpgl_lens_warp_mapper_h_
00004 //:
00005 // \file
00006 // \brief A lens distortion adaptor for vil_warp
00007 // \author Matt Leotta
00008 // \date August 22, 2005
00009 
00010 #include <vpgl/vpgl_lens_distortion.h>
00011 #include <vil/vil_image_view.h>
00012 #include <vgl/vgl_point_2d.h>
00013 #include <vgl/vgl_vector_2d.h>
00014 #include <vgl/vgl_box_2d.h>
00015 #include <vgl/vgl_homg_point_2d.h>
00016 #include <vcl_cassert.h>
00017 
00018 //: Compute a bounding box in the distorted space for an existing box
00019 // This is computed by sampling alone the box boundary edges
00020 // \note in general this is not the inverse of vpgl_lens_unwarp_bounds
00021 template <class DataT, class BoxT>
00022 vgl_box_2d<BoxT>
00023 vpgl_lens_warp_bounds(const vpgl_lens_distortion<DataT>& lens,
00024                       const vgl_box_2d<BoxT>& box,
00025                       BoxT step_size = BoxT(1))
00026 {
00027   vgl_box_2d<BoxT> new_box;
00028   for (BoxT x=box.min_x(); x<=box.max_x(); x+=step_size){
00029     vgl_point_2d<DataT> p1(lens.distort(vgl_homg_point_2d<DataT>(x,box.min_y())));
00030     new_box.add(vgl_point_2d<BoxT>( BoxT(p1.x()), BoxT(p1.y()) ));
00031     vgl_point_2d<DataT> p2(lens.distort(vgl_homg_point_2d<DataT>(x,box.max_y())));
00032     new_box.add(vgl_point_2d<BoxT>( BoxT(p2.x()), BoxT(p2.y()) ));
00033   }
00034   for (BoxT y=box.min_y(); y<=box.max_y(); y+=step_size){
00035     vgl_point_2d<DataT> p1(lens.distort(vgl_homg_point_2d<DataT>(box.min_x(),y)));
00036     new_box.add(vgl_point_2d<BoxT>( BoxT(p1.x()), BoxT(p1.y()) ));
00037     vgl_point_2d<DataT> p2(lens.distort(vgl_homg_point_2d<DataT>(box.max_x(),y)));
00038     new_box.add(vgl_point_2d<BoxT>( BoxT(p2.x()), BoxT(p2.y()) ));;
00039   }
00040   return new_box;
00041 }
00042 
00043 //: Compute a bounding box for an existing box in the distorted space
00044 // This is computed by sampling alone the box boundary edges
00045 // \note in general this is not the inverse of vpgl_lens_warp_bounds
00046 template <class DataT, class BoxT>
00047 vgl_box_2d<BoxT>
00048 vpgl_lens_unwarp_bounds(const vpgl_lens_distortion<DataT>& lens,
00049                         const vgl_box_2d<BoxT>& box,
00050                         BoxT step_size = BoxT(1))
00051 {
00052   vgl_box_2d<BoxT> new_box;
00053   for (BoxT x=box.min_x(); x<=box.max_x(); x+=step_size){
00054     vgl_point_2d<DataT> p1(lens.undistort(vgl_homg_point_2d<DataT>(x,box.min_y())));
00055     new_box.add(vgl_point_2d<BoxT>( BoxT(p1.x()), BoxT(p1.y()) ));
00056     vgl_point_2d<DataT> p2(lens.undistort(vgl_homg_point_2d<DataT>(x,box.max_y())));
00057     new_box.add(vgl_point_2d<BoxT>( BoxT(p2.x()), BoxT(p2.y()) ));
00058   }
00059   for (BoxT y=box.min_y(); y<=box.max_y(); y+=step_size){
00060     vgl_point_2d<DataT> p1(lens.undistort(vgl_homg_point_2d<DataT>(box.min_x(),y)));
00061     new_box.add(vgl_point_2d<BoxT>( BoxT(p1.x()), BoxT(p1.y()) ));
00062     vgl_point_2d<DataT> p2(lens.undistort(vgl_homg_point_2d<DataT>(box.max_x(),y)));
00063     new_box.add(vgl_point_2d<BoxT>( BoxT(p2.x()), BoxT(p2.y()) ));;
00064   }
00065   return new_box;
00066 }
00067 
00068 
00069 //: A warping function to apply lens distortion to an image
00070 // This function automatically sets the translation of the distortion function
00071 // and computes the appropriate image size such that all distorted pixel
00072 // lie in the resulting image
00073 template <class sType, class dType, class T, class InterpFunctor>
00074 vil_image_view<dType>
00075 vpgl_lens_warp_resize(const vil_image_view<sType>& in,
00076                       dType /*out_dummy*/,
00077                       vpgl_lens_distortion<T>& ld,
00078                       InterpFunctor interp)
00079 {
00080   vgl_box_2d<int> bounds = vpgl_lens_warp_bounds(ld, vgl_box_2d<int>(0,in.ni(),0,in.nj()));
00081   vgl_vector_2d<T> offset(T(-bounds.min_x()), T(-bounds.min_y()));
00082   ld.set_translation( offset, true );
00083   vil_image_view<dType> out(bounds.width(), bounds.height(), in.nplanes());
00084   vpgl_lens_warp(in, out, ld, interp);
00085   return out;
00086 }
00087 
00088 
00089 //: A version of vil_warp specialized for lens warping with iterative undistort
00090 // The algorithm uses the result at the previous pixel as an initial guess
00091 // which should reduce iterations until convergence
00092 template <class sType, class dType, class T, class InterpFunctor>
00093 void vpgl_lens_warp(const vil_image_view<sType>& in,
00094                     vil_image_view<dType>& out,
00095                     const vpgl_lens_distortion<T>& ld,
00096                     InterpFunctor interp)
00097 {
00098   unsigned const out_w = out.ni();
00099   unsigned const out_h = out.nj();
00100 
00101   assert(out.nplanes() == in.nplanes());
00102 
00103   vgl_homg_point_2d<T> init(T(0),T(0));
00104   for (unsigned oy = 0; oy < out_h; ++oy)
00105   {
00106     vgl_homg_point_2d<T> unwarp_pt = init;
00107     for (unsigned ox = 0; ox < out_w; ++ox)
00108     {
00109       // *** Find (ix, iy) from (ox,oy)
00110       double ix, iy;
00111       unwarp_pt = ld.undistort(vgl_homg_point_2d<T>(ox,oy),&unwarp_pt);
00112       if (oy == 0) init = unwarp_pt;
00113       ix = unwarp_pt.x()/unwarp_pt.w();
00114       iy = unwarp_pt.y()/unwarp_pt.w();
00115       for (unsigned p = 0; p < out.nplanes(); ++p)
00116       {
00117         out(ox, oy, p) = dType(interp(in, ix, iy, p));
00118       }
00119     }
00120   }
00121 }
00122 
00123 
00124 //: A warping function to apply lens distortion to an image
00125 // This function automatically sets the translation of the distortion function
00126 // and computes the appropriate image size such that all distorted pixel
00127 // lie in the resulting image
00128 template <class sType, class dType, class T, class InterpFunctor>
00129 vil_image_view<dType>
00130 vpgl_lens_unwarp_resize(const vil_image_view<sType>& in,
00131                         dType /*out_dummy*/,
00132                         vpgl_lens_distortion<T>& ld,
00133                         InterpFunctor interp)
00134 {
00135   vgl_box_2d<int> bounds = vpgl_lens_unwarp_bounds(ld, vgl_box_2d<int>(0,in.ni(),0,in.nj()));
00136   vgl_vector_2d<T> offset(T(-bounds.min_x()), T(-bounds.min_y()));
00137   ld.set_translation( offset, false );
00138   vil_image_view<dType> out(bounds.width(), bounds.height(), in.nplanes());
00139   vpgl_lens_unwarp(in, out, ld, interp);
00140   return out;
00141 }
00142 
00143 
00144 //: A version of vil_warp specialized for lens unwarping
00145 template <class sType, class dType, class T, class InterpFunctor>
00146 void vpgl_lens_unwarp(const vil_image_view<sType>& in,
00147                       vil_image_view<dType>& out,
00148                       const vpgl_lens_distortion<T>& ld,
00149                       InterpFunctor interp)
00150 {
00151   unsigned const out_w = out.ni();
00152   unsigned const out_h = out.nj();
00153 
00154   assert(out.nplanes() == in.nplanes());
00155 
00156   for (unsigned oy = 0; oy < out_h; ++oy)
00157   {
00158     for (unsigned ox = 0; ox < out_w; ++ox)
00159     {
00160       vgl_point_2d<T> pt = ld.distort(vgl_homg_point_2d<T>(ox,oy));
00161       for (unsigned p = 0; p < out.nplanes(); ++p)
00162       {
00163         out(ox, oy, p) = dType(interp(in, pt.x(), pt.y(), p));
00164       }
00165     }
00166   }
00167 }
00168 
00169 #endif // vpgl_lens_warp_mapper_h_