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