contrib/brl/bbas/bdgl/bdgl_region_algs.cxx
Go to the documentation of this file.
00001 #include "bdgl_region_algs.h"
00002 //:
00003 // \file
00004 #include <vcl_cmath.h>
00005 #include <vcl_cstdlib.h>
00006 #include <vdgl/vdgl_digital_region.h>
00007 
00008 //:
00009 //--------------------------------------------------------------------------
00010 // Finds the Mahalanobis distance between the intensity distributions
00011 // of two regions.  If there are not enough pixels in either or both
00012 // regions to reliably determine the distance then -1 is returned.
00013 //--------------------------------------------------------------------------
00014 float bdgl_region_algs::
00015 mahalanobis_distance(vdgl_digital_region_sptr const& r1,
00016                      vdgl_digital_region_sptr const& r2)
00017 {
00018   //need this many points for standard deviation and mean to be valid
00019   const unsigned int min_npts = 5;
00020   const float SMALL = 1;
00021   if (!r1 || !r2)
00022     return -1.f;
00023   if (r1->Npix()<min_npts || r2->Npix()<min_npts)
00024     return -1.f;
00025   float m1 = r1->Io(), m2 = r2->Io();
00026   float s1 = r1->Io_sd(), s2 = r2->Io_sd();
00027   //make sure the standard deviations are well-behaved
00028   if (s1<SMALL) s1 = SMALL;
00029   if (s2<SMALL) s2 = SMALL;
00030   float s_sq = (s1*s1*s2*s2)/(s1*s1 + s2*s2);
00031   float d = vcl_sqrt((m1-m2)*(m1-m2)/s_sq);
00032   vcl_cout << "MDistance||(" << r1->Npix()
00033            << ")(Xo:" << r1->Xo() << " Yo:" << r1 ->Yo()
00034            << " Io:" << r1 ->Io() << ")::(" << r2->Npix()
00035            << " Xo:" << r2->Xo() << " Yo:" << r2 ->Yo()
00036            << " Io:" << r2 ->Io() <<")||= " << d << vcl_endl;
00037   return d;
00038 }
00039 
00040 float bdgl_region_algs::intensity_distance(vdgl_digital_region_sptr const& r1,
00041                                            vdgl_digital_region_sptr const& r2)
00042 {
00043   const unsigned int min_npts = 5;
00044   const float SMALL = 1;
00045   if (!r1 || !r2)
00046     return -1.f;
00047   if (r1->Npix()<min_npts || r2->Npix()<min_npts)
00048     return -1.f;
00049   float m1 = r1->Io(), m2 = r2->Io();
00050   if (vcl_fabs(m1-m2)<SMALL)
00051     return 0;
00052   float msq = (m1+m2)*(m1+m2);
00053   double d = 2.0*vcl_sqrt((m1-m2)*(m1-m2)/msq);
00054   vcl_cout << "Intensity Distance||(" << r1->Npix()
00055            << ")(Xo:" << r1->Xo() << " Yo:" << r1 ->Yo()
00056            << " Io:" << r1 ->Io() << ")::(" << r2->Npix()
00057            << " Xo:" << r2->Xo() << " Yo:" << r2 ->Yo()
00058            << " Io:" << r2 ->Io() <<")||= " << d << vcl_endl;
00059   return float(d);
00060 }
00061 
00062 bool bdgl_region_algs::merge(vdgl_digital_region_sptr const& r1,
00063                              vdgl_digital_region_sptr const& r2,
00064                              vdgl_digital_region_sptr& rm)
00065 {
00066   if (!r1 || !r2)
00067     return false;
00068   //trivial cases
00069   int n1 = r1->Npix(), n2 = r2->Npix();
00070   if (n1==0)
00071     return r2;
00072   if (n2==0)
00073     return r1;
00074   int n = n1 + n2;
00075   if (!n)
00076     return false;
00077   float* Xm = new float[n];
00078   float* Ym = new float[n];
00079   unsigned short* Im = new unsigned short[n];
00080 
00081   float const* X1 = r1->Xj();
00082   float const* Y1 = r1->Yj();
00083   unsigned short const* I1 = r1->Ij();
00084 
00085   float const* X2 = r2->Xj();
00086   float const* Y2 = r2->Yj();
00087   unsigned short const* I2 = r2->Ij();
00088 
00089   for (int i = 0; i<n1; i++)
00090   {
00091     Xm[i] = X1[i];
00092     Ym[i] = Y1[i];
00093     Im[i] = I1[i];
00094   }
00095   int j = n1;
00096   for (int i = 0; i<n2; i++,j++)
00097   {
00098     Xm[j] = X2[i];
00099     Ym[j] = Y2[i];
00100     Im[j] = I2[i];
00101   }
00102   rm = new vdgl_digital_region(n, Xm, Ym, Im);
00103   delete[] Xm;
00104   delete[] Ym;
00105   delete[] Im;
00106   return true;
00107 }
00108 
00109 static int increasing_compare(const void *x1, const void *x2)
00110 {
00111   const unsigned short* f1 = (const unsigned short*)x1;
00112   const unsigned short* f2 = (const unsigned short*)x2;
00113   if (*f1<*f2)
00114     return -1;
00115   else if (*f1==*f2)
00116     return 0;
00117   else
00118     return 1;
00119 }
00120 
00121 static int decreasing_compare(const void *x1, const void *x2)
00122 {
00123   const unsigned short* f1 = (const unsigned short*)x1;
00124   const unsigned short* f2 = (const unsigned short*)x2;
00125   if (*f1>*f2)
00126     return -1;
00127   else if (*f1==*f2)
00128     return 0;
00129   else
00130     return 1;
00131 }
00132 
00133 //: Computes the maximum average distance between the intensity samples in two regions.
00134 float
00135 bdgl_region_algs::earth_mover_distance(vdgl_digital_region_sptr const& r1,
00136                                        vdgl_digital_region_sptr const& r2)
00137 {
00138   const unsigned int min_npts = 5;
00139   if (!r1 || !r2)
00140     return -1.f;
00141   const unsigned int n1 = r1->Npix(), n2 = r2->Npix();
00142   if (n1<min_npts || n2<min_npts)
00143     return -1.f;
00144   unsigned short *I1 = new unsigned short[n1],
00145                  *I2 = new unsigned short[n2];
00146   vcl_memcpy(I1, r1->Ij(), n1*sizeof(unsigned short));
00147   vcl_memcpy(I2, r2->Ij(), n2*sizeof(unsigned short));
00148   //Sort the intensities in each region
00149   vcl_qsort( (void*)I1, n1, sizeof(unsigned short), increasing_compare );
00150   vcl_qsort( (void*)I2, n2, sizeof(unsigned short), decreasing_compare );
00151   //Match up the smallest intensities in the smaller region with
00152   //the largest intensities in the larger region.  This provides a
00153   //measure of the distance between the two regions
00154   double sum = 0;
00155   unsigned int n_smaller = n1; if (n2<n_smaller) n_smaller=n2;
00156   for (unsigned int i = 0; i<n_smaller; ++i)
00157   {
00158     double d = double(I1[i]) - double(I2[i]);
00159     sum += vcl_sqrt(d*d);
00160   }
00161   delete[] I1; delete[] I2;
00162   sum /= n_smaller;
00163 #ifdef DEBUG
00164   vcl_cout << "EarthMover Max Distance||(" << r1->Npix()
00165            << ")(Xo:"<< r1->Xo() << " Yo:" << r1->Yo()
00166            << " Io:" << r1->Io() << ")::(" << r2->Npix()
00167            << " Xo:" << r2->Xo() << " Yo:" << r2->Yo()
00168            << " Io:" << r2->Io() << ")||= "<< sum << vcl_endl;
00169 #endif
00170   return float(sum);
00171 }