MorphologicalAttributeFilters
Public API documentation
Loading...
Searching...
No Matches
DepthStableRegionComputer.hpp
1#pragma once
2
3#include "../attributes/AttributeComputation.hpp"
4#include "../trees/detail/TreeStabilityNeighborhood.hpp"
5#include "../trees/MorphologicalTree.hpp"
6#include "../utils/Common.hpp"
7#include "detail/VariationMeasure.hpp"
8
9#include <concepts>
10#include <limits>
11#include <stdexcept>
12#include <utility>
13#include <vector>
14
15namespace mmcfilters {
16
39template<std::floating_point Real = float>
41public:
44
45private:
46 const MorphologicalTree& tree;
47 const Real* attrView_ = nullptr;
48 std::vector<Real> ownedAttr_;
49 Real maxVariation = Real{10};
50 Real minAttr = Real{0};
51 Real maxAttr;
52 int num = 0;
53 std::vector<Real> variation;
54 std::vector<NodeId> ascendants;
55 std::vector<NodeId> descendants;
56
57 static void validateOwnedAttributeSize(const MorphologicalTree& tree, const std::vector<Real>& attr) {
58 if (attr.size() != static_cast<std::size_t>(tree.getNumInternalNodeSlots())) {
59 throw std::invalid_argument("DepthStableRegionComputer attribute size must match the internal node slot count.");
60 }
61 }
62
63 DepthStableRegionComputer(const MorphologicalTree& tree, const Real* attr, std::vector<Real> ownedAttr)
64 : tree(tree),
65 attrView_(nullptr),
66 ownedAttr_(std::move(ownedAttr)),
67 maxAttr(static_cast<Real>(tree.getNumColsOfImage() * tree.getNumRowsOfImage())) {
68 this->attrView_ = this->ownedAttr_.empty() ? attr : this->ownedAttr_.data();
69 }
70
71public:
75 DepthStableRegionComputer(const MorphologicalTree& tree, std::vector<Real> attr)
76 : DepthStableRegionComputer(tree, nullptr, [&]() {
77 validateOwnedAttributeSize(tree, attr);
78 return std::move(attr);
79 }()) {}
80
85 : DepthStableRegionComputer(tree, attr, {}) {
86 if (attr == nullptr) {
87 throw std::invalid_argument("DepthStableRegionComputer requires a non-null attribute buffer for the raw-pointer constructor.");
88 }
89 }
90
96
100 [[nodiscard]] std::vector<uint8_t> computeByDepth(int depthDelta) {
101 detail::StabilityNeighborhood neighborhood =
102 detail::computeDepthStabilityNeighborhood(this->tree, depthDelta);
103 this->ascendants = std::move(neighborhood.ascendants);
104 this->descendants = std::move(neighborhood.descendants);
105
106 auto attrAt = [this](NodeId node) -> Real {
107 return this->getAttribute(node);
108 };
109 this->variation =
110 detail::computeVariationsFromNeighborhood<Real>(
111 this->tree,
112 this->ascendants,
113 this->descendants,
114 attrAt);
115 return detail::selectStrictVariationMinima<Real>(
116 this->tree,
117 this->variation,
118 this->ascendants,
119 this->descendants,
120 attrAt,
121 this->maxVariation,
122 this->minAttr,
123 this->maxAttr,
124 this->num);
125 }
126
131 detail::validateStabilityNeighborhoodShape(
132 this->tree,
133 this->ascendants,
134 this->descendants,
135 "DepthStableRegionComputer::getVariation");
136 if (this->variation.size() != static_cast<std::size_t>(this->tree.getNumInternalNodeSlots())) {
137 throw std::logic_error("DepthStableRegionComputer::getVariation requires computeByDepth to run first.");
138 }
139 auto attrAt = [this](NodeId nodeId) -> Real {
140 return this->getAttribute(nodeId);
141 };
142 return detail::computeVariationValue<Real>(
143 node,
144 this->ascendants,
145 this->descendants,
146 attrAt);
147 }
148
153 if (this->attrView_ == nullptr) {
154 auto area = AttributeComputation::computeSingleTopologyAttribute<Real>(this->tree, AREA);
155 this->ownedAttr_ = std::move(area.second);
156 this->attrView_ = this->ownedAttr_.data();
157 }
158 return this->attrView_[static_cast<std::size_t>(node)];
159 }
160
165 detail::validateStabilityNeighborhoodShape(
166 this->tree,
167 this->ascendants,
168 this->descendants,
169 "DepthStableRegionComputer::nodeWithMinimumVariationInWindow");
170 if (this->variation.size() != static_cast<std::size_t>(this->tree.getNumInternalNodeSlots())) {
171 throw std::logic_error("DepthStableRegionComputer::nodeWithMinimumVariationInWindow requires computeByDepth to run first.");
172 }
173 return detail::nodeWithMinimumVariationInWindow<Real>(
174 node,
175 this->variation,
176 this->ascendants,
177 this->descendants);
178 }
179
183 [[nodiscard]] NodeId ascendantInStabilityWindow(NodeId node) const { return this->ascendants[static_cast<std::size_t>(node)]; }
184
188 [[nodiscard]] NodeId descendantInStabilityWindow(NodeId node) const { return this->descendants[static_cast<std::size_t>(node)]; }
189
193 std::vector<Real>& getVariations() { return variation; }
194
198 [[nodiscard]] int getNumNodes() const { return num; }
199
203 void setMaxVariation(Real value) { this->maxVariation = value; }
204
208 void setMinAttribute(Real value) { this->minAttr = value; }
209
213 void setMaxAttribute(Real value) { this->maxAttr = value; }
214};
215
216} // namespace mmcfilters
int NodeId
Node identifier type used throughout the project.
Definition Common.hpp:17
Detects stable regions from a topological depth window.
void setMinAttribute(Real value)
Sets the lower bound of the accepted attribute interval.
NodeId nodeWithMinimumVariationInWindow(NodeId node) const
Returns the node with minimum variation in the depth window.
DepthStableRegionComputer(const MorphologicalTree &tree, const Real *attr)
Creates a detector backed by a non-owning attribute buffer.
int getNumNodes() const
Returns the number of nodes selected in the last run.
NodeId ascendantInStabilityWindow(NodeId node) const
Returns the ascendant used in the current depth window.
Real getVariation(NodeId node)
Returns the variation score currently associated with a node.
void setMaxAttribute(Real value)
Sets the upper bound of the accepted attribute interval.
NodeId descendantInStabilityWindow(NodeId node) const
Returns the descendant used in the current depth window.
void setMaxVariation(Real value)
Sets the maximum accepted variation value.
std::vector< uint8_t > computeByDepth(int depthDelta)
Computes the stable-region indicator vector for a positive depth delta.
DepthStableRegionComputer(const MorphologicalTree &tree, std::vector< Real > attr)
Creates a detector backed by an owned increasing-attribute buffer.
DepthStableRegionComputer(const MorphologicalTree &tree)
Creates a detector that lazily computes topology-only AREA.
Real getAttribute(NodeId node)
Returns the increasing attribute used by the criterion.
std::vector< Real > & getVariations()
Returns the current variation array, indexed by node slot.
Mutable morphological tree built directly on proper parts and dense node ids.
Owning result for one computed scalar attribute layout and buffer.
std::vector< Real > second
Flat per-node attribute buffer indexed through first.