Milena (Olena)
User documentation 2.0a Id
|
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