3#include "DualMinMaxTreeIncrementalFilter.hpp"
4#include "../MorphologicalTreeFactory.hpp"
5#include "../../utils/Image.hpp"
12namespace mmcfilters::adjust {
22enum class CasfComponentTreesAttribute { Area, BoundingBoxWidth, BoundingBoxHeight, BoundingBoxDiagonal };
95 std::unique_ptr<attribute_computer_t> minAttributeComputer_;
97 std::unique_ptr<attribute_computer_t> maxAttributeComputer_;
99 std::unique_ptr<DualMinMaxTreeIncrementalFilter<T>> adjust_;
101 std::vector<double> minAttributeBuffer_;
103 std::vector<double> maxAttributeBuffer_;
105 std::vector<NodeId> pruneCandidateQueue_;
107 std::vector<NodeId> selectedPruneCandidates_;
109 CasfComponentTreesAttribute attribute_ = CasfComponentTreesAttribute::Area;
119 static std::unique_ptr<attribute_computer_t> makeAttributeComputer(CasfComponentTreesAttribute
attribute) {
121 case CasfComponentTreesAttribute::Area:
122 return std::make_unique<DynamicAreaAttributeComputer<T>>();
123 case CasfComponentTreesAttribute::BoundingBoxWidth:
124 return std::make_unique<DynamicBoundingBoxAttributeComputer<T>>(BoundingBoxMeasure::Width);
125 case CasfComponentTreesAttribute::BoundingBoxHeight:
126 return std::make_unique<DynamicBoundingBoxAttributeComputer<T>>(BoundingBoxMeasure::Height);
127 case CasfComponentTreesAttribute::BoundingBoxDiagonal:
128 return std::make_unique<DynamicBoundingBoxAttributeComputer<T>>(BoundingBoxMeasure::DiagonalLength);
130 throw std::runtime_error(
"Unknown CASF component-tree attribute.");
147 const std::vector<NodeId>& selectPruneCandidates(
const tree_t& tree,
const std::vector<double>&
attribute,
double threshold) {
148 pruneCandidateQueue_.clear();
149 selectedPruneCandidates_.clear();
154 return selectedPruneCandidates_;
157 pruneCandidateQueue_.push_back(root);
160 while (
head < pruneCandidateQueue_.size()) {
168 selectedPruneCandidates_.push_back(
nodeId);
174 pruneCandidateQueue_.push_back(
childId);
179 return selectedPruneCandidates_;
193 const std::vector<NodeId>
maxCandidates = selectPruneCandidates(maxTree_, maxAttributeBuffer_,
threshold);
196 const std::vector<NodeId>
minCandidates = selectPruneCandidates(minTree_, minAttributeBuffer_,
threshold);
210 minAttributeComputer_(makeAttributeComputer(
attribute)), maxAttributeComputer_(makeAttributeComputer(
attribute)), attribute_(
attribute) {
211 if (!
image ||
image->getNumRows() <= 0 ||
image->getNumColumns() <= 0 ||
image->getSize() <= 0) {
212 throw std::invalid_argument(
"CasfComponentTrees requires a non-empty image.");
215 adjust_ = std::make_unique<DualMinMaxTreeIncrementalFilter<T>>(&minTree_, &maxTree_, adjacency_);
216 adjust_->setAttributeComputer(*minAttributeComputer_, *maxAttributeComputer_, minAttributeBuffer_, maxAttributeBuffer_);
217 minAttributeComputer_->computeAttribute(minTree_, minAttributeBuffer_);
218 maxAttributeComputer_->computeAttribute(maxTree_, maxAttributeBuffer_);
220 const size_t maxNodes =
static_cast<size_t>(std::max(minTree_.topology().numInternalNodeSlots(), maxTree_.topology().numInternalNodeSlots()));
221 pruneCandidateQueue_.reserve(
maxNodes);
222 selectedPruneCandidates_.reserve(
maxNodes);
int NodeId
Node identifier type used throughout the project.
constexpr NodeId InvalidNode
Sentinel value used to denote an invalid node identifier.
Public construction facade for all high-level morphological trees.
Mutable connected-subset tree on a finite pixel domain.
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.
ChildrenRange children(NodeId nodeId) const
Returns a fail-fast range over the direct children of nodeId.
NodeId root() const
Returns the current hierarchy root.
Immutable regular-grid 2D adjacency with allocation-free traversal.
Wrapper pairing MorphologicalTree topology with an external altitude buffer.
const MorphologicalTree & topology() const noexcept
Returns read-only access to the owned topology.
ImagePtr< T > reconstructFromNodeAltitudes() const
Reconstructs an image by assigning each proper part its smallest-node 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.
Connected alternating sequential filter on paired component trees.
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.
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.
Owning result for one computed scalar attribute layout and buffer.