contrib/mul/vimt/vimt_resample_bilin.h
Go to the documentation of this file.
00001 #ifndef vimt_resample_bilin_h_
00002 #define vimt_resample_bilin_h_
00003 //:
00004 // \file
00005 // \brief Sample grid of points in one image and place in another
00006 // \author Tim Cootes
00007 
00008 #include <vcl_cassert.h>
00009 #include <vil/vil_resample_bilin.h>
00010 #include <vil/algo/vil_gauss_reduce.h>
00011 #include <vgl/vgl_point_2d.h>
00012 #include <vgl/vgl_vector_2d.h>
00013 #include <vimt/vimt_image_2d_of.h>
00014 
00015 //: Sample grid of points in one image and place in another, using bilinear interpolation.
00016 //  dest_image(i,j,p) is sampled from the src_image at
00017 //  p+i.u+j.v, where i=[0..n1-1], j=[0..n2-1] in world co-ordinates.
00018 //
00019 //  dest_image resized to (n1,n2,src_image.nplanes())
00020 //
00021 //  dest_image.world2im() set up so that the world co-ordinates in src and dest match
00022 //
00023 //  Points outside image return zero.
00024 // \relatesalso vimt_image_view
00025 template <class sType, class dType>
00026 inline void vimt_resample_bilin(
00027   const vimt_image_2d_of<sType>& src_image,
00028   vimt_image_2d_of<dType>& dest_image,
00029   const vgl_point_2d<double>& p,
00030   const vgl_vector_2d<double>& u,
00031   const vgl_vector_2d<double>& v,
00032   int n1, int n2)
00033 {
00034   // Not implemented for projective yet
00035   assert(src_image.world2im().form()!=vimt_transform_2d::Projective);
00036 
00037   const vimt_transform_2d& s_w2i = src_image.world2im();
00038   vgl_point_2d<double> im_p = s_w2i(p);
00039   vgl_vector_2d<double> im_u = s_w2i.delta(p, u);
00040   vgl_vector_2d<double> im_v = s_w2i.delta(p, v);
00041 
00042   vil_resample_bilin(src_image.image(),dest_image.image(),
00043                      im_p.x(),im_p.y(),  im_u.x(),im_u.y(),
00044                      im_v.x(),im_v.y(), n1,n2);
00045 
00046   // Point (i,j) in dest corresponds to p+i.u+j.v,
00047   // an affine transformation for image to world
00048   vimt_transform_2d d_i2w;
00049   d_i2w.set_affine(p,u,v);
00050   dest_image.set_world2im(d_i2w.inverse());
00051 }
00052 
00053 
00054 //: Sample grid of points in one image and place in another, using bilinear interpolation.
00055 //  dest_image(i,j,p) is sampled from the src_image at
00056 //  p+i.u+j.v, where i=[0..n1-1], j=[0..n2-1] in world co-ordinates.
00057 //
00058 //  dest_image resized to (n1,n2,src_image.nplanes())
00059 //
00060 //  dest_image.world2im() set up so that the world co-ordinates in src and dest match
00061 //
00062 //  Points outside image return the value of the nearest valid pixel.
00063 // \relatesalso vimt_image_view
00064 template <class sType, class dType>
00065 inline void vimt_resample_bilin_edge_extend(
00066   const vimt_image_2d_of<sType>& src_image,
00067   vimt_image_2d_of<dType>& dest_image,
00068   const vgl_point_2d<double>& p,
00069   const vgl_vector_2d<double>& u,
00070   const vgl_vector_2d<double>& v,
00071   int n1, int n2)
00072 {
00073   // Not implemented for projective yet
00074   assert(src_image.world2im().form()!=vimt_transform_2d::Projective);
00075 
00076   const vimt_transform_2d& s_w2i = src_image.world2im();
00077   vgl_point_2d<double> im_p = s_w2i(p);
00078   vgl_vector_2d<double> im_u = s_w2i.delta(p, u);
00079   vgl_vector_2d<double> im_v = s_w2i.delta(p, v);
00080 
00081   vil_resample_bilin_edge_extend(src_image.image(),dest_image.image(),
00082                                  im_p.x(),im_p.y(),  im_u.x(),im_u.y(),
00083                                  im_v.x(),im_v.y(), n1,n2);
00084 
00085   // Point (i,j) in dest corresponds to p+i.u+j.v,
00086   // an affine transformation for image to world
00087   vimt_transform_2d d_i2w;
00088   d_i2w.set_affine(p,u,v);
00089   dest_image.set_world2im(d_i2w.inverse());
00090 }
00091 
00092 
00093 //: Resample an image using appropriate smoothing if the resolution changes significantly.
00094 //  dest_image(i,j,p) is sampled from the src_image at
00095 //  p+i.u+j.v, where i=[0..n1-1], j=[0..n2-1] in world co-ordinates.
00096 //
00097 //  dest_image resized to (n1,n2,src_image.nplanes())
00098 //
00099 //  dest_image.world2im() set up so that the world co-ordinates in src and dest match
00100 //
00101 //  Points outside image return the value of the nearest valid pixel.
00102 // \relatesalso vimt_image_view
00103 template <class sType, class dType>
00104 inline void vimt_resample_bilin_smoothing_edge_extend(
00105   const vimt_image_2d_of<sType>& src_image,
00106   vimt_image_2d_of<dType>& dest_image,
00107   const vgl_point_2d<double>& p,
00108   const vgl_vector_2d<double>& u,
00109   const vgl_vector_2d<double>& v,
00110   int n1, int n2)
00111 {
00112   // Not implemented for projective yet
00113   assert(src_image.world2im().form()!=vimt_transform_2d::Projective);
00114 
00115   vimt_transform_2d scaling;
00116   scaling.set_zoom_only(0.5,0,0);
00117 
00118   vimt_image_2d_of<sType> im = src_image;
00119   vgl_vector_2d<double> im_d = im.world2im().delta(p, u) + im.world2im().delta(p, v);
00120 
00121   // If step length (in pixels) >> 1, smooth and reduce image x2.
00122   // Don't use strict Nyqusit limit.
00123   // Since we are just using factor 2 smoothing and reduction,
00124   // we have to tradeoff aliasing with information loss.
00125   while (im_d.length() > 1.33*1.414 && im.image().ni() > 5 && im.image().nj() > 5)
00126   {
00127     vimt_image_2d_of<sType> dest;
00128     vil_image_view<sType> work;
00129     vil_gauss_reduce(im.image(), dest.image(), work);
00130 
00131     dest.set_world2im(scaling * im.world2im());
00132 
00133     // re-establish loop invariant
00134     im = dest;
00135     im_d = im.world2im().delta(p, u) + im.world2im().delta(p, v);
00136   }
00137 
00138   vimt_resample_bilin_edge_extend(im, dest_image, p, u, v, n1, n2);
00139 }
00140 
00141 
00142 //: Resample an image using appropriate smoothing if the resolution changes significantly.
00143 //  dest_image(i,j,p) is sampled from the src_image at
00144 //  p+i.u+j.v, where i=[0..n1-1], j=[0..n2-1] in world co-ordinates.
00145 //
00146 //  dest_image resized to (n1,n2,src_image.nplanes())
00147 //
00148 //  dest_image.world2im() set up so that the world co-ordinates in src and dest match
00149 //
00150 //  Points outside image return 0.
00151 // \relatesalso vimt_image_view
00152 template <class sType, class dType>
00153 inline void vimt_resample_bilin_smoothing(
00154   const vimt_image_2d_of<sType>& src_image,
00155   vimt_image_2d_of<dType>& dest_image,
00156   const vgl_point_2d<double>& p,
00157   const vgl_vector_2d<double>& u,
00158   const vgl_vector_2d<double>& v,
00159   int n1, int n2)
00160 {
00161   // Not implemented for projective yet
00162   assert(src_image.world2im().form()!=vimt_transform_2d::Projective);
00163 
00164   vimt_transform_2d scaling;
00165   scaling.set_zoom_only(0.5,0,0);
00166 
00167   vimt_image_2d_of<sType> im = src_image;
00168   vgl_vector_2d<double> im_d = im.world2im().delta(p, u) + im.world2im().delta(p, v);
00169 
00170   // If step length (in pixels) >> 1, smooth and reduce image x2.
00171   // Don't use strict Nyqusit limit.
00172   // Since we are just using factor 2 smoothing and reduction,
00173   // we have to tradeoff aliasing with information loss.
00174   while (im_d.length() > 1.33*1.414 && im.image().ni() > 5 && im.image().nj() > 5)
00175   {
00176     vimt_image_2d_of<sType> dest;
00177     vil_image_view<sType> work;
00178     vil_gauss_reduce(im.image(), dest.image(), work);
00179 
00180     dest.set_world2im(scaling * im.world2im());
00181 
00182     // re-establish loop invariant
00183     im = dest;
00184     im_d = im.world2im().delta(p, u) + im.world2im().delta(p, v);
00185   }
00186 
00187   vimt_resample_bilin(im, dest_image, p, u, v, n1, n2);
00188 }
00189 
00190 #endif // vimt_resample_bilin_h_