mmcfilters
Public API documentation
Loading...
Searching...
No Matches
MorphologicalTreeFactory.hpp
1#pragma once
2
3#include "MorphologicalTree.hpp"
4#include "TreeOfShapesBuilder.hpp"
5#include "TreeAltitudeAlgorithms.hpp"
6#include "ValuedMorphologicalTree.hpp"
7#include "ComponentTreeBuilder.hpp"
8#include "ExtremumResidualTreeByCTsBuilder.hpp"
9#include "detail/HigraHierarchyDetail.hpp"
10#include "detail/MorphologicalTreeConstructionTag.hpp"
11#include "../utils/Image.hpp"
12#include "../utils/Contract.hpp"
13
14#include <cstddef>
15#include <cstdint>
16#include <optional>
17#include <span>
18#include <utility>
19#include <vector>
20
21namespace mmcfilters {
22
51 private:
57 template <AltitudeValue T> static void validateComponentTreeImage(const ImagePtr<T>& img, const char* context) {
58 MMCFILTERS_CONTRACT_REQUIRE(img != nullptr, throw std::invalid_argument(std::string(context) + " requires a non-null image."));
59 MMCFILTERS_CONTRACT_REQUIRE(img->getNumRows() > 0 && img->getNumColumns() > 0 && img->getSize() > 0,
60 throw std::invalid_argument(std::string(context) + " requires a non-empty 2D image."));
62 }
63
69 static void validateTreeOfShapesImage(const ImageUInt8Ptr& img) {
70 if (!img) {
71 throw std::invalid_argument("MorphologicalTreeFactory::createTreeOfShapes requires a non-null image.");
72 }
73 if (img->getNumRows() <= 0 || img->getNumColumns() <= 0 || img->getSize() <= 0) {
74 throw std::invalid_argument("MorphologicalTreeFactory::createTreeOfShapes requires a non-empty 2D image.");
75 }
76 }
77
78 public:
92 template <AltitudeValue T> [[nodiscard]] static ValuedMorphologicalTree<T> createMaxTree(ImagePtr<T> img, double radius = 1.5) {
93 validateComponentTreeImage(img, "MorphologicalTreeFactory::createMaxTree");
94 RegularGridAdjacency2D adjacency(img->getNumRows(), img->getNumColumns(), radius);
95 return detail::materializeNativeHierarchy<T>(
96 ComponentTreeBuilder(std::move(adjacency), true).build(img), std::nullopt,
97 detail::MaterializedVersionPolicy::PreserveLinkedConstruction);
98 }
99
111 validateComponentTreeImage(img, "MorphologicalTreeFactory::createMaxTree");
112 MMCFILTERS_CONTRACT_REQUIRE(adjacency.getNumRows() == img->getNumRows() && adjacency.getNumColumns() == img->getNumColumns(),
113 throw std::invalid_argument("Component-tree adjacency domain must match the input image domain."));
114 return detail::materializeNativeHierarchy<T>(
115 ComponentTreeBuilder(std::move(adjacency), true).build(img), std::nullopt,
116 detail::MaterializedVersionPolicy::PreserveLinkedConstruction);
117 }
118
132 template <AltitudeValue T> [[nodiscard]] static ValuedMorphologicalTree<T> createMinTree(ImagePtr<T> img, double radius = 1.5) {
133 validateComponentTreeImage(img, "MorphologicalTreeFactory::createMinTree");
134 RegularGridAdjacency2D adjacency(img->getNumRows(), img->getNumColumns(), radius);
135 return detail::materializeNativeHierarchy<T>(
136 ComponentTreeBuilder(std::move(adjacency), false).build(img), std::nullopt,
137 detail::MaterializedVersionPolicy::PreserveLinkedConstruction);
138 }
139
148 validateComponentTreeImage(img, "MorphologicalTreeFactory::createMinTree");
149 MMCFILTERS_CONTRACT_REQUIRE(adjacency.getNumRows() == img->getNumRows() && adjacency.getNumColumns() == img->getNumColumns(),
150 throw std::invalid_argument("Component-tree adjacency domain must match the input image domain."));
151 return detail::materializeNativeHierarchy<T>(
152 ComponentTreeBuilder(std::move(adjacency), false).build(img), std::nullopt,
153 detail::MaterializedVersionPolicy::PreserveLinkedConstruction);
154 }
155
162 template <AltitudeValue T>
165 return createExtremumResidualTreeByCTs(std::move(img), std::move(adjacency));
166 }
167
174 template <AltitudeValue T>
177 return createExtremumResidualTreeByCTs(std::move(img), radius);
178 }
179
191 template <AltitudeValue T>
194 ExtremumResidualTreeByCTsBuilder<T> builder(std::move(adjacency));
195 return detail::materializeNativeHierarchy<T>(builder.build(img));
196 }
197
205 template <AltitudeValue T>
208 RegularGridAdjacency2D adjacency(img->getNumRows(), img->getNumColumns(), radius);
209 return createExtremumResidualTreeByCTs(std::move(img), std::move(adjacency));
210 }
211
234 template <class Altitude = std::uint8_t>
236 validateTreeOfShapesImage(img);
237 TreeOfShapesBuilder builder(std::move(convention));
238 return detail::materializeNativeHierarchy<Altitude>(std::move(builder).build<Altitude>(img));
239 }
240
267 template <AltitudeValue T>
268 [[nodiscard]] static ValuedMorphologicalTree<T> createFromHigraParent(std::span<const NodeId> parent, std::span<const T> nodeAltitudes, int rows,
269 int columns, MorphologicalTreeKind kind,
270 std::optional<RegularGridAdjacency2D> adjacency = std::nullopt) {
271 auto imported = detail::adaptHigraHierarchy<T>(parent, nodeAltitudes, rows, columns, kind, std::move(adjacency));
272 return detail::materializeNativeHierarchy<T>(std::move(imported.hierarchy), imported.internalNodeOffset,
273 detail::MaterializedVersionPolicy::PreserveLinkedConstruction);
274 }
275};
276
277} // namespace mmcfilters
#define MMCFILTERS_CONTRACT_REQUIRE(condition,...)
Evaluates a caller precondition and its failure action only in checked builds.
Definition Contract.hpp:53
#define MMCFILTERS_CONTRACT_CHECKED_ONLY(...)
Executes validation statements only when defensive checks are enabled.
Definition Contract.hpp:67
std::shared_ptr< ImageUInt8 > ImageUInt8Ptr
Shared pointer to an 8-bit unsigned image.
Definition Image.hpp:260
MorphologicalTreeKind
Declared construction family of one morphological tree.
Builds max-trees and min-trees with union-find.
Public construction facade for all high-level morphological trees.
static ValuedMorphologicalTree< T > createExtremumResidualTreeByCTs(ImagePtr< T > img, RegularGridAdjacency2D adjacency)
Builds the extremum residual tree by synchronized component trees.
static ValuedMorphologicalTree< T > createExtremumResidualTree(ImagePtr< T > img, RegularGridAdjacency2D adjacency)
Builds the extremum residual tree through synchronized component trees.
static ValuedMorphologicalTree< T > createExtremumResidualTree(ImagePtr< T > img, double radius=1.5)
Builds the extremum residual tree through synchronized component trees with a radius adjacency.
static ValuedMorphologicalTree< T > createMaxTree(ImagePtr< T > img, double radius=1.5)
Builds a typed valuedTree max-tree from an image.
static ValuedMorphologicalTree< T > createFromHigraParent(std::span< const NodeId > parent, std::span< const T > nodeAltitudes, int rows, int columns, MorphologicalTreeKind kind, std::optional< RegularGridAdjacency2D > adjacency=std::nullopt)
Imports a static Higra parent/altitude hierarchy.
static ValuedMorphologicalTree< Altitude > createTreeOfShapes(ImageUInt8Ptr img, TopographicConvention convention={})
Builds a valued tree of shapes from an 8-bit image.
static ValuedMorphologicalTree< T > createExtremumResidualTreeByCTs(ImagePtr< T > img, double radius=1.5)
Builds the extremum residual tree with a radius adjacency.
static ValuedMorphologicalTree< T > createMinTree(ImagePtr< T > img, RegularGridAdjacency2D adjacency)
Builds a min-tree with an explicit regular-grid 2D adjacency.
static ValuedMorphologicalTree< T > createMinTree(ImagePtr< T > img, double radius=1.5)
Builds a typed valuedTree min-tree from an image.
static ValuedMorphologicalTree< T > createMaxTree(ImagePtr< T > img, RegularGridAdjacency2D adjacency)
Builds a max-tree with an explicit regular-grid 2D adjacency.
Immutable regular-grid 2D adjacency with allocation-free traversal.
int getNumColumns() const noexcept
Returns the number of columns in the attached grid domain.
int getNumRows() const noexcept
Returns the number of rows in the attached grid domain.
static void validateFiniteImageAltitudes(const ImagePtr< T > &image, const char *context)
Rejects non-finite floating-point pixels before using an image as altitude source.
Builds trees of shapes (ToS) using a union-find construction.
Owning result for one computed scalar attribute layout and buffer.
Complete discrete convention retained by a tree-of-shapes result.