Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
morpho.hh
1 // Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
2 //
3 // This file is part of Olena.
4 //
5 // Olena is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation, version 2 of the License.
8 //
9 // Olena is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // As a special exception, you may use this file as part of a free
18 // software project without restriction. Specifically, if other files
19 // instantiate templates or use macros or inline functions from this
20 // file, or you compile this file and link it with other files to produce
21 // an executable, this file does not by itself cause the resulting
22 // executable to be covered by the GNU General Public License. This
23 // exception does not however invalidate any other reasons why the
24 // executable file might be covered by the GNU General Public License.
25 
26 #ifndef APPS_GRAPH_MORPHO_MORPHO_HH
27 # define APPS_GRAPH_MORPHO_MORPHO_HH
28 
39 # include <mln/core/alias/complex_image.hh>
40 # include <mln/core/image/image2d.hh>
41 
42 # include <mln/core/image/dmorph/image_if.hh>
43 
44 # include <mln/core/image/dmorph/extension_ima.hh>
45 
46 # include <mln/core/routine/extend.hh>
47 # include <mln/core/routine/duplicate.hh>
48 
49 # include <mln/core/site_set/p_n_faces_piter.hh>
50 # include <mln/core/image/complex_neighborhoods.hh>
51 # include <mln/core/image/complex_neighborhood_piter.hh>
52 
53 # include <mln/world/inter_pixel/dim2/is_pixel.hh>
54 # include <mln/world/inter_pixel/dim2/is_edge.hh>
55 # include <mln/world/inter_pixel/neighb2d.hh>
56 
57 # include <mln/data/paste.hh>
58 
59 # include <mln/morpho/dilation.hh>
60 # include <mln/morpho/erosion.hh>
61 
62 # include <mln/topo/is_n_face.hh>
63 
64 
65 /*---------------.
66 | Graph traits. |
67 `---------------*/
68 
69 namespace trait
70 {
72  template <typename I>
73  struct graph
74  {
75  /* Empty by default.
76 
77  Specializations must provide these static member functions:
78 
79  static F1 is_vertex()
80  static F2 is_edge()
81  static W1 v2e()
82  static W2 e2v()
83 
84  where F1, F2, W1 and W2 are types depending on I.
85  */
86  };
87 
88  // ----------------------------------------------------------- //
89  // Graph traits for (mln::image2d-based) cubical 2-complexes. //
90  // ----------------------------------------------------------- //
91 
93  template <typename T>
94  struct graph< mln::image2d<T> >
95  {
96  // Return a functor saying whether a psite is a vertex or not.
97  static
98  const mln::world::inter_pixel::dim2::is_pixel& is_vertex()
99  {
100  static mln::world::inter_pixel::dim2::is_pixel is_vertex_fun;
101  return is_vertex_fun;
102  }
103 
104  // Return a functor saying whether a psite is a vertex or not.
105  static
106  const mln::world::inter_pixel::dim2::is_edge& is_edge()
107  {
108  static mln::world::inter_pixel::dim2::is_edge is_edge_fun;
109  return is_edge_fun;
110  }
111 
112  // Return a window containing the edges adjacent to a vertex.
113  static
114  const mln::window2d& v2e()
115  {
116  return mln::world::inter_pixel::v2e().win();
117  }
118 
119  // Return a window containing the vertices adjacent to an edge.
120  static
122  {
123  return mln::world::inter_pixel::e2v().win();
124  }
125  };
126 
127  // ---------------------------------------- //
128  // Graph traits for (general) 1-complexes. //
129  // ---------------------------------------- //
130 
132  template <typename G, typename V>
133  struct graph< mln::complex_image<1, G, V> >
134  {
135  // Return a functor saying whether a psite is a vertex or not.
136  static
137  const mln::topo::is_n_face<0>& is_vertex()
138  {
139  static mln::topo::is_n_face<0> is_vertex_fun;
140  return is_vertex_fun;
141  }
142 
143  // Return a functor saying whether a psite is a vertex or not.
144  static
145  const mln::topo::is_n_face<1>& is_edge()
146  {
147  static mln::topo::is_n_face<1> is_edge_fun;
148  return is_edge_fun;
149  }
150 
151  // Return a window containing the edges adjacent to a vertex.
152  static
153  const mln::complex_higher_window<1, G>& v2e()
154  {
155  static mln::complex_higher_window<1, G> v2e_win;
156  return v2e_win;
157  }
158 
159  // Return a window containing the vertices adjacent to an edge.
160  static
161  const mln::complex_lower_window<1, G>& e2v()
162  {
163  static mln::complex_lower_window<1, G> e2v_win;
164  return e2v_win;
165  }
166  };
167 
168 } // end of namespace trait
169 
170 
171 /*----------------------------.
172 | Vertices-edges combinator. |
173 `----------------------------*/
174 
175 /* The original paper uses an operator `\ovee' to combine node and
176  edge graphs. However, this symbol requires the use of the
177  `stmaryrd' package, and Doyxgen provides no means to require it.
178  So, we use a more ``standard'' symbol instead (`\oplus'). */
179 
182 template <typename I>
183 inline
184 mln_concrete(I)
185 combine(const mln::Image<I>& vertices_, const mln::Image<I>& edges_)
186 {
187  typedef trait::graph<I> T;
188  const I& vertices = mln::exact(vertices_);
189  const I& edges = mln::exact(edges_);
190 
191  mln_precondition(vertices.domain() == edges.domain());
192  mln_concrete(I) output;
193  mln::initialize(output, vertices);
194  mln::data::fill(output, false);
195  mln::data::paste(vertices | T::is_vertex(), output);
196  mln::data::paste(edges | T::is_edge(), output);
197  return output;
198 }
199 
200 
201 /*-------------------------.
202 | Dilations and erosions. |
203 `-------------------------*/
204 
205 // ----------------------------- //
206 // Core dilations and erosions. //
207 // ----------------------------- //
208 
209 /* Note: When writing
210 
211  dilation(ima | vertices);
212 
213  `vertices' is a predicate on sites (p2b function), which
214  is not efficient, since both vertices and edges will be browsed.
215 
216  It would be very nice if `vertices' could be an actual site set,
217  so that `ima | vertices' creates a morpher smart enough to
218  browse /only/ vertices. */
219 
220 
222 template <typename I>
223 inline
224 mln_concrete(I)
225 dilation_e2v(const mln::Image<I>& input)
226 {
227  typedef trait::graph<I> T;
228 
229  mln_concrete(I) output;
230  mln::initialize(output, mln::exact(input));
231  mln::data::fill(output, false);
232  mln::data::paste(mln::morpho::dilation(mln::extend(input | T::is_vertex(),
233  input),
234  T::v2e()),
235  output);
236  return output;
237 }
238 
240 template <typename I>
241 inline
242 mln_concrete(I)
243 erosion_v2e(const mln::Image<I>& input)
244 {
245  typedef trait::graph<I> T;
246 
247  mln_concrete(I) output;
248  mln::initialize(output, mln::exact(input));
249  mln::data::fill(output, false);
250  mln::data::paste(mln::morpho::erosion(mln::extend(input | T::is_edge(),
251  input),
252  T::e2v()),
253  output);
254  return output;
255 }
256 
258 template <typename I>
259 inline
260 mln_concrete(I)
261 erosion_e2v(const mln::Image<I>& input)
262 {
263  typedef trait::graph<I> T;
264 
265  mln_concrete(I) output;
266  mln::initialize(output, mln::exact(input));
267  mln::data::fill(output, false);
268  mln::data::paste(mln::morpho::erosion(mln::extend(input | T::is_vertex(),
269  input),
270  T::v2e()),
271  output);
272  return output;
273 }
274 
276 template <typename I>
277 inline
278 mln_concrete(I)
279 dilation_v2e(const mln::Image<I>& input)
280 {
281  typedef trait::graph<I> T;
282 
283  mln_concrete(I) output;
284  mln::initialize(output, mln::exact(input));
285  mln::data::fill(output, false);
286  mln::data::paste(mln::morpho::dilation(mln::extend(input | T::is_edge(),
287  input),
288  T::e2v()),
289  output);
290  return output;
291 }
292 
293 
294 // ------------------------------ //
295 // Other dilations and erosions. //
296 // ------------------------------ //
297 
299 template <typename I>
300 inline
301 mln_concrete(I)
302 dilation_vertex(const mln::Image<I>& input)
303 {
304  return dilation_e2v(dilation_v2e(input));
305 }
306 
308 template <typename I>
309 inline
310 mln_concrete(I)
311 erosion_vertex(const mln::Image<I>& input)
312 {
313  return erosion_e2v(erosion_v2e(input));
314 }
315 
316 
318 template <typename I>
319 inline
320 mln_concrete(I)
321 dilation_edge(const mln::Image<I>& input)
322 {
323  return dilation_v2e(dilation_e2v(input));
324 }
325 
327 template <typename I>
328 inline
329 mln_concrete(I)
330 erosion_edge(const mln::Image<I>& input)
331 {
332  return erosion_v2e(erosion_e2v(input));
333 }
334 
335 
337 template <typename I>
338 inline
339 mln_concrete(I)
340 dilation_graph(const mln::Image<I>& input)
341 {
342  return combine(dilation_vertex(input), dilation_edge(input));
343 }
344 
346 template <typename I>
347 inline
348 mln_concrete(I)
349 erosion_graph(const mln::Image<I>& input)
350 {
351  return combine(erosion_vertex(input), erosion_edge(input));
352 }
353 
354 
355 /*-------------------------.
356 | Additional adjunctions. |
357 `-------------------------*/
358 
359 template <typename I>
360 inline
361 mln_concrete(I)
362 alpha1(const mln::Image<I>& input)
363 {
364  mln_concrete(I) vertices;
365  mln::initialize(vertices, input);
366  mln::data::fill(vertices, true);
367  return combine(vertices, input);
368 }
369 
370 template <typename I>
371 inline
372 mln_concrete(I)
373 beta1(const mln::Image<I>& input)
374 {
375  return combine(dilation_e2v(input), input);
376 }
377 
378 template <typename I>
379 inline
380 mln_concrete(I)
381 alpha2(const mln::Image<I>& input)
382 {
383  return combine(input, erosion_v2e(input));
384 }
385 
386 template <typename I>
387 inline
388 mln_concrete(I)
389 beta2(const mln::Image<I>& input)
390 {
391  mln_concrete(I) edges;
392  mln::initialize(edges, input);
393  mln::data::fill(edges, false);
394  return combine(input, edges);
395 }
396 
397 template <typename I>
398 inline
399 mln_concrete(I)
400 alpha3(const mln::Image<I>& input)
401 {
402  return combine(erosion_e2v(input), erosion_v2e(erosion_e2v(input)));
403 }
404 
405 template <typename I>
406 inline
407 mln_concrete(I)
408 beta3(const mln::Image<I>& input)
409 {
410  return combine(dilation_e2v(dilation_v2e(input)), dilation_v2e(input));
411 }
412 
413 
414 /*------------------------.
415 | Openings and closings. |
416 `------------------------*/
417 
419 template <typename I>
420 inline
421 mln_concrete(I)
422 opening_vertex(const mln::Image<I>& input)
423 {
424  return dilation_vertex(erosion_vertex(input));
425 }
426 
428 template <typename I>
429 inline
430 mln_concrete(I)
431 closing_vertex(const mln::Image<I>& input)
432 {
433  return erosion_vertex(dilation_vertex(input));
434 }
435 
436 
438 template <typename I>
439 inline
440 mln_concrete(I)
441 opening_edge(const mln::Image<I>& input)
442 {
443  return dilation_edge(erosion_edge(input));
444 }
445 
447 template <typename I>
448 inline
449 mln_concrete(I)
450 closing_edge(const mln::Image<I>& input)
451 {
452  return erosion_edge(dilation_edge(input));
453 }
454 
455 
457 template <typename I>
458 inline
459 mln_concrete(I)
460 opening_graph(const mln::Image<I>& input)
461 {
462  return combine(opening_vertex(input), opening_edge(input));
463 }
464 
466 template <typename I>
467 inline
468 mln_concrete(I)
469 closing_graph(const mln::Image<I>& input)
470 {
471  return combine(closing_vertex(input), closing_edge(input));
472 }
473 
474 
475 /*----------------------------------.
476 | Half-openings and half-closings. |
477 `----------------------------------*/
478 
480 template <typename I>
481 inline
482 mln_concrete(I)
483 half_opening_vertex(const mln::Image<I>& input)
484 {
485  return dilation_e2v(erosion_v2e(input));
486 }
487 
489 template <typename I>
490 inline
491 mln_concrete(I)
492 half_closing_vertex(const mln::Image<I>& input)
493 {
494  return erosion_e2v(dilation_v2e(input));
495 }
496 
497 
499 template <typename I>
500 inline
501 mln_concrete(I)
502 half_opening_edge(const mln::Image<I>& input)
503 {
504  return dilation_v2e(erosion_e2v(input));
505 }
506 
508 template <typename I>
509 inline
510 mln_concrete(I)
511 half_closing_edge(const mln::Image<I>& input)
512 {
513  return erosion_v2e(dilation_e2v(input));
514 }
515 
516 
518 template <typename I>
519 inline
520 mln_concrete(I)
521 half_opening_graph(const mln::Image<I>& input)
522 {
523  return combine(half_opening_vertex(input), half_opening_edge(input));
524 }
525 
527 template <typename I>
528 inline
529 mln_concrete(I)
530 half_closing_graph(const mln::Image<I>& input)
531 {
532  return combine(half_closing_vertex(input), half_closing_edge(input));
533 }
534 
535 
536 /*-------------------------------------------------------.
537 | Parameterized openings and closings (granulometries). |
538 `-------------------------------------------------------*/
539 
541 template <typename I>
542 inline
543 mln_concrete(I)
544 opening(const mln::Image<I>& input, unsigned lambda)
545 {
546  unsigned i = lambda / 2;
547  unsigned j = lambda % 2;
548  mln_concrete(I) output = mln::duplicate(input);
549  for (unsigned m = 0; m < i; ++m)
550  output = erosion_graph(output);
551  for (unsigned m = 0; m < j; ++m)
552  output = half_opening_graph(output);
553  for (unsigned m = 0; m < i; ++m)
554  output = dilation_graph(output);
555  return output;
556 }
557 
559 template <typename I>
560 inline
561 mln_concrete(I)
562 closing(const mln::Image<I>& input, unsigned lambda)
563 {
564  unsigned i = lambda / 2;
565  unsigned j = lambda % 2;
566  mln_concrete(I) output = mln::duplicate(input);
567  for (unsigned m = 0; m < i; ++m)
568  output = dilation_graph(output);
569  for (unsigned m = 0; m < j; ++m)
570  output = half_closing_graph(output);
571  for (unsigned m = 0; m < i; ++m)
572  output = erosion_graph(output);
573  return output;
574 }
575 
576 /*-------------------------------.
577 | Alternate Sequential Filters. |
578 `-------------------------------*/
579 
581 template <typename I>
582 inline
583 mln_concrete(I)
584 asf(const mln::Image<I>& input, unsigned lambda)
585 {
586  mln_concrete(I) output = mln::duplicate(input);
587  for (unsigned m = 1; m <= lambda; ++m)
588  output = opening(closing(output, m), m);
589  return output;
590 }
591 
592 #endif // ! APPS_GRAPH_MORPHO_MORPHO_HH