contrib/brl/bseg/brip/brip_blobwise_mutual_info.txx
Go to the documentation of this file.
00001 // This is brl/bseg/brip/brip_blobwise_mutual_info.txx
00002 #ifndef brip_blobwise_mutual_info_txx_
00003 #define brip_blobwise_mutual_info_txx_
00004 //:
00005 // \file
00006 // \brief Calculate the mutual information between the images.
00007 // \author Matt Leotta
00008 
00009 #include "brip_blobwise_mutual_info.h"
00010 #include "brip_histogram.h"
00011 #include "brip_mutual_info.h"
00012 #include <bil/algo/bil_blob_finder.h>
00013 #include <vil/algo/vil_binary_dilate.h>
00014 #include <vil/algo/vil_binary_erode.h>
00015 #include <vil/vil_math.h>
00016 #include <vcl_vector.h>
00017 #include <vcl_cassert.h>
00018 #include <vcl_algorithm.h>
00019 
00020 //: Calculate the Mutual Information between the images.
00021 template<class T>
00022 void brip_blobwise_mutual_info (const vil_image_view<T>& img1,
00023                                 const vil_image_view<T>& img2,
00024                                 const vil_image_view<T>& weights, //if weight is under a certain value, then dont use for MI
00025                                 const vil_image_view<bool>& mask,
00026                                       vil_image_view<T>& mi_img )
00027 {
00028 #if 0
00029   //pixel gradient weight must be higher than this
00030   const T minWeight = .1;
00031 #endif
00032   //blob region is just a vector of vil_chords (rows in image)
00033   bil_blob_finder finder(mask);
00034   vcl_vector<vil_chord> region;
00035   while (finder.next_4con_region(region))
00036   {
00037     //gather vector of samples
00038     vcl_vector<T> x_samps;
00039     vcl_vector<T> y_samps;
00040     vcl_vector<double> weight_samps;
00041     vcl_vector<vil_chord>::iterator iter;
00042     for (iter=region.begin(); iter!=region.end(); ++iter) {
00043       //add each pixel in this row to blob
00044       for (unsigned i=iter->ilo; i<iter->ihi+1; ++i) {
00045 #if 0
00046         if ( weights(i, iter->j) > minWeight )
00047 #endif
00048         {
00049           x_samps.push_back( img1(i, iter->j) );
00050           y_samps.push_back( img2(i, iter->j) );
00051           weight_samps.push_back( weights(i, iter->j) );
00052         }
00053       }
00054     }
00055 
00056     //calculate mutual information between these two sets of samples
00057     vil_image_view<T> x(1, x_samps.size());
00058     vil_image_view<T> y(1, x_samps.size());
00059     vil_image_view<double> wImg(1, x_samps.size());
00060     for (unsigned int i=0; i<x.size(); ++i) {
00061       x(0, i) = x_samps[i];
00062       y(0, i) = y_samps[i];
00063       wImg(0,i) = weight_samps[i];
00064     }
00065     vcl_vector<double> x_hist, y_hist;
00066     vcl_vector<vcl_vector<double> > joint_hist;
00067 
00068     unsigned n_bins = 32;
00069     double min = -vnl_math::pi,
00070            max =  vnl_math::pi;
00071     double mag1, mag2, mag3;
00072     mag1 = brip_histogram(x, x_hist, min, max, n_bins);
00073     mag2 = brip_histogram(y, y_hist, min, max, n_bins);
00074     mag3 = brip_joint_histogram(x, y, joint_hist, min, max, n_bins);
00075 
00076 #if 0
00077     factor in prior prob distribution
00078     for (unsigned int i=0; i<x_hist.size(); ++i) {
00079       x_hist[i]++;
00080       mag1++;
00081     }
00082     for (int i=0; i<y_hist.size(); ++i) {
00083       y_hist[i]++;
00084       mag2++;
00085     }
00086     for (int i=0; i<joint_hist.size(); ++i) {
00087       for (int j=0; j<joint_hist[i].size(); ++j) {
00088         joint_hist[i][j] += 1.0/n_bins;
00089         mag3 += 1.0/n_bins;
00090       }
00091     }
00092 #endif // 0
00093 
00094     double H1, H2, H3, MI;
00095     H1 = brip_hist_entropy(x_hist, mag1);
00096     H2 = brip_hist_entropy(y_hist, mag2);
00097     H3 = brip_hist_entropy(joint_hist, mag3);
00098     MI = H1 + H2 - H3;
00099 
00100     //if it's empty, we should return max MI as default
00101     if (x_samps.size() == 0)
00102       MI = 5.0;
00103 
00104     if (MI != MI) {
00105       vcl_cout<<"mutual info is NAN\n"
00106               <<"  num samps = "<<x_samps.size()<<vcl_endl;
00107     }
00108     if ( vcl_fabs(MI-.6702) < .0001 ) {
00109       vcl_cout<<"MID BLOB samps:\n"
00110               <<"  num samps = "<<x_samps.size()<<vcl_endl;
00111     }
00112     if (x_samps.size() == 0) {
00113       vcl_cout<<"ZERO SAMPLE SET:\n"
00114               <<"   MI = "<<MI<<'\n'
00115               <<"   H1 = "<<H1<<'\n'
00116               <<"   H2 = "<<H2<<'\n'
00117               <<"   Hxy= "<<H3<<vcl_endl;
00118     }
00119 
00120 
00121     //store mutual information value back in MI img
00122     for (iter=region.begin(); iter!=region.end(); ++iter)
00123       for (unsigned i=iter->ilo; i<iter->ihi+1; ++i)
00124         mi_img(i, iter->j) = (T)MI;
00125   } //end blob while
00126 }
00127 
00128 
00129 template<class T>
00130 void brip_blobwise_kl_div( const vil_image_view<T>& img1,
00131                            const vil_image_view<T>& img2,
00132                            const vil_image_view<bool>& mask,
00133                                  vil_image_view<T>& mi_img )
00134 {
00135   //------------------------------------------------
00136   // iterate over each blob,
00137   //   compute KL div for blob distribution in img1 to img2
00138   //------------------------------------------------
00139   bil_blob_finder finder(mask);
00140   vcl_vector<vil_chord> region;
00141   while (finder.next_4con_region(region))
00142   {
00143     //gather vector of samples
00144     vcl_vector<T> x_samps;
00145     vcl_vector<T> y_samps;
00146     vcl_vector<vil_chord>::iterator iter;
00147     for (iter=region.begin(); iter!=region.end(); ++iter) {
00148       //add each pixel in this row to blob
00149       for (unsigned i=iter->ilo; i<iter->ihi+1; ++i) {
00150         x_samps.push_back( img1(i, iter->j) );
00151         y_samps.push_back( img2(i, iter->j) );
00152       }
00153     }
00154 
00155     //move samples into a 1-d image for KL div calc
00156     vil_image_view<T> x(1, x_samps.size());
00157     vil_image_view<T> y(1, x_samps.size());
00158     for (unsigned int i=0; i<x.size(); ++i) {
00159       x(0, i) = x_samps[i];
00160       y(0, i) = y_samps[i];
00161     }
00162 
00163     //---find global min/max values
00164     T min1, max1, min2, max2;
00165     vil_math_value_range(x, min1, max1);
00166     vil_math_value_range(y, min2, max2);
00167     double min = vcl_min(min1, min2);
00168     double max = vcl_max(max1, max2);
00169 
00170     //compute the number of bins as a function of num samps
00171     unsigned n_bins = vcl_min((int) x_samps.size()/2, 32);
00172 
00173     //bin the two blob samples
00174     vcl_vector<double> x_hist, y_hist;
00175     vcl_vector<vcl_vector<double> > joint_hist;
00176     double magX = brip_histogram(x, x_hist, min, max, n_bins);
00177     double magY = brip_histogram(y, y_hist, min, max, n_bins);
00178 
00179     //factor in prior prob distribution
00180     for (unsigned int i=0; i<x_hist.size(); ++i) {
00181       x_hist[i] += .01/n_bins;
00182       magX      += .01/n_bins;
00183       y_hist[i] += .01/n_bins;
00184       magY      += .01/n_bins;
00185     }
00186     T KL = (T)brip_hist_kl_div(x_hist, magX, y_hist, magY);
00187 
00188     //store mutual information value back in MI img
00189     for (iter=region.begin(); iter!=region.end(); ++iter)
00190       for (unsigned i=iter->ilo; i<iter->ihi+1; ++i)
00191         mi_img(i, iter->j) = KL;
00192 
00193 #if 0
00194     //print out debug info
00195     iter = region.begin();
00196     int startI = iter->ilo,
00197         startJ = iter->j;
00198     if (startI > 422 && startI < 460 && startJ>280 && startJ<310) {
00199       vcl_cout<<"BLOB with size "<<x_samps.size()<<'\n'
00200               <<"  histX (inimg) = ";
00201       for (int i=0; i<x_hist.size(); ++i) vcl_cout<<x_hist[i]/magX<<' ';
00202       vcl_cout<<'\n'
00203               <<"  histY (expimg)= ";
00204       for (int i=0; i<y_hist.size(); ++i) vcl_cout<<y_hist[i]/magY<<' ';
00205       vcl_cout<<'\n'
00206               <<"  KL div = "<<KL<<vcl_endl;
00207     }
00208 #endif
00209   } //end blob while
00210 }
00211 
00212 
00213 // Macro to perform manual instantiations
00214 #define BRIP_BLOBWISE_MUTUAL_INFO_INSTANTIATE(T) \
00215   template \
00216   void brip_blobwise_mutual_info (const vil_image_view<T >& img1, \
00217                                   const vil_image_view<T >& img2, \
00218                                   const vil_image_view<T >& weights, \
00219                                   const vil_image_view<bool>& mask, \
00220                                         vil_image_view<T >& mi_img ); \
00221   template \
00222   void brip_blobwise_kl_div( const vil_image_view<T >& img1, \
00223                              const vil_image_view<T >& img2, \
00224                              const vil_image_view<bool>& mask, \
00225                                    vil_image_view<T >& mi_img )
00226 
00227 #endif // brip_blobwise_mutual_info_txx_