contrib/mul/vil3d/algo/vil3d_abs_shuffle_distance.txx
Go to the documentation of this file.
00001 #ifndef vil3d_abs_shuffle_distance_txx_
00002 #define vil3d_abs_shuffle_distance_txx_
00003 //:
00004 // \file
00005 // \brief Compute shuffle distance between two images
00006 // \author Vlad Petrovic and Tim Cootes
00007 
00008 #include "vil3d_abs_shuffle_distance.h"
00009 #include <vcl_cassert.h>
00010 
00011 //: Computes shuffle distance between image1 and image2
00012 // For each pixel in image1 it finds the pixel in image2 with
00013 // the closest value in an offset area defined by the element.
00014 // Returns mean over all pixels of this minimum value.
00015 // \relatesalso vil3d_image_view
00016 // \relatesalso vil3d_structuring_element
00017 template <class T1, class T2>
00018 double vil3d_abs_shuffle_distance(const vil3d_image_view<T1>& image1,
00019                                   const vil3d_image_view<T2>& image2,
00020                                   const vil3d_structuring_element& element,
00021                                   bool include_borders)
00022 {
00023   // Get image dimensions
00024   unsigned ni = image1.ni();
00025   unsigned nj = image1.nj();
00026   unsigned nk = image1.nk();
00027   // Assert images are single plain and same size
00028   assert(image1.nplanes()==1);
00029   assert(image2.nplanes()==1);
00030   assert(image2.ni()==ni);
00031   assert(image2.nj()==nj);
00032   assert(image2.nk()==nk);
00033 
00034   vcl_ptrdiff_t istep1 = image1.istep(), jstep1 = image1.jstep(), kstep1 = image1.kstep(),
00035                 istep2 = image2.istep(), jstep2 = image2.jstep(), kstep2 = image2.kstep();
00036 
00037   vcl_vector<vcl_ptrdiff_t> offset;
00038   vil3d_compute_offsets(offset, element, istep1, jstep1, kstep1);
00039 
00040   // Define box in which all element will be valid
00041   int ilo = -element.min_i();
00042   int ihi = ni-1-element.max_i();
00043   int jlo = -element.min_j();
00044   int jhi = nj-1-element.max_j();
00045   int klo = -element.min_k();
00046   int khi = nk-1-element.max_k();
00047 
00048   double sum=0.0;
00049 
00050   if (include_borders)
00051   {
00052     // Deal with left edge
00053     for (unsigned int i=0; int(i)<ilo; ++i)
00054       for (unsigned int j=0; j<nj; ++j)
00055         for (unsigned int k=0; k<nk; ++k)
00056           sum+=vil3d_abs_shuffle_distance(image1(i,j,k),image2,0,element,i,j,k);
00057     // Deal with right edge
00058     for (unsigned int i=ihi+1; i<ni; ++i)
00059       for (unsigned int j=0;j<nj;++j)
00060         for (unsigned int k=0; k<nk; ++k)
00061           sum+=vil3d_abs_shuffle_distance(image1(i,j,k),image2,0,element,i,j,k);
00062 
00063     // Deal with bottom edge
00064     for (unsigned int i=ilo; int(i)<=ihi; ++i)
00065       for (unsigned int j=0; int(j)<jlo; ++j)
00066         for (unsigned int k=klo; int(k)<khi; ++k)
00067           sum+=vil3d_abs_shuffle_distance(image1(i,j,k),image2,0,element,i,j,k);
00068     // Deal with top edge
00069     for (unsigned int i=ilo; int(i)<=ihi; ++i)
00070       for (unsigned int j=jhi+1; j<nj; ++j)
00071         for (unsigned int k=klo; int(k)<khi; ++k)
00072           sum+=vil3d_abs_shuffle_distance(image1(i,j,k),image2,0,element,i,j,k);
00073 
00074     // Deal with front edge
00075     for (unsigned int i=ilo; int(i)<=ihi; ++i)
00076       for (unsigned int j=jlo; int(j)<jhi; ++j)
00077         for (unsigned int k=0; int(k)<klo; ++k)
00078           sum+=vil3d_abs_shuffle_distance(image1(i,j,k),image2,0,element,i,j,k);
00079     // Deal with back edge
00080     for (unsigned int i=ilo; int(i)<=ihi; ++i)
00081       for (unsigned int j=jlo; int(j)<jhi; ++j)
00082         for (unsigned int k=khi+1; k<nk; ++k)
00083           sum+=vil3d_abs_shuffle_distance(image1(i,j,k),image2,0,element,i,j,k);
00084   }
00085 
00086   const T1* image1_start = image1.origin_ptr();
00087   const T2* image2_start = image2.origin_ptr();
00088 
00089   for (unsigned int k=klo; int(k)<=khi; ++k)
00090     for (unsigned int j=jlo; int(j)<=jhi; ++j)
00091     {
00092       const T1* p1 = image1_start + k*kstep1 + j*jstep1 + ilo*istep1;
00093       const T2* p2 = image2_start + k*kstep2 + j*jstep2 + ilo*istep2;
00094 
00095       for (int i=ilo; i<=ihi; ++i,p1+=istep1,p2+=istep2)
00096         sum += vil3d_abs_shuffle_distance(*p1,p2,&offset[0],offset.size());
00097     }
00098 
00099   // Work out the number of evaluated pixels
00100   int np = ni*nj*nk;
00101   if (!include_borders) np = (1+ihi-ilo)*(1+jhi-jlo)*(1+khi-klo);
00102 
00103   return sum/np;
00104 }
00105 
00106 
00107 //: Computes shuffle distance between image1 and image2
00108 // For each pixel in image1 it finds the pixel in image2 with
00109 // the closest value in an offset area defined by the element.
00110 // \relatesalso vil3d_image_view
00111 // \relatesalso vil3d_structuring_element
00112 template <class T1, class T2>
00113 void vil3d_abs_shuffle_distance(const vil3d_image_view<T1>& image1,
00114                                 const vil3d_image_view<T2>& image2,
00115                                 const vil3d_structuring_element& element,
00116                                 vil3d_image_view<T1>& image3)
00117 {
00118   vcl_cout << "image1: " << image1 << vcl_endl
00119            << "image2: " << image2 << vcl_endl;
00120 
00121   // Get image dimensions
00122   unsigned ni = image1.ni();
00123   unsigned nj = image1.nj();
00124   unsigned nk = image1.nk();
00125   // Assert images are single plain and same size
00126   assert(image1.nplanes()==1);
00127   assert(image2.nplanes()==1);
00128   assert(image2.ni()==ni);
00129   assert(image2.nj()==nj);
00130   assert(image2.nk()==nk);
00131 
00132   image3.set_size( ni, nj, nk );
00133 
00134   vcl_ptrdiff_t istep1 = image1.istep(), jstep1 = image1.jstep(), kstep1 = image1.kstep(),
00135                 istep2 = image2.istep(), jstep2 = image2.jstep(), kstep2 = image2.kstep(),
00136                 istep3 = image3.istep(), jstep3 = image3.jstep(), kstep3 = image3.kstep();
00137 
00138   vcl_vector<vcl_ptrdiff_t> offset;
00139   vil3d_compute_offsets(offset, element, istep1, jstep1, kstep1);
00140 
00141   // Define box in which all element will be valid
00142   int ilo = -element.min_i();
00143   int ihi = ni-1-element.max_i();
00144   int jlo = -element.min_j();
00145   int jhi = nj-1-element.max_j();
00146   int klo = -element.min_k();
00147   int khi = nk-1-element.max_k();
00148 
00149   // if (include_borders)
00150   {
00151     // Deal with left edge
00152     for (unsigned int i=0; int(i)<ilo; ++i)
00153       for (unsigned int j=0; j<nj; ++j)
00154         for (unsigned int k=0; k<nk; ++k)
00155           image3(i,j,k)=(T1)vil3d_abs_shuffle_distance(image1(i,j,k),image2,0,element,i,j,k);
00156 
00157     // Deal with right edge
00158     for (unsigned int i=ihi+1; i<ni; ++i)
00159       for (unsigned int j=0;j<nj;++j)
00160         for (unsigned int k=0; k<nk; ++k)
00161           image3(i,j,k)=(T1)vil3d_abs_shuffle_distance(image1(i,j,k),image2,0,element,i,j,k);
00162 
00163     // Deal with bottom edge
00164     for (unsigned int i=ilo; int(i)<=ihi; ++i)
00165       for (unsigned int j=0; int(j)<jlo; ++j)
00166         for (unsigned int k=0; k<nk; ++k)
00167           image3(i,j,k)=(T1)vil3d_abs_shuffle_distance(image1(i,j,k),image2,0,element,i,j,k);
00168 
00169     // Deal with top edge
00170     for (unsigned int i=ilo; int(i)<=ihi; ++i)
00171       for (unsigned int j=jhi+1; j<nj; ++j)
00172         for (unsigned int k=0; k<nk; ++k)
00173           image3(i,j,k)=(T1)vil3d_abs_shuffle_distance(image1(i,j,k),image2,0,element,i,j,k);
00174 
00175     // Deal with front edge
00176     for (unsigned int i=ilo; int(i)<=ihi; ++i)
00177       for (unsigned int j=jlo; int(j)<=jhi; ++j)
00178         for (unsigned int k=0; int(k)<klo; ++k)
00179           image3(i,j,k)=(T1)vil3d_abs_shuffle_distance(image1(i,j,k),image2,0,element,i,j,k);
00180 
00181     // Deal with back edge
00182     for (unsigned int i=ilo; int(i)<=ihi; ++i)
00183       for (unsigned int j=jlo; int(j)<=jhi; ++j)
00184         for (unsigned int k=khi+1; k<nk; ++k)
00185           image3(i,j,k)=(T1)vil3d_abs_shuffle_distance(image1(i,j,k),image2,0,element,i,j,k);
00186   }
00187 
00188   const T1* image1_start = image1.origin_ptr();
00189   const T2* image2_start = image2.origin_ptr();
00190   T1* image3_start = image3.origin_ptr();
00191 
00192   for (unsigned int k=klo; int(k)<=khi; ++k)
00193     for (unsigned int j=jlo; int(j)<=jhi; ++j)
00194     {
00195       const T1* p1 = image1_start + k*kstep1 + j*jstep1 + ilo*istep1;
00196       const T2* p2 = image2_start + k*kstep2 + j*jstep2 + ilo*istep2;
00197       T1* p3 = image3_start + k*kstep3 + j*jstep3 + ilo*istep3;
00198 
00199       for (int i=ilo; i<=ihi; ++i,p1+=istep1,p2+=istep2,p3+=istep3)
00200         *p3 = static_cast<T1>(vil3d_abs_shuffle_distance(*p1,p2,&offset[0],offset.size()));
00201     }
00202 }
00203 
00204 
00205 #undef VIL3D_ABS_SHUFFLE_DISTANCE_INSTANTIATE
00206 #define VIL3D_ABS_SHUFFLE_DISTANCE_INSTANTIATE( T1, T2 ) \
00207 template double vil3d_abs_shuffle_distance(const vil3d_image_view< T1 >& image1, \
00208                                            const vil3d_image_view< T2 >& image2, \
00209                                            const vil3d_structuring_element& element, \
00210                                            bool include_borders)
00211 
00212 #undef VIL3D_ABS_SHUFFLE_DISTANCE_INSTANTIATE2
00213 #define VIL3D_ABS_SHUFFLE_DISTANCE_INSTANTIATE2( T1, T2 ) \
00214 template void vil3d_abs_shuffle_distance(const vil3d_image_view< T1 >& image1, \
00215                                          const vil3d_image_view< T2 >& image2, \
00216                                          const vil3d_structuring_element& element, \
00217                                          vil3d_image_view< T1 >& image3)
00218 
00219 #endif // vil3d_abs_shuffle_distance_txx_