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

More doc + small fixes

parent 21cf5ccd
Pipeline #30574 passed with stages
in 18 minutes and 36 seconds
...@@ -21,8 +21,8 @@ Pylene. ...@@ -21,8 +21,8 @@ Pylene.
Notes Notes
----- -----
* Before computing the MToS, the user should add a border to the image, with the values of this border set to the median value of the border of the original image * Before computing the MToS, the user should add a border to the image, with the values of this border set to the median value of the border of the original image.
* The resulting nodemap is sixteen times bigger than the original image. The user is advised to reduce the nodemap before doing any processing. (**FIXME** to keep ?) * The MToS not having values related to the nodes, the user has to compute a value.
Example Example
------- -------
...@@ -45,16 +45,14 @@ This example computes a grain filter, which removes all the node which have an a ...@@ -45,16 +45,14 @@ This example computes a grain filter, which removes all the node which have an a
// Function to remove the border // Function to remove the border
mln::image2d<int> remove_border(mln::image2d<int> n); mln::image2d<int> remove_border(mln::image2d<int> n);
// Accumulator to compute the mean of each node, without taking into account the values of the holes // Accumulator to compute the mean of the pixel values of each node, without taking into account the values of the holes
// (it only takes into account the value of the connected component related to a node)
struct mean_node_accu : mln::Accumulator<mean_node_accu> struct mean_node_accu : mln::Accumulator<mean_node_accu>
{ {
using result_type = decltype(std::declval<mln::rgb8>() + std::declval<mln::rgb8>()); using result_type = decltype(std::declval<mln::rgb8>() + std::declval<mln::rgb8>());
public: public:
template <typename Pix> void take(const mln::rgb8& v)
void take(const Pix& pix)
{ {
m_sum += pix.val(); m_sum += v;
m_count++; m_count++;
} }
...@@ -91,7 +89,7 @@ This example computes a grain filter, which removes all the node which have an a ...@@ -91,7 +89,7 @@ This example computes a grain filter, which removes all the node which have an a
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_pixels(nm, ima, mean_node_accu()); auto mean = t.compute_attribute_on_values(nm, ima, mean_node_accu());
// 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()));
......
...@@ -21,10 +21,9 @@ namespace ...@@ -21,10 +21,9 @@ namespace
{ {
using result_type = decltype(std::declval<mln::rgb8>() + std::declval<mln::rgb8>()); using result_type = decltype(std::declval<mln::rgb8>() + std::declval<mln::rgb8>());
public: public:
template <typename Pix> void take(const mln::rgb8& v)
void take(const Pix& pix)
{ {
m_sum += pix.val(); m_sum += v;
m_count++; m_count++;
} }
...@@ -149,12 +148,12 @@ int main(int argc, char* argv[]) ...@@ -149,12 +148,12 @@ int main(int argc, char* argv[])
mln::io::imsave(heat_depth, argv[2]); mln::io::imsave(heat_depth, argv[2]);
} }
auto [t, nm] = mln::morpho::details::satmaxtree(depth_map); auto [t, nm] = mln::morpho::details::satmaxtree(depth_map, {0, 0});
nm = reduce_nodemap(nm); nm = reduce_nodemap(nm);
nm = remove_border(nm); nm = remove_border(nm);
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] >= 200; });
auto mean = t.compute_attribute_on_pixels(nm, ima, mean_node_accu()); auto mean = t.compute_attribute_on_values(nm, ima, mean_node_accu());
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]);
......
...@@ -6,5 +6,10 @@ ...@@ -6,5 +6,10 @@
namespace mln::morpho::details namespace mln::morpho::details
{ {
std::pair<component_tree<>, image2d<int>> satmaxtree(image2d<std::uint16_t> depth_map); /// \brief Compute the hole-filled maxtree of a depth map
/// \param depth_map The input depth map
/// \param pstart The rooting point of the satmaxtree
/// \return A pair (tree, nodemap) where tree is the resulting satmaxtree (values are not kept)
/// and a map image point -> tree node
std::pair<component_tree<>, image2d<int>> satmaxtree(image2d<std::uint16_t> depth_map, point2d pstart);
} }
\ No newline at end of file
...@@ -8,9 +8,24 @@ ...@@ -8,9 +8,24 @@
namespace mln::morpho::details namespace mln::morpho::details
{ {
/// \brief Compute the inclusion graph of the trees given in input
/// \param trees The input trees
/// \param nodemaps The nodemaps related to each tree
/// \param depths The depths attribute of each tree
/// \param The number of tree given in argument
/// \return A pair (graph, tree_to_graph) where graph is the inclusion graph and tree_to_graph
/// is a map (tree_index, tree_node) -> graph_node
std::pair<std::vector<std::set<int>>, std::vector<std::vector<int>>> std::pair<std::vector<std::set<int>>, std::vector<std::vector<int>>>
compute_inclusion_graph(component_tree<>* trees, image2d<int>* nodemaps, std::vector<int>* depths, int ntrees); compute_inclusion_graph(component_tree<>* trees, image2d<int>* nodemaps, std::vector<int>* depths, int ntrees);
/// \brief Compute the depth map of an inclusion graph
/// \param graph The inclusion graph
/// \param tree_to_graph A map (tree_index, tree_node) -> graph_node
/// \param nodemaps The nodemaps of each tree which built the inclusion graph
/// \return The depth map of the inclusion graph (The depth should not exceed 2^16)
/// FIXME: For future optimization, the arguments should be change to
/// (const std::vector<std::set<int>>& graph, const std::vector<int>& tree_to_graph, image2d<int>* nodemaps, const
/// std::vector<int>& tree_shapes)
image2d<std::uint16_t> compute_depth_map(const std::vector<std::set<int>>& graph, image2d<std::uint16_t> compute_depth_map(const std::vector<std::set<int>>& graph,
const std::vector<std::vector<int>>& tree_to_graph, image2d<int>* nodemaps); const std::vector<std::vector<int>>& tree_to_graph, image2d<int>* nodemaps);
} // namespace mln::morpho::details } // namespace mln::morpho::details
\ No newline at end of file
...@@ -21,7 +21,7 @@ namespace mln::morpho ...@@ -21,7 +21,7 @@ namespace mln::morpho
const auto [gos, tree_to_graph] = mln::morpho::details::compute_inclusion_graph(trees, nodemaps, depths, 3); const auto [gos, tree_to_graph] = mln::morpho::details::compute_inclusion_graph(trees, nodemaps, depths, 3);
auto depth_map = mln::morpho::details::compute_depth_map(gos, tree_to_graph, nodemaps); auto depth_map = mln::morpho::details::compute_depth_map(gos, tree_to_graph, nodemaps);
auto [t, nm] = mln::morpho::details::satmaxtree(depth_map); auto [t, nm] = mln::morpho::details::satmaxtree(depth_map, pstart);
return {std::move(t), std::move(nm)}; return {std::move(t), std::move(nm)};
} }
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
namespace mln::morpho::details namespace mln::morpho::details
{ {
std::pair<component_tree<>, image2d<int>> satmaxtree(image2d<std::uint16_t> depth_map) std::pair<component_tree<>, image2d<int>> satmaxtree(image2d<std::uint16_t> depth_map, point2d pstart)
{ {
auto [t, nm] = mln::morpho::tos(depth_map, {0, 0}); auto [t, nm] = mln::morpho::tos(depth_map, pstart);
const int num_node = static_cast<int>(t.parent.size()); const int num_node = static_cast<int>(t.parent.size());
std::vector<std::uint16_t> delta(num_node, 0); std::vector<std::uint16_t> delta(num_node, 0);
......
...@@ -208,7 +208,7 @@ namespace mln::morpho::details ...@@ -208,7 +208,7 @@ namespace mln::morpho::details
std::vector<int> graph_depth(graph.size(), -1); std::vector<int> graph_depth(graph.size(), -1);
graph_depth[0] = 0; graph_depth[0] = 0;
// FIXME : Optimization removing the transpose (modify topo_sort) /// FIXME: Optimization removing the transpose (modify topo_sort)
std::vector<std::set<int>> gT(graph.size()); std::vector<std::set<int>> gT(graph.size());
for (int v = 0; v < (int)graph.size(); v++) for (int v = 0; v < (int)graph.size(); v++)
{ {
......
...@@ -112,9 +112,6 @@ TEST(Morpho, DepthMap) ...@@ -112,9 +112,6 @@ TEST(Morpho, DepthMap)
TEST(Morpho, Satmaxtree) TEST(Morpho, Satmaxtree)
{ {
// Test satmaxtree computation from depth map
auto [t, nm] = mln::morpho::details::satmaxtree(depth_map_ref);
std::vector<int> parent_ref = {-1, 0, 1, 1, 3, 3, 3, 3, 3, 3, 1, 10, 10, std::vector<int> parent_ref = {-1, 0, 1, 1, 3, 3, 3, 3, 3, 3, 1, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 21, 21, 10}; 10, 10, 10, 10, 10, 10, 10, 10, 10, 21, 21, 10};
...@@ -138,6 +135,9 @@ TEST(Morpho, Satmaxtree) ...@@ -138,6 +135,9 @@ TEST(Morpho, Satmaxtree)
{20, 10, 10, 10, 17, 10, 10, 10, 10, 10, 10, 10, 16, 10, 10, 10, 18}, // {20, 10, 10, 10, 17, 10, 10, 10, 10, 10, 10, 10, 16, 10, 10, 10, 18}, //
}; };
// Test satmaxtree computation from depth map
auto [t, nm] = mln::morpho::details::satmaxtree(depth_map_ref, {0, 0});
ASSERT_EQ(t.parent.size(), parent_ref.size()); ASSERT_EQ(t.parent.size(), parent_ref.size());
for (int i = 0; i < (int)parent_ref.size(); i++) for (int i = 0; i < (int)parent_ref.size(); i++)
......
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