Commit 78673e3c authored by Baptiste Esteban's avatar Baptiste Esteban
Browse files

Add documentation about alphatree

parent 329d1450
Pipeline #27782 passed with stages
in 16 minutes and 1 second
......@@ -6,38 +6,52 @@ Include :file:`<mln/morpho/alphatree.hpp>`
.. cpp:namespace:: mln::morpho
.. cpp:function:: auto alphatree(Image f, Neighborhood nbh);
.. cpp:function:: auto alphatree(Image f, Neighborhood nbh, F dist);
Compute the alphatree (also known as quasi-flat zone hierarchy) and returns a pair
`(tree, node_map)`. See :doc:`component_tree` for more information about the
representation of tree.
representation of tree.
:param input: The input image
:param nbh: The neighborhood
:return: A pair `(tree, node_map)` where *tree* is of type
`component_tree<image_value_t<I>>` and `node_map` is a mapping from each point to the
node *id* in the tree.
:precondition: ``f.domain().has(pinf)``
:param nbh: The neighborhood
:param dist: The function weighting the edges between two pixels
:return: A pair `(tree, node_map)` where *tree* is of type ``component_tree<std::invoke_result_t<F, image_value_t<Image>, image_value_t<Image>>>`` and *node_map* is a mapping between the image pixels and the node of the tree.
.. rubric:: Requirements
* ``image_value_t<I>`` is :cpp:concept:`std::totally_ordered`
* ``std::invoke_result_t<F, image_value_t<Image>, image_value_t<Image>>`` is :cpp:concept:`std::totally_ordered`
.. rubric:: Example
::
#include <mln/accu/accumulators/mean.hpp>
#include <mln/morpho/alphatree.hpp>
#include <mln/core/image/ndimage.hpp>
#include <mln/core/neighborhood/c4.hpp>
#include <mln/morpho/cut.hpp> // for horizontal_cut_labelization_from
mln::image2d<uint8_t> input = ...;
// Compute the alphatree
auto [tree, node_map] = mln::morpho::alphatree(input, mln::c4);
// Compute an attribute (for example the average pixels value at each node, as below)
auto mean = t.compute_attribute_on_values(node_map, input, mln::accu::accumulators::mean<std::uint8_t>());
// Making an horizontal cut of the tree
auto th = ...;
auto cut = mln::morpho::horizontal_cut_labelization_from(t, node_map, th, mean);
.. list-table::
* - .. figure:: /images/alphatree_cut_color.png
Cut of the alphatree with a threshold of 10
- .. figure:: /images/alphatree_cut_gray.png
Cut of the alphatree with a threshold of 3
Notes
-----
......
......@@ -57,6 +57,8 @@ add_image("area_filter"
add_image("blobs_watershed" "${DOCUMENTATION_IMAGE_DIR}/blobs_binary.png" blobs_distance_transform.png blobs_segmentation.png)
add_image("alphatree_example" "${PYLENE_IMAGE_DIR}/lena.ppm" alphatree_cut_color.png)
add_image("alphatree_example" "${PYLENE_IMAGE_DIR}/lena.pgm" alphatree_cut_gray.png)
add_custom_target(build-images
DEPENDS "${DOCUMENTATION_IMAGES}")
......@@ -70,6 +72,7 @@ target_link_libraries(doc-lib Pylene::Pylene)
link_libraries(Pylene::Pylene)
link_libraries(doc-lib)
add_executable(alphatree_example alphatree_example.cpp)
add_executable(erosion-cli erosion-cli.cpp)
add_executable(staff_lines staff_lines.cpp)
add_executable(component_tree_1 component_tree_1.cpp)
......
#include <mln/accu/accumulators/mean.hpp>
#include <mln/core/colors.hpp>
#include <mln/core/image/ndimage.hpp>
#include <mln/core/image/view/cast.hpp>
#include <mln/core/neighborhood/c4.hpp>
#include <mln/io/imread.hpp>
#include <mln/io/imsave.hpp>
#include <mln/morpho/alphatree.hpp>
#include <mln/morpho/cut.hpp>
#include <iostream>
template <typename V>
void process_example(const mln::image2d<V>& img, const std::string& cut_filename, double threshold)
{
// 2. Build the alphatree
auto [t, nm] = mln::morpho::alphatree(img, mln::c4);
using th_value_type = decltype(t.values)::value_type;
// 3. Compute the mean attribute
auto mean = t.compute_attribute_on_values(nm, img, mln::accu::accumulators::mean<V>());
// 4. Compute a cut of the alphatree
auto cut = mln::morpho::horizontal_cut_labelization_from(t, nm, th_value_type(threshold), mean);
// 5. Save the output cut
mln::io::imsave(mln::view::cast<V>(cut), cut_filename);
}
int main(int argc, char* argv[])
{
if (argc < 3)
{
std::cerr << "Invalid number of argument\nUsage: " << argv[0] << " input_filename cut_filename\n";
return 1;
}
auto in_filename = std::string(argv[1]);
auto cut_filename = std::string(argv[2]);
// 1. Read the input image
mln::ndbuffer_image in;
in = mln::io::imread(in_filename);
if (in.sample_type() == mln::sample_type_id::UINT8)
{
const auto* img = in.cast_to<std::uint8_t, 2>();
process_example(*img, cut_filename, 3);
}
else if (in.sample_type() == mln::sample_type_id::RGB8)
{
const auto* img = in.cast_to<mln::rgb8, 2>();
process_example(*img, cut_filename, 10);
}
else
{
std::cerr << "Unhandled sample type format\n";
return 1;
}
return 0;
}
\ No newline at end of file
......@@ -2,10 +2,11 @@
#include <mln/morpho/component_tree.hpp>
#include <vector>
namespace mln::morpho
{
template <typename V, typename Nodemap, typename L>
auto horizontal_cut_labelization_from(const component_tree<V>& t, Nodemap nm, V th, ::ranges::span<L> vals);
template <typename V, typename Nodemap, typename L>
auto horizontal_cut_labelization_from(const component_tree<V>& t, Nodemap nm, V th, const std::vector<L>& vals);
......@@ -14,15 +15,16 @@ namespace mln::morpho
******************/
template <typename V, typename Nodemap, typename L>
auto horizontal_cut_labelization_from(const component_tree<V>& t, Nodemap nm, V th, const std::vector<L>& vals)
auto horizontal_cut_labelization_from(const component_tree<V>& t, Nodemap nm, V th, ::ranges::span<L> vals)
{
static_assert(mln::is_a_v<Nodemap, mln::details::Image>);
static_assert(std::is_same_v<image_value_t<Nodemap>, int>);
using ValueType = std::remove_cv_t<L>;
assert(vals.size() == t.parent.size());
assert(static_cast<std::size_t>(vals.size()) == t.parent.size());
image_ch_value_t<Nodemap, L> lbl = imchvalue<L>(nm);
image_concrete_t<Nodemap> cut_nm = imconcretize(nm);
image_ch_value_t<Nodemap, ValueType> lbl = imchvalue<ValueType>(nm);
image_concrete_t<Nodemap> cut_nm = imconcretize(nm);
mln_foreach (auto p, nm.domain())
{
......@@ -36,4 +38,10 @@ namespace mln::morpho
return lbl;
}
template <typename V, typename Nodemap, typename L>
auto horizontal_cut_labelization_from(const component_tree<V>& t, Nodemap nm, V th, const std::vector<L>& vals)
{
return horizontal_cut_labelization_from(t, nm, th, ::ranges::make_span(vals.data(), vals.size()));
}
} // namespace mln::morpho
\ No newline at end of file
#include <mln/morpho/alphatree.hpp>
#include <mln/core/colors.hpp>
#include <mln/core/image/ndimage.hpp>
#include <mln/core/neighborhood/c4.hpp>
#include <mln/morpho/alphatree.hpp>
#include <mln/morpho/cut.hpp>
#include <fixtures/ImageCompare/image_compare.hpp>
#include <gtest/gtest.h>
#include <cmath>
#include <iostream>
template <typename V>
mln::image2d<int> //
cut(const mln::morpho::component_tree<V>& t, mln::image2d<int>& node_map, int alpha)
......@@ -151,9 +146,8 @@ TEST(Morpho, AlphaTreeRGB8)
auto [t, nm] = mln::morpho::alphatree(
ima, mln::c4, [](const auto& a, const auto& b) -> int { return mln::functional::l2dist_t<>()(a, b); });
std::vector<int> rng(t.parent.size());
auto rng = std::vector<int>(t.parent.size());
std::iota(rng.begin(), rng.end(), 0);
ASSERT_IMAGES_EQ_EXP(mln::morpho::horizontal_cut_labelization_from(t, nm, 0, rng), nm);
ASSERT_IMAGES_EQ_EXP(mln::morpho::horizontal_cut_labelization_from(t, nm, 8, rng), ref_8);
ASSERT_IMAGES_EQ_EXP(mln::morpho::horizontal_cut_labelization_from(t, nm, 16, rng), ref_16);
......
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