mmcfilters
Public API documentation
Loading...
Searching...
No Matches
DepthStableRegionComputer.hpp
1#pragma once
2
3#include "../attributes/AttributeComputation.hpp"
4#include "../trees/detail/TreeNeighborhood.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
157 throw std::invalid_argument("DepthStableRegionComputer requires a positive depth window radius."));
158 detail::TreeNeighborhood neighborhood(this->tree);
159 neighborhood.computeByDepth(depthWindowRadius);
160 this->ancestors = std::move(neighborhood.ancestors);
161 this->descendants = std::move(neighborhood.descendants);
162
163 auto attrAt = [this](NodeId node) -> Real { return this->getAttribute(node); };
164 this->variation = detail::computeVariationsFromNeighborhood<Real>(this->tree, this->ancestors, this->descendants, attrAt);
165 std::vector<uint8_t> selected = detail::selectStrictVariationMinima<Real>(this->tree, this->variation, this->ancestors, this->descendants, attrAt,
166 this->maxVariation, this->minAttr, this->maxAttr, this->num);
167 this->hasComputed_ = true;
168 return selected;
169 }
170
178 requireComputed("DepthStableRegionComputer::getVariation");
179 detail::validateStabilityNeighborhoodShape(this->tree, this->ancestors, this->descendants, "DepthStableRegionComputer::getVariation");
180 auto attrAt = [this](NodeId nodeId) -> Real { return this->getAttribute(nodeId); };
181 return detail::computeVariationValue<Real>(node, this->ancestors, this->descendants, attrAt);
182 }
183
191 if (attributeData() == nullptr) {
192 auto area = AttributeComputation::computeSingleTopologyAttribute<Real>(this->tree, Area);
193 this->ownedAttr_ = std::move(area.second);
194 }
195 const Real* data = attributeData();
196 if (data == nullptr) {
197 throw std::logic_error("DepthStableRegionComputer attribute storage is unavailable.");
198 }
199 return data[static_cast<std::size_t>(node)];
200 }
201
209 requireComputed("DepthStableRegionComputer::nodeWithMinimumVariationInWindow");
210 detail::validateStabilityNeighborhoodShape(this->tree, this->ancestors, this->descendants,
211 "DepthStableRegionComputer::nodeWithMinimumVariationInWindow");
212 return detail::nodeWithMinimumVariationInWindow<Real>(node, this->variation, this->ancestors, this->descendants);
213 }
214
222 requireComputed("DepthStableRegionComputer::ancestorInStabilityWindow");
223 return this->ancestors[static_cast<std::size_t>(node)];
224 }
225
233 requireComputed("DepthStableRegionComputer::descendantInStabilityWindow");
234 return this->descendants[static_cast<std::size_t>(node)];
235 }
236
242 [[nodiscard]] std::vector<Real>& getVariations() {
243 requireComputed("DepthStableRegionComputer::getVariations");
244 return variation;
245 }
246
252 [[nodiscard]] int numNodes() const {
253 requireComputed("DepthStableRegionComputer::numNodes");
254 return num;
255 }
256
262 void setMaxVariation(Real value) { this->maxVariation = value; }
263
269 void setMinAttribute(Real value) { this->minAttr = value; }
270
276 void setMaxAttribute(Real value) { this->maxAttr = value; }
277};
278
279} // 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.