$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
apps/papers/levillain.09.ismm/graph.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 
27 #include <iostream>
28 
29 #include <vector>
30 
31 #include <mln/core/image/image2d.hh>
32 #include <mln/core/alias/neighb2d.hh>
33 
34 #include <mln/labeling/blobs.hh>
35 #include <mln/io/pgm/load.hh>
36 #include <mln/io/pgm/save.hh>
37 #include <mln/data/stretch.hh>
38 #include <mln/debug/println.hh>
39 #include <mln/draw/line.hh>
40 #include <mln/pw/all.hh>
41 #include <mln/binarization/threshold.hh>
42 
43 #include <mln/value/int_u8.hh>
44 #include <mln/value/label_8.hh>
45 #include <mln/core/alias/point2d.hh>
46 
47 #include <mln/core/site_set/p_faces.hh>
48 #include <mln/core/image/complex_image.hh>
49 #include <mln/core/alias/complex_geometry.hh>
50 #include <mln/core/alias/complex_image.hh>
51 
52 // FIXME: Include these elsewhere? (In complex_image.hh?)
53 #include <mln/core/image/complex_neighborhoods.hh>
54 #include <mln/core/image/complex_neighborhood_piter.hh>
55 #include <mln/core/image/complex_windows.hh>
56 
57 #include <mln/data/fill.hh>
58 #include <mln/morpho/gradient.hh>
59 #include <mln/labeling/colorize.hh>
60 
61 #include "io.hh"
62 #include "influence_zones.hh"
63 #include "chain.hh"
64 
65 
66 // FIXME: Clean up and move into Milena?
68 make_complex_image(const mln::image2d<mln::value::int_u8>& input)
69 {
70  using namespace mln;
71  using mln::value::int_u8;
72 
73  /*----------------------------------------.
74  | Complex + complex geometry (location). |
75  `----------------------------------------*/
76 
78 
79  unsigned nlabels;
80  image2d<unsigned> label =
81  labeling::blobs(mln::binarization::threshold(input, 1), c4(), nlabels);
82 
83  std::cout << "n seeds = " << nlabels << std::endl;
84  {
85  image2d<int_u8> lab(label.domain());
86  data::paste(label, lab);
87  }
88 
89  image2d<unsigned> iz = influence_zones(label, c4());
90  {
91  image2d<int_u8> IZ(iz.domain());
92  data::paste(iz, IZ);
93  }
94 
95 #if 0
97 #endif
98 
99  // Make graph/complex.
100 
101  std::vector< std::vector<bool> > adj(nlabels + 1);
102  for (unsigned l = 1; l <= nlabels; ++l)
103  adj[l].resize(nlabels + 1, false);
104 
105  {
106  box2d::piter p(iz.domain());
107  for_all(p)
108  {
109  point2d r = p + right, b = p + down;
110  if (iz.has(r) && iz(p) != iz(r))
111  {
112  if (iz(p) <= iz(r))
113  adj[iz(p)][iz(r)] = true;
114  else
115  adj[iz(r)][iz(p)] = true;
116  }
117  if (iz.has(b) && iz(p) != iz(b))
118  {
119  if (iz(p) <= iz(b))
120  adj[iz(p)][iz(b)] = true;
121  else
122  adj[iz(b)][iz(p)] = true;
123  }
124  }
125  }
126 
127  // end of mk_graph
128 
129 
130  const unsigned D = 1;
131 
133 
134  typedef point2d P;
136  G geom;
137 
138  // Convenience typedefs.
139  typedef topo::n_face<0, D> vertex;
140  typedef topo::n_face<1, D> edge;
141 
142  {
143 
144  // 0-faces (vertices).
145  std::vector<vertex> v;
146  {
147  box2d::piter p(label.domain());
148  for_all(p)
149  if (label(p) != 0)
150  {
151  geom.add_location(p);
152  v.push_back(c.add_face());
153  }
154  }
155 
156  std::cout << "v size = " << v.size() << std::endl;
157 
158  // 1-faces (edges).
159  std::vector<edge> e;
160  {
161  for (unsigned l = 1; l <= nlabels; ++l)
162  for (unsigned ll = l + 1; ll <= nlabels; ++ll)
163  if (adj[l][ll])
164  e.push_back( c.add_face(-v[l-1] + v[ll-1]) );
165  }
166 
167  std::cout << "e size = " << e.size() << std::endl;
168 
169  }
170 
171 
172  /*---------------------.
173  | Complex-based pset. |
174  `---------------------*/
175 
176  p_complex<D, G> pc(c, geom);
177 
178  /*----------------------.
179  | Complex-based image. |
180  `----------------------*/
181 
182  // An image type built on a 1-complex with unsigned values on each
183  // face (both vertices and edges).
184  typedef complex_image<D, G, int_u8> output_t;
185 
186  // Create and initialize an image based on PC.
187  output_t output(pc);
188 
189  // Color OUTPUT's vertices with INPUT's values.
190  p_n_faces_fwd_piter<D, G> v(output.domain(), 0);
191  for_all(v)
192  output(v) = input(v.to_site().front());
193 
194  // Use a medium gray to color edges.
195  p_n_faces_fwd_piter<D, G> e(output.domain(), 1);
196  for_all(e)
197  output(e) = 128;
198 
199  return output;
200 }
201 
202 
203 // FIXME: Move to Milena?
204 template <unsigned D, typename G, typename V>
206 make_elt_win(const mln::complex_image<D, G, V>& /* ima */)
207 {
209 }
210 
211 // FIXME: Move to Milena?
212 template <unsigned D, typename G, typename V>
214 make_elt_nbh(const mln::complex_image<D, G, V>& /* ima */)
215 {
217 }
218 
219 
220 int main(int argc, char* argv[])
221 {
222  if (argc != 4)
223  {
224  std::cerr << "usage: " << argv[0] << " seeds.pgm lambda output.neato"
225  << std::endl;
226  std::exit(1);
227  }
228  std::string input_filename = argv[1];
229  unsigned lambda = atoi(argv[2]);
230  std::string output_filename = argv[3];
231 
232  using namespace mln;
233  using mln::value::int_u8;
234  // Use clearer names.
235  typedef int_u8_1complex_image2d int_u8_graph_image2d;
236 
237  typedef int_u8_graph_image2d input;
238  typedef value::label_8 label;
239  typedef mln_ch_value_(input, label) output;
240  label nbasins;
241 
242  // Seeds.
243  image2d<int_u8> seeds = io::pgm::load<int_u8>(input_filename);
244  // Input image computed from the graph of influence zones (IZ) of seeds.
245  typedef int_u8_graph_image2d ima_t;
246  ima_t ima = make_complex_image(seeds);
247 #if 0
248  io::neato::save(ima, "graph.neato");
249 #endif
250 
251  // Gradient.
252  input g = morpho::gradient(ima, make_elt_win(ima));
253 
254 #if 0
255  // FIXME: get the name as argument.
256  io::neato::save(g, "graph-g.neato");
257 #endif
258 
259  // Chain.
260  output s = chain(g, make_elt_nbh(g), lambda, nbasins);
262  output_filename);
263 }