Commit 72d0a739 authored by Roland Levillain's avatar Roland Levillain
Browse files

Replace ad hoc code by Milena's in apps/graph-morpho.

	* apps/graph-morpho/morpho.hh
	(dilation(const mln::Image<I>&, const mln::Neighborhood<N>&))
	(erosion(const mln::Image<I>&, const mln::Neighborhood<N>&)):
	Remove functions.
	(dilation_e2v(const mln::Image<I>&))
	(erosion_v2e(const mln::Image<I>&))
	(erosion_e2v(const mln::Image<I>&))
	(dilation_v2e(const mln::Image<I>&)):
	Use mln::dilation and mln::erosion instead of these ad hoc
	dilation and erosion routines.
	Use mln::image_if and mln::extend instead of the ad hoc
	image_if_large.

git-svn-id: https://svn.lrde.epita.fr/svn/oln/trunk@4565 4aad255d-cdde-0310-9447-f3009e2ae8c0
parent 50a59cd1
2009-09-25 Roland Levillain <roland@lrde.epita.fr>
Replace ad hoc code by Milena's in apps/graph-morpho.
* apps/graph-morpho/morpho.hh
(dilation(const mln::Image<I>&, const mln::Neighborhood<N>&))
(erosion(const mln::Image<I>&, const mln::Neighborhood<N>&)):
Remove functions.
(dilation_e2v(const mln::Image<I>&))
(erosion_v2e(const mln::Image<I>&))
(erosion_e2v(const mln::Image<I>&))
(dilation_v2e(const mln::Image<I>&)):
Use mln::dilation and mln::erosion instead of these ad hoc
dilation and erosion routines.
Use mln::image_if and mln::extend instead of the ad hoc
image_if_large.
2009-09-25 Edwin Carlinet <carlinet@lrde.epita.fr>
 
