contrib/brl/bbas/bsta/bsta_joint_histogram_3d.txx
Go to the documentation of this file.
00001 #ifndef bsta_joint_histogram_3d_txx_
00002 #define bsta_joint_histogram_3d_txx_
00003 //:
00004 // \file
00005 #include "bsta_joint_histogram_3d.h"
00006 
00007 #include <vcl_cmath.h> // for log()
00008 #include <vcl_iostream.h>
00009 #include "bsta_gauss.h"
00010 #include <vnl/vnl_math.h> // for log2e == 1/vcl_log(2.0)
00011 template <class T>
00012 bsta_joint_histogram_3d<T>::bsta_joint_histogram_3d()
00013   : volume_valid_(false), volume_(0),
00014     nbins_a_(1), nbins_b_(1), nbins_c_(1),
00015     range_a_(0), range_b_(0), range_c_(0),
00016     delta_a_(0), delta_b_(0), delta_c_(0),
00017     min_a_(0), max_a_(0),
00018     min_b_(0), max_b_(0),
00019     min_c_(0), max_c_(0),
00020     min_prob_(0),
00021     counts_(1, 1, 1, T(0))
00022 {
00023   bsta_joint_histogram_3d_base::type_ = bsta_joint_histogram_3d_traits<T>::type();
00024 }
00025 
00026 template <class T>
00027 bsta_joint_histogram_3d<T>::bsta_joint_histogram_3d(const T range,
00028                                                     const unsigned nbins,
00029                                                     const T min_prob)
00030   : volume_valid_(false), volume_(0), nbins_a_(nbins), nbins_b_(nbins),
00031     nbins_c_(nbins), range_a_(range), range_b_(range), range_c_(range),
00032     delta_a_(0),delta_b_(0), delta_c_(0),
00033     min_a_(0), max_a_(range),
00034     min_b_(0), max_b_(range),
00035     min_c_(0), max_c_(range),
00036     min_prob_(min_prob),
00037     counts_(nbins, nbins, nbins, T(0))
00038 {
00039   bsta_joint_histogram_3d_base::type_ = bsta_joint_histogram_3d_traits<T>::type();
00040 
00041   if (nbins_a_>0&&nbins_b_>0&&nbins_c_>0)
00042   {
00043     delta_a_ = range_a_/nbins_a_;
00044     delta_b_ = range_b_/nbins_b_;
00045     delta_c_ = range_c_/nbins_c_;
00046   }
00047 }
00048 
00049 
00050 template <class T>
00051 bsta_joint_histogram_3d<T>::bsta_joint_histogram_3d(const T range_a,
00052                                                     const unsigned nbins_a,
00053                                                     const T range_b,
00054                                                     const unsigned nbins_b,
00055                                                     const T range_c,
00056                                                     const unsigned nbins_c,
00057                                                     const T min_prob)
00058   : volume_valid_(false), volume_(0), nbins_a_(nbins_a), nbins_b_(nbins_b),
00059     nbins_c_(nbins_c), range_a_(range_a), range_b_(range_b),range_c_(range_c),
00060     delta_a_(0),delta_b_(0),delta_c_(0),
00061     min_a_(0), max_a_(range_a), min_b_(0), max_b_(range_b),
00062     min_c_(0), max_c_(range_c), min_prob_(min_prob),
00063     counts_(nbins_a, nbins_b, nbins_c, T(0))
00064 {
00065   bsta_joint_histogram_3d_base::type_ = bsta_joint_histogram_3d_traits<T>::type();
00066 
00067   if (nbins_a_>0&&nbins_b_>0&&nbins_c_>0)
00068   {
00069     delta_a_ = range_a_/nbins_a_;
00070     delta_b_ = range_b_/nbins_b_;
00071     delta_c_ = range_c_/nbins_c_;
00072   }
00073 }
00074 
00075 template <class T>
00076 bsta_joint_histogram_3d<T>::bsta_joint_histogram_3d(const T min, const T max,
00077                                                     const unsigned nbins,
00078                                                     const T min_prob)
00079  : volume_valid_(false), volume_(0), nbins_a_(nbins), nbins_b_(nbins),
00080     nbins_c_(nbins), min_a_(min), max_a_(max), min_b_(min), max_b_(max),
00081     min_c_(min), max_c_(max), min_prob_(min_prob),
00082     counts_(nbins, nbins, nbins, T(0))
00083 {
00084   bsta_joint_histogram_3d_base::type_ = bsta_joint_histogram_3d_traits<T>::type();
00085 
00086   if (nbins>0) {
00087     range_a_ = max-min;
00088     delta_a_ = range_a_/nbins;
00089     range_b_ = range_a_;
00090     delta_b_ = delta_a_;
00091     range_c_ = range_a_;
00092     delta_c_ = delta_a_;
00093   }
00094   else {
00095     range_a_ = 0;
00096     delta_a_ = 0;
00097     range_b_ = 0;
00098     delta_b_ = 0;
00099     range_c_ = 0;
00100     delta_c_ = 0;
00101   }
00102 }
00103 
00104 template <class T>
00105 bsta_joint_histogram_3d<T>::bsta_joint_histogram_3d(const T min_a, const T max_a,
00106                                                     const unsigned nbins_a,
00107                                                     const T min_b, const T max_b,
00108                                                     const unsigned nbins_b,
00109                                                     const T min_c, const T max_c,
00110                                                     const unsigned nbins_c,
00111                                                     const T min_prob)
00112   : volume_valid_(false), volume_(0), nbins_a_(nbins_a), nbins_b_(nbins_b),
00113     nbins_c_(nbins_c), min_a_(min_a), max_a_(max_a),
00114     min_b_(min_b), max_b_(max_b),
00115     min_c_(min_c), max_c_(max_c),
00116     min_prob_(min_prob),
00117     counts_(nbins_a, nbins_b, nbins_c, T(0))
00118 {
00119   bsta_joint_histogram_3d_base::type_ = bsta_joint_histogram_3d_traits<T>::type();
00120 
00121   if (nbins_a>0) {
00122     range_a_ = max_a-min_a;
00123     delta_a_ = range_a_/nbins_a;
00124   }
00125   else {
00126     range_a_ = 0;
00127     delta_a_ = 0;
00128   }
00129   if (nbins_b>0) {
00130     range_b_ = max_b-min_b;
00131     delta_b_ = range_b_/nbins_b;
00132   }
00133   else {
00134     range_b_ = 0;
00135     delta_b_ = 0;
00136   }
00137   if (nbins_c>0) {
00138     range_c_ = max_c-min_c;
00139     delta_c_ = range_c_/nbins_c;
00140   }
00141   else {
00142     range_c_ = 0;
00143     delta_c_ = 0;
00144   }
00145 }
00146 
00147 template <class T>
00148 void bsta_joint_histogram_3d<T>::upcount(T a, T mag_a,
00149                                          T b, T mag_b,
00150                                          T c, T mag_c)
00151 {
00152   if (a<min_a_||a>max_a_)
00153     return;
00154   if (b<min_b_||b>max_b_)
00155     return;
00156   if (c<min_c_||c>max_c_)
00157     return;
00158   int bin_a =-1, bin_b = -1, bin_c = -1;
00159   for (unsigned i = 0; i<nbins_a_; i++)
00160     if ((i+1)*delta_a_>=(a-min_a_))
00161     {
00162       bin_a = i;
00163       break;
00164     }
00165   for (unsigned i = 0; i<nbins_b_; i++)
00166     if ((i+1)*delta_b_>=(b-min_b_))
00167     {
00168       bin_b = i;
00169       break;
00170     }
00171   for (unsigned i = 0; i<nbins_c_; i++)
00172     if ((i+1)*delta_c_>=(c-min_c_))
00173     {
00174       bin_c = i;
00175       break;
00176     }
00177   if (bin_a<0||bin_b<0||bin_c<0) return;
00178   T v = counts_[bin_a][bin_b][bin_c] + mag_a + mag_b + mag_c;
00179   counts_[bin_a][bin_b][bin_c]=v;
00180   volume_valid_ = false;
00181 }
00182 
00183 template <class T>
00184 void bsta_joint_histogram_3d<T>::compute_volume() const
00185 {
00186   volume_=0;
00187   for (unsigned a = 0; a<nbins_a_; a++)
00188     for (unsigned b =0; b<nbins_b_; b++)
00189       for (unsigned c =0; c<nbins_c_; c++)
00190         volume_ += counts_[a][b][c];
00191   volume_valid_ = true;
00192 }
00193 
00194 template <class T>
00195 T bsta_joint_histogram_3d<T>::p(unsigned a, unsigned b, unsigned c) const
00196 {
00197   if (a>=nbins_a_)
00198     return 0;
00199   if (b>=nbins_b_)
00200     return 0;
00201   if (c>=nbins_c_)
00202     return 0;
00203   if (!volume_valid_)
00204     compute_volume();
00205   if (volume_ == T(0))
00206     return 0;
00207   else
00208     return counts_[a][b][c]/volume_;
00209 }
00210 
00211 template <class T>
00212 T bsta_joint_histogram_3d<T>::p(T a, T b, T c) const
00213 {
00214   if (a<min_a_||a>max_a_)
00215     return 0;
00216   if (b<min_b_||b>max_b_)
00217     return 0;
00218   if (c<min_c_||c>max_c_)
00219     return 0;
00220   if (!volume_valid_)
00221     compute_volume();
00222   if (volume_ == T(0))
00223     return 0;
00224   unsigned bina = 0, binb = 0, binc = 0;
00225   bool found = false;
00226   for (unsigned ia = 0; (ia<nbins_a_)&&!found; ++ia)
00227     if ((ia+1)*delta_a_>=(a-min_a_)) {
00228       bina = ia;
00229       found = true;
00230     }
00231   if (!found)
00232     return 0;
00233   found = false;
00234   for (unsigned ib = 0; (ib<nbins_b_)&&!found; ++ib)
00235     if ((ib+1)*delta_b_>=(b-min_b_)) {
00236       binb = ib;
00237       found = true;
00238     }
00239   if (!found)
00240     return 0;
00241   found = false;
00242   for (unsigned ic = 0; (ic<nbins_c_)&&!found; ++ic)
00243     if ((ic+1)*delta_c_>=(c-min_c_)) {
00244       binc = ic;
00245       found = true;
00246     }
00247   if (!found)
00248     return 0;
00249   return counts_[bina][binb][binc]/volume_;
00250 }
00251 
00252 template <class T>
00253 void bsta_joint_histogram_3d<T>::parzen(const T sigma)
00254 {
00255   if (sigma<=0)
00256     return;
00257   double sd = (double)sigma;
00258   vbl_array_3d<double> in(nbins_a_, nbins_b_, nbins_c_), out;
00259   for (unsigned int a = 0; a<nbins_a_; a++)
00260     for (unsigned int b = 0; b<nbins_b_; b++)
00261       for (unsigned int c = 0; c<nbins_c_; c++)
00262       in[a][b][c] = (double)counts_[a][b][c];
00263 
00264   bsta_gauss::bsta_3d_gaussian(sd, in, out);
00265 
00266   for (unsigned int a = 0; a<nbins_a_; a++)
00267     for (unsigned int b = 0; b<nbins_b_; b++)
00268       for (unsigned int c = 0; c<nbins_c_; c++)
00269         counts_[a][b][c] = (T)out[a][b][c];
00270 }
00271 
00272 //: The average and variance bin value for row a using counts to compute probs
00273 //  T avg_and_variance_bin_for_row_a(const unsigned a) const;
00274 #if 0
00275 template <class T>
00276 bool bsta_joint_histogram_3d<T>::avg_and_variance_bin_for_row_a(const unsigned a, T & avg, T & var) const
00277 {
00278   if (a >= nbins_a_)
00279     return false;
00280 
00281   T sum = 0;
00282   for (unsigned b =0; b<nbins_b_; b++)
00283     sum += counts_[a][b];
00284 
00285   if (sum <= 0)
00286     return false;
00287 
00288   avg = 0;
00289   for (unsigned b =0; b<nbins_b_; b++)
00290     avg += ((b+1)*delta_b_/2)*(counts_[a][b]/sum);
00291 
00292   var = 0;
00293   for (unsigned b =0; b<nbins_b_; b++) {
00294     T dif = (b+1)*delta_b_/2-avg;
00295     var += vcl_pow(dif, T(2.0))*(counts_[a][b]/sum);
00296   }
00297 
00298   return true;
00299 }
00300 #endif
00301 template <class T>
00302 T bsta_joint_histogram_3d<T>::volume() const
00303 {
00304   if (!volume_valid_)
00305     compute_volume();
00306   return volume_;
00307 }
00308 
00309 template <class T>
00310 T bsta_joint_histogram_3d<T>::entropy() const
00311 {
00312   T ent = 0;
00313   for (unsigned i = 0; i<nbins_a_; ++i)
00314     for (unsigned j = 0; j<nbins_b_; ++j)
00315       for (unsigned k = 0; k<nbins_c_; ++k)
00316       {
00317         T pijk = this->p(i,j,k);
00318         if (pijk>min_prob_)
00319           ent -= pijk*T(vcl_log(pijk));
00320       }
00321   ent *= (T)vnl_math::log2e;
00322   return ent;
00323 }
00324 
00325 #if 0
00326 template <class T>
00327 void bsta_joint_histogram_3d<T>::parzen(const T sigma)
00328 {
00329   if (sigma<=0)
00330     return;
00331   double sd = (double)sigma;
00332   vbl_array_2d<double> in(nbins_a_, nbins_b_), out;
00333   for (unsigned row = 0; row<nbins_a_; row++)
00334     for (unsigned col = 0; col<nbins_b_; col++)
00335       in[row][col] = (double)counts_[row][col];
00336 
00337   bsta_gauss::bsta_2d_gaussian(sd, in, out);
00338 
00339   for (unsigned row = 0; row<nbins_a_; row++)
00340     for (unsigned col = 0; col<nbins_b_; col++)
00341       counts_[row][col] = (T)out[row][col];
00342 }
00343 #endif
00344 
00345 template <class T>
00346 T bsta_joint_histogram_3d<T>::get_count(T a, T b, T c) const
00347 {
00348   T pv = this->p(a,b,c);
00349   if (volume_valid_)
00350     return pv*volume_;
00351   return pv*this->volume();
00352 }
00353 
00354 template <class T>
00355 void bsta_joint_histogram_3d<T>::clear()
00356 {
00357   volume_valid_ = false;
00358   volume_ = 0;
00359   counts_.fill(T(0));
00360 }
00361 
00362 template <class T>
00363 void bsta_joint_histogram_3d<T>::print(vcl_ostream& os) const
00364 {
00365   for (unsigned a = 0; a<nbins_a_; a++)
00366     for (unsigned b = 0; b<nbins_b_; b++)
00367       for (unsigned c = 0; c<nbins_c_; c++)
00368         if (p(a,b,c) > 0)
00369           os << "p[" << a << "][" << b << "][" << c << "]=" << p(a,b,c) << '\n';
00370 }
00371 
00372 template <class T>
00373 void bsta_joint_histogram_3d<T>::print_to_vrml(vcl_ostream& os,
00374                                                bool relative_prob_scale,
00375                                                T red, T green, T blue) const
00376 {
00377   // we need to scale the display, find magnitude of largest value
00378   T max = (T)0;
00379   T min_delta = delta_a_;
00380   if (delta_b_<min_delta)
00381     min_delta = delta_b_;
00382   if (delta_c_<min_delta)
00383     min_delta = delta_c_;
00384   T rad_scale = min_delta/2;
00385   if (relative_prob_scale){
00386   for (unsigned a = 0; a<nbins_a_; a++)
00387     for (unsigned b = 0; b<nbins_b_; b++)
00388       for (unsigned c = 0; c<nbins_c_; c++){
00389         T v = p(a,b,c);
00390         if (v > max)
00391           max = v;
00392       }
00393   if (max <= T(0)) return;
00394   rad_scale = min_delta/max/2;
00395   }
00396   os << "#VRML V2.0 utf8\n"
00397      << "Group { children [\n";
00398 
00399   for (unsigned a = 0; a<nbins_a_; a++)
00400   {
00401     for (unsigned b = 0; b<nbins_b_; b++)
00402     {
00403       for (unsigned c = 0; c<nbins_c_; c++)
00404       {
00405         T v = p(a,b,c);
00406         if (v>min_prob_)
00407           os << "Transform {\n"
00408              << "  translation " << a*delta_a_ << ' ' << b*delta_b_
00409              << ' ' << c*delta_c_ << '\n'
00410              << "  children Shape {\n"
00411              << "    geometry Sphere { radius " <<  rad_scale*v << "}\n"
00412              << "    appearance DEF A1 Appearance {"
00413              << "      material Material {\n"
00414              << "        diffuseColor " << red << ' '
00415              << green << ' ' << blue << '\n'
00416              << "        emissiveColor .3 0 0\n"
00417              << "      }\n"
00418              << "    }\n"
00419              << "  }\n"
00420              << "}\n";
00421       }
00422     }
00423   }
00424   // The bounding box for the 3-d grid
00425   os << "Transform {\n"
00426      << "  translation " << delta_a_*(nbins_a_-1)/2.0f << ' '
00427      << delta_b_*(nbins_b_-1)/2.0f << ' ' << delta_c_*(nbins_c_-1)/2.0f << '\n'
00428      << "  children Shape {\n"
00429      << "    geometry Box { size " << delta_a_*(nbins_a_-1)
00430      << ' ' << delta_b_*(nbins_b_-1)
00431      << ' ' << delta_c_*(nbins_c_-1) << " }\n"
00432      << "    appearance Appearance {\n"
00433      << "      material Material {\n"
00434      << "       diffuseColor 1 1 1\n"
00435      << "       transparency 0.8\n"
00436      << "    }\n"
00437      << "  }\n"
00438      << "}\n"
00439   // the "a" axis
00440      << "Transform {\n"
00441      << "  translation " << 0.0 << ' '
00442      << -delta_b_*(nbins_b_-1)/2.0f <<' '<<-delta_c_*(nbins_c_-1)/2.0f << '\n'
00443      << "  children Shape {\n"
00444      << "    geometry Box { size " << delta_a_*(nbins_a_-1)
00445      << ' ' << 0.05*min_delta
00446      << ' ' << 0.05*min_delta << " }\n"
00447      << "    appearance Appearance {\n"
00448      << "      material Material {\n"
00449      << "       emissiveColor 1 0 0\n"
00450      << "       transparency 0.0\n"
00451      << "    }\n"
00452      << "  }\n"
00453      << "}\n"
00454   // the "b" axis
00455      << "Transform {\n"
00456      << "  translation " << -delta_a_*(nbins_a_-1)/2.0f << ' '
00457      << delta_b_*(nbins_b_-1)/2.0f <<' '<< 0.0 << '\n'
00458      << "  children Shape {\n"
00459      << "    geometry Box { size " << 0.05*min_delta
00460      << ' ' << delta_b_*(nbins_b_-1)
00461      << ' ' << 0.05*min_delta << " }\n"
00462      << "    appearance Appearance {\n"
00463      << "      material Material {\n"
00464      << "       emissiveColor 0 1 0\n"
00465      << "       transparency 0.0\n"
00466      << "    }\n"
00467      << "  }\n"
00468      << "}\n"
00469   // the "c" axis
00470      << "Transform {\n"
00471      << "  translation " << 0.0 << ' '
00472      << -delta_b_*(nbins_b_-1)/2.0f <<' '<< delta_c_*(nbins_c_-1)/2.0f << '\n'
00473      << "  children Shape {\n"
00474      << "    geometry Box { size " << 0.05*min_delta
00475      << ' ' << 0.05*min_delta
00476      << ' ' << delta_c_*(nbins_c_-1)  << " }\n"
00477      << "    appearance Appearance {\n"
00478      << "      material Material {\n"
00479      << "       emissiveColor 0 0 1\n"
00480      << "       transparency 0.0\n"
00481      << "    }\n"
00482      << "  }\n"
00483      << "}\n"
00484   // the background
00485      << "Background { skyColor 1 1 1 }\n"
00486      << "NavigationInfo { type \"EXAMINE\" }\n"
00487      << "] }\n";
00488 }
00489 
00490 #if 0
00491 template <class T>
00492 void bsta_joint_histogram_3d<T>::print_to_m(vcl_ostream& os) const
00493 {
00494   os << "y = zeros(" << nbins_a_ << ", " << nbins_b_ << ");\n";
00495   for (unsigned a = 0; a<nbins_a_; a++) {
00496     for (unsigned b = 0; b<nbins_b_; b++) {
00497       if (p(a,b) > 0) {
00498         os << "y(" << a+1 << ", " << b+1 << ") = " << p(a,b) << "; ";
00499         //os << "y(" << a+1 << ", " << b+1 << ") = " << counts_[a][b] << "; ";
00500       }
00501     }
00502     //os << '\n';
00503   }
00504   //os << '\n';
00505   os << "bar3(y,'detached');\n";
00506 }
00507 #endif // 0
00508 
00509 template <class T>
00510 void bsta_joint_histogram_3d<T>::print_to_text(vcl_ostream& os) const
00511 {
00512   os << "nbins_a \t nbins_b \t nbins_c\n"
00513      << nbins_a_ << '\t' << nbins_b_ << '\t' << nbins_c_ << '\n';
00514 
00515   for (unsigned a = 0; a<nbins_a_; a++)
00516   {
00517     for (unsigned b = 0; b<nbins_b_; b++)
00518     {
00519       for (unsigned c = 0; c<nbins_c_; c++)
00520       {
00521         os << get_count(a,b,c) << '\t';
00522       }
00523       os << '\n';
00524     }
00525     os << '\n';
00526   }
00527   os << "\n probs:\n";
00528   for (unsigned a = 0; a<nbins_a_; a++)
00529   {
00530     for (unsigned b = 0; b<nbins_b_; b++)
00531     {
00532       for (unsigned c = 0; c<nbins_c_; c++)
00533       {
00534         os << p(a,b,c) << '\t';
00535       }
00536       os << '\n';
00537     }
00538     os << '\n';
00539   }
00540 }
00541 
00542 #undef BSTA_JOINT_HISTOGRAM_3D_INSTANTIATE
00543 #define BSTA_JOINT_HISTOGRAM_3D_INSTANTIATE(T) \
00544 template class bsta_joint_histogram_3d<T >
00545 
00546 #endif // bsta_joint_histogram_3d_txx_