
* apps/papers/levillain.09.ismm/classif-graph.cc: New. * apps/papers/levillain.09.ismm/Makefile.am (noinst_PROGRAMS): Add classif-graph. (classif_graph_SOURCES): New. (noinst_DATA): Add classwst-graph.ppm. (classwst-graph.ppm): New target. --- milena/ChangeLog | 11 ++ milena/apps/papers/levillain.09.ismm/Makefile.am | 15 ++- .../{classif-1complex.cc => classif-graph.cc} | 162 +++++++++----------- 3 files changed, 93 insertions(+), 95 deletions(-) copy milena/apps/papers/levillain.09.ismm/{classif-1complex.cc => classif-graph.cc} (61%) diff --git a/milena/ChangeLog b/milena/ChangeLog index f25821c..bad4207 100644 --- a/milena/ChangeLog +++ b/milena/ChangeLog @@ -1,3 +1,14 @@ +2011-10-11 Roland Levillain <roland@lrde.epita.fr> + + Graph-based version of the classification example. + + * apps/papers/levillain.09.ismm/classif-graph.cc: New. + * apps/papers/levillain.09.ismm/Makefile.am (noinst_PROGRAMS): + Add classif-graph. + (classif_graph_SOURCES): New. + (noinst_DATA): Add classwst-graph.ppm. + (classwst-graph.ppm): New target. + 2011-10-10 Roland Levillain <roland@lrde.epita.fr> Rename apps/papers/levillain.09.ismm/classif.cc. diff --git a/milena/apps/papers/levillain.09.ismm/Makefile.am b/milena/apps/papers/levillain.09.ismm/Makefile.am index 3651c4f..79814de 100644 --- a/milena/apps/papers/levillain.09.ismm/Makefile.am +++ b/milena/apps/papers/levillain.09.ismm/Makefile.am @@ -25,12 +25,14 @@ AM_CXXFLAGS = $(APPS_CXXFLAGS) noinst_HEADERS = chain.hh io.hh influence_zones.hh -noinst_PROGRAMS = image2d graph complex classif-1complex +noinst_PROGRAMS = image2d graph complex classif-graph classif-1complex image2d_SOURCES = image2d.cc graph_SOURCES = graph.cc complex_SOURCES = complex.cc -# This example has been shown in the ISMM 2009 presentation only (not -# in the paper). +# This example (implemented both with graph- and 1-complex-based +# images) has been shown in the ISMM 2009 presentation only (not in +# the paper). +classif_graph_SOURCES = classif-graph.cc classif_1complex_SOURCES = classif-1complex.cc # Input images. @@ -38,7 +40,9 @@ classif_1complex_SOURCES = classif-1complex.cc dist_noinst_DATA = seeds.pgm m283-c.off classseedsi.pbm # Output images. -noinst_DATA = lena-s.ppm graph-s.png m283-s.off classwst-1complex.ppm +noinst_DATA = \ + lena-s.ppm graph-s.png m283-s.off \ + classwst-graph.ppm classwst-1complex.ppm MOSTLYCLEANFILES = $(noinst_DATA) graph-s.neato # FIXME: Also generate intermediate images (gradients, etc.). @@ -54,5 +58,8 @@ graph-s.neato: seeds.pgm graph$(EXEEXT) m283-s.off: m283-c.off complex$(EXEEXT) ./complex$(EXEEXT) $< 100 $@ +classwst-graph.ppm: classseedsi.pbm classif-graph$(EXEEXT) + ./classif-graph$(EXEEXT) $< 4 $@ + classwst-1complex.ppm: classseedsi.pbm classif-1complex$(EXEEXT) ./classif-1complex$(EXEEXT) $< 4 $@ diff --git a/milena/apps/papers/levillain.09.ismm/classif-1complex.cc b/milena/apps/papers/levillain.09.ismm/classif-graph.cc similarity index 61% copy from milena/apps/papers/levillain.09.ismm/classif-1complex.cc copy to milena/apps/papers/levillain.09.ismm/classif-graph.cc index 43853e3..36a6369 100644 --- a/milena/apps/papers/levillain.09.ismm/classif-1complex.cc +++ b/milena/apps/papers/levillain.09.ismm/classif-graph.cc @@ -41,12 +41,9 @@ #include <mln/value/int_u8.hh> #include <mln/core/alias/point2d.hh> -#include <mln/core/site_set/p_faces.hh> -#include <mln/core/image/complex_image.hh> -#include <mln/core/alias/complex_image.hh> +#include <mln/util/site_pair.hh> -#include <mln/core/image/complex_neighborhoods.hh> -#include <mln/core/image/complex_neighborhood_piter.hh> +#include <mln/core/image/edge_image.hh> #include <mln/data/fill.hh> #include <mln/norm/l2.hh> @@ -56,13 +53,15 @@ #include "influence_zones.hh" #include "chain.hh" +/* FIXME: Introduce aliases for common specializations of graph images + such as the return type of make_graph_image. */ /** Create a 1-complex (graph) image from the connected components of \a seeds. The values associated to a 1-face (edge) is equal to the L2-distance between its two adjacent vertices. The values on a 0-face (vertex) is set to 0. */ -mln::int_u8_1complex_image2d -make_complex_image(const mln::image2d<bool>& seeds) +mln::edge_image<mln::util::site_pair<mln::point2d>, mln::value::int_u8> +make_graph_image(const mln::image2d<bool>& seeds) { using namespace mln; using mln::value::int_u8; @@ -98,9 +97,9 @@ make_complex_image(const mln::image2d<bool>& seeds) #endif } - /*--------------------------------. - | Construction of the 1-complex. | - `--------------------------------*/ + /*----------------------------. + | Construction of the graph. | + `----------------------------*/ // Adjacency matrix. std::vector< std::vector<bool> > adj(nlabels + 1); @@ -129,67 +128,68 @@ make_complex_image(const mln::image2d<bool>& seeds) } } + // Graph structure. + typedef util::graph G; + G g; - const unsigned D = 1; - // 1-complex data structure. - topo::complex<D> c; + // Vertices. Note that vertex 0 corresponds to the background, and + // is therefore not connected to any other vertex. + g.add_vertices(nlabels + 1); - typedef point2d P; - // Geometry (spatial locations) associated to the complex's faces. - typedef geom::complex_geometry<D, P> G; - G geom; - - // Convenience typedefs. - typedef topo::n_face<0, D> vertex; - typedef topo::n_face<1, D> edge; + // Sites associated to edges. + typedef util::site_pair<point2d> site_t; + typedef fun::i2v::array<site_t> fsite_t; + fsite_t sites; { - // 0-faces (vertices). - std::vector<vertex> v; + // Vertices locations. + std::vector<point2d> v_site (nlabels + 1, point2d(0,0)); { box2d::piter p(label.domain()); for_all(p) if (label(p) != 0) - { - geom.add_location(p); - v.push_back(c.add_face()); - } + v_site[label(p)] = p; } - std::cout << "v size = " << v.size() << std::endl; + std::cout << "v_site size = " << v_site.size() << std::endl; - // 1-faces (edges). - std::vector<edge> e; + // Edges. + std::vector<util::edge_id_t> e; { for (unsigned l = 1; l <= nlabels; ++l) for (unsigned ll = l + 1; ll <= nlabels; ++ll) if (adj[l][ll]) - // Create an edge as an oriented (``algebraic'') face. - e.push_back(c.add_face(-v[l-1] + v[ll-1])); + { + sites.append(site_t(v_site[l], v_site[ll])); + e.push_back(g.add_edge(l, ll)); + } } std::cout << "e size = " << e.size() << std::endl; } - /*-------------------------. - | Complex-based site set. | - `-------------------------*/ - - p_complex<D, G> pc(c, geom); - - /*----------------------. - | Complex-based image. | - `----------------------*/ - - // An image type built on a 1-complex with int_u8 values on each - // face (both vertices and edges). - typedef complex_image<D, G, int_u8> dist_ima_t; - - // Create and initialize an image based on PC. - dist_ima_t dist_ima(pc); + /*-------------. + | Edge image. | + `-------------*/ + + /* FIXME: edge_image should provide a ctor to initialize an instance + with just a graph an an edge-to-site function (but no values). + Currently this is not possible. Hence the ``adhead of time'' + creation of these values . */ + // Values. + typedef fun::i2v::array<int_u8> dist_values_t; + dist_values_t dist_values(sites.size()); + for (unsigned i = 0; i < dist_values.size(); ++i) + dist_values(i) = 0; + + + // Type of an edge-valued graph image located in a discrete 2D space + // with int_u8 values on each edge. + typedef edge_image<site_t, int_u8, util::graph> dist_ima_t; + dist_ima_t dist_ima(g, sites, dist_values); data::fill(dist_ima, 0u); - /*--------------------------------. - | Complex-based image iterators. | - `--------------------------------*/ + /*------------------------. + | Graph image iterators. | + `------------------------*/ accu::stat::max<int_u8> dist_max; @@ -197,23 +197,14 @@ make_complex_image(const mln::image2d<bool>& seeds) image2d<int_u8> canvas(seeds.domain()); data::fill(canvas, 0); - // Iterator on the edges of DIST_IMA. - p_n_faces_fwd_piter<D, G> e(dist_ima.domain(), 1); - // n-face to (n-1)-faces neighborhood (here, the pair of vertices - // adjacent to an edge). - typedef complex_lower_neighborhood<D, G> v_nbh_t; - v_nbh_t v_nbh; - // For each edge (1-face), compute the distance between the two - // adjacent vertices (0-faces). - mln_niter_(v_nbh_t) v(v_nbh, e); + // Iterator on (the edges of) DIST_IMA. + mln_piter_(dist_ima_t) e(dist_ima.domain()); for_all(e) { - v.start(); - point2d p1 = v.to_site().front(); - v.next(); - point2d p2 = v.to_site().front(); - v.next(); - mln_invariant(!v.is_valid()); + // Site associated to E. + site_t p = e; + point2d p1 = e.first(); + point2d p2 = e.second(); dist_ima(e) = norm::l2_distance(p1.to_vec(), p2.to_vec()); dist_max.take(dist_ima(e)); @@ -253,27 +244,22 @@ main(int argc, char* argv[]) image2d<bool> seeds; io::pbm::load(seeds, input_filename); - // Shortcut: type of a 1-complex image located in a discrete 2D - // space with int_u8 values for each face. - typedef int_u8_1complex_image2d ima_t; - // Shortcuts: dimension and geometry (set of spatial locations) - // associated to this image type. - const unsigned D = 1; - typedef mln_geom_(ima_t) G; + // Shortcut: type of an edge-valued graph image located in a + // discrete 2D space with int_u8 values for each edge. + typedef edge_image<util::site_pair<point2d>, int_u8> ima_t; // Image computed from the graph of influence zones (IZ) of seeds. - ima_t ima = make_complex_image(seeds); + ima_t ima = make_graph_image(seeds); - // Adjacency relation between two n-faces through a shared adjacent - // (n-1)-face. (An edge is adjacent to its neighboring edges; a - // vertex has no neighbors.) - typedef complex_lower_dim_connected_n_face_neighborhood<D, G> nbh_t; + // IMA's elementary neighborhood: adjacency relation between two + // edges through a shared vertex + typedef ima_t::nbh_t nbh_t; nbh_t nbh; typedef unsigned wst_val_t; wst_val_t nbasins; // Output image type. - typedef complex_image<D, G, wst_val_t> wst_ima_t; + typedef edge_image<util::site_pair<point2d>, wst_val_t> wst_ima_t; // Chain. wst_ima_t wst_ima = chain(ima, nbh, lambda, nbasins); @@ -283,21 +269,15 @@ main(int argc, char* argv[]) image2d<int_u8> canvas_wst(seeds.domain()); data::fill(canvas_wst, 255); - // Iterator on the edges (1-faces) of WST_IMA. - p_n_faces_fwd_piter<D, G> e(wst_ima.domain(), 1); - typedef complex_lower_neighborhood<D, G> v_nbh_t; - v_nbh_t v_nbh; - // Iterator on the vertices adjacent to E. - mln_niter_(v_nbh_t) v(v_nbh, e); + // Iterator on (the edges of) WST_IMA. + mln_piter_(wst_ima_t) e(wst_ima.domain()); for_all(e) { - v.start(); - point2d p1 = v.to_site().front(); - v.next(); - point2d p2 = v.to_site().front(); - v.next(); - mln_invariant(!v.is_valid()); + // Site associated to E. + util::site_pair<point2d> p = e; + point2d p1 = e.first(); + point2d p2 = e.second(); draw::line(canvas_wst, p1, p2, wst_ima(e)); } -- 1.7.2.5