Commit cf7233e9 authored by Edwin Carlinet's avatar Edwin Carlinet
Browse files

Make the ToS use the original levels (not the depth).

parent 5b702052
......@@ -12,18 +12,12 @@
namespace mln::morpho::experimental
{
// namespace details
// {
// void filter_treeT(const int* parent, std::size_t n, e_filtering strategy, F predicate);
// void filter_tree(const int* parent, std::size_t n, e_filtering strategy, std::function<bool(int)> predicate);
// }
enum ct_filtering
{
CT_FILTER_DIRECT,
CT_FILTER_MIN,
CT_FILTER_MAX,
CT_FILTER_SUBTRACTIVE
// CT_FILTER_SUBTRACTIVE (not yet implemented)
};
......@@ -100,6 +94,20 @@ namespace mln::morpho::experimental
compute_attribute_on_points(I node_map, Accu acc);
/// \brief Compute attribute on pixels
///
/// Compute attribute with pixels (point + value) given from an image
///
/// \param node_map Image point -> node_id mapping
/// \param values Image point -> value mapping
/// \param acc Accumulator to apply on values
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);
/// \brief Reconstruct an image from an attribute map
///
/// \param node_map Image point -> node_id mapping
......@@ -130,9 +138,9 @@ namespace mln::morpho::experimental
public:
template <class I>
image_ch_value_t<I, T> reconstruct(I node_map)
image_ch_value_t<std::remove_reference_t<I>, T> reconstruct(I&& node_map)
{
return this->reconstruct_from(std::move(node_map), ::ranges::make_span(values.data(), values.size()));
return this->reconstruct_from(std::forward<I>(node_map), ::ranges::make_span(values.data(), values.size()));
}
......@@ -150,7 +158,7 @@ namespace mln::morpho::experimental
std::size_t n = parent.size();
for (std::size_t i = 1; i < n; ++i)
if (!pred(parent[i]))
if (parent[i] > 0 && !pred(parent[i])) // If the parent[i] > 0 <=> not the root
parent[i] = parent[parent[i]];
}
......@@ -160,7 +168,7 @@ namespace mln::morpho::experimental
{
mln_foreach_new(auto& id, node_map.new_values())
{
if (!pred(id))
if (id > 0 && !pred(id))
id = this->parent[id];
}
}
......@@ -170,6 +178,8 @@ namespace mln::morpho::experimental
template <class F>
void component_tree<void>::filter(ct_filtering strategy, F pred)
{
mln_entering("mln::morpho::component_tree::filter");
std::size_t n = parent.size();
// Node pass status
......@@ -213,6 +223,8 @@ namespace mln::morpho::experimental
template <class I, class F>
void component_tree<void>::filter(ct_filtering strategy, I node_map, F pred)
{
mln_entering("mln::morpho::component_tree::filter");
std::size_t n = parent.size();
// Node pass status
......@@ -264,6 +276,8 @@ namespace mln::morpho::experimental
std::vector<typename accu::result_of<Accu, image_point_t<I>>::type>
component_tree<void>::compute_attribute_on_points(I node_map, Accu acc)
{
mln_entering("mln::morpho::component_tree::compute_attribute_on_points");
static_assert(mln::is_a<I, mln::experimental::Image>());
static_assert(mln::is_a<Accu, mln::AccumulatorLike>());
using R = typename accu::result_of<Accu, image_point_t<I>>::type;
......@@ -295,6 +309,8 @@ namespace mln::morpho::experimental
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)
{
mln_entering("mln::morpho::component_tree::compute_attribute_on_values");
static_assert(mln::is_a<I, mln::experimental::Image>());
static_assert(mln::is_a<Accu, mln::AccumulatorLike>());
using R = typename accu::result_of<Accu, image_value_t<J>>::type;
......@@ -305,7 +321,7 @@ namespace mln::morpho::experimental
// Accumulate for each point
auto zz = mln::view::zip(node_map, input);
mln_foreach_new((auto [node_id, val]), zz.values())
mln_foreach_new((auto [node_id, val]), zz.new_values())
attr[node_id].take(val);
......@@ -323,12 +339,46 @@ namespace mln::morpho::experimental
return out;
}
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)
{
mln_entering("mln::morpho::component_tree::compute_attribute_on_pixels");
static_assert(mln::is_a<I, mln::experimental::Image>());
static_assert(mln::is_a<Accu, mln::AccumulatorLike>());
using R = typename accu::result_of<Accu, image_pixel_t<J>>::type;
auto a = accu::make_accumulator(acc, image_pixel_t<J>());
std::vector<decltype(a)> attr(parent.size(), a);
// Accumulate for each point
mln_foreach_new (auto px, values.new_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]);
// Extract values
std::vector<R> out(n);
for (std::size_t i = 0; i < n; ++i)
out[i] = attr[i].to_result();
return out;
}
template <class I, class V>
image_ch_value_t<I, V> component_tree<void>::reconstruct_from(I node_map, ::ranges::span<V> values) const
{
mln_entering("mln::morpho::component_tree::reconstruction");
image_ch_value_t<I, V> out = imchvalue<V>(node_map);
auto zz = mln::view::zip(node_map, out);
......
......@@ -16,7 +16,8 @@ namespace mln::morpho::experimental::details
{
/// Propagation
template <class I>
void propagation(I inf, I sup, image_ch_value_t<I, int> out, image_point_t<I> pstart, int& max_depth);
std::vector<image_value_t<I>> //
propagation(I inf, I sup, image_ch_value_t<I, int> out, image_point_t<I> pstart, int& max_depth);
/******************************************/
......@@ -44,14 +45,14 @@ namespace mln::morpho::experimental::details
template <class I>
void propagation(I inf, I sup, image_ch_value_t<I, int> ord, image_point_t<I> pstart, int& max_depth)
std::vector<image_value_t<I>> //
propagation(I inf, I sup, image_ch_value_t<I, int> ord, image_point_t<I> pstart, int& max_depth)
{
mln_entering("mln::morpho::details::propagation");
using P = image_point_t<I>;
using V = image_value_t<I>;
static_assert(P::ndim == 2 || P::ndim == 3, "Invalid number of dimension");
assert(inf.domain() == sup.domain());
assert(inf.domain() == ord.domain());
......@@ -78,9 +79,11 @@ namespace mln::morpho::experimental::details
// if (compute_indexes)
// sorted_indexes->reserve(ord.domain().size());
auto F = to_infsup(inf, sup);
pset<I> queue(inf);
pset<I> queue(inf);
std::vector<V> depth2lvl;
auto p = pstart;
V previous_level = inf(p);
......@@ -90,12 +93,16 @@ namespace mln::morpho::experimental::details
// sorted_indexes->push_back(p);
int depth = 0;
depth2lvl.push_back(previous_level);
while (!queue.empty())
{
auto [cur_level, p] = queue.pop(previous_level);
if (cur_level != previous_level)
{
++depth;
depth2lvl.push_back(cur_level);
}
// if (compute_indexes)
// sorted_indexes->push_back(p);
......@@ -139,6 +146,7 @@ namespace mln::morpho::experimental::details
previous_level = cur_level;
}
max_depth = depth;
return depth2lvl;
}
......
......@@ -6,6 +6,8 @@
#include <mln/morpho/experimental/private/propagation.hpp>
#include <mln/core/image/view/cast.hpp>
#include <range/v3/algorithm/transform.hpp>
namespace mln::morpho::experimental
{
......@@ -35,6 +37,7 @@ namespace mln::morpho::experimental
using Domain = image_domain_t<I>;
using P = image_point_t<I>;
using V = image_value_t<I>;
static_assert(std::is_same_v<Domain, mln::experimental::box2d> || std::is_same_v<Domain, mln::experimental::box3d>,
"Only 2D or 3D regular domain supported");
......@@ -46,13 +49,21 @@ namespace mln::morpho::experimental
auto [inf, sup] = details::immersion(input);
image_ch_value_t<I, int> ord = imchvalue<int>(inf).adjust(nbh);
details::propagation(inf, sup, ord, pstart, max_depth);
auto depth2lvl = details::propagation(inf, sup, ord, pstart, max_depth);
if (max_depth >= (1 << 16))
throw std::runtime_error("The ToS is too deep (too many number of levels)");
auto casted = mln::view::cast<uint16_t>(ord);
return maxtree(casted, nbh);
auto [t1, node_map] = maxtree(casted, nbh);
std::size_t n = t1.parent.size();
component_tree<V> t2;
t2.parent = std::move(t1.parent);
t2.values.resize(n);
::ranges::transform(t1.values, std::begin(t2.values), [&depth2lvl](int l) -> V { return depth2lvl[l]; });
return std::make_pair(std::move(t2), std::move(node_map));
}
} // namespace mln::morpho::experimental
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