2 #include <mln/core/image/image2d.hh>
3 #include <mln/value/int_u8.hh>
5 #include <mln/io/pgm/load.hh>
6 #include <mln/io/pbm/save.hh>
7 #include <mln/io/pgm/save.hh>
8 #include <mln/io/ppm/save.hh>
10 #include <mln/literal/colors.hh>
11 #include <mln/literal/white.hh>
13 #include <mln/core/routine/duplicate.hh>
14 #include <mln/data/fill.hh>
16 #include <mln/accu/stat/max.hh>
17 #include <mln/pw/all.hh>
18 #include <mln/core/image/dmorph/image_if.hh>
20 #include <mln/debug/filename.hh>
21 #include <mln/morpho/laplacian.hh>
22 #include <mln/win/rectangle2d.hh>
23 #include <mln/estim/min_max.hh>
25 #include <mln/labeling/background.hh>
26 #include <mln/labeling/compute.hh>
27 #include <mln/labeling/colorize.hh>
28 #include <mln/fun/vvvv2v/mean.hh>
29 #include <mln/fun/vv2v/mean.hh>
30 #include <mln/fun/v2v/abs.hh>
31 #include <mln/math/mean.hh>
33 #include <mln/world/k1/immerse.hh>
34 #include <mln/world/k1/un_immerse.hh>
35 #include <mln/world/k1/neighb2d.hh>
36 #include <mln/world/k2/immerse.hh>
37 #include <mln/world/k2/is_primary_2_face.hh>
38 #include <mln/world/k2/fill_non_primary_from_primary_2_faces.hh>
39 #include <mln/world/kn/is_2_face.hh>
40 #include <mln/world/kn/fill_1_from_aux_2_faces.hh>
41 #include <mln/world/kn/fill_1_from_2_faces.hh>
42 #include <mln/world/kn/fill_2_from_1_faces.hh>
43 #include <mln/world/kn/dilate_0_from_1_faces.hh>
44 #include <mln/world/kn/is_0_or_1_face.hh>
45 #include <mln/world/kn/display_enlarged.hh>
47 #include <mln/debug/println.hh>
48 #include <mln/debug/println_with_border.hh>
56 struct f_zero_t : Function_vv2v< f_zero_t >
59 bool operator()(
int v1,
int v2)
const
65 typedef mln::fun::vv2v::mean<unsigned> f_mean;
69 struct lap_fill2_k2_t : Function_vv2v< lap_fill2_k2_t<V> >
71 typedef mln_equiv(V) result;
72 typedef mln_equiv(V) argument;
74 mln_equiv(V) operator()(const mln_equiv(V)& v1, const mln_equiv(V)& v2)
const
85 struct lap_fill4_k2_t : Function_vvvv2v< lap_fill4_k2_t<V> >
87 typedef mln_equiv(V) result;
88 typedef mln_equiv(V) argument;
90 mln_equiv(V) operator()(const mln_equiv(V)& v1, const mln_equiv(V)& v2,
91 const mln_equiv(V)& v3, const mln_equiv(V)& v4)
const
93 if (v1 * v2 * v3 * v4 <= 0)
96 return (v1 + v2 + v3 + v4) / 4;
101 doit_k1(
const image2d<value::int_u8>& in,
unsigned size)
103 using namespace world;
105 box2d b = in.domain();
107 win::rectangle2d rect(size, size);
108 image2d<value::int_u8>
112 data::fill(grad, pw::value(dil) - pw::value(ero));
114 image2d<int> lap =
duplicate((pw::value(dil) + pw::value(ero) - pw::cst(2) * pw::value(in)) | b);
116 int lap_min, lap_max;
119 std::cout << lap_min <<
' ' << lap_max << std::endl;
122 image2d<int> lap_k1 = world::k1::immerse(lap);
123 box2d B = lap_k1.domain();
124 data::fill((lap_k1 | world::kn::is_0_or_1_face).rw(), 0);
127 image2d<bool> lap_zero_k1(B);
130 world::kn::fill_1_from_aux_2_faces(lap_zero_k1, lap_k1, f_zero);
133 data::fill((lap_zero_k1 |world::kn::is_2_face).rw(), pw::value(lap_k1) == pw::cst(0));
136 world::kn::dilate_0_from_1_faces(lap_zero_k1);
140 lap_zero_k1_enlarged = world::kn::display_enlarged(lap_zero_k1, 5);
145 image2d<value::int_u8> grad_on_01f(B);
148 world::kn::fill_1_from_aux_2_faces(grad_on_01f,
149 world::k1::immerse(grad), f_mean());
150 kn::fill_0_from_1_faces(grad_on_01f, accu::stat::max<value::int_u8>());
154 image2d<value::int_u8>
155 grad_on_01f_enlarged = world::kn::display_enlarged(grad_on_01f, 5);
161 world::kn::fill_2_from_1_faces((grad_on_01f | pw::value(lap_zero_k1)).rw(), fun::vvvv2v::mean<int>());
162 data::fill((grad_on_01f | (pw::value(lap_zero_k1) == pw::cst(
false))).rw(), 0u);
163 grad_on_01f_enlarged = world::kn::display_enlarged(grad_on_01f, 5);
170 image2d<unsigned> lap_lbl = k1::un_immerse(lap_lbl_k1);
172 util::array<float> mean_val =
labeling::compute(accu::stat::mean<value::int_u8>(), in, lap_lbl, nlabels);
173 util::array<value::int_u8> mean_val_u8;
174 convert::from_to(mean_val, mean_val_u8);
176 image2d<value::int_u8> lap_abs =
data::transform(lap, fun::v2v::abs<int,value::int_u8>());
180 util::array<value::int_u8>
max =
labeling::compute(accu::stat::max<value::int_u8>(), lap_abs, lap_lbl, nlabels);
189 util::array<float> mean_grad =
labeling::compute(accu::stat::mean<value::int_u8>(), grad, lap_lbl, nlabels);
190 image2d<value::int_u8> grad_mean_on_contours(lap_lbl_k1.domain());
192 mln_piter_(image2d<value::int_u8>) p(lap_lbl_k1.domain());
194 if (kn::is_1_face_vertical(p)
195 && lap_lbl_k1(p + left) != lap_lbl_k1(p + right))
197 grad_mean_on_contours(p) = math::mean(mean_grad[lap_lbl_k1(p + left)],
198 mean_grad[lap_lbl_k1(p + right)]);
200 else if (kn::is_1_face_horizontal(p)
201 && lap_lbl_k1(p +
up) != lap_lbl_k1(p + down))
203 grad_mean_on_contours(p) = math::mean(mean_grad[lap_lbl_k1(p +
up)],
204 mean_grad[lap_lbl_k1(p + down)]);
206 kn::fill_0_from_1_faces(grad_mean_on_contours, accu::stat::max<value::int_u8>());
239 doit_k2(
const image2d<value::int_u8>& in,
unsigned size)
241 using namespace world;
243 box2d b = in.domain();
245 win::rectangle2d rect(size, size);
246 image2d<value::int_u8>
250 data::fill(grad, pw::value(dil) - pw::value(ero));
252 image2d<int> lap =
duplicate((pw::value(dil) + pw::value(ero) - pw::cst(2) * pw::value(in)) | b);
255 typedef value::intsub<2> T;
256 typedef value::interval<value::intsub<2> > V;
257 image2d<V> lap_k2 = k2::immerse(lap, V());
261 k2::fill_non_primary_from_primary_2_faces(lap_k2, lap_fill2_k2_t<V>(), lap_fill4_k2_t<V>());
274 std::cerr <<
"usage: " << argv[0] <<
" input.pgm size outprefix" << std::endl;
275 std::cerr <<
" sample use: " << argv[0] <<
" lena.pgm 5 out_lena" << std::endl;
281 int main(
int argc,
char* argv[])
289 int size = std::atoi(argv[2]);
296 debug::internal::filename_prefix = argv[3];