Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
inter_pixel.cc
1 #include <mln/core/image/image2d.hh>
2 #include <mln/core/alias/neighb2d.hh>
3 #include <mln/core/var.hh>
4 
5 #include <mln/value/int_u8.hh>
6 #include <mln/value/label_16.hh>
7 #include <mln/value/rgb8.hh>
8 
9 #include <mln/io/pgm/all.hh>
10 #include <mln/io/ppm/save.hh>
11 
12 #include <mln/data/convert.hh>
13 #include <mln/data/fill.hh>
14 #include <mln/debug/int2rgb.hh>
15 #include <mln/display/display_region.hh>
16 #include <mln/literal/colors.hh>
17 #include <mln/math/diff_abs.hh>
18 #include <mln/morpho/closing/volume.hh>
19 #include <mln/morpho/elementary/gradient.hh>
20 #include <mln/morpho/watershed/flooding.hh>
21 #include <mln/world/inter_pixel/compute.hh>
22 #include <mln/world/inter_pixel/display_edge.hh>
23 #include <mln/world/inter_pixel/display_region.hh>
24 #include <mln/world/inter_pixel/immerse.hh>
25 #include <mln/world/inter_pixel/is_pixel.hh>
26 #include <mln/world/inter_pixel/is_separator.hh>
27 #include <mln/world/inter_pixel/neighb2d.hh>
28 
29 
30 using namespace mln;
31 using value::int_u8;
32 using value::label_16;
33 using value::rgb8;
34 
35 
36 struct dist_t : Function_vv2v<dist_t>
37 {
38  typedef int_u8 result;
39 
40  template <typename V>
41  int_u8 operator()(const V v1, const V v2) const
42  {
43  return math::diff_abs(v1, v2);
44  }
45 } dist;
46 
47 
48 
49 int main(int argc, char* argv[])
50 {
51  if (argc != 2)
52  {
53  std::cout << "Usage: " << argv[0] << " input.pgm" << std::endl;
54  return 1;
55  }
56 
57  image2d<int_u8> input;
58  io::pgm::load(input, argv[1]);
59 
60  // Gradient.
61  image2d<int_u8> grad = morpho::elementary::gradient(input, c4());
62  io::pgm::save(grad, "gradient.pgm");
63 
64  label_16 nbasins;
65 
66  // Normal watershed.
67  image2d<label_16> normal_wst = morpho::watershed::flooding(input, c4(), nbasins);
68  io::ppm::save(display::display_region(input, normal_wst, literal::red), "normal_watershed.ppm");
69 
70 
71 
72  // Distance on edges.
73  typedef image_if<image2d<int_u8>, world::inter_pixel::is_pixel> Ix;
74  Ix imax = world::inter_pixel::immerse(input);
75  image_if<image2d<int_u8>, world::inter_pixel::is_separator> edges;
76  edges = world::inter_pixel::compute(imax, dist);
77 
78  io::pgm::save(world::inter_pixel::display_edge(edges.unmorph_(), 0, 3), "edge_dist.pgm");
79 
80  // Color on edge image.
81  image2d<rgb8> edge_color = data::convert(rgb8(), edges.unmorph_());
82  mln_piter_(image2d<int_u8>) p(input.domain());
83  for_all(p)
84  convert::from_to(input(p), opt::at(edge_color, p.row() * 2, p.col() * 2));
85  data::fill((edge_color | world::inter_pixel::is_separator()).rw(), literal::green);
86  data::fill((edge_color | world::inter_pixel::is_zero_face()).rw(), literal::blue);
87  io::ppm::save(edge_color, "edge_color.ppm");
88 
89  // Color on stretched edge image.
90  box2d b = edge_color.bbox();
91  image2d<rgb8> edge_stretch(make::box2d(((b.pmin()[0] + 1) / 2) * 4, ((b.pmin()[1] + 1) / 2) * 4,
92  ((b.pmax()[0] + 1) / 2 + 1) * 4 - 2, ((b.pmax()[1] + 1) / 2 + 1) * 4 - 2));
93  typedef image_if<image2d<rgb8>, world::inter_pixel::is_separator> edge_t;
94  edge_t edge_sep = edge_color | world::inter_pixel::is_separator();
95  mln_piter_(edge_t) q(edge_sep.domain());
96  for_all(q)
97  if (q.row() % 2) // horizontal edge
98  {
99  unsigned row = (q.row() / 2 + 1) * 4 - 1;
100  unsigned col = (q.col() / 2) * 4;
101  for (unsigned i = 0; i < 3; ++i)
102  opt::at(edge_stretch, row, col + i) = literal::green;
103  }
104  else // vertical edge
105  {
106  unsigned row = (q.row() / 2) * 4;
107  unsigned col = (q.col() / 2 + 1) * 4 - 1;
108  for (unsigned i = 0; i < 3; ++i)
109  opt::at(edge_stretch, row + i, col) = literal::green;
110  }
111  mln_VAR(edge_zero, edge_color | world::inter_pixel::is_zero_face());
112  mln_piter_(edge_zero_t) ez(edge_zero.domain());
113  for_all(ez)
114  opt::at(edge_stretch, ((ez.row() + 1) / 2) * 4 - 1, ((ez.col() + 1) / 2) * 4 - 1) = literal::blue;
115  mln_VAR(edge_pix, edge_color | world::inter_pixel::is_pixel());
116  mln_piter_(edge_pix_t) ex(edge_pix.domain());
117  for_all(ex)
118  for (int i = 0; i < 3; ++i)
119  for (int j = 0; j < 3; ++j)
120  opt::at(edge_stretch, (ex.row() / 2) * 4 + i, (ex.col() / 2) * 4 + j) = edge_color(ex);
121  io::ppm::save(edge_stretch, "edge_stretch.ppm");
122 
123 
124  // On edges watershed.
125  mln_VAR(edge_clo, morpho::closing::volume(edges, world::inter_pixel::e2e(), 25));
126  mln_VAR(edge_wst, morpho::watershed::flooding(edge_clo, world::inter_pixel::e2e(), nbasins));
127  io::ppm::save(world::inter_pixel::display_region(input, edge_wst.unmorph_(), literal::red), "edge_watershed.ppm");
128 
129  return 0;
130 }