Commit 3363574a authored by Roland Levillain's avatar Roland Levillain
Browse files

New morpher example: recording a breadth-first thinning.

	* apps/morphers/recorder-bft.cc: New.
	* apps/morphers/image2d-skel.hh: New.
	* apps/morphers/Makefile.am (noinst_PROGRAMS): Add recorder-bft.
	(recorder_wst_SOURCES): New.
	(recorder_SOURCES, recorder_wst_SOURCES, mask_recorder_SOURCES):
	Move recorder.hh...
	(noinst_HEADERS): ...here (new variable).
	(MOSTLYCLEANFILES): Add lena-bft??????.pbm.
parent bd2670fb
2011-11-28 Roland Levillain <roland@lrde.epita.fr>
New morpher example: recording a breadth-first thinning.
* apps/morphers/recorder-bft.cc: New.
* apps/morphers/image2d-skel.hh: New.
* apps/morphers/Makefile.am (noinst_PROGRAMS): Add recorder-bft.
(recorder_wst_SOURCES): New.
(recorder_SOURCES, recorder_wst_SOURCES, mask_recorder_SOURCES):
Move recorder.hh...
(noinst_HEADERS): ...here (new variable).
(MOSTLYCLEANFILES): Add lena-bft??????.pbm.
2011-11-24 Roland Levillain <roland@lrde.epita.fr>
 
New morpher example: recording a watershed transform.
......@@ -25,17 +25,22 @@ AM_CXXFLAGS = $(APPS_CXXFLAGS)
noinst_PROGRAMS = \
mask+channel \
recorder \
recorder-bft \
recorder-wst \
mask+recorder
noinst_HEADERS = recorder.hh
mask_channel_SOURCES = mask+channel.cc
recorder_SOURCES = recorder.cc recorder.hh
recorder_wst_SOURCES = recorder-wst.cc recorder.hh
mask_recorder_SOURCES = mask+recorder.cc recorder.hh
recorder_SOURCES = recorder.cc
recorder_bft_SOURCES = recorder-bft.cc image2d-skel.hh
recorder_wst_SOURCES = recorder-wst.cc
mask_recorder_SOURCES = mask+recorder.cc
MOSTLYCLEANFILES = \
lena-mask-channel.ppm \
lena-fill??????.ppm \
lena-bft??????.pbm \
lena-wst??????.ppm \
lena-roi-fill??????.ppm
......
// Copyright (C) 2010, 2011 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/>.
//
// As a special exception, you may use this file as part of a free
// software project 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_MORPHERS_IMAGE2D_SKEL_HH
# define APPS_MORPHERS_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.
/* FIXME: Remove this file as soon as patches from the mesh-segm-skel
branch have been merged into the current branch. */
# include <mln/topo/is_simple_2d.hh>
/** \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_t
does not fit (yet) in the canvas of
mln::topo::skeleton::breadth_first_thinning. */
template <typename I, typename N>
class is_simple_2d : public mln::Function_v2b< is_simple_2d<I, N> >,
private mln::topo::is_simple_2d_t<N>
{
public:
typedef mln::topo::is_simple_2d_t<N> super;
/// 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)
: super(mln::exact(nbh_fg)),
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::Image<I>& ima)
: super(mln::exact(nbh_fg)),
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 check(*ima_, p);
}
private:
/// The image.
const I* ima_;
};
template <typename I>
void
detach(const mln_psite(I)& p, mln::Image<I>& ima)
{
mln::exact(ima)(p) = false;
}
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_MORPHERS_IMAGE2D_SKEL_HH
// Copyright (C) 2011 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/>.
//
// As a special exception, you may use this file as part of a free
// software project 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.
/// \file
/// \brief Exercise a morpher recording every change in the morphed
/// image with the breadth-first thinning.
///
/// To produce an AVI movie from the `lena-bft*.pbm' files, use:
///
/// for f in lena-bft*pbm; convert $f -define png:bit-depth=8 -scale 2500% $(basename $f .pbm).png
/// mencoder "mf://lena-bft*.png" -o lena-bft.avi -ovc lavc -lavcopts gray:vcodec=mjpeg
///
/// Note: the `-define png:bit-depth=8' option prevents convert from
/// creating an image with 1-bit channels (since the image is binary)
/// and forces it to use 8-bit channels. Indeed mencoder is unable to
/// process PNG images with 1-bit channel(s).
///
/// The output `lena-bft.avi' can be embedded in a PDF file. */
/* FIXME: Modernize this program as soon as patches from the
mesh-segm-skel branch have been merged into the current branch. */
#include <string>
#include <mln/core/image/image2d.hh>
#include <mln/core/alias/neighb2d.hh>
#include <mln/win/multiple_size.hh>
#include <mln/make/dual_neighb.hh>
#include <mln/data/compare.hh>
#include <mln/topo/skeleton/breadth_first_thinning.hh>
#include <mln/test/predicate.hh>
#include <mln/pw/value.hh>
#include <mln/labeling/colorize.hh>
#include <mln/io/pbm/load.hh>
#include <mln/io/pbm/save.hh>
#include "apps/morphers/recorder.hh"
/* FIXME: Temporarily reuse an old file from apps/generic-skel instead
of newer files integrated into the library (but not merged in). */
#include "apps/morphers/image2d-skel.hh"
#include "apps/data.hh"
int main()
{
using namespace mln;
typedef image2d<bool> I;
I lena = io::pbm::load(MLN_IMG_DIR "/tiny.pbm");
// Attach recorder to input image.
typedef decorated_image< I, recorder<I> > J;
J lena_rec = record(lena);
// Dual neighborhood.
typedef neighb< win::multiple_size<2, window2d, pw::value_<I> > > N;
N nbh = make::dual_neighb(lena, c4(), c8());
// Simplicity criterion functor.
::is_simple_2d<J, N> is_simple(nbh);
// Constraint.
::is_not_end_point<J, neighb2d> constraint(c4(), lena_rec);
J bft_rec = topo::skeleton::breadth_first_thinning(lena_rec, nbh,
is_simple, ::detach<J>,
constraint);
// Dump recorded frames.
/* FIXME: Hand-made (it partly duplicates ppm::save() (or more
precisely pbm::save()) for decorated_image's). We should be able
to process sequences of images. */
bool output_initialized_p = false;
for (size_t i = 0; i < bft_rec.decoration().sequence.size(); ++i)
{
I frame = bft_rec.decoration().sequence[i];
// Skip frames until the inital image has been seen.
if (frame == lena)
output_initialized_p = true;
if (!output_initialized_p)
continue;
std::stringstream s;
s << std::setfill ('0') << std::setw (6) << i;
io::pbm::save(frame, std::string("lena-bft") + s.str() + ".pbm");
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment