histogram.hh

00001 // Copyright (C) 2001, 2002, 2003, 2004  EPITA Research and Development Laboratory
00002 //
00003 // This file is part of the Olena Library.  This library is free
00004 // software; you can redistribute it and/or modify it under the terms
00005 // of the GNU General Public License version 2 as published by the
00006 // Free Software Foundation.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this library; see the file COPYING.  If not, write to
00015 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
00016 // MA 02111-1307, USA.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software library without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to
00022 // produce an executable, this file does not by itself cause the
00023 // resulting executable to be covered by the GNU General Public
00024 // License.  This exception does not however invalidate any other
00025 // reasons why the executable file might be covered by the GNU General
00026 // Public License.
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     } // end of namespace internal
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     } // end of namespace abstract
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       // check the size
00685       precondition(v.size() == im.npoints());
00686 
00687       // calculate the histogram of the image
00688       utils::histogram<val> histo(im);
00689 
00690       // Initialize the array of pointer to the point in the result.
00691       // With the histogram the number of each color can be deduced and
00692       // then it calculates an array of pointer for quick access to each
00693       // value of the image.
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       // Now iterate on the image to sort point in the order of their
00702       // level
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   } // end of namespace utils
00772 
00773 } // end of namespace oln
00774 
00775 #endif // ! OLENA_UTILS_HISTOGRAM_HH

Generated on Thu Apr 15 20:13:10 2004 for Olena by doxygen 1.3.6-20040222