$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
mesh-complex-segm.cc
1 // Copyright (C) 2008, 2009, 2011 EPITA Research and Development
2 // Laboratory (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
31 
32 #include <cstdlib>
33 #include <cmath>
34 
35 #include <utility>
36 #include <iostream>
37 
38 #include <mln/core/image/complex_image.hh>
39 #include <mln/core/image/complex_neighborhoods.hh>
40 
41 #include <mln/morpho/closing/area.hh>
42 #include <mln/morpho/watershed/flooding.hh>
43 
44 #include <mln/literal/white.hh>
45 
46 #include <mln/io/off/load.hh>
47 #include <mln/io/off/save.hh>
48 
49 
50 
51 int main(int argc, char* argv[])
52 {
53  if (argc != 4)
54  {
55  std::cerr << "usage: " << argv[0] << " input.off lambda output.off"
56  << std::endl;
57  std::exit(1);
58  }
59 
60  std::string input_filename = argv[1];
61  unsigned lambda = atoi(argv[2]);
62  std::string output_filename = argv[3];
63 
64  /*----------------.
65  | Complex image. |
66  `----------------*/
67 
68  // Input type.
69  typedef mln::float_2complex_image3df float_input_t;
70  // Dimension of the image (and therefore of the complex).
71  static const unsigned D = float_input_t::dim;
72  // Geometry of the image.
73  typedef mln_geom_(float_input_t) G;
74 
75  float_input_t float_input;
76  mln::io::off::load(float_input, input_filename);
77 
78  // Convert the float image into an unsigned image because some
79  // algorithms do not handle float images well.
80  /* FIXME: This is bad: float images should be handled as-is. At
81  least, we should use a decent conversion, using an optimal affine
82  transformation (stretching/shrinking) or any other kind of
83  interpolation. */
84  typedef mln::unsigned_2complex_image3df ima_t;
85  ima_t input(float_input.domain());
86  mln_piter_(ima_t) p(input.domain());
87  for_all(p)
88  input(p) = 1000 * float_input(p);
89 
90  // Values on edges.
91  mln::p_n_faces_fwd_piter<D, G> e(input.domain(), 1);
92  typedef mln::complex_higher_neighborhood<D, G> adj_polygons_nbh_t;
93  adj_polygons_nbh_t adj_polygons_nbh;
94  mln_niter_(adj_polygons_nbh_t) adj_p(adj_polygons_nbh, e);
95  // Iterate on edges (1-faces).
96  for_all(e)
97  {
98  float s = 0.0f;
99  unsigned n = 0;
100  for_all(adj_p)
101  {
102  s += input(adj_p);
103  ++n;
104  }
105  input(e) = s / n;
106  // An edge should be adjacent to two polygons at most.
107  mln_invariant(n <= 2);
108  }
109 
110  /*-----------------.
111  | Simplification. |
112  `-----------------*/
113 
115  typedef
117  adj_edges_nbh_t;
118  adj_edges_nbh_t adj_edges_nbh;
119 
120  ima_t closed_input = mln::morpho::closing::area(input, adj_edges_nbh, lambda);
121 
122  /*------.
123  | WST. |
124  `------*/
125 
126  /* FIXME: Note that the WST is doing too much work, since we have
127  not constrained the domain of the image to 1-faces only.
128  It would be great if we could use something like this:
129 
130  closed_input | mln::p_faces<1, D, G>(closed_input.domain())
131 
132  as input of the WST. */
133 
134  // Compute the WST on edges.
135  typedef unsigned wst_val_t;
136  wst_val_t nbasins;
137  typedef mln::unsigned_2complex_image3df wst_ima_t;
138  wst_ima_t wshed =
139  mln::morpho::watershed::flooding(closed_input, adj_edges_nbh, nbasins);
140  std::cout << "nbasins = " << nbasins << std::endl;
141 
142  // Label polygons (i.e., propagate labels from edges to polygons).
143  for_all(e)
144  if (wshed(e) != 0)
145  for_all(adj_p)
146  wshed(adj_p) = wshed(e);
147 
148  /*---------.
149  | Output. |
150  `---------*/
151 
152  mln::rgb8_2complex_image3df output(wshed.domain());
153  mln::data::fill(output, mln::literal::white);
154 
155  // FIXME: Use a colorize functor instead.
156  // Choose random colors for each basin number.
157  std::vector<mln::value::rgb8> basin_color (nbasins + 1);
158  for (unsigned i = 0; i <= nbasins; ++i)
159  basin_color[i] = mln::value::rgb8(random() % 256,
160  random() % 256,
161  random() % 256);
162  mln_piter_(ima_t) f(wshed.domain());
163  for_all(f)
164  output(f) = basin_color[wshed(f)];
165 
166  mln::io::off::save(output, output_filename);
167 }