core/vil1/vil1_ncc.txx

Go to the documentation of this file.
00001 // This is core/vil1/vil1_ncc.txx
00002 #ifndef vil1_ncc_txx_
00003 #define vil1_ncc_txx_
00004 
00005 /*
00006   capes@robots.ox.ac.uk
00007 */
00008 #include "vil1_ncc.h"
00009 #include <vcl_cassert.h>
00010 #include <vcl_cmath.h> // vcl_sqrt()
00011 
00012 template <class I1, class I2, class O>
00013 O vil1_ncc(vil1_memory_image_of<I1> const &a,
00014            vil1_memory_image_of<I2> const &b,
00015            O *)
00016 {
00017   assert(a.width() == b.width());
00018   assert(a.height() == b.height());
00019   unsigned w = a.width();
00020   unsigned h = a.height();
00021 
00022   // initialize accumulator
00023   O acc(0);
00024   O mean1(0);
00025   O mean2(0);
00026   O var1(0);
00027   O var2(0);
00028 
00029   for (unsigned j=0; j<h; ++j) {
00030     // get raster pointers. faster on non-optimized builds.
00031     I1 const *ra = a[j];
00032     I2 const *rb = b[j];
00033 
00034     // compute means
00035     for (unsigned i=0; i<w; ++i) {
00036       mean1 += O(ra[i]);
00037       mean2 += O(rb[i]);
00038     }
00039   }
00040   mean1 /= O(w*h);
00041   mean2 /= O(w*h);
00042 
00043   for (unsigned j=0; j<h; ++j) {
00044     // get raster pointers. faster on non-optimized builds.
00045     I1 const *ra = a[j];
00046     I2 const *rb = b[j];
00047 
00048     // accumulate
00049     for (unsigned i=0; i<w; ++i) {
00050       O tmp1 = O(ra[i]) - mean1;
00051       O tmp2 = O(rb[i]) - mean2;
00052       var1 += tmp1 * tmp1;
00053       var2 += tmp2 * tmp2;
00054       acc += tmp1 * tmp2;
00055     }
00056   }
00057   var1 /= O(w*h);
00058   var2 /= O(w*h);
00059 
00060   // Looks a bit dumb I know, but makes it clear what's going on...
00061   return acc / (vcl_sqrt(w*h*var1) * vcl_sqrt(w*h*var2));
00062 }
00063 
00064 //--------------------------------------------------------------------------------
00065 
00066 #if defined(VCL_GCC_295)
00067 // for 2.7 we'd have to instantiate the inline function, which can't be done
00068 // in the macro as it would conflict with the specialization.
00069 template <class T, class A>
00070 inline A vil1_ncc_cond(T const &x, A *) { return A(x); }
00071 
00072 VCL_DEFINE_SPECIALIZATION
00073 inline double vil1_ncc_cond(unsigned char const &x, double *) { return (double(x)-127.5)/127.5; }
00074 #else
00075 # define vil1_ncc_cond(x, ptr_to_A) (x) //(typeof *ptr_to_A)(x)
00076 #endif
00077 
00078 template <class T1, class T2, class A>
00079 A vil1_ncc(T1 const * const *I1, int x1, int y1,
00080            T2 const * const *I2, int x2, int y2,
00081            int size, A *)
00082 {
00083   unsigned N = 0;
00084   A S1=0, S2 = 0;
00085   A S11=0, S12=0, S22=0;
00086 
00087   for (int j=-size; j<=size; ++j) {
00088     T1 const *row1 = I1[y1+j];
00089     T2 const *row2 = I2[y2+j];
00090     for (int i=-size; i<=size; ++i) {
00091       A im1 = vil1_ncc_cond(row1[x1+i], (A*)0);
00092       A im2 = vil1_ncc_cond(row2[x2+i], (A*)0);
00093       N += 1;
00094       S1 += im1; S2 += im2;
00095       S11 += im1*im1; S12 += im1*im2; S22 += im2*im2;
00096     }
00097   }
00098 
00099   return (N*S12 - S1*S2) / vcl_sqrt((N*S11 - S1*S1) * (N*S22 - S2*S2));
00100 }
00101 
00102 //--------------------------------------------------------------------------------
00103 
00104 #define VIL1_NCC_INSTANTIATE(I1, I2, O) \
00105 template O vil1_ncc(vil1_memory_image_of<I1 > const &, \
00106                     vil1_memory_image_of<I2 > const &, \
00107                     O *); \
00108 template O vil1_ncc(I1 const * const *, int, int, \
00109                     I2 const * const *, int, int, \
00110                     int, O *)
00111 
00112 #endif // vil1_ncc_txx_

Generated on Mon Mar 8 05:09:33 2010 for core/vil1 by  doxygen 1.5.1