• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List

morpho.hh

00001 // Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
00002 //
00003 // This file is part of Olena.
00004 //
00005 // Olena is free software: you can redistribute it and/or modify it under
00006 // the terms of the GNU General Public License as published by the Free
00007 // Software Foundation, version 2 of the License.
00008 //
00009 // Olena is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with Olena.  If not, see <http://www.gnu.org/licenses/>.
00016 //
00017 // As a special exception, you may use this file as part of a free
00018 // software project without restriction.  Specifically, if other files
00019 // instantiate templates or use macros or inline functions from this
00020 // file, or you compile this file and link it with other files to produce
00021 // an executable, this file does not by itself cause the resulting
00022 // executable to be covered by the GNU General Public License.  This
00023 // exception does not however invalidate any other reasons why the
00024 // executable file might be covered by the GNU General Public License.
00025 
00026 #ifndef APPS_GRAPH_MORPHO_MORPHO_HH
00027 # define APPS_GRAPH_MORPHO_MORPHO_HH
00028 
00039 # include <mln/core/alias/complex_image.hh>
00040 # include <mln/core/image/image2d.hh>
00041 
00042 # include <mln/core/image/dmorph/image_if.hh>
00043 
00044 # include <mln/core/image/dmorph/extension_ima.hh>
00045 
00046 # include <mln/core/routine/extend.hh>
00047 # include <mln/core/routine/duplicate.hh>
00048 
00049 # include <mln/core/site_set/p_n_faces_piter.hh>
00050 # include <mln/core/image/complex_neighborhoods.hh>
00051 # include <mln/core/image/complex_neighborhood_piter.hh>
00052 
00053 # include <mln/world/inter_pixel/dim2/is_pixel.hh>
00054 # include <mln/world/inter_pixel/dim2/is_edge.hh>
00055 # include <mln/world/inter_pixel/neighb2d.hh>
00056 
00057 # include <mln/data/paste.hh>
00058 
00059 # include <mln/morpho/dilation.hh>
00060 # include <mln/morpho/erosion.hh>
00061 
00062 # include <mln/topo/is_n_face.hh>
00063 
00064 
00065 /*---------------.
00066 | Graph traits.  |
00067 `---------------*/
00068 
00069 namespace trait
00070 {
00072   template <typename I>
00073   struct graph
00074   {
00075     /* Empty by default.
00076 
00077        Specializations must provide these static member functions:
00078 
00079          static F1 is_vertex()
00080          static F2 is_edge()
00081          static W1 v2e()
00082          static W2 e2v()
00083 
00084        where F1, F2, W1 and W2 are types depending on I.
00085     */
00086   };
00087 
00088   // ----------------------------------------------------------- //
00089   // Graph traits for (mln::image2d-based) cubical 2-complexes.  //
00090   // ----------------------------------------------------------- //
00091 
00093   template <typename T>
00094   struct graph< mln::image2d<T> >
00095   {
00096     // Return a functor saying whether a psite is a vertex or not.
00097     static
00098     const mln::world::inter_pixel::dim2::is_pixel& is_vertex()
00099     {
00100       static mln::world::inter_pixel::dim2::is_pixel is_vertex_fun;
00101       return is_vertex_fun;
00102     }
00103 
00104     // Return a functor saying whether a psite is a vertex or not.
00105     static
00106     const mln::world::inter_pixel::dim2::is_edge& is_edge()
00107     {
00108       static mln::world::inter_pixel::dim2::is_edge is_edge_fun;
00109       return is_edge_fun;
00110     }
00111 
00112     // Return a window containing the edges adjacent to a vertex.
00113     static
00114     const mln::window2d& v2e()
00115     {
00116       return mln::world::inter_pixel::v2e().win();
00117     }
00118 
00119     // Return a window containing the vertices adjacent to an edge.
00120     static
00121     const mln::world::inter_pixel::dbl_window2d& e2v()
00122     {
00123       return mln::world::inter_pixel::e2v().win();
00124     }
00125   };
00126 
00127   // ---------------------------------------- //
00128   // Graph traits for (general) 1-complexes.  //
00129   // ---------------------------------------- //
00130 
00132   template <typename G, typename V>
00133   struct graph< mln::complex_image<1, G, V> >
00134   {
00135     // Return a functor saying whether a psite is a vertex or not.
00136     static
00137     const mln::topo::is_n_face<0>& is_vertex()
00138     {
00139       static mln::topo::is_n_face<0> is_vertex_fun;
00140       return is_vertex_fun;
00141     }
00142 
00143     // Return a functor saying whether a psite is a vertex or not.
00144     static
00145     const mln::topo::is_n_face<1>& is_edge()
00146     {
00147       static mln::topo::is_n_face<1> is_edge_fun;
00148       return is_edge_fun;
00149     }
00150 
00151     // Return a window containing the edges adjacent to a vertex.
00152     static
00153     const mln::complex_higher_window<1, G>& v2e()
00154     {
00155       static mln::complex_higher_window<1, G> v2e_win;
00156       return v2e_win;
00157     }
00158 
00159     // Return a window containing the vertices adjacent to an edge.
00160     static
00161     const mln::complex_lower_window<1, G>& e2v()
00162     {
00163       static mln::complex_lower_window<1, G> e2v_win;
00164       return e2v_win;
00165     }
00166   };
00167 
00168 } // end of namespace trait
00169 
00170 
00171 /*----------------------------.
00172 | Vertices-edges combinator.  |
00173 `----------------------------*/
00174 
00175 /* The original paper uses an operator `\ovee' to combine node and
00176    edge graphs.  However, this symbol requires the use of the
00177    `stmaryrd' package, and Doyxgen provides no means to require it.
00178    So, we use a more ``standard'' symbol instead (`\oplus').  */
00179 
00182 template <typename I>
00183 inline
00184 mln_concrete(I)
00185 combine(const mln::Image<I>& vertices_, const mln::Image<I>& edges_)
00186 {
00187   typedef trait::graph<I> T;
00188   const I& vertices = mln::exact(vertices_);
00189   const I& edges = mln::exact(edges_);
00190 
00191   mln_precondition(vertices.domain() == edges.domain());
00192   mln_concrete(I) output;
00193   mln::initialize(output, vertices);
00194   mln::data::fill(output, false);
00195   mln::data::paste(vertices | T::is_vertex(), output);
00196   mln::data::paste(edges | T::is_edge(), output);
00197   return output;
00198 }
00199 
00200 
00201 /*-------------------------.
00202 | Dilations and erosions.  |
00203 `-------------------------*/
00204 
00205 // ----------------------------- //
00206 // Core dilations and erosions.  //
00207 // ----------------------------- //
00208 
00209 /* Note: When writing
00210 
00211      dilation(ima | vertices);
00212 
00213    `vertices' is a predicate on sites (p2b function), which
00214    is not efficient, since both vertices and edges will be browsed.
00215 
00216    It would be very nice if `vertices' could be an actual site set,
00217    so that `ima | vertices' creates a morpher smart enough to
00218    browse /only/ vertices.  */
00219 
00220 
00222 template <typename I>
00223 inline
00224 mln_concrete(I)
00225 dilation_e2v(const mln::Image<I>& input)
00226 {
00227   typedef trait::graph<I> T;
00228 
00229   mln_concrete(I) output;
00230   mln::initialize(output, mln::exact(input));
00231   mln::data::fill(output, false);
00232   mln::data::paste(mln::morpho::dilation(mln::extend(input | T::is_vertex(),
00233                                                        input),
00234                                            T::v2e()),
00235                      output);
00236   return output;
00237 }
00238 
00240 template <typename I>
00241 inline
00242 mln_concrete(I)
00243 erosion_v2e(const mln::Image<I>& input)
00244 {
00245   typedef trait::graph<I> T;
00246 
00247   mln_concrete(I) output;
00248   mln::initialize(output, mln::exact(input));
00249   mln::data::fill(output, false);
00250   mln::data::paste(mln::morpho::erosion(mln::extend(input | T::is_edge(),
00251                                                       input),
00252                                           T::e2v()),
00253                      output);
00254   return output;
00255 }
00256 
00258 template <typename I>
00259 inline
00260 mln_concrete(I)
00261 erosion_e2v(const mln::Image<I>& input)
00262 {
00263   typedef trait::graph<I> T;
00264 
00265   mln_concrete(I) output;
00266   mln::initialize(output, mln::exact(input));
00267   mln::data::fill(output, false);
00268   mln::data::paste(mln::morpho::erosion(mln::extend(input | T::is_vertex(),
00269                                                       input),
00270                                            T::v2e()),
00271                      output);
00272   return output;
00273 }
00274 
00276 template <typename I>
00277 inline
00278 mln_concrete(I)
00279 dilation_v2e(const mln::Image<I>& input)
00280 {
00281   typedef trait::graph<I> T;
00282 
00283   mln_concrete(I) output;
00284   mln::initialize(output, mln::exact(input));
00285   mln::data::fill(output, false);
00286   mln::data::paste(mln::morpho::dilation(mln::extend(input | T::is_edge(),
00287                                                        input),
00288                                            T::e2v()),
00289                      output);
00290   return output;
00291 }
00292 
00293 
00294 // ------------------------------ //
00295 // Other dilations and erosions.  //
00296 // ------------------------------ //
00297 
00299 template <typename I>
00300 inline
00301 mln_concrete(I)
00302 dilation_vertex(const mln::Image<I>& input)
00303 {
00304   return dilation_e2v(dilation_v2e(input));
00305 }
00306 
00308 template <typename I>
00309 inline
00310 mln_concrete(I)
00311 erosion_vertex(const mln::Image<I>& input)
00312 {
00313   return erosion_e2v(erosion_v2e(input));
00314 }
00315 
00316 
00318 template <typename I>
00319 inline
00320 mln_concrete(I)
00321 dilation_edge(const mln::Image<I>& input)
00322 {
00323   return dilation_v2e(dilation_e2v(input));
00324 }
00325 
00327 template <typename I>
00328 inline
00329 mln_concrete(I)
00330 erosion_edge(const mln::Image<I>& input)
00331 {
00332   return erosion_v2e(erosion_e2v(input));
00333 }
00334 
00335 
00337 template <typename I>
00338 inline
00339 mln_concrete(I)
00340 dilation_graph(const mln::Image<I>& input)
00341 {
00342   return combine(dilation_vertex(input), dilation_edge(input));
00343 }
00344 
00346 template <typename I>
00347 inline
00348 mln_concrete(I)
00349 erosion_graph(const mln::Image<I>& input)
00350 {
00351   return combine(erosion_vertex(input), erosion_edge(input));
00352 }
00353 
00354 
00355 /*-------------------------.
00356 | Additional adjunctions.  |
00357 `-------------------------*/
00358 
00359 template <typename I>
00360 inline
00361 mln_concrete(I)
00362 alpha1(const mln::Image<I>& input)
00363 {
00364   mln_concrete(I) vertices;
00365   mln::initialize(vertices, input);
00366   mln::data::fill(vertices, true);
00367   return combine(vertices, input);
00368 }
00369 
00370 template <typename I>
00371 inline
00372 mln_concrete(I)
00373 beta1(const mln::Image<I>& input)
00374 {
00375   return combine(dilation_e2v(input), input);
00376 }
00377 
00378 template <typename I>
00379 inline
00380 mln_concrete(I)
00381 alpha2(const mln::Image<I>& input)
00382 {
00383   return combine(input, erosion_v2e(input));
00384 }
00385 
00386 template <typename I>
00387 inline
00388 mln_concrete(I)
00389 beta2(const mln::Image<I>& input)
00390 {
00391   mln_concrete(I) edges;
00392   mln::initialize(edges, input);
00393   mln::data::fill(edges, false);
00394   return combine(input, edges);
00395 }
00396 
00397 template <typename I>
00398 inline
00399 mln_concrete(I)
00400 alpha3(const mln::Image<I>& input)
00401 {
00402   return combine(erosion_e2v(input), erosion_v2e(erosion_e2v(input)));
00403 }
00404 
00405 template <typename I>
00406 inline
00407 mln_concrete(I)
00408 beta3(const mln::Image<I>& input)
00409 {
00410   return combine(dilation_e2v(dilation_v2e(input)), dilation_v2e(input));
00411 }
00412 
00413 
00414 /*------------------------.
00415 | Openings and closings.  |
00416 `------------------------*/
00417 
00419 template <typename I>
00420 inline
00421 mln_concrete(I)
00422 opening_vertex(const mln::Image<I>& input)
00423 {
00424   return dilation_vertex(erosion_vertex(input));
00425 }
00426 
00428 template <typename I>
00429 inline
00430 mln_concrete(I)
00431 closing_vertex(const mln::Image<I>& input)
00432 {
00433   return erosion_vertex(dilation_vertex(input));
00434 }
00435 
00436 
00438 template <typename I>
00439 inline
00440 mln_concrete(I)
00441 opening_edge(const mln::Image<I>& input)
00442 {
00443   return dilation_edge(erosion_edge(input));
00444 }
00445 
00447 template <typename I>
00448 inline
00449 mln_concrete(I)
00450 closing_edge(const mln::Image<I>& input)
00451 {
00452   return erosion_edge(dilation_edge(input));
00453 }
00454 
00455 
00457 template <typename I>
00458 inline
00459 mln_concrete(I)
00460 opening_graph(const mln::Image<I>& input)
00461 {
00462   return combine(opening_vertex(input), opening_edge(input));
00463 }
00464 
00466 template <typename I>
00467 inline
00468 mln_concrete(I)
00469 closing_graph(const mln::Image<I>& input)
00470 {
00471   return combine(closing_vertex(input), closing_edge(input));
00472 }
00473 
00474 
00475 /*----------------------------------.
00476 | Half-openings and half-closings.  |
00477 `----------------------------------*/
00478 
00480 template <typename I>
00481 inline
00482 mln_concrete(I)
00483 half_opening_vertex(const mln::Image<I>& input)
00484 {
00485   return dilation_e2v(erosion_v2e(input));
00486 }
00487 
00489 template <typename I>
00490 inline
00491 mln_concrete(I)
00492 half_closing_vertex(const mln::Image<I>& input)
00493 {
00494   return erosion_e2v(dilation_v2e(input));
00495 }
00496 
00497 
00499 template <typename I>
00500 inline
00501 mln_concrete(I)
00502 half_opening_edge(const mln::Image<I>& input)
00503 {
00504   return dilation_v2e(erosion_e2v(input));
00505 }
00506 
00508 template <typename I>
00509 inline
00510 mln_concrete(I)
00511 half_closing_edge(const mln::Image<I>& input)
00512 {
00513   return erosion_v2e(dilation_e2v(input));
00514 }
00515 
00516 
00518 template <typename I>
00519 inline
00520 mln_concrete(I)
00521 half_opening_graph(const mln::Image<I>& input)
00522 {
00523   return combine(half_opening_vertex(input), half_opening_edge(input));
00524 }
00525 
00527 template <typename I>
00528 inline
00529 mln_concrete(I)
00530 half_closing_graph(const mln::Image<I>& input)
00531 {
00532   return combine(half_closing_vertex(input), half_closing_edge(input));
00533 }
00534 
00535 
00536 /*-------------------------------------------------------.
00537 | Parameterized openings and closings (granulometries).  |
00538 `-------------------------------------------------------*/
00539 
00541 template <typename I>
00542 inline
00543 mln_concrete(I)
00544 opening(const mln::Image<I>& input, unsigned lambda)
00545 {
00546   unsigned i = lambda / 2;
00547   unsigned j = lambda % 2;
00548   mln_concrete(I) output = mln::duplicate(input);
00549   for (unsigned m = 0; m < i; ++m)
00550     output = erosion_graph(output);
00551   for (unsigned m = 0; m < j; ++m)
00552     output = half_opening_graph(output);
00553   for (unsigned m = 0; m < i; ++m)
00554     output = dilation_graph(output);
00555   return output;
00556 }
00557 
00559 template <typename I>
00560 inline
00561 mln_concrete(I)
00562 closing(const mln::Image<I>& input, unsigned lambda)
00563 {
00564   unsigned i = lambda / 2;
00565   unsigned j = lambda % 2;
00566   mln_concrete(I) output = mln::duplicate(input);
00567   for (unsigned m = 0; m < i; ++m)
00568     output = dilation_graph(output);
00569   for (unsigned m = 0; m < j; ++m)
00570     output = half_closing_graph(output);
00571   for (unsigned m = 0; m < i; ++m)
00572     output = erosion_graph(output);
00573   return output;
00574 }
00575 
00576 /*-------------------------------.
00577 | Alternate Sequential Filters.  |
00578 `-------------------------------*/
00579 
00581 template <typename I>
00582 inline
00583 mln_concrete(I)
00584 asf(const mln::Image<I>& input, unsigned lambda)
00585 {
00586   mln_concrete(I) output = mln::duplicate(input);
00587   for (unsigned m = 1; m <= lambda; ++m)
00588     output = opening(closing(output, m), m);
00589   return output;
00590 }
00591 
00592 #endif // ! APPS_GRAPH_MORPHO_MORPHO_HH

Generated on Tue Oct 4 2011 15:24:06 for Milena (Olena) by  doxygen 1.7.1