00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef OLENA_UTILS_HISTOGRAM_HH
00029 # define OLENA_UTILS_HISTOGRAM_HH
00030
00031
00032 # include <oln/core/image1d.hh>
00033
00034 # include <oln/core/image3d.hh>
00035
00036 # include <oln/convert/value_to_point.hh>
00037
00038 # include <oln/core/abstract/image.hh>
00039
00040 # include <ntg/core/pred_succ.hh>
00041
00042 # include <vector>
00043
00045 # define oln_cpt_type(H) mlc_exact_type(H)::cpt_type
00046
00047 # define oln_cpt_type_(H) mlc_exact_type_(H)::cpt_type
00048
00049 namespace oln {
00051 namespace utils {
00052
00054 namespace internal {
00056 template <typename T>
00057 struct img_max_size
00058 {
00059 private:
00060 typedef typename ntg_is_a(T, ntg::non_vectorial)::ensure_type
00061 ensure_type;
00062 public:
00063 typedef image1d_size size_type;
00064 typedef T comp_type;
00065
00066 image1d_size
00067 operator()()
00068 {
00069 size_type s(ntg_max_val(comp_type) - ntg_min_val(comp_type) + 1,
00070 1);
00071 return s;
00072 }
00073 };
00074
00075
00076 template <unsigned Qbits, template <unsigned> class S>
00077 struct img_max_size<ntg::color<3, Qbits, S> >
00078 {
00079 public:
00080 typedef image3d_size size_type;
00081 typedef typename ntg::color<3, Qbits, S>::comp_type comp_type;
00082
00083 image3d_size
00084 operator()()
00085 {
00086 size_type s(ntg_max_val(comp_type) - ntg_min_val(comp_type) + 1,
00087 ntg_max_val(comp_type) - ntg_min_val(comp_type) + 1,
00088 ntg_max_val(comp_type) - ntg_min_val(comp_type) + 1,
00089 1);
00090 return s;
00091 }
00092 };
00093 }
00094
00096 template <class Exact>
00097 struct hist_traits
00098 {
00099 };
00100
00101
00103 namespace abstract
00104 {
00109 template<class Exact = mlc::final>
00110 class histogram: public mlc_hierarchy::any<Exact>
00111 {
00112 public:
00113 typedef typename mlc::exact_vt<histogram<Exact>,
00114 Exact>::ret exact_type;
00115 typedef typename hist_traits<exact_type>::cpt_type cpt_type;
00116 typedef typename hist_traits<exact_type>::value_type value_type;
00117
00119 void
00120 clear()
00121 {
00122 this->exact().clear_impl();
00123 }
00125 const cpt_type
00126 operator[](const value_type &v)const
00127 {
00128 return this->exact().at(v);
00129 }
00131 cpt_type&
00132 operator[](const value_type &v)
00133 {
00134 return this->exact().at(v);
00135 }
00140 template <class I>
00141 void
00142 init(const oln::abstract::image<I> &img)
00143 {
00144 return this->exact().init_impl(img.exact());
00145 }
00146 };
00147 }
00148
00149 template<typename T,
00150 typename CPT = unsigned,
00151 class V2P = oln::convert::value_to_point<T>,
00152 class Exact = mlc::final>
00153 class histogram;
00154
00156 template <typename T,
00157 typename CPT,
00158 class V2P,
00159 class Exact>
00160 struct hist_traits<histogram<T, CPT, V2P, Exact> >
00161 {
00162 typedef CPT cpt_type;
00163 typedef T value_type;
00164 typedef V2P value_to_point_type;
00165
00166 typedef typename value_to_point_type::result_type point_type;
00168 enum {dim = point_type::dim};
00169 typedef typename dim_traits<dim, CPT>::img_type img_type;
00171 };
00172
00210 template<typename T,
00211 typename CPT,
00212 class V2P,
00213 class Exact>
00214 class histogram: public abstract::histogram
00215 <typename mlc::exact_vt<histogram<T, CPT, V2P, Exact>, Exact>::ret>
00216 {
00217 public:
00218 typedef typename mlc::exact_vt<histogram<T, CPT, V2P, Exact>,
00219 Exact>::ret exact_type;
00220 typedef typename hist_traits<exact_type>::value_type value_type;
00221 typedef typename hist_traits<exact_type>::cpt_type cpt_type;
00222 typedef typename hist_traits<exact_type>::value_to_point_type
00223 value_to_point_type;
00224 typedef typename hist_traits<exact_type>::point_type point_type;
00225 enum {dim = hist_traits<exact_type>::dim};
00226 typedef typename hist_traits<exact_type>::img_type img_type;
00227
00233 histogram(const value_to_point_type & c2p = value_to_point_type()):
00234 v2p_(c2p), img_(internal::img_max_size<value_type>()())
00235 {
00236 clear();
00237 }
00238
00240 template <class I>
00241 histogram(const oln::abstract::image<I> & input,
00242 const value_to_point_type & v2p = value_to_point_type()):
00243 v2p_(v2p), img_(internal::img_max_size<value_type>()())
00244 {
00245 clear();
00246 init(input);
00247 }
00248
00250 void
00251 clear_impl()
00252 {
00253 typename img_type::iter_type it(img_ );
00254 for_all(it)
00255 img_[it] = ntg_zero_val(cpt_type);
00256 }
00257
00259 const cpt_type
00260 at(const T &v)const
00261 {
00262 return img_[v2p_(v)];
00263 }
00265 cpt_type&
00266 at(const value_type &v)
00267 {
00268 return img_[v2p_(v)];
00269 }
00271 template <class I>
00272 void
00273 init_impl(const oln::abstract::image<I> &img)
00274 {
00275 oln_iter_type(I) it_img(img);
00276
00277 for_all(it_img)
00278 ++img_[v2p_(img[it_img])];
00279 }
00280
00282 const img_type &
00283 image() const
00284 {
00285 return img_;
00286 }
00287
00288 protected:
00289 const value_to_point_type v2p_;
00290 img_type img_;
00291 };
00292
00303 template<class T>
00304 inline oln_value_type(T)
00305 min(const abstract::histogram<T>& hist)
00306 {
00307 typedef typename ntg_is_a(oln_value_type(T),
00308 ntg::non_vectorial)::ensure_type ensure_type;
00309
00310 oln_value_type(T) i;
00311 for (i = ntg_min_val(oln_value_type(T));
00312 i != ntg_max_val(oln_value_type(T));
00313 i = ntg::succ(i))
00314 if (hist[i] > ntg_zero_val(oln_cpt_type(T)))
00315 break;
00316 return i;
00317 }
00328 template<class T>
00329 inline oln_value_type(T)
00330 max(const abstract::histogram<T>& hist)
00331 {
00332 typedef typename ntg_is_a(oln_value_type(T),
00333 ntg::non_vectorial)::ensure_type ensure_type;
00334
00335 oln_value_type(T) i;
00336 for (i = ntg_max_val(oln_value_type(T));
00337 i != ntg_min_val(oln_value_type(T));
00338 i = ntg::pred(i))
00339 if (hist[i] > ntg_zero_val(oln_cpt_type(T)))
00340 break;
00341 return i;
00342 }
00343
00344 template< typename T,
00345 typename CPT = unsigned,
00346 class V2P = convert::value_to_point<T>,
00347 class Exact = mlc::final>
00348 class histogram_minmax;
00349
00350 template <typename T,
00351 typename CPT,
00352 class V2P,
00353 class Exact>
00354 struct hist_traits<histogram_minmax<T, CPT, V2P, Exact> >
00355 : public hist_traits<histogram<T, CPT, V2P, Exact> >
00356 {};
00372 template< typename T,
00373 typename CPT,
00374 class V2P,
00375 class Exact>
00376 class histogram_minmax : public histogram
00377 <T, CPT, V2P,
00378 typename mlc::exact_vt<histogram_minmax<T, CPT, V2P, Exact>,
00379 Exact>::ret>
00380 {
00381 private:
00382 typedef typename ntg_is_a(T, ntg::non_vectorial)::ensure_type
00383 ensure_type;
00384 public:
00385 typedef typename mlc::exact_vt<histogram_minmax<T, CPT, V2P, Exact>,
00386 Exact>::ret exact_type;
00387 typedef typename hist_traits<exact_type>::value_type value_type;
00388 typedef typename hist_traits<exact_type>::cpt_type cpt_type;
00389 typedef typename hist_traits<exact_type>::value_to_point_type
00390 value_to_point_type;
00391 typedef typename hist_traits<exact_type>::point_type point_type;
00392 enum {dim = hist_traits<exact_type>::dim};
00393 typedef typename hist_traits<exact_type>::img_type img_type;
00394 typedef histogram<T, CPT, V2P, exact_type> upper_type;
00395
00396 histogram_minmax(const value_to_point_type & v2p = value_to_point_type()) :
00397 upper_type(v2p),
00398 min_(ntg_min_val(value_type)), max_(ntg_max_val(value_type)) {}
00399
00400 template <class I>
00401 histogram_minmax(const oln::abstract::image<I> & input,
00402 const value_to_point_type & v2p = value_to_point_type()) :
00403 upper_type(input, v2p),
00404 min_(ntg_min_val(value_type)), max_(ntg_max_val(value_type)) {}
00405
00407 const cpt_type
00408 at(const value_type& i) const
00409 {
00410 adjust(i);
00411 return img_[v2p_(i)];
00412 }
00413
00415 cpt_type&
00416 at(const value_type& i)
00417 {
00418 adjust(i);
00419 return img_[v2p_(i)];
00420 }
00421
00423 value_type
00424 min()
00425 {
00426 for (; min_ != ntg_max_val(value_type); min_ = ntg::succ(min_))
00427 if (img_[v2p_(min_)] > ntg_zero_val(cpt_type))
00428 break;
00429 return min_;
00430 }
00432 value_type
00433 max()
00434 {
00435 for (; max_ != ntg_min_val(value_type); max_ = ntg::pred(max_))
00436 if (img_[v2p_(max_)] > ntg_zero_val(cpt_type))
00437 break;
00438 return max_;
00439 }
00440
00441 protected:
00443 void
00444 adjust(const value_type &idx)
00445 {
00446 if (idx > max_)
00447 max_ = idx;
00448 if (idx < min_)
00449 min_ = idx;
00450 }
00451 value_type min_, max_;
00452 };
00453
00454
00455 template< typename T,
00456 typename CPT = unsigned,
00457 class V2P = convert::value_to_point<T>,
00458 class Exact = mlc::final>
00459 class histogram_min;
00460
00461 template <typename T,
00462 typename CPT,
00463 class V2P,
00464 class Exact>
00465 struct hist_traits<histogram_min<T, CPT, V2P, Exact> >
00466 : public hist_traits<histogram<T, CPT, V2P, Exact> >
00467 {};
00468
00473 template< typename T,
00474 typename CPT,
00475 class V2P,
00476 class Exact>
00477 class histogram_min : public histogram<T, CPT, V2P,
00478 typename mlc::exact_vt<histogram_min<T, CPT, V2P, Exact>,
00479 Exact>::ret>
00480 {
00481 private:
00482 typedef typename ntg_is_a(T, ntg::non_vectorial)::ensure_type
00483 ensure_type;
00484
00485 public:
00486 typedef typename mlc::exact_vt<histogram_min<T, CPT, V2P, Exact>,
00487 Exact>::ret exact_type;
00488 typedef typename hist_traits<exact_type>::value_type value_type;
00489 typedef typename hist_traits<exact_type>::cpt_type cpt_type;
00490 typedef typename hist_traits<exact_type>::value_to_point_type
00491 value_to_point_type;
00492 typedef typename hist_traits<exact_type>::point_type point_type;
00493 enum {dim = hist_traits<exact_type>::dim};
00494 typedef typename hist_traits<exact_type>::img_type img_type;
00495 typedef histogram<T, CPT, V2P, exact_type> upper_type;
00496
00497 histogram_min(const value_to_point_type & v2p = value_to_point_type()) :
00498 upper_type(v2p), min_(ntg_min_val(value_type)) {}
00499
00500 template <class I>
00501 histogram_min(const oln::abstract::image<I> & input,
00502 const value_to_point_type & v2p = value_to_point_type()) :
00503 upper_type(input, v2p), min_(ntg_min_val(value_type)) {}
00504
00506 const cpt_type
00507 at(const value_type& i) const
00508 {
00509 return img_[v2p_(i)];
00510 }
00511
00513 cpt_type&
00514 at(const value_type& i)
00515 {
00516 adjust(i);
00517 return img_[v2p_(i)];
00518 }
00520 value_type
00521 min()
00522 {
00523 for (; min_ != ntg_max_val(value_type); min_ = succ(min_))
00524 if (img_[v2p_(min_)] > ntg_zero_val(cpt_type))
00525 break;
00526 return min_;
00527 }
00529 value_type
00530 res()
00531 {
00532 return min();
00533 }
00534
00535 protected:
00537 void
00538 adjust(const value_type& idx)
00539 {
00540 if (idx < min_)
00541 min_ = idx;
00542 }
00543 value_type min_;
00544 };
00545
00546 template< typename T,
00547 typename CPT = unsigned,
00548 class V2P = convert::value_to_point<T>,
00549 class Exact = mlc::final>
00550 class histogram_max;
00551
00552 template <typename T,
00553 typename CPT,
00554 class V2P,
00555 class Exact>
00556 struct hist_traits<histogram_max<T, CPT, V2P, Exact> >
00557 : public hist_traits<histogram<T, CPT, V2P, Exact> >
00558 {};
00559
00564 template< typename T,
00565 typename CPT,
00566 class V2P,
00567 class Exact>
00568 class histogram_max : public histogram<T, CPT, V2P,
00569 typename mlc::exact_vt<histogram_max<T, CPT, V2P, Exact>,
00570 Exact>::ret>
00571 {
00572 private:
00573 typedef typename ntg_is_a(T, ntg::non_vectorial)::ensure_type
00574 ensure_type;
00575
00576 public:
00577 typedef typename mlc::exact_vt<histogram_max<T, CPT, V2P, Exact>,
00578 Exact>::ret exact_type;
00579 typedef typename hist_traits<exact_type>::value_type value_type;
00580 typedef typename hist_traits<exact_type>::cpt_type cpt_type;
00581 typedef typename hist_traits<exact_type>::value_to_point_type
00582 value_to_point_type;
00583 typedef typename hist_traits<exact_type>::point_type point_type;
00584 enum {dim = hist_traits<exact_type>::dim};
00585 typedef typename hist_traits<exact_type>::img_type img_type;
00586 typedef histogram<T, CPT, V2P, exact_type> upper_type;
00587
00588 histogram_max(const value_to_point_type & v2p = value_to_point_type()) :
00589 upper_type(v2p),max_(ntg_max_val(value_type)) {}
00590
00591 template <class I>
00592 histogram_max(const oln::abstract::image<I> & input,
00593 const value_to_point_type & v2p = value_to_point_type()) :
00594 upper_type(input, v2p),max_(ntg_max_val(value_type)) {}
00595
00597 const cpt_type
00598 at(const value_type& i) const
00599 {
00600 return img_[v2p_(i)];
00601 }
00602
00604 cpt_type&
00605 at(const value_type& i)
00606 {
00607 adjust(i);
00608 return img_[v2p_(i)];
00609 }
00611 value_type
00612 max()
00613 {
00614 for (; max_ != ntg_min_val(value_type); max_ = ntg::pred(max_))
00615 if (img_[v2p_(max_)] > ntg_zero_val(cpt_type))
00616 break;
00617 return max_;
00618 }
00620 value_type
00621 res()
00622 {
00623 return max();
00624 }
00625
00626 protected:
00627
00629 void
00630 adjust(const value_type& idx)
00631 {
00632 if (idx > max_)
00633 max_ = idx;
00634 }
00635 value_type max_;
00636 };
00637
00639 template< typename T, typename CPT, class V2P, class Exact >
00640 inline T
00641 min(histogram_minmax<T, CPT, V2P, Exact>& hist)
00642 {
00643 return hist.min();
00644 }
00646 template< typename T, typename CPT, class V2P, class Exact >
00647 inline T
00648 min(histogram_min<T, CPT, V2P, Exact>& hist)
00649 {
00650 return hist.min();
00651 }
00653 template< typename T, typename CPT, class V2P, class Exact >
00654 inline T
00655 max(histogram_minmax<T, CPT, V2P, Exact>& hist)
00656 {
00657 return hist.max();
00658 }
00660 template< typename T, typename CPT, class V2P, class Exact >
00661 inline T
00662 max(histogram_max<T, CPT, V2P, Exact>& hist)
00663 {
00664 return hist.max();
00665 }
00674 template<class I>
00675 void
00676 distrib_sort(const oln::abstract::image<I>& im,
00677 std::vector<oln_point_type(I)> &v)
00678 {
00679 typedef oln_value_type(I) val;
00680
00681 typedef typename ntg_is_a(val, ntg::non_vectorial)::ensure_type
00682 ensure_type;
00683
00684
00685 precondition(v.size() == im.npoints());
00686
00687
00688 utils::histogram<val> histo(im);
00689
00690
00691
00692
00693
00694 const ntg_cumul_type(val) card = ntg_max_val(val)
00695 - ntg_min_val(val) + 1;
00696 std::vector<oln_point_type(I)* > ptr(card);
00697 ptr[0] = &(v[0]);
00698 for (ntg_cumul_type(val) i = 1; i < card; ++i)
00699 ptr[i] = ptr[i - 1] + histo[i - 1 + ntg_min_val(val)];
00700
00701
00702
00703 oln_iter_type(I) p(im);
00704 for_all(p)
00705 *(ptr[unsigned(im[p] - ntg_min_val(val))]++) = p;
00706 }
00707
00717 template<class I>
00718 void
00719 distrib_sort_inv(const oln::abstract::image<I>& im,
00720 std::vector<oln_point_type(I)> &v)
00721 {
00722 typedef oln_value_type(I) val;
00723
00724 typedef typename ntg_is_a(val, ntg::non_vectorial)::ensure_type
00725 ensure_type;
00726
00727 precondition(v.size() == im.npoints());
00728
00729 utils::histogram<val> histo(im);
00730
00731 const ntg_cumul_type(val) card = ntg_max_val(val)
00732 - ntg_min_val(val) + 1;
00733 std::vector<oln_point_type(I)* > ptr(card);
00734 ptr[card - 1] = &(v[0]);
00735
00736 for (ntg_signed_cumul_type(val) i = card - 2; i >= 0; --i)
00737 ptr[i] = ptr[i + 1] + histo[i + 1 + ntg_min_val(val)];
00738
00739 oln_iter_type(I) p(im);
00740 for_all(p)
00741 *(ptr[unsigned(im[p] - ntg_min_val(val))]++) = p;
00742 }
00743
00748 template <bool reverse>
00749 struct select_distrib_sort
00750 {
00751 template <class I>
00752 void
00753 operator ()(const oln::abstract::image<I>& im,
00754 std::vector<oln_point_type(I)> &v)
00755 {
00756 distrib_sort_inv(im, v);
00757 }
00758 };
00759
00760 template <>
00761 struct select_distrib_sort<true>
00762 {
00763 template <class I>
00764 void
00765 operator ()(const oln::abstract::image<I>& im,
00766 std::vector<oln_point_type(I)> &v)
00767 {
00768 distrib_sort(im, v);
00769 }
00770 };
00771 }
00772
00773 }
00774
00775 #endif // ! OLENA_UTILS_HISTOGRAM_HH