00001 #ifndef bsta_joint_histogram_txx_
00002 #define bsta_joint_histogram_txx_
00003
00004
00005 #include "bsta_joint_histogram.h"
00006
00007 #include <vcl_cmath.h>
00008 #include <vcl_iostream.h>
00009 #include "bsta_gauss.h"
00010 #include <vnl/vnl_math.h>
00011 template <class T>
00012 bsta_joint_histogram<T>::bsta_joint_histogram()
00013 : volume_valid_(false), volume_(0),
00014 nbins_a_(1), nbins_b_(1),
00015 range_a_(0), range_b_(0),
00016 delta_a_(0), delta_b_(0),
00017 min_a_(0), max_a_(0),
00018 min_b_(0), max_b_(0),
00019 min_prob_(0),
00020 counts_(1, 1, T(0))
00021 {
00022 bsta_joint_histogram_base::type_ = bsta_joint_histogram_traits<T>::type();
00023 }
00024
00025 template <class T>
00026 bsta_joint_histogram<T>::bsta_joint_histogram(const T range,
00027 const unsigned int nbins,
00028 const T min_prob)
00029 : volume_valid_(false), volume_(0), nbins_a_(nbins), nbins_b_(nbins),
00030 range_a_(range), range_b_(range),delta_a_(0),delta_b_(0), min_a_(0),
00031 max_a_(range), min_b_(0), max_b_(range), min_prob_(min_prob),
00032 counts_(nbins, nbins, T(0))
00033 {
00034 bsta_joint_histogram_base::type_ = bsta_joint_histogram_traits<T>::type();
00035 if (nbins_a_>0&&nbins_b_>0)
00036 {
00037 delta_a_ = range_a_/nbins_a_;
00038 delta_b_ = range_b_/nbins_b_;
00039 }
00040 }
00041
00042 template <class T>
00043 bsta_joint_histogram<T>::bsta_joint_histogram(const T range_a,
00044 const unsigned int nbins_a,
00045 const T range_b,
00046 const unsigned int nbins_b,
00047 const T min_prob)
00048 : volume_valid_(false), volume_(0), nbins_a_(nbins_a), nbins_b_(nbins_b),
00049 range_a_(range_a), range_b_(range_b),delta_a_(0),delta_b_(0),min_a_(0),
00050 max_a_(range_a), min_b_(0), max_b_(range_b), min_prob_(min_prob),
00051 counts_(nbins_a, nbins_b, T(0))
00052 {
00053 bsta_joint_histogram_base::type_ = bsta_joint_histogram_traits<T>::type();
00054 if (nbins_a_>0&&nbins_b_>0)
00055 {
00056 delta_a_ = range_a_/nbins_a_;
00057 delta_b_ = range_b_/nbins_b_;
00058 }
00059 }
00060
00061 template <class T>
00062 bsta_joint_histogram<T>::bsta_joint_histogram(const T min_a, const T max_a,
00063 const unsigned int nbins_a,
00064 const T min_b, const T max_b,
00065 const unsigned int nbins_b,
00066 const T min_prob)
00067 : volume_valid_(false), volume_(0), nbins_a_(nbins_a), nbins_b_(nbins_b),
00068 min_a_(min_a), max_a_(max_a), min_b_(min_b), max_b_(max_b),
00069 min_prob_(min_prob), counts_(nbins_a, nbins_b, T(0))
00070 {
00071 bsta_joint_histogram_base::type_ = bsta_joint_histogram_traits<T>::type();
00072 if (nbins_a>0) {
00073 range_a_ = max_a-min_a;
00074 delta_a_ = range_a_/nbins_a;
00075 }
00076 else {
00077 range_a_ = 0;
00078 delta_a_ = 0;
00079 }
00080 if (nbins_b>0) {
00081 range_b_ = max_b-min_b;
00082 delta_b_ = range_b_/nbins_b;
00083 }
00084 else {
00085 range_b_ = 0;
00086 delta_b_ = 0;
00087 }
00088 }
00089
00090 template <class T>
00091 void bsta_joint_histogram<T>::upcount(T a, T mag_a,
00092 T b, T mag_b)
00093 {
00094 if (a<min_a_||a>max_a_)
00095 return;
00096 if (b<min_b_||b>max_b_)
00097 return;
00098 int bin_a =-1, bin_b = -1;
00099 for (unsigned int i = 0; i<nbins_a_; i++)
00100 if ((i+1)*delta_a_>=(a-min_a_))
00101 {
00102 bin_a = i;
00103 break;
00104 }
00105 for (unsigned int i = 0; i<nbins_b_; i++)
00106 if ((i+1)*delta_b_>=(b-min_b_))
00107 {
00108 bin_b = i;
00109 break;
00110 }
00111 if (bin_a<0||bin_b<0) return;
00112 T v = counts_[bin_a][bin_b]+ mag_a + mag_b;
00113 counts_.put(bin_a, bin_b, v);
00114 volume_valid_ = false;
00115 }
00116
00117 template <class T>
00118 void bsta_joint_histogram<T>::compute_volume() const
00119 {
00120 volume_=0;
00121 for (unsigned int a = 0; a<nbins_a_; a++)
00122 for (unsigned int b =0; b<nbins_b_; b++)
00123 volume_ += counts_[a][b];
00124 volume_valid_ = true;
00125 }
00126
00127 template <class T>
00128 T bsta_joint_histogram<T>::p(unsigned int a, unsigned int b) const
00129 {
00130 if (a>=nbins_a_)
00131 return 0;
00132 if (b>=nbins_b_)
00133 return 0;
00134 if (!volume_valid_)
00135 compute_volume();
00136 if (volume_ == T(0))
00137 return 0;
00138 else
00139 return counts_[a][b]/volume_;
00140 }
00141
00142 template <class T>
00143 T bsta_joint_histogram<T>::p(T a, T b) const
00144 {
00145 if (a<min_a_||a>max_a_)
00146 return 0;
00147 if (b<min_b_||b>max_b_)
00148 return 0;
00149 if (!volume_valid_)
00150 compute_volume();
00151 if (volume_ == T(0))
00152 return 0;
00153 unsigned r = 0, c = 0;
00154 bool found = false;
00155 for (unsigned ia = 0; (ia<nbins_a_)&&!found; ++ia)
00156 if ((ia+1)*delta_a_>=(a-min_a_)) {
00157 r = ia;
00158 found = true;
00159 }
00160 if (!found)
00161 return 0;
00162 found = false;
00163 for (unsigned ib = 0; (ib<nbins_b_)&&!found; ++ib)
00164 if ((ib+1)*delta_b_>=(b-min_b_)) {
00165 c = ib;
00166 found = true;
00167 }
00168 if (!found)
00169 return false;
00170 return counts_[r][c]/volume_;
00171 }
00172
00173
00174
00175 template <class T>
00176 bool bsta_joint_histogram<T>::avg_and_variance_bin_for_row_a(const unsigned int a, T & avg, T & var) const
00177 {
00178 if (a >= nbins_a_)
00179 return false;
00180
00181 T sum = 0;
00182 for (unsigned int b =0; b<nbins_b_; b++)
00183 sum += counts_[a][b];
00184
00185 if (sum <= 0)
00186 return false;
00187
00188 avg = 0;
00189 for (unsigned int b =0; b<nbins_b_; b++)
00190 avg += ((b+1)*delta_b_/2)*(counts_[a][b]/sum);
00191
00192 var = 0;
00193 for (unsigned int b =0; b<nbins_b_; b++) {
00194 T dif = (b+1)*delta_b_/2-avg;
00195 var += vcl_pow(dif, T(2.0))*(counts_[a][b]/sum);
00196 }
00197
00198 return true;
00199 }
00200
00201 template <class T>
00202 T bsta_joint_histogram<T>::volume() const
00203 {
00204 if (!volume_valid_)
00205 compute_volume();
00206 return volume_;
00207 }
00208
00209 template <class T>
00210 T bsta_joint_histogram<T>::entropy() const
00211 {
00212 T ent = 0;
00213 for (unsigned int i = 0; i<nbins_a_; ++i)
00214 for (unsigned int j = 0; j<nbins_b_; ++j)
00215 {
00216 T pij = this->p(i,j);
00217 if (pij>min_prob_)
00218 ent -= pij*T(vcl_log(pij));
00219 }
00220 ent *= (T)vnl_math::log2e;
00221 return ent;
00222 }
00223
00224 template <class T>
00225 T bsta_joint_histogram<T>::mutual_information() const
00226 {
00227 T mutual_information = T(0);
00228
00229
00230 vcl_vector<T> pa(nbins_a_,T(0)),pb(nbins_b_,T(0));
00231 for (unsigned a = 0; a < nbins_a_; ++a)
00232 for (unsigned b = 0; b < nbins_b_; ++b)
00233 {
00234 pa[a] += this->p(a,b);
00235 pb[b] += this->p(a,b);
00236 }
00237
00238
00239 for (unsigned a = 0; a < nbins_a_; ++a)
00240 for (unsigned b = 0; b < nbins_b_; ++b)
00241 if (p(a,b) != 0 && pa[a] != 0 && pb[b] != 0)
00242 mutual_information+=this->p(a,b)*(vcl_log(this->p(a,b)) - (vcl_log(pa[a]) + vcl_log(pb[b])) );
00243
00244
00245 mutual_information *= (T)vnl_math::log2e;
00246
00247 return mutual_information;
00248 }
00249
00250 template <class T>
00251 T bsta_joint_histogram<T>::renyi_entropy() const
00252 {
00253 T ent = 0, sum = 0;
00254 for (unsigned int i = 0; i<nbins_a_; ++i)
00255 for (unsigned int j = 0; j<nbins_b_; ++j)
00256 {
00257 T pij = this->p(i,j);
00258 sum += pij*pij;
00259 }
00260 if (sum>min_prob_)
00261 ent = - T(vcl_log(sum))*(T)vnl_math::log2e;
00262 return ent;
00263 }
00264
00265 template <class T>
00266 T bsta_joint_histogram<T>::entropy_marginal_a() const
00267 {
00268 T ent = 0;
00269 vcl_vector<T> counts_a(nbins_a_, T(0));
00270 T count_a_sum = T(0);
00271 for (unsigned int i = 0; i<nbins_a_; ++i)
00272 for (unsigned int j = 0; j <nbins_b_; ++j)
00273 {
00274 counts_a[i] += this->get_count(i,j);
00275 count_a_sum += this->get_count(i,j);
00276 }
00277
00278 for (unsigned int i = 0; i <nbins_a_; ++i) {
00279 T pi = counts_a[i]/count_a_sum;
00280 if (pi>min_prob_)
00281 ent -= pi*T(vcl_log(pi));
00282 }
00283 ent *= (T)vnl_math::log2e;
00284 return ent;
00285 }
00286
00287 template <class T>
00288 void bsta_joint_histogram<T>::parzen(const T sigma)
00289 {
00290 if (sigma<=0)
00291 return;
00292 double sd = (double)sigma;
00293 vbl_array_2d<double> in(nbins_a_, nbins_b_), out;
00294 for (unsigned int row = 0; row<nbins_a_; row++)
00295 for (unsigned int col = 0; col<nbins_b_; col++)
00296 in[row][col] = (double)counts_[row][col];
00297
00298 bsta_gauss::bsta_2d_gaussian(sd, in, out);
00299
00300 for (unsigned int row = 0; row<nbins_a_; row++)
00301 for (unsigned int col = 0; col<nbins_b_; col++)
00302 counts_[row][col] = (T)out[row][col];
00303 }
00304
00305 template <class T>
00306 T bsta_joint_histogram<T>::get_count(T a, T b) const
00307 {
00308 T pv = this->p(a,b);
00309 if (volume_valid_)
00310 return pv*volume_;
00311 return pv*this->volume();
00312 }
00313
00314 template <class T>
00315 void bsta_joint_histogram<T>::clear()
00316 {
00317 volume_valid_ = false;
00318 volume_ = 0;
00319 counts_.fill(T(0));
00320 }
00321
00322 template <class T>
00323 void bsta_joint_histogram<T>::print(vcl_ostream& os) const
00324 {
00325 for (unsigned int a = 0; a<nbins_a_; a++)
00326 for (unsigned int b = 0; b<nbins_b_; b++)
00327 if (p(a,b) > 0)
00328 os << "p[" << a << "][" << b << "]=" << p(a,b) << '\n';
00329 }
00330
00331 template <class T>
00332 void bsta_joint_histogram<T>::print_to_vrml(vcl_ostream& os) const
00333 {
00334
00335 T max = (T)0;
00336 for (unsigned int a = 0; a<nbins_a_; a++)
00337 for (unsigned int b = 0; b<nbins_b_; b++)
00338 if (p(a,b) > max)
00339 max = p(a,b);
00340 float avg = static_cast<float>(0.5*(nbins_a_ + nbins_b_));
00341 os << "#VRML V2.0 utf8\n"
00342 << "Group { children [\n";
00343
00344 for (unsigned int a = 0; a<nbins_a_; a++)
00345 {
00346 for (unsigned int b = 0; b<nbins_b_; b++)
00347 {
00348 float height = (max > 0) ? float((p(a,b)/max)*avg) : 0.0f;
00349 os << "Transform {\n"
00350 << " translation " << a << ' ' << b << ' ' << height << '\n'
00351 << " children Shape {\n"
00352 << " geometry Sphere { radius 0.2 }\n"
00353 << " appearance DEF A1 Appearance {"
00354 << " material Material {\n"
00355 << " diffuseColor 1 0 0\n"
00356 << " emissiveColor .3 0 0\n"
00357 << " }\n"
00358 << " }\n"
00359 << " }\n"
00360 << "}\n"
00361 << "Transform {\n"
00362 << " translation " << a << ' ' << b << ' ' << height/2.0 << '\n'
00363 << " rotation 1 0 0 " << vnl_math::pi/2.0 << '\n'
00364 << " children Shape {\n"
00365 << " appearance USE A1\n"
00366 << " geometry Cylinder { radius 0.05 height " << height << " }\n"
00367 << " }\n"
00368 << "}\n";
00369 }
00370 }
00371 os << "Transform {\n"
00372 << " translation " << (nbins_a_-1)/2.0f << ' ' << (nbins_b_-1)/2.0f << " 0\n"
00373 << " children Shape {\n"
00374 << " geometry Box { size " << nbins_a_-1 << ' ' << nbins_b_-1 << " 0.3 }\n"
00375 << " appearance Appearance {\n"
00376 << " material Material { diffuseColor 0.8 0.8 0.8 }\n"
00377 << " }\n"
00378 << " }\n"
00379 << "}\n"
00380
00381 << "Transform {\n"
00382 << " translation 0.0 0.0 0.0\n"
00383 << " children Shape {\n"
00384 << " geometry Box { size " << "1.0 1.0 1.0 }\n"
00385 << " appearance Appearance {\n"
00386 << " material Material { diffuseColor 0.0 1.0 0.0 }\n"
00387 << " }\n"
00388 << " }\n"
00389 << "}\n"
00390
00391 << "Transform {\n"
00392 << " translation " << (nbins_a_-1)/2.0f << " 0 0\n"
00393 << " children Shape {\n"
00394 << " geometry Box { size " << (nbins_a_-1) << " 0.5 0.5 }\n"
00395 << " appearance Appearance {\n"
00396 << " material Material { diffuseColor 1.0 0.0 0.0 }\n"
00397 << " }\n"
00398 << " }\n"
00399 << "}\n"
00400
00401 << "Transform {\n"
00402 << " translation 0 " << (nbins_b_-1)/2.0f << " 0\n"
00403 << " children Shape {\n"
00404 << " geometry Box { size " << 0.5 << ' ' << (nbins_b_-1) << " 0.5 }\n"
00405 << " appearance Appearance {\n"
00406 << " material Material { diffuseColor 0.0 0.8 0.8 }\n"
00407 << " }\n"
00408 << " }\n"
00409 << "}\n"
00410
00411 << "Background { skyColor 1 1 1 }\n"
00412 << "NavigationInfo { type \"EXAMINE\" }\n"
00413 << "] }\n";
00414 }
00415
00416 template <class T>
00417 void bsta_joint_histogram<T>::print_to_m(vcl_ostream& os) const
00418 {
00419 os << "y = zeros(" << nbins_a_ << ", " << nbins_b_ << ");\n";
00420 for (unsigned int a = 0; a<nbins_a_; a++) {
00421 for (unsigned int b = 0; b<nbins_b_; b++) {
00422 if (p(a,b) > 0) {
00423 os << "y(" << a+1 << ", " << b+1 << ") = " << p(a,b) << "; ";
00424
00425 }
00426 }
00427
00428 }
00429
00430 os << "bar3(y,'detached');\n";
00431 }
00432
00433 template <class T>
00434 void bsta_joint_histogram<T>::print_to_text(vcl_ostream& os) const
00435 {
00436 os << nbins_a_ << '\t' << nbins_b_ << '\n';
00437 for (unsigned int a = 0; a<nbins_a_; a++)
00438 {
00439 for (unsigned int b = 0; b<nbins_b_; b++)
00440 {
00441 os << get_count(a,b) << '\t';
00442 }
00443 os << '\n';
00444 }
00445 os << "\n probs:\n";
00446 for (unsigned int a = 0; a<nbins_a_; a++)
00447 {
00448 for (unsigned int b = 0; b<nbins_b_; b++)
00449 {
00450 os << p(a,b) << '\t';
00451 }
00452 os << '\n';
00453 }
00454 }
00455
00456 #undef BSTA_JOINT_HISTOGRAM_INSTANTIATE
00457 #define BSTA_JOINT_HISTOGRAM_INSTANTIATE(T) \
00458 template class bsta_joint_histogram<T >
00459
00460 #endif // bsta_joint_histogram_txx_