Commit c65ff69c authored by Baptiste Esteban's avatar Baptiste Esteban
Browse files

Add a propagate option to the component tree attribute computations

parent 1e9ea92c
Pipeline #30940 passed with stage
in 17 minutes and 25 seconds
......@@ -148,15 +148,16 @@ A :cpp:class:`component_tree` `t` has the following methods.
.. cpp:namespace-push:: template <class V> component_tree
.. cpp:function:: auto compute_attribute_on_points(Image node_map, Accumulator accu) const
auto compute_attribute_on_values(Image node_map, Image values, Accumulator accu) const
auto compute_attribute_on_pixels(Image node_map, Image values, Accumulator accu) const
.. cpp:function:: auto compute_attribute_on_points(Image node_map, Accumulator accu, bool propagate) const
auto compute_attribute_on_values(Image node_map, Image values, Accumulator accu, bool propagate) const
auto compute_attribute_on_pixels(Image node_map, Image values, Accumulator accu, bool propagate) const
Accumulate the points of each component.
:param node_map: An image thats maps: point -> node id
:param values: An image where values to accumlate are taken from
:param accu: The feature to compute
:param propagate: Option to propagate the values to the parent (default: true)
:return: A vector mapping for each node the result of accumulation.
......
......@@ -44,26 +44,6 @@ This example computes a grain filter, which removes all the node having an area
// Function to get the median of the border values
mln::rgb8 get_median_on_border(mln::image2d<mln::rgb8> ima);
// Accumulator to compute the mean of the pixel values of each node, without taking into account the values of the holes
struct mean_node_accu : mln::Accumulator<mean_node_accu>
{
using result_type = decltype(std::declval<mln::rgb8>() + std::declval<mln::rgb8>());
public:
void take(const mln::rgb8& v)
{
m_sum += v;
m_count++;
}
void take(const mean_node_accu&) {}
result_type to_result() const { return m_count > 1 ? static_cast<result_type>(m_sum / m_count) : m_sum; }
private:
result_type m_sum = {0, 0, 0};
int m_count = 0;
};
int main(void)
{
mln::image2d<mln::rgb8> ima;
......@@ -92,7 +72,7 @@ This example computes a grain filter, which removes all the node having an area
t.filter(mln::morpho::CT_FILTER_DIRECT, nm, [&area](int n) { return area[n] >= 100; });
// Compute the mean of the connected component of each nodes
auto mean = t.compute_attribute_on_values(nm, ima, mean_node_accu());
auto mean = t.compute_attribute_on_values(nm, ima, mln::accu::features::mean<>(), false);
// Reconstruct the tree
auto rec = t.reconstruct_from(nm, ranges::make_span(mean.data(), mean.size()));
......
#include <mln/accu/accumulators/count.hpp>
#include <mln/accu/accumulators/max.hpp>
#include <mln/accu/accumulators/mean.hpp>
#include <mln/core/algorithm/accumulate.hpp>
#include <mln/core/colors.hpp>
#include <mln/core/extension/padding.hpp>
......@@ -20,26 +21,6 @@
namespace
{
struct mean_node_accu : mln::Accumulator<mean_node_accu>
{
using result_type = decltype(std::declval<mln::rgb8>() + std::declval<mln::rgb8>());
public:
void take(const mln::rgb8& v)
{
m_sum += v;
m_count++;
}
void take(const mean_node_accu&) {}
result_type to_result() const { return m_count > 1 ? static_cast<result_type>(m_sum / m_count) : m_sum; }
private:
result_type m_sum = {0, 0, 0};
int m_count = 0;
};
mln::rgb8 get_median_on_border(mln::image2d<mln::rgb8> ima)
{
std::vector<mln::rgb8> border;
......@@ -134,7 +115,7 @@ int main(int argc, char* argv[])
auto area = t.compute_attribute_on_points(nm, mln::accu::accumulators::count<int>());
t.filter(mln::morpho::CT_FILTER_DIRECT, nm, [&area](int n) { return area[n] >= 100; });
auto mean = t.compute_attribute_on_values(nm, ima, mean_node_accu());
auto mean = t.compute_attribute_on_values(nm, ima, mln::accu::features::mean<>(), false);
auto rec = t.reconstruct_from(nm, ranges::make_span(mean.data(), mean.size()));
mln::io::imsave(mln::view::cast<mln::rgb8>(rec), argv[3]);
......
......@@ -88,9 +88,10 @@ namespace mln::morpho
/// \param node_map Image point -> node_id mapping
/// \param values Image point -> value mapping
/// \param acc Accumulator to apply on values
/// \param propagate Boolean to propagate the values to the parent
template <class I, class J, class Accu>
std::vector<typename accu::result_of<Accu, image_value_t<J>>::type> //
compute_attribute_on_values(I node_map, J values, Accu acc) const;
compute_attribute_on_values(I node_map, J values, Accu acc, bool propagate = true) const;
/// \brief Compute attribute on values
///
......@@ -99,9 +100,10 @@ namespace mln::morpho
/// \param node_map Image point -> node_id mapping
/// \param values Image point -> value mapping
/// \param acc Accumulator to apply on points
/// \param propagate Boolean to propagate the values to the parent
template <class I, class Accu>
std::vector<typename accu::result_of<Accu, image_point_t<I>>::type> //
compute_attribute_on_points(I node_map, Accu acc) const;
compute_attribute_on_points(I node_map, Accu acc, bool propagate = true) const;
/// \brief Compute attribute on pixels
......@@ -111,9 +113,10 @@ namespace mln::morpho
/// \param node_map Image point -> node_id mapping
/// \param values Image point -> value mapping
/// \param acc Accumulator to apply on values
/// \param propagate Boolean to propagate the values to the parent
template <class I, class J, class Accu>
std::vector<typename accu::result_of<Accu, image_pixel_t<J>>::type> //
compute_attribute_on_pixels(I node_map, J values, Accu acc) const;
compute_attribute_on_pixels(I node_map, J values, Accu acc, bool propagate = true) const;
/// \brief Compute the horizontal cut of a hierarchie at level `threshold` and return a nodemap
/// valued with the node indices of the lowest nodes satisfying levels[n] > threshold
......@@ -297,7 +300,7 @@ namespace mln::morpho
template <class I, class Accu>
std::vector<typename accu::result_of<Accu, image_point_t<I>>::type>
component_tree<void>::compute_attribute_on_points(I node_map, Accu acc) const
component_tree<void>::compute_attribute_on_points(I node_map, Accu acc, bool propagate) const
{
mln_entering("mln::morpho::component_tree::compute_attribute_on_points");
......@@ -313,12 +316,13 @@ namespace mln::morpho
mln_foreach (auto px, node_map.pixels())
attr[px.val()].take(px.point());
// Propgate to parent
std::size_t n = parent.size();
for (std::size_t i = n - 1; i > 0; --i)
attr[parent[i]].take(attr[i]);
const std::size_t n = parent.size();
if (propagate)
{
// Propgate to parent
for (std::size_t i = n - 1; i > 0; --i)
attr[parent[i]].take(attr[i]);
}
// Extract values
std::vector<R> out(n);
......@@ -330,7 +334,7 @@ namespace mln::morpho
template <class I, class J, class Accu>
std::vector<typename accu::result_of<Accu, image_value_t<J>>::type> //
component_tree<void>::compute_attribute_on_values(I node_map, J input, Accu acc) const
component_tree<void>::compute_attribute_on_values(I node_map, J input, Accu acc, bool propagate) const
{
mln_entering("mln::morpho::component_tree::compute_attribute_on_values");
......@@ -347,12 +351,13 @@ namespace mln::morpho
mln_foreach ((auto [node_id, val]), zz.values())
attr[node_id].take(val);
// Propgate to parent
std::size_t n = parent.size();
for (std::size_t i = n - 1; i > 0; --i)
attr[parent[i]].take(attr[i]);
const std::size_t n = parent.size();
if (propagate)
{
// Propgate to parent
for (std::size_t i = n - 1; i > 0; --i)
attr[parent[i]].take(attr[i]);
}
// Extract values
std::vector<R> out(n);
......@@ -364,7 +369,7 @@ namespace mln::morpho
template <class I, class J, class Accu>
std::vector<typename accu::result_of<Accu, image_pixel_t<J>>::type> //
component_tree<void>::compute_attribute_on_pixels(I node_map, J values, Accu acc) const
component_tree<void>::compute_attribute_on_pixels(I node_map, J values, Accu acc, bool propagate) const
{
mln_entering("mln::morpho::component_tree::compute_attribute_on_pixels");
......@@ -380,12 +385,13 @@ namespace mln::morpho
mln_foreach (auto px, values.pixels())
attr[node_map(px.point())].take(px);
// Propgate to parent
std::size_t n = parent.size();
for (std::size_t i = n - 1; i > 0; --i)
attr[parent[i]].take(attr[i]);
const std::size_t n = parent.size();
if (propagate)
{
// Propgate to parent
for (std::size_t i = n - 1; i > 0; --i)
attr[parent[i]].take(attr[i]);
}
// Extract values
std::vector<R> out(n);
......
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