3#include "DualMinMaxTreeIncrementalFilter.hpp"
4#include "../MorphologicalTreeFactory.hpp"
11namespace mmcfilters::adjust {
21enum class CasfComponentTreesAttribute {
83template<AltitudeValue T>
93 std::unique_ptr<attribute_computer_t> minAttributeComputer_;
94 std::unique_ptr<attribute_computer_t> maxAttributeComputer_;
95 std::unique_ptr<DualMinMaxTreeIncrementalFilter<T>> adjust_;
96 std::vector<double> minAttributeBuffer_;
97 std::vector<double> maxAttributeBuffer_;
98 std::vector<NodeId> pruneCandidateQueue_;
99 std::vector<NodeId> selectedPruneCandidates_;
100 CasfComponentTreesAttribute attribute_ = CasfComponentTreesAttribute::AREA;
107 static std::unique_ptr<attribute_computer_t> makeAttributeComputer(CasfComponentTreesAttribute
attribute) {
109 case CasfComponentTreesAttribute::AREA:
110 return std::make_unique<DynamicAreaAttributeComputer<T>>();
111 case CasfComponentTreesAttribute::BOUNDING_BOX_WIDTH:
112 return std::make_unique<DynamicBoundingBoxAttributeComputer<T>>(BoundingBoxMeasure::WIDTH);
113 case CasfComponentTreesAttribute::BOUNDING_BOX_HEIGHT:
114 return std::make_unique<DynamicBoundingBoxAttributeComputer<T>>(BoundingBoxMeasure::HEIGHT);
115 case CasfComponentTreesAttribute::BOUNDING_BOX_DIAGONAL:
116 return std::make_unique<DynamicBoundingBoxAttributeComputer<T>>(BoundingBoxMeasure::DIAGONAL_LENGTH);
118 throw std::runtime_error(
"Unknown CASF component-tree attribute.");
130 const std::vector<NodeId>& selectPruneCandidates(
const tree_t& tree,
const std::vector<double>&
attribute,
double threshold) {
131 pruneCandidateQueue_.clear();
132 selectedPruneCandidates_.clear();
137 return selectedPruneCandidates_;
140 pruneCandidateQueue_.push_back(
root);
143 while (
head < pruneCandidateQueue_.size()) {
151 selectedPruneCandidates_.push_back(
nodeId);
157 pruneCandidateQueue_.push_back(
childId);
162 return selectedPruneCandidates_;
174 const std::vector<NodeId>
maxCandidates = selectPruneCandidates(maxTree_, maxAttributeBuffer_,
threshold);
177 const std::vector<NodeId>
minCandidates = selectPruneCandidates(minTree_, minAttributeBuffer_,
threshold);
192 minAttributeComputer_(makeAttributeComputer(
attribute)),
193 maxAttributeComputer_(makeAttributeComputer(
attribute)),
196 throw std::invalid_argument(
"CasfComponentTrees requires a non-empty image.");
199 adjust_ = std::make_unique<DualMinMaxTreeIncrementalFilter<T>>(&minTree_, &maxTree_, adjacency_);
200 adjust_->setAttributeComputer(*minAttributeComputer_, *maxAttributeComputer_, minAttributeBuffer_, maxAttributeBuffer_);
201 minAttributeComputer_->computeAttribute(minTree_, minAttributeBuffer_);
202 maxAttributeComputer_->computeAttribute(maxTree_, maxAttributeBuffer_);
204 const size_t maxNodes =
static_cast<size_t>(
205 std::max(minTree_.topology().getNumInternalNodeSlots(), maxTree_.topology().getNumInternalNodeSlots()));
206 pruneCandidateQueue_.reserve(
maxNodes);
207 selectedPruneCandidates_.reserve(
maxNodes);
int NodeId
Node identifier type used throughout the project.
constexpr NodeId InvalidNode
Sentinel value used to denote an invalid node identifier.
Two-dimensional adjacency relation with configurable radius and efficient iteration.
Public construction facade for all high-level morphological trees.
Mutable morphological tree built directly on proper parts and dense node ids.
ChildrenRange getChildren(NodeId nodeId) const
Returns a fail-fast range over the direct children of nodeId.
bool isAlive(NodeId nodeId) const
Tests whether a node slot currently represents a live node.
bool isRoot(NodeId nodeId) const
Tests whether nodeId is the current root.
NodeId getRoot() const
Returns the current hierarchy root.
Wrapper pairing MorphologicalTree topology with an external altitude buffer.
ImagePtr< T > reconstructionImage() const
Reconstructs an image by assigning each proper part its owner altitude.
std::pair< std::vector< NodeId >, std::vector< T > > exportHigraHierarchy() const
Exports the current live rooted tree to a new compact Higra parent/altitude representation.
const MorphologicalTree & topology() const noexcept
Returns read-only access to the owned topology.
Connected alternating sequential filter on paired component trees.
image_ptr_t filter(const std::vector< double > &thresholds)
Runs the CASF on the threshold sequence and returns the filtered image.
std::pair< std::vector< NodeId >, std::vector< T > > exportMinTree() const
Exports the current min-tree as a compact static parent/altitude pair.
std::pair< std::vector< NodeId >, std::vector< T > > exportMaxTree() const
Exports the current max-tree as a compact static parent/altitude pair.
const tree_t & minTree() const noexcept
Returns the current min-tree state.
CasfComponentTreesAttribute attribute() const noexcept
Returns the increasing attribute configured for this CASF instance.
const tree_t & maxTree() const noexcept
Returns the current max-tree state.
CasfComponentTrees(image_ptr_t image, CasfComponentTreesAttribute attribute=CasfComponentTreesAttribute::AREA, double radius=1.5)
Initializes the CASF state from the input image and the chosen attribute.
Owning result for one computed scalar attribute layout and buffer.