Commit 3614dc12 authored by Thierry Geraud's avatar Thierry Geraud
Browse files

Add morphological top-hats and contrast.

	* tests/morpho_gradient.cc: Fix doc.
	* mln/geom/pmin_pmax.hh (pmin_pmax): Overload for point set.
	* mln/geom/bbox.hh: Update.
	* mln/morpho/includes.hh (include): Add mln/test/positive.hh
	and mln/arith/plus.hh.
	* mln/morpho/gradient.hh: Add commentaries.

	* tests/morpho_contrast.cc: New.
	* mln/morpho/contrast.hh: New.
	* mln/morpho/top_hat.hh: New.


git-svn-id: https://svn.lrde.epita.fr/svn/oln/trunk@1059 4aad255d-cdde-0310-9447-f3009e2ae8c0
parent 18232963
2007-08-29 Thierry Geraud <thierry.geraud@lrde.epita.fr>
Add morphological top-hats and contrast.
* tests/morpho_gradient.cc: Fix doc.
* mln/geom/pmin_pmax.hh (pmin_pmax): Overload for point set.
* mln/geom/bbox.hh: Update.
* mln/morpho/includes.hh (include): Add mln/test/positive.hh
and mln/arith/plus.hh.
* mln/morpho/gradient.hh: Add commentaries.
* tests/morpho_contrast.cc: New.
* mln/morpho/contrast.hh: New.
* mln/morpho/top_hat.hh: New.
2007-08-28 Thierry Geraud <thierry.geraud@lrde.epita.fr>
Replace 2D specific methods in 2D images by routines.
......
......@@ -100,8 +100,7 @@ namespace mln
mln_precondition(pset.npoints() != 0);
typedef mln_point(S) P;
mln_piter(S) p(pset);
std::pair<P, P> pp = geom::pmin_pmax(p);
std::pair<P, P> pp = geom::pmin_pmax(pset);
box_<P> tmp(pp.first, pp.second);
// FIXME: mln_postcondition(tmp <= pset.bbox());
......
......@@ -36,6 +36,10 @@
# include <utility>
# include <mln/core/concept/point_set.hh>
# include <mln/core/concept/box.hh>
namespace mln
{
......@@ -44,6 +48,19 @@ namespace mln
{
/// Compute the minimum and maximum points of point set \p s.
template <typename S>
std::pair<mln_point(S), mln_point(S)>
pmin_pmax(const Point_Set<S>& s);
/// Compute the minimum and maximum points, \p pmin and \p max,
/// of point set \p s.
template <typename S>
void
pmin_pmax(const Point_Set<S>& s, mln_point(S)& pmin, mln_point(S)& pmax);
/// Compute the minimum and maximum points when browsing with
/// iterator \p p.
template <typename I>
......@@ -61,40 +78,86 @@ namespace mln
# ifndef MLN_INCLUDE_ONLY
// Versions with point iterator.
template <typename I>
std::pair<mln_point(I), mln_point(I)>
pmin_pmax(Point_Iterator<I>& p_)
void
pmin_pmax(const Point_Iterator<I>& p_, mln_point(I)& pmin, mln_point(I)& pmax)
{
I& p = exact(p_);
typedef mln_point(I) P;
std::pair<P, P> tmp;
P& pmin = tmp.first;
P& pmax = tmp.second;
I p = exact(p_); // a copy of p_
// init with first point
p.start();
mln_precondition(p.is_valid());
pmin = pmax = p;
// update with remaining points
typedef mln_point(I) P;
for_all_remaining(p)
for (unsigned i = 0; i < P::dim; ++i)
if (p[i] < pmin[i])
pmin[i] = p[i];
else if (p[i] > pmax[i])
pmax[i] = p[i];
}
template <typename I>
std::pair<mln_point(I), mln_point(I)>
pmin_pmax(const Point_Iterator<I>& p)
{
typedef mln_point(I) P;
std::pair<P, P> tmp;
pmin_pmax(p, tmp.first, tmp.second); // calls the previous version
return tmp;
}
template <typename I>
// Versions with point set.
namespace impl
{
// General case.
template <typename S>
void
pmin_pmax_(const Point_Set<S>& s, mln_point(S)& pmin, mln_point(S)& pmax)
{
mln_piter(S) it(exact(s));
pmin_pmax(it, pmin, pmax);
}
// Box.
template <typename B>
void
pmin_pmax_(const Box<B>& b, mln_point(B)& pmin, mln_point(B)& pmax)
{
pmin = exact(b).pmin();
pmax = exact(b).pmax();
}
} // end of namespace mln::geom::impl
template <typename S>
void
pmin_pmax(const Point_Iterator<I>& p, mln_point(I)& pmin, mln_point(I)& pmax)
pmin_pmax(const Point_Set<S>& s, mln_point(S)& pmin, mln_point(S)& pmax)
{
typedef mln_point(I) P;
std::pair<P, P> tmp = pmin_pmax(p);
pmin = tmp.first;
pmax = tmp.second;
mln_precondition(exact(s).npoints() != 0);
impl::pmin_pmax_(exact(s), pmin, pmax);
}
template <typename S>
std::pair<mln_point(S), mln_point(S)>
pmin_pmax(const Point_Set<S>& s)
{
mln_precondition(exact(s).npoints() != 0);
typedef mln_point(S) P;
std::pair<P, P> tmp;
pmin_pmax(p_, tmp.first, tmp.second); // calls the previous version
return tmp;
}
# endif // ! MLN_INCLUDE_ONLY
......
// Copyright (C) 2007 EPITA Research and Development Laboratory
//
// This file is part of the Olena 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 MLN_MORPHO_CONTRAST_HH
# define MLN_MORPHO_CONTRAST_HH
/*! \file mln/morpho/contrast.hh
*
* \brief Morphological contrast operator (based on top-hats).
*
* \todo Save memory.
*/
# include <mln/morpho/top_hat.hh>
namespace mln
{
namespace morpho
{
/*! Morphological contrast operator (based on top-hats).
*
* This operator is Id + wth_B - bth_B.
*/
template <typename I, typename W, typename O>
void contrast(const Image<I>& input, const Window<W>& win,
Image<O>& output);
# ifndef MLN_INCLUDE_ONLY
template <typename I, typename W, typename O>
void contrast(const Image<I>& input_, const Window<W>& win_, Image<O>& output_)
{
const I& input = exact(input_);
const W& win = exact(win_);
O& output = exact(output_);
mln_precondition(output.domain() == input.domain());
mln_precondition(! win.is_empty());
top_hat_white(input, win, output); // output = wth
arith::plus_inplace(output, input); // now output = wth + input
O temp(input.domain());
top_hat_black(input, win, temp); // temp = bth
arith::minus_inplace(output, temp); // now output = wth + input - bth
}
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::morpho
} // end of namespace mln
#endif // ! MLN_MORPHO_CONTRAST_HH
......@@ -31,10 +31,11 @@
/*! \file mln/morpho/gradient.hh
*
* \brief Morphological gradient.
*
* \todo Save memory.
*/
# include <mln/morpho/includes.hh>
# include <mln/test/positive.hh>
namespace mln
......@@ -82,11 +83,10 @@ namespace mln
mln_precondition(output.domain() == input.domain());
mln_precondition(! win.is_empty());
dilation(input, win, output); // output = dilation
O temp(input.domain());
erosion(input, win, temp);
dilation(input, win, output);
arith::minus_inplace(output, temp);
erosion(input, win, temp); // temp = erosion
arith::minus_inplace(output, temp); // now output = dilation - erosion
mln_postcondition(test::positive(output));
}
......@@ -103,9 +103,8 @@ namespace mln
mln_precondition(! win.is_empty());
O temp(input.domain());
erosion(input, win, temp);
arith::minus(input, temp, output);
erosion(input, win, temp); // temp = erosion
arith::minus(input, temp, output); // output = input - erosion
mln_postcondition(test::positive(output));
}
......@@ -121,10 +120,8 @@ namespace mln
mln_precondition(output.domain() == input.domain());
mln_precondition(! win.is_empty());
O temp(input.domain());
dilation(input, win, temp);
arith::minus(temp, input, output);
dilation(input, win, output); // output = dilation
arith::minus_inplace(output, input); // now output = dilation - input
mln_postcondition(test::positive(output));
}
......
......@@ -40,11 +40,14 @@
# include <mln/accu/min.hh>
# include <mln/accu/max.hh>
# include <mln/arith/plus.hh>
# include <mln/arith/minus.hh>
# include <mln/level/compare.hh>
# include <mln/level/fill.hh>
# include <mln/test/positive.hh>
# include <mln/border/resize.hh>
# include <mln/border/fill.hh>
......
// Copyright (C) 2007 EPITA Research and Development Laboratory
//
// This file is part of the Olena 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 MLN_MORPHO_TOP_HAT_HH
# define MLN_MORPHO_TOP_HAT_HH
/*! \file mln/morpho/top_hat.hh
*
* \brief Morphological top-hats.
*
* \todo Save memory.
*/
# include <mln/morpho/opening.hh>
# include <mln/morpho/closing.hh>
namespace mln
{
namespace morpho
{
/*! Morphological white top-hat (for object / light objects).
*
* This operator is Id - ope_B.
*/
template <typename I, typename W, typename O>
void top_hat_white(const Image<I>& input, const Window<W>& win,
Image<O>& output);
/*! Morphological black top-hat (for background / dark objects).
*
* This operator is clo_B - Id.
*/
template <typename I, typename W, typename O>
void top_hat_black(const Image<I>& input, const Window<W>& win,
Image<O>& output);
/*! Morphological self-complementary top-hat.
*
* This operator is \n
* = top_hat_white + top_hat_black \n
* = (input - opening) + (closing - input) \n
* = closing - opening. \n
*/
template <typename I, typename W, typename O>
void top_hat_self_complementary(const Image<I>& input, const Window<W>& win,
Image<O>& output);
# ifndef MLN_INCLUDE_ONLY
template <typename I, typename W, typename O>
void top_hat_white(const Image<I>& input_, const Window<W>& win_, Image<O>& output_)
{
const I& input = exact(input_);
const W& win = exact(win_);
O& output = exact(output_);
mln_precondition(output.domain() == input.domain());
mln_precondition(! win.is_empty());
O temp(input.domain());
opening(input, win, temp); // temp = opening
arith::minus(input, temp, output); // output = input - opening
mln_postcondition(test::positive(output));
}
template <typename I, typename W, typename O>
void top_hat_black(const Image<I>& input_, const Window<W>& win_, Image<O>& output_)
{
const I& input = exact(input_);
const W& win = exact(win_);
O& output = exact(output_);
mln_precondition(output.domain() == input.domain());
mln_precondition(! win.is_empty());
closing(input, win, output); // output = closing
arith::minus_inplace(output, input); // now output = closing - input
mln_postcondition(test::positive(output));
}
template <typename I, typename W, typename O>
void top_hat_self_complementary(const Image<I>& input_, const Window<W>& win_, Image<O>& output_)
{
const I& input = exact(input_);
const W& win = exact(win_);
O& output = exact(output_);
mln_precondition(output.domain() == input.domain());
mln_precondition(! win.is_empty());
closing(input, win, output); // output = closing
O temp(input.domain());
opening(input, win, temp); // temp = opening
arith::minus_inplace(output, temp); // now output = closing - opening
mln_postcondition(test::positive(output));
}
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::morpho
} // end of namespace mln
#endif // ! MLN_MORPHO_TOP_HAT_HH
// Copyright (C) 2007 EPITA Research and Development Laboratory
//
// This file is part of the Olena 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.
/*! \file tests/morpho_contrast.cc
*
* \brief Test on mln::morpho::contrast.
*/
#include <mln/core/image2d_b.hh>
#include <mln/core/win/rectangle2d.hh>
#include <mln/io/load_pgm.hh>
#include <mln/io/save_pgm.hh>
#include <mln/value/int_u8.hh>
#include <mln/morpho/contrast.hh>
#include <mln/level/saturate.hh>
int main()
{
using namespace mln;
using value::int_u8;
win::rectangle2d rect(5, 5);
border::thickness = 2;
image2d_b<int_u8>
lena = io::load_pgm("../img/tiny.pgm"),
out(lena.domain());
image2d_b<int> tmp(lena.domain());
morpho::contrast(lena, rect, tmp);
level::saturate(tmp, out);
io::save_pgm(out, "out.pgm");
}
......@@ -25,9 +25,9 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
/*! \file tests/erosion.cc
/*! \file tests/morpho_gradient.cc
*
* \brief Test on mln::morpho::erosion.
* \brief Test on mln::morpho::gradient.
*/
#include <mln/core/image2d_b.hh>
......
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