27 #ifndef MLN_CLUSTERING_KMEAN_RGB_HH
28 # define MLN_CLUSTERING_KMEAN_RGB_HH
100 # include <mln/accu/stat/histo3d_rgb.hh>
102 # include <mln/algebra/vec.hh>
104 # include <mln/core/concept/image.hh>
105 # include <mln/core/contract.hh>
106 # include <mln/core/image/image2d.hh>
107 # include <mln/core/macros.hh>
109 # include <mln/data/compute.hh>
110 # include <mln/data/fill.hh>
111 # include <mln/data/transform.hh>
113 # include <mln/debug/println.hh>
115 # include <mln/io/ppm/save.hh>
116 # include <mln/io/pgm/save.hh>
118 # include <mln/labeling/colorize.hh>
119 # include <mln/labeling/mean_values.hh>
121 # include <mln/literal/zero.hh>
122 # include <mln/literal/one.hh>
124 # include <mln/math/min.hh>
125 # include <mln/math/sqr.hh>
127 # include <mln/norm/l2.hh>
129 # include <mln/opt/at.hh>
131 # include <mln/debug/trace.hh>
133 # include <mln/trait/value_.hh>
135 # include <mln/util/array.hh>
137 # include <mln/value/int_u.hh>
138 # include <mln/value/rgb8.hh>
139 # include <mln/value/label_8.hh>
170 template <
typename T,
unsigned n,
typename I>
174 const unsigned k_center,
175 const unsigned watch_dog,
176 const unsigned n_times);
184 # ifndef MLN_INCLUDE_ONLY
490 template <
unsigned n>
491 struct rgbn_to_lbl8 : Function_v2v< rgbn_to_lbl8<n> >
493 typedef value::rgb<n> argument;
494 typedef value::label_8 result;
495 typedef value::label_8 t_label;
496 typedef image3d<t_label> t_group_img;
500 rgbn_to_lbl8(t_group_img group) : _group(group) {}
502 result operator()(
const argument& c)
const
504 value::label_8 tmp =
opt::at(_group, c.blue(), c.red(), c.green());
511 template <
typename T,
unsigned n>
512 struct rgb_to_dist : Function_v2v< rgb_to_dist<T,n> >
514 typedef value::rgb<n> argument;
516 typedef T t_result1d;
517 typedef algebra::vec<3,T> t_result3d;
518 typedef image3d<unsigned> t_histo_img;
523 rgb_to_dist(t_result3d mean, t_histo_img
histo) : _mean(mean),
526 result operator()(
const argument& c)
const
528 t_result1d diff2_row =
math::sqr(c.row() - _mean[0]);
529 t_result1d diff2_col =
math::sqr(c.col() - _mean[1]);
530 t_result1d diff2_sli =
math::sqr(c.sli() - _mean[2]);
531 t_result1d tmp = _histo(c)*(diff2_row + diff2_col + diff2_sli);
537 template <
typename T,
unsigned n,
typename I>
539 mln_ch_value(I,value::label_8)
540 kmean_image2d_rgb(const Image<I>& point__,
541 const
unsigned k_center,
542 const
unsigned watch_dog = 10,
543 const
unsigned n_times = 10)
545 mln_trace(
"mln::clustering::impl::kmean_image2d_rgb");
547 const I& point =
exact(point__);
548 typedef mln_value(I) V;
549 mlc_is(V,
value::rgb<n>)::check();
550 mlc_bool(mln_site_(I)::dim == 2u)::check();
551 mln_precondition(point.is_valid());
554 typedef
value::rgb<8> t_rgb;
555 typedef
value::label<8> t_label;
556 typedef
value::rgb<n> t_value;
557 typedef mln_trait_value_comp(t_value,0) t_value_comp0;
558 typedef mln_trait_value_comp(t_value,1) t_value_comp1;
559 typedef mln_trait_value_comp(t_value,2) t_value_comp2;
560 typedef
T t_result1d;
561 typedef algebra::vec<3,
T> t_result3d;
563 typedef I t_point_img;
564 typedef image3d<
unsigned> t_histo_img;
565 typedef util::array<t_result1d> t_number_img;
566 typedef util::array<t_result3d> t_mean_img;
567 typedef util::array<t_result1d> t_variance_img;
569 typedef image3d<t_label> t_group_img;
570 typedef image3d<t_result1d> t_distance_val;
571 typedef util::array<t_distance_val> t_distance_img;
573 typedef mln_ch_value(I,t_label) t_label_dbg;
574 typedef image2d<t_rgb> t_color_dbg;
575 typedef image2d<t_value> t_mean_dbg;
577 typedef image1d<t_result3d> t_mean_val;
578 typedef util::array<t_mean_val> t_mean_set;
579 typedef util::array<t_mean_set> t_mean_cnv;
580 typedef image1d<t_result1d> t_variance_val;
581 typedef util::array<t_variance_val> t_variance_cnv;
585 mln_precondition(point.is_valid());
587 static const
unsigned _N_TRIES = 3;
589 typedef accu::meta::stat::histo3d_rgb t_histo3d_rgb;
591 t_result1d _within_variance;
593 unsigned _k_center = k_center;
594 unsigned _watch_dog = watch_dog;
595 unsigned _n_times = n_times;
596 t_point_img _point = point;
599 t_histo_img _histo =
data::
compute(t_histo3d_rgb(),
603 t_number_img _number;
605 t_variance_img _variance;
607 for (
unsigned i = 0; i < _k_center; ++i)
615 unsigned _current_step = 0;
616 unsigned _current_launching = 0;
617 bool _is_number_valid =
false;
619 unsigned _launching_min;
620 t_result1d _variance_min;
621 t_mean_img _mean_min;
626 t_distance_img _distance;
629 t_label_dbg _label_dbg;
630 t_color_dbg _color_dbg;
631 t_mean_dbg _mean_dbg;
634 t_mean_cnv _mean_cnv;
635 t_variance_cnv _variance_cnv;
641 mln_min(t_value_comp0),
642 mln_min(t_value_comp1)),
643 point3d(mln_max(t_value_comp2),
644 mln_max(t_value_comp0),
645 mln_max(t_value_comp1))));
647 for (
unsigned i = 0; i < _k_center; ++i)
649 t_distance_val img(
box3d(
point3d(mln_min(t_value_comp2),
650 mln_min(t_value_comp0),
651 mln_min(t_value_comp1)),
652 point3d(mln_max(t_value_comp2),
653 mln_max(t_value_comp0),
654 mln_max(t_value_comp1))));
656 _distance.append(img);
666 for (
unsigned i = 0; i < _n_times; ++i)
672 _variance_cnv.append(img);
675 for (
unsigned i = 0; i < _k_center; ++i)
679 for (
unsigned j = 0; j < _n_times; ++j)
685 mean_set.append(img);
688 _mean_cnv.append(mean_set);
695 _variance_min = mln_max(t_result1d);
696 _current_launching = 0;
698 while (_current_launching < _n_times)
702 t_result1d old_variance = mln_max(t_result1d);
703 _within_variance = mln_max(t_result1d);
708 t_value_comp0 min_comp0 = mln_min(t_value_comp0);
709 t_value_comp0 max_comp0 = mln_max(t_value_comp0);
710 t_value_comp1 min_comp1 = mln_min(t_value_comp1);
711 t_value_comp1 max_comp1 = mln_max(t_value_comp1);
712 t_value_comp2 min_comp2 = mln_min(t_value_comp2);
713 t_value_comp2 max_comp2 = mln_max(t_value_comp2);
714 mln_eiter(t_mean_img) l(_mean);
718 _mean[l.index_()][0]=(rand()%(max_comp0-min_comp0))+min_comp0;
719 _mean[l.index_()][1]=(rand()%(max_comp1-min_comp1))+min_comp1;
720 _mean[l.index_()][2]=(rand()%(max_comp2-min_comp2))+min_comp2;
728 for (
unsigned i = 0; i < _k_center; ++i)
735 mln_piter(t_distance_val) d(_distance[i].domain());
739 t_result1d diff2_row =
math::sqr(d.row() - _mean[i][0]);
740 t_result1d diff2_col =
math::sqr(d.col() - _mean[i][1]);
741 t_result1d diff2_sli =
math::sqr(d.sli() - _mean[i][2]);
742 _distance[i](d) = _histo(d)*
743 (diff2_row + diff2_col + diff2_sli);
751 old_variance = _within_variance;
755 mln_piter(t_group_img) rgb(_group.domain());
759 mln_eiter(t_distance_img) l(_distance);
760 t_result1d
min = mln_max(t_result1d);
761 t_label label = mln_max(t_label);
765 if (
min > _distance[l.index_()](rgb))
767 min = _distance[l.index_()](rgb);
780 mln_eiter(t_number_img) en(_number);
781 mln_eiter(t_mean_img) em(_mean);
789 mln_piter(t_group_img) rgb(_group.domain());
793 _mean[_group(rgb)][0] += rgb.row() * _histo(rgb);
794 _mean[_group(rgb)][1] += rgb.col() * _histo(rgb);
795 _mean[_group(rgb)][2] += rgb.sli() * _histo(rgb);
796 _number(_group(rgb)) += _histo(rgb);
799 mln_eiter(t_mean_img) l(_mean);
803 _is_number_valid = (0 != _number[l.index_()]);
805 if (!_is_number_valid)
808 _mean[l.index_()] /= _number[l.index_()];
815 if (!_is_number_valid)
820 for (
unsigned i = 0; i < _k_center; ++i)
822 mln_piter(t_distance_val) d(_distance[i].domain());
827 t_result1d diff2_row =
math::sqr(d.row() - _mean[i][0]);
828 t_result1d diff2_col =
math::sqr(d.col() - _mean[i][1]);
829 t_result1d diff2_sli =
math::sqr(d.sli() - _mean[i][2]);
830 _distance[i](d) = _histo(d)*
831 (diff2_row + diff2_col + diff2_sli);
839 mln_eiter(t_variance_img) l(_variance);
845 mln_piter(t_group_img) rgb(_group.domain());
849 if (l.index_() == _group(rgb))
850 _variance[l.index_()] += _distance[l.index_()](rgb);
853 _within_variance += _variance[l.index_()];
863 while (_current_step < _watch_dog &&
864 _within_variance < old_variance);
871 if ((_is_number_valid && (_current_step < _watch_dog))||
874 if (_within_variance < _variance_min)
876 _variance_min = _within_variance;
878 _launching_min = _current_launching;
890 ++_current_launching;
937 template <
typename T,
unsigned n,
typename I>
939 mln_ch_value(I,value::label_8)
940 kmean_rgb_dispatch(const Image<I>& img,
941 const
unsigned k_center,
942 const
unsigned watch_dog,
943 const
unsigned n_times,
944 const
value::rgb<n>& ,
947 return impl::kmean_image2d_rgb<T,n>(img, k_center, watch_dog, n_times);
950 template <
typename T,
unsigned n,
typename I,
typename V,
typename P>
952 mln_ch_value(I,value::label_8)
953 kmean_rgb_dispatch(const Image<I>& ,
961 mlc_abort(I)::check();
963 typedef mln_ch_value(I, value::label_8) output_t;
968 template <typename
T,
unsigned n, typename I>
970 mln_ch_value(I,
value::label_8)
971 kmean_rgb_dispatch(const Image<I>& img,
972 const
unsigned k_center,
973 const
unsigned watch_dog,
974 const
unsigned n_times)
976 typedef mln_value(I) V;
977 typedef mln_site(I) P;
978 return kmean_rgb_dispatch<T,n>(img, k_center, watch_dog,
990 template <typename T,
unsigned n, typename I>
992 mln_ch_value(I,
value::label_8)
994 const
unsigned k_center,
995 const
unsigned watch_dog,
996 const
unsigned n_times)
998 mln_trace(
"mln::clustering::kmean_rgb");
1000 mln_ch_value(I, value::label_8)
1001 output = internal::kmean_rgb_dispatch<T,n>(point, k_center,
1002 watch_dog, n_times);
1008 # endif // ! MLN_INCLUDE_ONLY
1014 #endif // ! MLN_CLUSTERING_KMEAN_RGB_HH