Commit 9646e5b3 authored by Edwin Carlinet's avatar Edwin Carlinet
Browse files

Add extinction value computation routine.

	*  mln/core/always.hpp: New.
	*  mln/morpho/canvas/unionfind.hpp: Fix root issue.
	*  mln/morpho/extinction.hpp,
	*  tests/morpho/CMakeLists.txt,
	*  tests/morpho/extinction.cpp: New.
parent 1702bf39
#ifndef MLN_CORE_ALWAYS_HPP
# define MLN_CORE_ALWAYS_HPP
namespace mln
{
/// \brief Function object that always return the same value
template <class T>
struct always_t;
/// \brief Function object that always return true
struct yes_t;
/// \brief Function object that always return false
struct no_t;
/*******************************/
/*** Implementation ***/
/*******************************/
template <class T>
struct always_t
{
constexpr
always_t(T x = T())
: m_x(x)
{
}
template <class... TArgs>
constexpr
T
operator() (TArgs...) const
{
return m_x;
}
private:
T m_x;
};
struct yes_t : always_t<bool>
{
constexpr yes_t()
: always_t<bool>(true)
{
}
};
struct no_t : always_t<bool>
{
constexpr no_t()
: always_t<bool>(false)
{
}
};
static constexpr no_t no;
static constexpr yes_t yes;
}
#endif // ! MLN_CORE_ALWAYS_HPP
......@@ -106,6 +106,8 @@ namespace mln
status(p) = status(p) || term(p);
}
// Set the root status to PASS
status(S.back()) = PASS;
// Reverse, canonize and call on_finish
mln_reverse_foreach(p, S)
......
#ifndef MLN_MORPHO_EXTINCTION_HPP
# define MLN_MORPHO_EXTINCTION_HPP
# include <mln/core/image/image.hpp>
# include <mln/core/neighborhood/neighborhood.hpp>
# include <mln/morpho/canvas/unionfind.hpp>
# include <mln/core/always.hpp>
namespace mln
{
namespace morpho
{
/// \brief Compute the extinction value of each minima
///
/// If a node is not a local minima, its extinction value is null.
/// Otherwise, it is the value of the attribute for which the minima
/// is extincted. If no attribute is given, this is the dynamic.
template <class I, class N, class Compare = std::less<mln_value(I)> >
mln_concrete(I)
extinction(const Image<I>& ima,
const Neighborhood<N>& nbh,
const Compare& cmp = Compare());
/***********************/
/*** Implementation ***/
/***********************/
namespace internal
{
template <class I, class Compare>
struct extinction_dynamic_ufind_visitor
{
void on_make_set(const mln_point(I)& p)
{
amin(p) = p;
}
void on_union(const mln_point(I)& p,
const mln_point(I)& q)
{
mln_point(I) mp = amin(p);
mln_point(I) mq = amin(q);
if (cmp(f(mp), f(mq))) { // mp is the minimum
amin(q) = mp;
extinction(mq) = f(q) - f(mq);
} else { // mq is the minimum
amin(q) = mq;
extinction(mp) = f(q) - f(mp);
}
}
void on_finish(dontcare_t, dontcare_t)
{
}
const I& f;
mln_ch_value(I, mln_point(I))& amin;
mln_concrete(I)& extinction;
Compare cmp;
};
}
template <class I, class N, class Compare = std::less<mln_value(I)> >
mln_concrete(I)
extinction(const Image<I>& ima_,
const Neighborhood<N>& nbh_,
const Compare& cmp = Compare())
{
mln_entering("mln::morpho::extinction");
const I& ima = exact(ima_);
const N& nbh = exact(nbh_);
mln_concrete(I) extinction;
mln_ch_value(I, mln_point(I)) amin;
resize(extinction, ima);
resize(amin, ima);
internal::extinction_dynamic_ufind_visitor<I, Compare>
viz = {ima, amin, extinction, cmp};
auto par = canvas::unionfind(ima, nbh, no, cmp, viz);
// Set root extinction value
{
mln_viter(v, par);
v.init();
mln_point(I) root = *v;
extinction(amin(root)) = ima(root) - ima(amin(root));
}
// Propagate extinction value to minima flatzones ?
// Is that necessary ?
mln_exiting();
return extinction;
}
}
}
#endif // ! MLN_MORPHO_EXTINCTION_HPP
......@@ -6,10 +6,13 @@ add_executable(maxtree maxtree.cpp)
add_core_test(maxtree maxtree)
set_target_properties(maxtree PROPERTIES OUTPUT_NAME maxtree_old)
add_executable(saturate saturate.cpp)
target_link_libraries(saturate -lfreeimage)
add_core_test(saturate saturate)
add_executable(saturate saturate.cpp)
add_executable(dilate dilate.cpp)
add_executable(extinction extinction.cpp)
add_executable(dilate dilate.cpp)
target_link_libraries(saturate -lfreeimage)
target_link_libraries(dilate -lfreeimage)
add_core_test(dilate dilate)
add_core_test(saturate saturate)
add_core_test(dilate dilate)
add_core_test(extinction extinction)
#include <mln/core/image/image2d.hpp>
#include <mln/core/neighb2d.hpp>
#include <mln/core/grays.hpp>
#include <mln/core/algorithm/equal.hpp>
#include <mln/morpho/extinction.hpp>
#define BOOST_TEST_MODULE Morpho
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_SUITE(extinction)
using namespace mln;
BOOST_AUTO_TEST_CASE(extinction_0)
{
image2d<uint8> ima = { {0,3,2},
{2,2,3},
{2,3,1} };
image2d<uint8> ref = { {3,0,1},
{0,0,0},
{0,0,2} };
auto E = morpho::extinction(ima, c4);
BOOST_CHECK(equal(E, ref));
}
BOOST_AUTO_TEST_CASE(extinction_1)
{
image2d<uint8> ima = { {0,3,2},
{2,2,3},
{2,1,1} };
image2d<uint8> ref = { {3,0,1},
{0,0,0},
{0,1,1} };
auto E = morpho::extinction(ima, c4);
BOOST_CHECK(equal(E, ref));
}
BOOST_AUTO_TEST_SUITE_END()
Markdown is supported
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