Commit 553ea23a authored by Edwin Carlinet's avatar Edwin Carlinet
Browse files

Implementation of accumulators.

	* mln/accu/accumulator.hpp
	* mln/accu/accumulator_base.hpp
	* mln/accu/accumulators/count.hpp
	* mln/accu/accumulators/mean.hpp
	* mln/accu/accumulators/sum.hpp
	* mln/accu/dontcare.hpp
	* mln/core/concept/accumulator.hpp
	* mln/labeling/blobs.hpp
	* tests/CMakeLists.txt
	* tests/accu/CMakeLists.txt
	* tests/accu/count.cpp
	* tests/accu/mean.cpp
	* tests/accu/sum.cpp: New
parent 1a2d0800
// Copyright (C) 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 ACCUMULATOR_HPP
# define ACCUMULATOR_HPP
# include <mln/core/concept/accumulator.hpp>
namespace mln
{
namespace accu
{
struct NoOpAccumulator
namespace features
{
}
template <typename T>
void take(const T&)
{
}
void take(const NoOpAccumulator&)
{
}
template <typename T>
void untake(const T&)
{
}
namespace accumulators
{
}
};
namespace extractor
{
}
}
......
#ifndef MLN_ACCU_ACCUMULATOR_BASE_HPP
# define ACCUMULATOR_BASE_HPP
# include <boost/fusion/container/list.hpp>
# include <boost/fusion/include/for_each.hpp>
# include <boost/fusion/include/find_if.hpp>
# include <boost/fusion/include/transform.hpp>
# include <type_traits>
# include <boost/utility/enable_if.hpp>
namespace mln
{
namespace accu
{
namespace internal
{
template <typename T>
struct feature_to_accu
{
template <typename F>
struct apply
{
typedef typename F::template apply<T>::type type;
};
};
struct accu_init
{
template <typename Accu>
void operator () (Accu& acc) const { acc.init(); }
};
template <typename T>
struct accu_take
{
accu_take(const T& x) : m_x(x) {}
template <typename Accu>
void operator () (Accu& acc) const { acc.take(m_x); }
private:
const T& m_x;
};
template <typename T>
struct accu_untake
{
accu_untake(const T& x) : m_x(x) {}
template <typename Accu>
void operator () (Accu& acc) const { acc.untake(m_x); }
private:
const T& m_x;
};
template <typename Feature>
struct accu_has_feature
{
template <typename Accu>
struct apply
{
typedef typename std::is_same<typename Accu::feature, Feature>::type type;
};
};
template <typename AccuList, typename Feature>
struct acculist_has_feature
{
typedef typename boost::fusion::result_of::find_if<AccuList, accu_has_feature<Feature> >::type iterator;
typedef typename boost::fusion::result_of::end<AccuList>::type end;
static constexpr bool value = not std::is_same<iterator, end>::value;
};
template <typename AccuList, typename Feature>
struct acculist_get_feature
{
typedef typename boost::fusion::result_of::find_if<AccuList, accu_has_feature<Feature> >::type iterator;
typedef typename boost::fusion::result_of::deref<iterator>::type accu;
typedef decltype(extract (std::declval<accu>(), Feature ()) ) type;
};
}
template <typename Accu, typename T, typename... depends>
struct composite_accumulator_base : Accumulator<Accu>
{
typedef T argument_type;
typedef boost::fusion::list<depends...> dependances;
void init()
{
boost::fusion::for_each(m_accus, internal::accu_init ());
}
void take(const argument_type& x)
{
boost::fusion::for_each(m_accus, internal::accu_take<argument_type>(x));
}
template <typename Other>
void take(const Accumulator<Other>& other)
{
boost::fusion::for_each(m_accus, internal::accu_take<Other>(exact(other)));
}
void untake(const argument_type& x)
{
boost::fusion::for_each(m_accus, internal::accu_untake<argument_type>(x));
}
template <typename Feature>
friend
typename boost::lazy_enable_if_c< internal::acculist_has_feature<dependances, Feature>::value,
internal::acculist_get_feature<dependances, Feature> >::type
extract(const composite_accumulator_base& accu, Feature feat)
{
auto res = boost::fusion::find_if< internal::accu_has_feature<Feature> >(accu.m_accus);
return extract(*res, feat);
}
private:
dependances m_accus;
};
}
}
#endif // ! ACCUMULATOR_BASE_HPP
#ifndef MLN_ACCU_ACCUMULATOTS_COUNT_HPP
# define MLN_ACCU_ACCUMULATOTS_COUNT_HPP
# include <mln/accu/accumulator.hpp>
# include <mln/accu/dontcare.hpp>
# include <utility>
namespace mln
{
namespace accu
{
namespace accumulators
{
template <typename CountType = std::size_t>
struct count;
}
namespace features
{
template <typename CountType = std::size_t>
struct count;
}
namespace extractor
{
template <typename A>
inline
typename A::return_type
count(const Accumulator<A>& acc)
{
return extract(exact(acc), features::count<> ());
}
}
namespace features
{
template <typename CountType>
struct count
{
template <typename T>
struct apply
{
typedef accumulators::count<CountType> type;
};
};
}
namespace accumulators
{
template <typename CountType>
struct count : Accumulator< count<CountType> >
{
typedef dontcare argument_type;
typedef CountType return_type;
typedef features::count<> feature;
count()
: m_count (0)
{
}
void init()
{
m_count = 0;
}
void take(const dontcare&)
{
++m_count;
}
void untake(const dontcare&)
{
--m_count;
}
template <typename Other>
void take(const Accumulator<Other>& other)
{
m_count += extractor::count(other);
}
friend
return_type extract(const count& accu, features::count<> )
{
return accu.m_count;
}
private:
CountType m_count;
};
}
}
}
#endif // !MLN_ACCU_ACCUMULATOTS_COUNT_HPP
#ifndef MLN_ACCU_ACCUMULATOTS_MEAN_HPP
# define MLN_ACCU_ACCUMULATOTS_MEAN_HPP
# include <mln/accu/accumulators/sum.hpp>
# include <mln/accu/accumulators/count.hpp>
# include <mln/accu/accumulator_base.hpp>
namespace mln
{
namespace accu
{
namespace accumulators
{
template <typename T, typename SumType = decltype( std::declval<T>() + std::declval<T>() ) >
struct mean;
}
namespace features
{
template <typename SumType = void>
struct mean;
}
namespace extractor
{
template <typename A>
inline
typename A::return_type
mean(const Accumulator<A>& acc)
{
return extract(exact(acc), features::mean<> ());
}
}
namespace features
{
template <typename SumType>
struct mean
{
template <typename T>
struct apply
{
typedef accumulators::mean<T, SumType> type;
};
};
template <>
struct mean<void>
{
template <typename T>
struct apply
{
typedef accumulators::mean<T> type;
};
};
}
namespace accumulators
{
template <typename T, typename SumType>
struct mean : composite_accumulator_base< mean<T, SumType>, T, sum<T, SumType>, count<> >
{
typedef T argument_type;
typedef SumType return_type;
typedef features::mean<> feature;
friend
SumType extract(const mean& accu, features::mean<> )
{
return extractor::sum(accu) / extractor::count(accu);
}
private:
SumType m_sum;
};
}
}
}
#endif // ! MLN_ACCU_ACCUMULATOTS_MEAN_HPP
#ifndef MLN_ACCU_ACCUMULATOTS_SUM_HPP
# define MLN_ACCU_ACCUMULATOTS_SUM_HPP
/// \file
/// FIXME: use literal::zero instead of default initialization
# include <mln/accu/accumulator.hpp>
# include <utility>
namespace mln
{
namespace accu
{
namespace accumulators
{
template <typename T, typename SumType = decltype( std::declval<T>() + std::declval<T>() )>
struct sum;
}
namespace features
{
template <typename SumType = void>
struct sum;
}
namespace extractor
{
template <typename A>
typename A::return_type
sum(const Accumulator<A>& acc)
{
return extract(exact(acc), features::sum<> ());
}
}
namespace features
{
template <typename SumType>
struct sum
{
template <typename T>
struct apply
{
typedef accumulators::sum<T, SumType> type;
};
};
template <>
struct sum<void>
{
template <typename T>
struct apply
{
typedef accumulators::sum<T> type;
};
};
}
namespace accumulators
{
template <typename T, typename SumType>
struct sum : Accumulator< sum<T, SumType> >
{
typedef T argument_type;
typedef SumType return_type;
typedef features::sum<> feature;
sum()
: m_sum ( SumType() )
{
}
void init()
{
m_sum = SumType();
}
void take(const T& v)
{
m_sum += v;
}
void untake(const T& v)
{
m_sum -= v;
}
template <typename Other>
void take(const Accumulator<Other>& other)
{
m_sum += extractor::sum(other);
}
friend
SumType extract(const sum& accu, features::sum<> )
{
return accu.m_sum;
}
private:
SumType m_sum;
};
}
}
}
#endif // !MLN_ACCU_ACCUMULATOTS_SUM_HPP
#ifndef DONTCARE_HPP
# define DONTCARE_HPP
namespace mln
{
namespace accu
{
struct dontcare
{
template <typename T>
dontcare(T )
{
};
};
}
}
#endif // ! DONTCARE_HPP
#ifndef MLN_CORE_CONCEPT_ACCUMULATOR_HPP
# define MLN_CORE_CONCEPT_ACCUMULATOR_HPP
# include <mln/core/concept/object.hpp>
# include <mln/core/concept/check.hpp>
# include <boost/concept_check.hpp>
......@@ -8,7 +9,7 @@ namespace mln
{
template <typename Acc>
struct Accumulator
struct Accumulator : Object<Acc>
{
BOOST_CONCEPT_USAGE(Accumulator)
......
#ifndef MLN_LABELING_BLOBS_HPP
# define MLN_LABELING_BLOBS_HPP
# include <mln/core/image/image.hpp>
# include <vector>
namespace mln
{
namespace labeling
{
template <typename I, typename Neighborhood, typename Label = unsigned>
std::pair< mln_ch_value(I, Label), Label >
blobs(const Image<I>& ima, Neighborhood nbh, Label lbl = Label());
/******************************/
/*** Implementation ***/
/******************************/
template <typename I, typename Label>
std::pair< mln_ch_value(I, Label), Label >
blobs(const Image<I>& ima, Neighborhood nbh, Label lbl)
{
typedef mln_value(I) V;
typedef mln_point(I) P;
mln_ch_value(I, Label) out;
resize(out, ima);
std::vector<P> queue;
queue.reserve(ima.domain().size());
mln_foreach(P p, ima.domain())
{
if (out(p) == UNSEEN)
{
V val = ima(p);
queue.push_back(p);
++lbl;
while (not queue.empty())
{
q = queue.pop_back();
out(q) = lbl;
mln_forall(n)
{
if (ima.domain().has(n) and out(n) == UNSEEN and
ima(n) == val)
}
}
}
}
}
}
}
#endif // ! MLN_LABELING_BLOBS_HPP
......@@ -2,5 +2,5 @@
link_libraries(${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
add_definitions(-DBOOST_TEST_DYN_LINK)