Milena (Olena)
User documentation 2.0a Id
|
00001 // Copyright (C) 2008, 2009, 2010 EPITA Research and Development 00002 // Laboratory (LRDE) 00003 // 00004 // This file is part of Olena. 00005 // 00006 // Olena is free software: you can redistribute it and/or modify it under 00007 // the terms of the GNU General Public License as published by the Free 00008 // Software Foundation, version 2 of the License. 00009 // 00010 // Olena is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 // General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Olena. If not, see <http://www.gnu.org/licenses/>. 00017 // 00018 // As a special exception, you may use this file as part of a free 00019 // software project without restriction. Specifically, if other files 00020 // instantiate templates or use macros or inline functions from this 00021 // file, or you compile this file and link it with other files to produce 00022 // an executable, this file does not by itself cause the resulting 00023 // executable to be covered by the GNU General Public License. This 00024 // exception does not however invalidate any other reasons why the 00025 // executable file might be covered by the GNU General Public License. 00026 00031 00032 #include <iostream> 00033 #include <fstream> 00034 #include <sstream> 00035 #include <iomanip> 00036 00037 #include <mln/value/int_u8.hh> 00038 #include <mln/value/rgb8.hh> 00039 #include <mln/literal/black.hh> 00040 #include <mln/literal/white.hh> 00041 00042 #include <mln/core/concept/function.hh> 00043 #include <mln/core/alias/point2d.hh> 00044 #include <mln/core/site_set/p_faces.hh> 00045 #include <mln/core/image/complex_image.hh> 00046 // FIXME: Include these elsewhere? (In complex_image.hh?) 00047 #include <mln/core/image/complex_neighborhoods.hh> 00048 #include <mln/core/image/complex_neighborhood_piter.hh> 00049 00050 #include <mln/data/fill.hh> 00051 00052 #include <mln/norm/l2.hh> 00053 00054 #include <mln/morpho/closing/area.hh> 00055 #include <mln/morpho/watershed/flooding.hh> 00056 00057 #include <mln/convert/to.hh> 00058 00059 #include <mln/debug/iota.hh> 00060 00061 // FIXME: To be put elsewhere (from milena/sandbox/geraud/wst_edge.cc). 00062 struct colorize : mln::Function_v2v< colorize > 00063 { 00064 typedef mln::value::rgb8 result; 00065 colorize(unsigned max) 00066 : lut(max + 1) 00067 { 00068 lut[0] = mln::literal::black; 00069 for (unsigned i = 1; i <= max; ++i) 00070 lut[i] = result(100 + std::rand() % 150, 00071 100 + std::rand() % 150, 00072 100 + std::rand() % 150); 00073 } 00074 result operator()(unsigned i) const 00075 { 00076 return lut[i]; 00077 } 00078 std::vector<result> lut; 00079 }; 00080 00081 00082 00083 int main() 00084 { 00085 using namespace mln; 00086 using mln::value::int_u8; 00087 00088 /*----------------------------------------. 00089 | Complex + complex geometry (location). | 00090 `----------------------------------------*/ 00091 00092 /* A (simplicial) 1-complex and its adjacency graph. 00093 00094 c 0 1 2 3 00095 r .------------------------ 00096 | v0 e3 v3 00097 0 | o-----------o v0----e3----v3 00098 | / \ / / \ / 00099 | / \ / / \ / 00100 1 | e0 / e1 / e4 e0 e1 e4 00101 | / \ / / \ / 00102 | / \ / / \ / 00103 2 | o-----------o v1----e2----v2 00104 | v1 e2 v2 00105 00106 v = vertex 00107 e = edge 00108 */ 00109 00110 00111 const unsigned D = 1; 00112 00113 topo::complex<D> c; 00114 00115 typedef point2d P; 00116 typedef geom::complex_geometry<D, P> G; 00117 G geom; 00118 00119 // Convenience typedefs. 00120 typedef topo::n_face<0, D> vertex; 00121 typedef topo::n_face<1, D> edge; 00122 00123 // 0-faces (vertices). 00124 vertex v0 = c.add_face(); geom.add_location(point2d(0,1)); 00125 vertex v1 = c.add_face(); geom.add_location(point2d(2,0)); 00126 vertex v2 = c.add_face(); geom.add_location(point2d(2,2)); 00127 vertex v3 = c.add_face(); geom.add_location(point2d(0,3)); 00128 00129 // 1-faces (edges). 00130 edge e0 = c.add_face(-v1 + v0); 00131 edge e1 = c.add_face(-v2 + v0); 00132 edge e2 = c.add_face(-v2 + v1); 00133 edge e3 = c.add_face(-v0 + v3); 00134 edge e4 = c.add_face(-v3 + v2); 00135 00136 /*---------------------. 00137 | Complex-based pset. | 00138 `---------------------*/ 00139 00140 p_complex<D, G> pc(c, geom); 00141 00142 /*----------------------. 00143 | Complex-based image. | 00144 `----------------------*/ 00145 00146 // An image type built on a 1-complex with unsigned values on each 00147 // face (both vertices and edges). 00148 typedef complex_image<D, G, unsigned> dist_ima_t; 00149 00150 // Create and initialize an image based on PC. 00151 dist_ima_t dist_ima(pc); 00152 data::fill(dist_ima, 0u); 00153 00154 /*--------------------------------. 00155 | Complex-based image iterators. | 00156 `--------------------------------*/ 00157 00158 // For each edge (1-face), compute the distance between the two 00159 // adjacent vertices (0-faces). 00160 p_n_faces_fwd_piter<D, G> e(dist_ima.domain(), 1); 00161 typedef complex_lower_neighborhood<D, G> v_nbh_t; 00162 v_nbh_t v_nbh; 00163 mln_niter_(v_nbh_t) v(v_nbh, e); 00164 for_all(e) 00165 { 00166 v.start(); 00167 point2d p1 = v.to_site().front(); 00168 v.next(); 00169 point2d p2 = v.to_site().front(); 00170 v.next(); 00171 mln_invariant(!v.is_valid()); 00172 00173 dist_ima(e) = convert::to<unsigned>(10 * norm::l2_distance(p1.to_vec(), p2.to_vec())); 00174 } 00175 // Initialize 0-faces to a dummy value, to prevent the watershed from 00176 // finding minima on 0-faces. 00177 p_n_faces_fwd_piter<D, G> v_(dist_ima.domain(), 0); 00178 for_all(v_) 00179 dist_ima(v_) = mln_max(mln_value_(dist_ima_t)); 00180 00181 // For all edges, iterate on adjacent edges (i.e., on edges sharing 00182 // an adjacent vertex). 00183 typedef complex_lower_dim_connected_n_face_neighborhood<D, G> nbh_t; 00184 nbh_t nbh; 00185 // Neighbor edge. 00186 mln_niter_(nbh_t) ne(nbh, e); 00187 for_all(e) 00188 { 00189 std::cout << "dist_ima(" << e << ") = " << dist_ima(e) 00190 << " -- adjacent edges :" << std::endl; 00191 for_all(ne) 00192 std::cout << " " << ne << std::endl; 00193 } 00194 00195 /*-----------------. 00196 | Simplification. | 00197 `-----------------*/ 00198 00199 // Currently, does nothing (lambda = 1). 00200 dist_ima_t closed_dist_ima = morpho::closing::area(dist_ima, nbh, 1); 00201 00202 /*------. 00203 | WST. | 00204 `------*/ 00205 00206 // Perform a Watershed Transform. 00207 typedef unsigned wst_val_t; 00208 wst_val_t nbasins; 00209 typedef complex_image<D, G, wst_val_t> wst_ima_t; 00210 wst_ima_t wshed = morpho::watershed::flooding(closed_dist_ima, nbh, nbasins); 00211 /* Note that since the image is based not only on the 1-faces but 00212 also on the 0-faces of the complex, and given the above 00213 neighborhood, the domain seen by the WST is not connected! It is 00214 actually composed of five components : 00215 00216 - a component containing all the 1-faces (egdes) which are all 00217 connected through 00218 mln::complex_lower_dim_connected_n_face_neighborhood; 00219 00220 - four (singleton) components corresponding to the 0-faces 00221 (vertices), connected to no other part of the complex according to 00222 mln::complex_lower_dim_connected_n_face_neighborhood. 00223 00224 Since the component made of the edges contains two local minima, 00225 the number of basins is equal to 6: 00226 00227 2 minima for the edges' component 00228 + 4 * 1 minima for the vertices's components 00229 -------------------------------------------- 00230 6 basins. 00231 00232 Hence the result. 00233 00234 00235 We definitely need a complex_image that can accept a subset of a 00236 complex as domain (or at least a p_face<N, D, P>. */ 00237 wst_val_t actual_nbasins = nbasins - c.nfaces_of_static_dim<0>(); 00238 std::cout << "nbasins = " << actual_nbasins << std::endl; 00239 00240 00241 colorize color(nbasins); 00242 00243 std::ofstream g("complex_image_wst-wst.neato"); 00244 g << "graph wst" << std::endl 00245 << "{" << std::endl 00246 << " graph [bgcolor = \"#000000\"]" << std::endl 00247 << " edge [color = \"#FFFFFF\"]" << std::endl 00248 << " node [color = \"#FFFFFF\", fontcolor = \"#FFFFFF\" ]" << std::endl; 00249 00250 // Vertices. 00251 typedef complex_higher_neighborhood<D, G> e_nbh_t; 00252 e_nbh_t e_nbh; 00253 mln_niter_(e_nbh_t) v_e(e_nbh, v_); 00254 for_all(v_) 00255 { 00256 // Find the adjacent basin (color). 00257 value::rgb8 basin_color = literal::white; 00258 for_all(v_e) 00259 if (wshed(v_e) != 0) 00260 { 00261 basin_color = color(wshed(v_e)); 00262 break; 00263 } 00264 std::ostringstream basin_color_str; 00265 basin_color_str << '#' 00266 << std::hex 00267 << std::setfill('0') 00268 << std::setw(2) << basin_color.red() 00269 << std::setw(2) << basin_color.green() 00270 << std::setw(2) << basin_color.blue() 00271 << std::dec; 00272 00273 g << " v" << v_.unproxy_().face_id() 00274 << " [pos = \"" 00275 << std::fixed << std::setprecision(1) 00276 << (float)v_.to_site().front()[1] << ", " 00277 << -(float)v_.to_site().front()[0] 00278 << "\", color = \"" << basin_color_str.str() 00279 << "\", fillcolor = \"" << basin_color_str.str() 00280 << "\", pin = \"true\", style=\"filled,setlinewidth(3)\"];" 00281 << std::endl; 00282 } 00283 00284 for_all(e) 00285 { 00286 value::rgb8 basin_color = color(wshed(e)); 00287 std::ostringstream basin_color_str; 00288 basin_color_str << '#' 00289 << std::hex 00290 << std::setfill('0') 00291 << std::setw(2) << basin_color.red() 00292 << std::setw(2) << basin_color.green() 00293 << std::setw(2) << basin_color.blue() 00294 << std::dec; 00295 00296 // Adjacent vertices. 00297 v.start(); 00298 topo::face<1> v1 = v.unproxy_().face(); 00299 point2d p1 = v.to_site().front(); 00300 v.next(); 00301 topo::face<1> v2 = v.unproxy_().face(); 00302 point2d p2 = v.to_site().front(); 00303 v.next(); 00304 mln_invariant(!v.is_valid()); 00305 00306 // Edges. 00307 g << " v" << v1.face_id() << " -- v" << v2.face_id() << " "; 00308 if (wshed(e) == 0) 00309 g << "[color = \"#FFFFFF\"];" << std::endl; 00310 else 00311 g << "[color = \"" << basin_color_str.str() 00312 << "\", style=\"setlinewidth(3)\"];" << std::endl; 00313 } 00314 00315 g << "}" << std::endl; 00316 g.close(); 00317 }