Add test for dual input and fix p_transformed test.
// Copyright (C) 2007, 2008, 2009 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_GRAPH_MORPHO_IMAGE_IF_LARGE_HH
# define APPS_GRAPH_MORPHO_IMAGE_IF_LARGE_HH
/// \file
///
/// \brief Definition of a image which domain is restricted by a
/// function 'site -> Boolean', but where routine has() returns true
/// for sites of the underlying (morphed) image even if they are not
/// validating the predicate.
// FIXME: This file is a workaround for the lack of ``tolerant''
// image_if, but there must be a better way.
# include <mln/core/internal/image_domain_morpher.hh>
# include <mln/core/site_set/p_if.hh>
# include <mln/pw/all.hh>
namespace mln
{
// Forward declaration.
template <typename I, typename F> struct image_if_large;
namespace internal
{
/// Data structure for \c mln::image_if_large<I,F>.
template <typename I, typename F>
struct data< image_if_large<I,F> >
{
data(I& ima, const F& f);
I ima_;
p_if<mln_domain(I), F> domain_;
};
} // end of namespace mln::internal
namespace trait
{
template <typename I, typename F>
struct image_< image_if_large<I,F> >
: default_image_morpher< I,
mln_value(I),
image_if_large<I,F> >
{
typedef trait::image::category::domain_morpher category;
// No extension of domain.
typedef trait::image::ext_domain::none ext_domain;
typedef trait::image::ext_value::irrelevant ext_value;
typedef trait::image::ext_io::irrelevant ext_io;
typedef trait::image::vw_io::none vw_io;
typedef trait::image::vw_set::none vw_set;
typedef trait::image::value_alignment::not_aligned value_alignment;
typedef trait::image::value_storage::disrupted value_storage;
};
} // end of namespace mln::trait
/// Image which domain is restricted by a function 'site ->
/// Boolean', but where routine has() returns true for sites of the
/// underlying (morphed) image even if they are not validating the
/// predicate.
///
/// \ingroup modimagedomainmorpher
//
template <typename I, typename F>
struct image_if_large
: public mln::internal::image_domain_morpher< I,
p_if<mln_domain(I), F>,
image_if_large<I, F> >
{
typedef image_if_large<I, F> self;
typedef mln_psite(self) psite;
/// Skeleton.
typedef image_if_large< tag::image_<I>, tag::function_<F> > skeleton;
/// Constructor without argument.
image_if_large();
/// Constructor from an image \p ima and a predicate \p f.
image_if_large(I& ima, const F& f);
void init_(I& ima, const F& f);
/// \brief Redefined psite membership method, returning true for
/// sites of the underlying (morphed) image even if they are not
/// validating the predicate.
///
/// This is the only difference with mln::image_if.
bool has(const psite& p) const;
/// Give the definition domain.
const p_if<mln_domain(I), F>& domain() const;
/// Const promotion via conversion.
operator image_if_large<const I, F>() const;
};
// Image || Function_v2b.
/// ima || f creates an image_if_large with the image ima and the function
/// f.
//
template <typename I, typename F>
image_if_large<I,F>
operator || (Image<I>& ima, const Function_v2b<F>& f);
/// ima || f creates an image_if_large with the image ima and the function
/// f.
//
template <typename I, typename F>
image_if_large<const I,F>
operator || (const Image<I>& ima, const Function_v2b<F>& f);
template <typename I, typename A>
image_if_large< const I, fun::C<bool(*)(A)> >
operator || (const Image<I>& ima, bool (*f)(A) );
template <typename I, typename A>
image_if_large< I, fun::C<bool(*)(A)> >
operator || (Image<I>& ima, bool (*f)(A) );
// // Construction helpers.
// template <typename I, typename A>
// image_if_large< const I, fun::C<bool(*)(A)> >
// make_image_if_large(const Image<I>& ima, bool (*f)(A) );
// template <typename I, typename A>
// image_if_large< I, fun::C<bool(*)(A)> >
// make_image_if_large(Image<I>& ima, bool (*f)(A) );
# ifndef MLN_INCLUDE_ONLY
// init_.
template <typename I, typename F>
void init_(tag::function_t, F& f, const image_if_large<I,F>& model)
{
f = model.domain().predicate();
}
template <typename I, typename F, typename J>
void init_(tag::image_t, image_if_large<I,F>& target, const J& model)
{
I ima;
init_(tag::image, ima, exact(model));
F f;
init_(tag::function, f, exact(model));
target.init_(ima, f);
}
// internal::data< image_if_large<I,F> >
namespace internal
{
template <typename I, typename F>
inline
data< image_if_large<I,F> >::data(I& ima, const F& f)
: ima_(ima),
domain_(ima.domain() | f)
{
}
}
// image_if_large<I,F>
template <typename I, typename F>
inline
image_if_large<I,F>::image_if_large()
{
}
template <typename I, typename F>
inline
image_if_large<I,F>::image_if_large(I& ima, const F& f)
{
init_(ima, f);
}
template <typename I, typename F>
inline
void
image_if_large<I,F>::init_(I& ima, const F& f)
{
mln_precondition(! this->is_valid());
this->data_ = new internal::data< image_if_large<I,F> >(ima, f);
}
template <typename I, typename F>
inline
bool
image_if_large<I,F>::has(const typename image_if_large<I,F>::psite& p) const
{
mln_precondition(exact(this)->is_valid());
// This method is more tolerant than mln::image_if's one (which
// returns this->domain().has(p)).
return this->data_->ima_.has(p);
}
template <typename I, typename F>
inline
const p_if<mln_domain(I), F>&
image_if_large<I,F>::domain() const
{
mln_precondition(this->is_valid());
return this->data_->domain_;
}
template <typename I, typename F>
inline
image_if_large<I,F>::operator image_if_large<const I,F>() const
{
mln_precondition(this->is_valid());
image_if_large<const I,F> tmp(this->data_->ima_,
this->data_->domain_.predicate());
return tmp;
}
// Operators.
template <typename I, typename F>
inline
image_if_large<I,F>
operator || (Image<I>& ima, const Function_v2b<F>& f)
{
image_if_large<I,F> tmp(exact(ima), exact(f));
return tmp;
}
template <typename I, typename F>
inline
image_if_large<const I, F>
operator || (const Image<I>& ima, const Function_v2b<F>& f)
{
image_if_large<const I, F> tmp(exact(ima), exact(f));
return tmp;
}
template <typename I, typename A>
image_if_large< const I, fun::C<bool(*)(A)> >
operator || (const Image<I>& ima, bool (*f)(A) )
{
return exact(ima) || convert::to_fun(f);
}
template <typename I, typename A>
image_if_large< I, fun::C<bool(*)(A)> >
operator || (Image<I>& ima, bool (*f)(A) )
{
return exact(ima) || convert::to_fun(f);
}
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln
#endif // ! APPS_GRAPH_MORPHO_IMAGE_IF_LARGE_HH
......@@ -41,6 +41,7 @@
# include <mln/core/image/dmorph/image_if.hh>
# include <mln/core/routine/extend.hh>
# include <mln/core/routine/duplicate.hh>
# include <mln/core/site_set/p_n_faces_piter.hh>
......@@ -53,7 +54,8 @@
# include <mln/data/paste.hh>
# include "apps/graph-morpho/image_if_large.hh"
# include <mln/morpho/dilation.hh>
# include <mln/morpho/erosion.hh>
// FIXME: Instead of providing several implementation, move specific
// parts (neighborhoods, etc.) to a graph_traits class, and write
......@@ -136,72 +138,6 @@ combine(const mln::Image<I>& vertices, const mln::Image<I>& edges)
| Dilations and erosions. |
`-------------------------*/
/// A neighborhood-aware and graph-friendly version of the binary dilation.
template <typename I, typename N>
mln_concrete(I)
dilation(const mln::Image<I>& input_, const mln::Neighborhood<N>& nbh_)
{
using namespace mln;
typedef mln_concrete(I) O;
const I& input = exact(input_);
const N& nbh = exact(nbh_);
O output;
initialize(output, input);
mln_piter(I) p(input.domain());
mln_niter(N) n(nbh, p);
for_all(p)
{
/* There is a slight difference with Milena's classical binary
dilation here: instead of initializing OUTPUT with INPUT, we
fill it with default (here, false) values. */
output(p) = false;
for_all(n) if (input.has(n))
if (input(n) == true)
{
output(p) = true;
break;
}
}
return output;
}
/// A neighborhood-aware and graph-friendly version of the binary erosion.
template <typename I, typename N>
mln_concrete(I)
erosion(const mln::Image<I>& input_, const mln::Neighborhood<N>& nbh_)
{
using namespace mln;
typedef mln_concrete(I) O;
const I& input = exact(input_);
const N& nbh = exact(nbh_);
O output;
initialize(output, input);
mln_piter(I) p(input.domain());
mln_niter(N) n(nbh, p);
for_all(p)
{
/* There is a slight difference with Milena's classical erosion
here: instead of initializing OUTPUT with INPUT, we fill it
with default (here, true) values. */
output(p) = true;
for_all(n) if (input.has(n))
if (input(n) == false)
{
output(p) = false;
break;
}
}
return output;
}
namespace impl
{
// ------------------------------------------ //
......@@ -341,11 +277,6 @@ namespace impl
// Implementations on (mln::image2d-based) cubical 2-complexes. //
// ------------------------------------------------------------- //
/* Note the operator `||' in the following routines: we have to use
our own ``tolerant'' version of mln::image_if (namely
mln::image_if_large) for these dilations and erosions to
work. */
/// Dilation from edges to vertices (\f$\delta^\bullet\f$) on
/// an mln::image2d<T>-based cubical complex.
template <typename T>
......@@ -353,10 +284,14 @@ namespace impl
mln::image2d<T>
dilation_e2v(const mln::image2d<T>& input)
{
using mln::world::inter_pixel::dim2::is_pixel;
using mln::world::inter_pixel::v2e;
mln::image2d<T> output(input.domain());
mln::data::fill(output, false);
mln::data::paste(dilation(input || mln::world::inter_pixel::dim2::is_pixel(),
mln::world::inter_pixel::v2e()),
mln::data::paste(mln::morpho::dilation(mln::extend(input | is_pixel(),
input),
v2e().win()),
output);
return output;
}
......@@ -368,10 +303,14 @@ namespace impl
mln::image2d<T>
erosion_v2e(const mln::image2d<T>& input)
{
using mln::world::inter_pixel::dim2::is_edge;
using mln::world::inter_pixel::e2v;
mln::image2d<T> output(input.domain());
mln::data::fill(output, false);
mln::data::paste(erosion(input || mln::world::inter_pixel::dim2::is_edge(),
mln::world::inter_pixel::e2v()),
mln::data::paste(mln::morpho::erosion(mln::extend(input | is_edge(),
input),
e2v().win()),
output);
return output;
}
......@@ -383,10 +322,14 @@ namespace impl
mln::image2d<T>
erosion_e2v(const mln::image2d<T>& input)
{
using mln::world::inter_pixel::dim2::is_pixel;
using mln::world::inter_pixel::v2e;
mln::image2d<T> output(input.domain());
mln::data::fill(output, false);
mln::data::paste(erosion(input || mln::world::inter_pixel::dim2::is_pixel(),
mln::world::inter_pixel::v2e()),
mln::data::paste(mln::morpho::erosion(mln::extend(input | is_pixel(),
input),
v2e().win()),
output);
return output;
}
......@@ -398,10 +341,14 @@ namespace impl
mln::image2d<T>
dilation_v2e(const mln::image2d<T>& input)
{
using mln::world::inter_pixel::dim2::is_edge;
using mln::world::inter_pixel::e2v;
mln::image2d<T> output(input.domain());
mln::data::fill(output, false);
mln::data::paste(dilation(input || mln::world::inter_pixel::dim2::is_edge(),
mln::world::inter_pixel::e2v()),
mln::data::paste(mln::morpho::dilation(mln::extend(input | is_edge(),
input),
e2v().win()),
output);
return output;
}
......
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