00001 #ifndef bsta_joint_histogram_3d_txx_
00002 #define bsta_joint_histogram_3d_txx_
00003
00004
00005 #include "bsta_joint_histogram_3d.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_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
00273
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
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
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
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
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
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
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
00500 }
00501 }
00502
00503 }
00504
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_