last-svn-commit-249-gced2cce New apps on generic skeletonization.

* apps/generic-skel/image2d-skel-unconstrained.cc, * apps/generic-skel/image2d-skel-with-end-points.cc, * apps/generic-skel/image2d-skel.hh: New. * apps/generic-skel/test-image2d-skel-unconstrained.in, * apps/generic-skel/test-image2d-skel-with-end-points.in: New tests. * apps/generic-skel/Makefile.am: New. * apps/Makefile.am (SUBDIRS): Add generic-skel. --- milena/ChangeLog | 14 ++ milena/apps/Makefile.am | 6 +- milena/apps/generic-skel/Makefile.am | 54 ++++++ .../image2d-skel-unconstrained.cc} | 53 +++++-- .../image2d-skel-with-end-points.cc} | 52 +++++-- milena/apps/generic-skel/image2d-skel.hh | 174 ++++++++++++++++++++ .../test-image2d-skel-unconstrained.in} | 7 +- .../test-image2d-skel-with-end-points.in} | 7 +- 8 files changed, 330 insertions(+), 37 deletions(-) create mode 100644 milena/apps/generic-skel/Makefile.am copy milena/apps/{mesh-segm-skel/off-to-vtk-bin.cc => generic-skel/image2d-skel-unconstrained.cc} (53%) copy milena/apps/{mesh-segm-skel/off-to-vtk-bin.cc => generic-skel/image2d-skel-with-end-points.cc} (53%) create mode 100644 milena/apps/generic-skel/image2d-skel.hh copy milena/apps/{mesh-segm-skel/test-mesh-complex-2-collapse.in => generic-skel/test-image2d-skel-unconstrained.in} (71%) copy milena/apps/{mesh-segm-skel/test-mesh-complex-2-collapse.in => generic-skel/test-image2d-skel-with-end-points.in} (70%) diff --git a/milena/ChangeLog b/milena/ChangeLog index f567ea8..16b07b7 100644 --- a/milena/ChangeLog +++ b/milena/ChangeLog @@ -1,3 +1,17 @@ +2010-08-20 Roland Levillain <roland@lrde.epita.fr> + + New apps on generic skeletonization. + + * apps/generic-skel/image2d-skel-unconstrained.cc, + * apps/generic-skel/image2d-skel-with-end-points.cc, + * apps/generic-skel/image2d-skel.hh: + New. + * apps/generic-skel/test-image2d-skel-unconstrained.in, + * apps/generic-skel/test-image2d-skel-with-end-points.in: + New tests. + * apps/generic-skel/Makefile.am: New. + * apps/Makefile.am (SUBDIRS): Add generic-skel. + 2011-04-12 Roland Levillain <roland@lrde.epita.fr> apps/graph-morpho: Catch up with current mln::topo::is_n_face. diff --git a/milena/apps/Makefile.am b/milena/apps/Makefile.am index c42ffd7..c15569b 100644 --- a/milena/apps/Makefile.am +++ b/milena/apps/Makefile.am @@ -1,4 +1,5 @@ -# Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE). +# Copyright (C) 2008, 2009, 2010 EPITA Research and Development +# Laboratory (LRDE). # # This file is part of Olena. # @@ -13,10 +14,9 @@ # # You should have received a copy of the GNU General Public License # along with Olena. If not, see <http://www.gnu.org/licenses/>. -# # Applied examples of Milena. -SUBDIRS = mesh-segm-skel graph-morpho constrained-connectivity +SUBDIRS = mesh-segm-skel generic-skel graph-morpho constrained-connectivity # Examples from papers. SUBDIRS += papers diff --git a/milena/apps/generic-skel/Makefile.am b/milena/apps/generic-skel/Makefile.am new file mode 100644 index 0000000..5ae65f5 --- /dev/null +++ b/milena/apps/generic-skel/Makefile.am @@ -0,0 +1,54 @@ +# Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE). +# +# This file is part of Olena. +# +# Olena is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, version 2 of the License. +# +# Olena is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Olena. If not, see <http://www.gnu.org/licenses/>. + +# Find Milena and trimesh headers. +AM_CPPFLAGS = -I$(top_srcdir)/milena +# Produce fast code. +APPS_CXXFLAGS = @APPS_CXXFLAGS@ +AM_CXXFLAGS = $(APPS_CXXFLAGS) + + +bin_PROGRAMS = image2d-skel-unconstrained image2d-skel-with-end-points +image2d_skel_unconstrained_SOURCES = image2d-skel-unconstrained.cc image2d-skel.hh +image2d_skel_with_end_points_SOURCES = image2d-skel-with-end-points.cc image2d-skel.hh + +EXTRA_DIST = test-image2d-skel-unconstrained.in test-image2d-skel-with-end-points.in + +# Use Make to generate Doxyfile instead of `configure', as advised by +# Autoconf's manual (see section ``Installation Directory +# Variables''). +edit = sed -e 's|@top_srcdir[@]|$(top_srcdir)|g' + +test-image2d-skel-unconstrained test-image2d-skel-with-end-points: Makefile + rm -f $@ $@.tmp + srcdir=''; \ + test -f ./$@.in || srcdir=$(srcdir)/; \ + $(edit) $${srcdir}$@.in >$@.tmp + chmod +x $@.tmp + chmod a-w $@.tmp + mv $@.tmp $@ + +test-image2d-skel-unconstrained: $(srcdir)/test-image2d-skel-unconstrained.in +test-image2d-skel-with-end-points: $(srcdir)/test-image2d-skel-with-end-points.in + +TESTS = test-image2d-skel-unconstrained test-image2d-skel-with-end-points +CLEANFILES = test-image2d-skel-unconstrained test-image2d-skel-with-end-points + +MOSTLYCLEANFILES = \ + picasso-skel-unconstrained.pbm \ + picasso-skel-with-end-points.pbm \ + tiny-skel-unconstrained.pbm \ + tiny-skel-with-end-points.pbm diff --git a/milena/apps/mesh-segm-skel/off-to-vtk-bin.cc b/milena/apps/generic-skel/image2d-skel-unconstrained.cc similarity index 53% copy from milena/apps/mesh-segm-skel/off-to-vtk-bin.cc copy to milena/apps/generic-skel/image2d-skel-unconstrained.cc index 926da7d..4459ba4 100644 --- a/milena/apps/mesh-segm-skel/off-to-vtk-bin.cc +++ b/milena/apps/generic-skel/image2d-skel-unconstrained.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE) +// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE) // // This file is part of the Milena Library. This library is free // software; you can redistribute it and/or modify it under the terms @@ -26,22 +26,26 @@ // Public License. /// \file +/// \brief A program computing an unconstrained skeleton of a 2D image. -/// \brief A program converting a binary OFF file (e.g. no value -/// attached to faces) into a VTK file. +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> -#include <iostream> +#include <mln/topo/skeleton/breadth_first_thinning.hh> -#include <mln/io/off/load.hh> -#include <mln/io/vtk/save.hh> +#include <mln/io/pbm/all.hh> + +#include "image2d-skel.hh" int main(int argc, char* argv[]) { + using namespace mln; + if (argc != 3) { - std::cerr << "usage: " << argv[0] << " input.off output.vtk" + std::cerr << "usage: " << argv[0] << " input.pbm output.pbm" << std::endl; std::exit(1); } @@ -49,12 +53,33 @@ main(int argc, char* argv[]) std::string input_filename = argv[1]; std::string output_filename = argv[2]; - typedef mln::bin_2complex_image3df ima_t; - ima_t ima; + typedef image2d<bool> I; + typedef neighb2d N; + + // Add a border of (at least) 1 pixel, to a guarantee a meaningful + // result of the computation of connectivity numbers (called within + // is_simple_2d); indeed, this computation always expects each pixel + // to have 8 neighboring sites. + border::thickness = 1; + + I input = io::pbm::load(input_filename); + + // FIXME: Use a dual neighborhood instead? + + // Foreground neighborhood. + neighb2d nbh_fg = c4(); + // Background neighborhood. + neighb2d nbh_bg = c8(); + + // Simplicity criterion functor. + ::is_simple_2d<I, N> is_simple(nbh_fg, nbh_bg); + // Detach procedure. + ::detach<I> detach; + // (Lack of) constraint. + fun::p2b::tautology constraint; - // FIXME: Converting bunny-holefilled.off to VTK took 30 sec, which - // is awfully slow. Time the load and save operations and find - // where is (are) the issue(s). - mln::io::off::load(ima, input_filename); - mln::io::vtk::save(ima, output_filename); + I output = topo::skeleton::breadth_first_thinning(input, nbh_fg, + is_simple, detach, + constraint); + io::pbm::save(output, output_filename); } diff --git a/milena/apps/mesh-segm-skel/off-to-vtk-bin.cc b/milena/apps/generic-skel/image2d-skel-with-end-points.cc similarity index 53% copy from milena/apps/mesh-segm-skel/off-to-vtk-bin.cc copy to milena/apps/generic-skel/image2d-skel-with-end-points.cc index 926da7d..604b065 100644 --- a/milena/apps/mesh-segm-skel/off-to-vtk-bin.cc +++ b/milena/apps/generic-skel/image2d-skel-with-end-points.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE) +// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE) // // This file is part of the Milena Library. This library is free // software; you can redistribute it and/or modify it under the terms @@ -26,22 +26,27 @@ // Public License. /// \file +/// \brief A program computing a skeleton of a 2D image, preserving +/// end points. -/// \brief A program converting a binary OFF file (e.g. no value -/// attached to faces) into a VTK file. +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> -#include <iostream> +#include <mln/topo/skeleton/breadth_first_thinning.hh> -#include <mln/io/off/load.hh> -#include <mln/io/vtk/save.hh> +#include <mln/io/pbm/all.hh> + +#include "image2d-skel.hh" int main(int argc, char* argv[]) { + using namespace mln; + if (argc != 3) { - std::cerr << "usage: " << argv[0] << " input.off output.vtk" + std::cerr << "usage: " << argv[0] << " input.pbm output.pbm" << std::endl; std::exit(1); } @@ -49,12 +54,31 @@ main(int argc, char* argv[]) std::string input_filename = argv[1]; std::string output_filename = argv[2]; - typedef mln::bin_2complex_image3df ima_t; - ima_t ima; + typedef image2d<bool> I; + typedef neighb2d N; + + // Add a border of (at least) 1 pixel, to a guarantee a meaningful + // result of the computation of connectivity numbers (called within + // is_simple_2d); indeed, this computation always expects each pixel + // to have 8 neighboring sites. + border::thickness = 1; + + I input = io::pbm::load(input_filename); + + // Foreground neighborhood. + neighb2d nbh_fg = c4(); + // Background neighborhood. + neighb2d nbh_bg = c8(); + + // Simplicity criterion functor. + ::is_simple_2d<I, N> is_simple(nbh_fg, nbh_bg); + // Detach procedure. + ::detach<I> detach; + // Constraint: do not remove end points. + is_not_end_point<I, N> constraint(nbh_fg, input); - // FIXME: Converting bunny-holefilled.off to VTK took 30 sec, which - // is awfully slow. Time the load and save operations and find - // where is (are) the issue(s). - mln::io::off::load(ima, input_filename); - mln::io::vtk::save(ima, output_filename); + I output = topo::skeleton::breadth_first_thinning(input, nbh_fg, + is_simple, detach, + constraint); + io::pbm::save(output, output_filename); } diff --git a/milena/apps/generic-skel/image2d-skel.hh b/milena/apps/generic-skel/image2d-skel.hh new file mode 100644 index 0000000..6cd8c50 --- /dev/null +++ b/milena/apps/generic-skel/image2d-skel.hh @@ -0,0 +1,174 @@ +// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of the Milena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. This exception does not however invalidate any other +// reasons why the executable file might be covered by the GNU General +// Public License. + +#ifndef APPS_GENERIC_SKEL_IMAGE2D_SKEL_HH +# define APPS_GENERIC_SKEL_IMAGE2D_SKEL_HH + +/// \file +/// \brief Definitions for a simplicity criterion and a constraint +/// to be used in the breadth-first thinning of a 2D regular image. + +# include <mln/topo/is_simple_2d.hh> + + +// FIXME: Split this file? + + +/** \brief An equivalent (for mln::image2d) of the + mln::topo::is_simple_cell functor, based on the mask-based + criterion mln::topo::is_simple_2d. + + This functor acts as an adapter, since mln::topo::is_simple_2d + does not fit (yet) in the canvas of + mln::topo::skeleton::breadth_first_thinning. Moreover, this code + is a bit easier to read since it does not make use of a dual + neighborhood (having a long and complex type). */ +template <typename I, typename N> +class is_simple_2d : public mln::Function_v2b< is_simple_2d<I, N> > +{ +public: + /// Result type of the functor. + typedef bool result; + + /// Build a functor. + /// + /// \param nbh_fg The foreground neighborhood. + /// \param nbh_bg The background neighborhood. + is_simple_2d(const mln::Neighborhood<N>& nbh_fg, + const mln::Neighborhood<N>& nbh_bg) + : nbh_fg_(mln::exact(nbh_fg)), nbh_bg_(mln::exact(nbh_bg)), + ima_(0) + { + } + + /// Build a functor, and assign an image to it. + /// + /// \param nbh_fg The foreground neighborhood. + /// \param nbh_bg The background neighborhood. + /// \apram ima The image. + is_simple_2d(const mln::Neighborhood<N>& nbh_fg, + const mln::Neighborhood<N>& nbh_bg, + const mln::Image<I>& ima) + : nbh_fg_(mln::exact(nbh_fg)), nbh_bg_(mln::exact(nbh_bg)), + ima_(mln::exact(&ima)) + { + } + + /// Set the underlying image. + void set_image(const mln::Image<I>& ima) + { + ima_ = mln::exact(&ima); + } + + /// Based on connectivity numbers. + bool operator()(const mln_psite(I)& p) const + { + return + mln::connectivity_number_2d(*ima_, nbh_fg_, p, true ) == 1 && + mln::connectivity_number_2d(*ima_, nbh_bg_, p, false) == 1; + } + +private: + /// The foreground neighborhood. + const N& nbh_fg_; + /// The background neighborhood. + const N& nbh_bg_; + /// The image. + const I* ima_; +}; + + +template <typename I> +class detach +{ +public: + /// Build a functor. + detach() + : ima_(0) + { + } + + /// Build a functor, and assign an image to it. + /// + /// \apram ima The image. + detach(mln::Image<I>& ima) + : ima_(mln::exact(&ima)) + { + } + + /// Set the underlying image. + void set_image(mln::Image<I>& ima) + { + ima_ = mln::exact(&ima); + } + + void operator()(const mln_psite(I)& p) const + { + (*ima_)(p) = false; + } + +private: + /// The image. + I* ima_; +}; + + +template <typename I, typename N> +struct is_not_end_point : public mln::Function_v2b< is_not_end_point<I, N> > +{ + /// Build a functor, and assign an image to it. + /// + /// \param nbh_fg The foreground neighborhood. + /// \apram ima The image. + is_not_end_point(const mln::Neighborhood<N>& nbh, + const mln::Image<I>& ima) + : nbh_(mln::exact(nbh)), + ima_(mln::exact(ima)) + { + } + + // Is \a p not a end point? + bool operator()(const mln_psite(I)& p) const + { + // Number of foreground neighbors pixels. + unsigned nneighbs = 0; + mln_niter(N) n(nbh_, p); + for_all(n) + if (ima_.has(n) && ima_(n)) + ++nneighbs; + return nneighbs != 1; + } + +private: + /// The foreground neighborhood. + const N& nbh_; + /// The image. + const I& ima_; +}; + + +#endif // ! APPS_GENERIC_SKEL_IMAGE2D_SKEL_HH diff --git a/milena/apps/mesh-segm-skel/test-mesh-complex-2-collapse.in b/milena/apps/generic-skel/test-image2d-skel-unconstrained.in similarity index 71% copy from milena/apps/mesh-segm-skel/test-mesh-complex-2-collapse.in copy to milena/apps/generic-skel/test-image2d-skel-unconstrained.in index d2a286b..b9f6b44 100644 --- a/milena/apps/mesh-segm-skel/test-mesh-complex-2-collapse.in +++ b/milena/apps/generic-skel/test-image2d-skel-unconstrained.in @@ -1,6 +1,6 @@ #! /bin/sh -# Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE). +# Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE). # # This file is part of Olena. # @@ -18,6 +18,7 @@ set -ex -mesh_dir=@top_srcdir@/milena/mesh +img_dir=@top_srcdir@/milena/img -time ./mesh-complex-2-collapse $mesh_dir/pseudo-manifold.vtk pseudo-manifold-2-collapse.vtk +./image2d-skel-unconstrained $img_dir/tiny.pbm tiny-skel-unconstrained.pbm +./image2d-skel-unconstrained $img_dir/picasso.pbm picasso-skel-unconstrained.pbm diff --git a/milena/apps/mesh-segm-skel/test-mesh-complex-2-collapse.in b/milena/apps/generic-skel/test-image2d-skel-with-end-points.in similarity index 70% copy from milena/apps/mesh-segm-skel/test-mesh-complex-2-collapse.in copy to milena/apps/generic-skel/test-image2d-skel-with-end-points.in index d2a286b..946e8fd 100644 --- a/milena/apps/mesh-segm-skel/test-mesh-complex-2-collapse.in +++ b/milena/apps/generic-skel/test-image2d-skel-with-end-points.in @@ -1,6 +1,6 @@ #! /bin/sh -# Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE). +# Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE). # # This file is part of Olena. # @@ -18,6 +18,7 @@ set -ex -mesh_dir=@top_srcdir@/milena/mesh +img_dir=@top_srcdir@/milena/img -time ./mesh-complex-2-collapse $mesh_dir/pseudo-manifold.vtk pseudo-manifold-2-collapse.vtk +./image2d-skel-with-end-points $img_dir/tiny.pbm tiny-skel-with-end-points.pbm +./image2d-skel-with-end-points $img_dir/picasso.pbm picasso-skel-with-end-points.pbm -- 1.5.6.5
participants (1)
-
Roland Levillain