Commit 18d640f0 authored by Baptiste Esteban's avatar Baptiste Esteban
Browse files

Add satmaxtree, mtos and grain_filter computation

parent 0b45cd9c
Pipeline #30511 failed with stages
in 18 minutes and 35 seconds
......@@ -64,7 +64,7 @@ add_image("watershed_hierarchy_example" "${PYLENE_IMAGE_DIR}/lena.pgm" watershed
add_image("saliency_example" "${PYLENE_IMAGE_DIR}/lena.pgm" saliency_watershed.png)
add_image("mtos_example" "${PYLENE_IMAGE_DIR}/lena.ppm" depth_map.png)
add_image("mtos_example" "${PYLENE_IMAGE_DIR}/lena.ppm" depth_map.png mtos_rec.png)
add_custom_target(build-images
DEPENDS "${DOCUMENTATION_IMAGES}")
......
#include <mln/accu/accumulators/mean.hpp>
#include <mln/core/colors.hpp>
#include <mln/core/image/ndimage.hpp>
#include <mln/core/image/view/channel.hpp>
......@@ -6,6 +7,7 @@
#include <mln/io/imsave.hpp>
#include <mln/morpho/tos.hpp>
#include <mln/morpho/private/satmaxtree.hpp>
#include <mln/morpho/private/trees_fusion.hpp>
#include <iostream>
......@@ -15,6 +17,26 @@
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;
};
/// \brief Add a border to the image with values set at the median value
mln::image2d<mln::rgb8> add_border(mln::image2d<mln::rgb8> ima)
{
mln::image2d<mln::rgb8> res(ima.width() + 2, ima.height() + 2);
......@@ -63,6 +85,7 @@ namespace
return res;
}
/// \brief Compute the maximum value of an image
std::uint16_t max(mln::image2d<std::uint16_t> ima)
{
std::uint16_t res = 0;
......@@ -71,14 +94,28 @@ namespace
return res;
}
/// \brief Reduce the size of a nodemap by a factor 2
mln::image2d<int> reduce_nodemap(mln::image2d<int> n)
{
mln::image2d<int> res((n.width() + 1) / 2, (n.height() + 1) / 2);
mln_foreach(auto p, n.domain())
{
if (p[0] % 2 == 0 && p[1] % 2 == 0)
{
res(mln::point2d{p[0] / 2, p[1] / 2}) = n(p);
}
}
return res;
}
} // namespace
int main(int argc, char* argv[])
{
if (argc < 3)
if (argc < 4)
{
std::cerr << "Invalid number of arguments\nUsage: " << argv[0] << " input_filename depth_map_filename\n";
std::cerr << "Invalid number of arguments\nUsage: " << argv[0] << " input_filename depth_map_filename rec_filename\n";
return 1;
}
......@@ -99,11 +136,21 @@ int main(int argc, char* argv[])
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);
std::uint16_t max_depth = max(depth_map);
auto normalized_depth = mln::view::transform(depth_map, [&max_depth](std::uint16_t a) -> float { return (float)a / (float)max_depth;});
auto heat_depth = mln::view::transform(normalized_depth, heat_lut);
{
std::uint16_t max_depth = max(depth_map);
auto normalized_depth =
mln::view::transform(depth_map, [&max_depth](std::uint16_t a) -> float { return (float)a / (float)max_depth; });
auto heat_depth = mln::view::transform(normalized_depth, heat_lut);
mln::io::imsave(heat_depth, argv[2]);
}
mln::io::imsave(heat_depth, argv[2]);
auto [t, nm] = mln::morpho::details::satmaxtree(depth_map);
nm = reduce_nodemap(reduce_nodemap(nm));
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 rec = t.reconstruct_from(nm, ::ranges::make_span(mean.data(), mean.size()));
mln::io::imsave(mln::view::cast<mln::rgb8>(rec), argv[3]);
return 0;
}
\ No newline at end of file
......@@ -86,6 +86,7 @@ target_sources(Pylene-core PRIVATE
src/morpho/hvector_unbounded.cpp
src/morpho/immersion.cpp
src/morpho/maxtree.cpp
src/morpho/satmaxtree.cpp
src/morpho/trees_fusion.cpp
src/morpho/unionfind.cpp
)
......
#pragma once
#include <mln/morpho/component_tree.hpp>
#include <tuple>
namespace mln::morpho::details
{
std::pair<component_tree<>, image2d<int>> satmaxtree(image2d<std::uint16_t> depth_map);
}
\ No newline at end of file
#include <mln/morpho/private/satmaxtree.hpp>
#include <mln/morpho/tos.hpp>
namespace mln::morpho::details
{
std::pair<component_tree<>, image2d<int>> satmaxtree(image2d<std::uint16_t> depth_map)
{
auto [t, nm] = mln::morpho::tos(depth_map, {0, 0});
const int num_node = t.parent.size();
std::vector<std::uint16_t> delta(num_node, 0);
for (int i = 1; i < num_node; i++)
{
delta[i] = delta[t.parent[i]];
if (t.values[i] <= t.values[t.parent[i]])
delta[i] += t.values[t.parent[i]] - t.values[i];
}
for (int i = 1; i < num_node; i++)
t.values[i] += delta[i];
t.filter(CT_FILTER_DIRECT, nm, [&t](int a) { return t.values[a] > t.values[t.parent[a]] || t.parent[a] == 0; });
return {std::move(t), std::move(nm)};
}
} // namespace mln::morpho::details
\ No newline at end of file
Markdown is supported
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