mmcfilters
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 "../utils/Contract.hpp"
8#include "detail/VariationMeasure.hpp"
9
10#include <concepts>
11#include <limits>
12#include <stdexcept>
13#include <string>
14#include <utility>
15#include <vector>
16
17namespace mmcfilters {
18
41template <std::floating_point Real = float> class DepthStableRegionComputer {
42 public:
45
46 private:
48 const MorphologicalTree& tree;
50 const Real* externalAttr_ = nullptr;
52 std::vector<Real> ownedAttr_;
54 Real maxVariation = Real{10};
56 Real minAttr = Real{0};
58 Real maxAttr;
60 int num = 0;
62 bool hasComputed_ = false;
64 std::vector<Real> variation;
66 std::vector<NodeId> ancestors;
68 std::vector<NodeId> descendants;
69
75 [[nodiscard]] const Real* attributeData() const noexcept { return ownedAttr_.empty() ? externalAttr_ : ownedAttr_.data(); }
76
82 void requireComputed(const char* context) const {
83 MMCFILTERS_CONTRACT_REQUIRE(hasComputed_, throw std::logic_error(std::string(context) + " requires computeByDepth to run first."));
84 }
85
92 static void validateOwnedAttributeSize(const MorphologicalTree& tree, const std::vector<Real>& attr) {
93 MMCFILTERS_CONTRACT_REQUIRE(attr.size() == static_cast<std::size_t>(tree.numInternalNodeSlots()),
94 throw std::invalid_argument("DepthStableRegionComputer attribute size must match the internal node slot count."));
95 }
96
104 DepthStableRegionComputer(const MorphologicalTree& tree, const Real* attr, std::vector<Real> ownedAttr)
105 : tree(tree), externalAttr_(attr), ownedAttr_(std::move(ownedAttr)),
106 maxAttr(static_cast<Real>(tree.numColumns() * tree.numRows())) {}
107
108 public:
115 DepthStableRegionComputer(const MorphologicalTree& tree, std::vector<Real> attr)
116 : DepthStableRegionComputer(tree, nullptr, [&]() {
117 validateOwnedAttributeSize(tree, attr);
118 return std::move(attr);
119 }()) {}
120
129 attr != nullptr,
130 throw std::invalid_argument("DepthStableRegionComputer requires a non-null attribute buffer for the raw-pointer constructor."));
131 }
132
139
148
156 detail::StabilityNeighborhood neighborhood = detail::computeDepthStabilityNeighborhood(this->tree, depthWindowRadius);
157 this->ancestors = std::move(neighborhood.ancestors);
158 this->descendants = std::move(neighborhood.descendants);
159
160 auto attrAt = [this](NodeId node) -> Real { return this->getAttribute(node); };
161 this->variation = detail::computeVariationsFromNeighborhood<Real>(this->tree, this->ancestors, this->descendants, attrAt);
162 std::vector<uint8_t> selected = detail::selectStrictVariationMinima<Real>(this->tree, this->variation, this->ancestors, this->descendants, attrAt,
163 this->maxVariation, this->minAttr, this->maxAttr, this->num);
164 this->hasComputed_ = true;
165 return selected;
166 }
167
175 requireComputed("DepthStableRegionComputer::getVariation");
176 detail::validateStabilityNeighborhoodShape(this->tree, this->ancestors, this->descendants, "DepthStableRegionComputer::getVariation");
177 auto attrAt = [this](NodeId nodeId) -> Real { return this->getAttribute(nodeId); };
178 return detail::computeVariationValue<Real>(node, this->ancestors, this->descendants, attrAt);
179 }
180
188 if (attributeData() == nullptr) {
189 auto area = AttributeComputation::computeSingleTopologyAttribute<Real>(this->tree, Area);
190 this->ownedAttr_ = std::move(area.second);
191 }
192 const Real* data = attributeData();
193 if (data == nullptr) {
194 throw std::logic_error("DepthStableRegionComputer attribute storage is unavailable.");
195 }
196 return data[static_cast<std::size_t>(node)];
197 }
198
206 requireComputed("DepthStableRegionComputer::nodeWithMinimumVariationInWindow");
207 detail::validateStabilityNeighborhoodShape(this->tree, this->ancestors, this->descendants,
208 "DepthStableRegionComputer::nodeWithMinimumVariationInWindow");
209 return detail::nodeWithMinimumVariationInWindow<Real>(node, this->variation, this->ancestors, this->descendants);
210 }
211
219 requireComputed("DepthStableRegionComputer::ancestorInStabilityWindow");
220 return this->ancestors[static_cast<std::size_t>(node)];
221 }
222
230 requireComputed("DepthStableRegionComputer::descendantInStabilityWindow");
231 return this->descendants[static_cast<std::size_t>(node)];
232 }
233
239 [[nodiscard]] std::vector<Real>& getVariations() {
240 requireComputed("DepthStableRegionComputer::getVariations");
241 return variation;
242 }
243
249 [[nodiscard]] int numNodes() const {
250 requireComputed("DepthStableRegionComputer::numNodes");
251 return num;
252 }
253
259 void setMaxVariation(Real value) { this->maxVariation = value; }
260
266 void setMinAttribute(Real value) { this->minAttr = value; }
267
273 void setMaxAttribute(Real value) { this->maxAttr = value; }
274};
275
276} // namespace mmcfilters
int NodeId
Node identifier type used throughout the project.
Definition Common.hpp:17
#define MMCFILTERS_CONTRACT_REQUIRE(condition,...)
Evaluates a caller precondition and its failure action only in checked builds.
Definition Contract.hpp:53
Detects stable regions from a topological depth window.
DepthStableRegionComputer(DepthStableRegionComputer &&) noexcept=default
Moves the evaluator while preserving its referenced tree.
void setMinAttribute(Real value)
Sets the lower bound of the accepted attribute interval.
std::vector< uint8_t > computeByDepth(int depthWindowRadius)
Computes the stable-region indicator vector for a positive depth-window radius.
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 numNodes() const
Returns the number of nodes selected in the last run.
DepthStableRegionComputer(const DepthStableRegionComputer &)=default
Copies the evaluator while preserving owned-buffer safety.
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.
NodeId ancestorInStabilityWindow(NodeId node) const
Returns the ancestor used in the current depth window.
void setMaxVariation(Real value)
Sets the maximum accepted variation value.
DepthStableRegionComputer(const MorphologicalTree &tree, std::vector< Real > attr)
Creates a detector backed by an owned increasing-attribute buffer.
Real variation_value_type
Floating-point type used to store variation scores.
DepthStableRegionComputer(const MorphologicalTree &tree)
Creates a detector that lazily computes topology-only AREA.
Real getAttribute(NodeId node)
Returns the increasing attribute used by the stability measure.
std::vector< Real > & getVariations()
Returns the current variation array, indexed by node slot.
Mutable connected-subset tree on a finite pixel domain.
Owning result for one computed scalar attribute layout and buffer.
std::vector< Real > second
Flat per-node attribute buffer indexed through first.