mmcfilters
Public API documentation
Loading...
Searching...
No Matches
MSERComputer.hpp
1#pragma once
2
3#include "../attributes/AttributeComputation.hpp"
4#include "../trees/detail/TreeStabilityNeighborhood.hpp"
5#include "../trees/detail/HierarchyCapabilityValidation.hpp"
6#include "../trees/MorphologicalTree.hpp"
7#include "../trees/TreeAltitudeAlgorithms.hpp"
8#include "../trees/ValuedMorphologicalTree.hpp"
9#include "../utils/Common.hpp"
10#include "../utils/Contract.hpp"
11#include "detail/VariationMeasure.hpp"
12
13#include <cassert>
14#include <cmath>
15#include <concepts>
16#include <limits>
17#include <memory>
18#include <span>
19#include <stdexcept>
20#include <string>
21#include <utility>
22#include <vector>
23
24namespace mmcfilters {
25
59template <AltitudeValue T, std::floating_point Real = float> class MSERComputer {
60 public:
63
64 private:
66 const ValuedMorphologicalTree<T>& valuedTree_;
68 const MorphologicalTree& tree;
70 const std::vector<T>& altitude_;
72 const Real* externalAttrMser_;
74 std::vector<Real> ownedAttrMser_;
76 Real maxVariation;
78 Real minAttr;
80 Real maxAttr;
82 int num = 0;
84 bool hasComputed_ = false;
86 std::vector<Real> variation;
88 std::vector<NodeId> ancestors;
90 std::vector<NodeId> descendants;
91
97 [[nodiscard]] const Real* attributeData() const noexcept { return ownedAttrMser_.empty() ? externalAttrMser_ : ownedAttrMser_.data(); }
98
104 void requireComputed(const char* context) const {
105 MMCFILTERS_CONTRACT_REQUIRE(hasComputed_, throw std::logic_error(std::string(context) + " requires computeMSER to run first."));
106 }
107
114 static void validateOwnedAttributeSize(const MorphologicalTree& tree, const std::vector<Real>& attr) {
115 MMCFILTERS_CONTRACT_REQUIRE(attr.size() == static_cast<std::size_t>(tree.numInternalNodeSlots()),
116 throw std::invalid_argument("MSERComputer attribute size must match the internal node slot count."));
117 }
118
126 MSERComputer(const ValuedMorphologicalTree<T>& valuedTree, const Real* attr_increasing, std::vector<Real> ownedAttr)
127 : valuedTree_(valuedTree), tree(valuedTree.topology()), altitude_(valuedTree.nodeAltitudes()), externalAttrMser_(attr_increasing),
128 ownedAttrMser_(std::move(ownedAttr)), maxVariation(Real{10}), minAttr(Real{0}),
129 maxAttr(static_cast<Real>(this->tree.numColumns() * this->tree.numRows())) {
130 TreeAltitudeAlgorithms::validateNodeAltitudeBufferShape(this->tree, std::span<const T>(this->altitude_));
131 detail::validateGlobalMonotoneAltitudeOrder(this->tree, "MSERComputer");
132 }
133
134 public:
143 validateOwnedAttributeSize(valuedTree.topology(), attr_increasing);
144 return std::move(attr_increasing);
145 }()) {}
146
157 attr_increasing != nullptr,
158 throw std::invalid_argument("MSERComputer requires a non-null attribute buffer for the raw-pointer constructor."));
159 }
160
167
169 MSERComputer(const MSERComputer&) = default;
176
181
191 detail::StabilityNeighborhood neighborhood =
192 detail::computeAltitudeStabilityNeighborhood(tree, std::span<const T>(altitude_), altitudeWindowRadius);
193 this->ancestors = std::move(neighborhood.ancestors);
194 this->descendants = std::move(neighborhood.descendants);
195
196 auto attrAt = [this](NodeId node) -> Real { return this->getAttrMSER(node); };
197 this->variation = detail::computeVariationsFromNeighborhood<Real>(this->tree, this->ancestors, this->descendants, attrAt);
198 std::vector<uint8_t> selected = detail::selectStrictVariationMinima<Real>(this->tree, this->variation, this->ancestors, this->descendants, attrAt,
199 this->maxVariation, this->minAttr, this->maxAttr, this->num);
200 this->hasComputed_ = true;
201 return selected;
202 }
203
211 requireComputed("MSERComputer::getVariation");
212 detail::validateStabilityNeighborhoodShape(this->tree, this->ancestors, this->descendants, "MSERComputer::getVariation");
213 auto attrAt = [this](NodeId nodeId) -> Real { return this->getAttrMSER(nodeId); };
214 return detail::computeVariationValue<Real>(node, this->ancestors, this->descendants, attrAt);
215 }
216
224 [[nodiscard]] Real getAttrMSER(NodeId node) {
225 if (attributeData() == nullptr) {
226 auto area = AttributeComputation::computeSingleAttribute<Real>(valuedTree_, Area);
227 ownedAttrMser_ = std::move(area.second);
228 }
229 const Real* data = attributeData();
230 if (data == nullptr) {
231 throw std::logic_error("MSERComputer attribute storage is unavailable.");
232 }
233 return data[node];
234 }
235
244 requireComputed("MSERComputer::nodeWithMinimumVariationInWindow");
245 detail::validateStabilityNeighborhoodShape(this->tree, this->ancestors, this->descendants, "MSERComputer::nodeWithMinimumVariationInWindow");
246 return detail::nodeWithMinimumVariationInWindow<Real>(node, this->variation, this->ancestors, this->descendants);
247 }
248
256 requireComputed("MSERComputer::ancestorInStabilityWindow");
257 return this->ancestors[static_cast<std::size_t>(node)];
258 }
259
267 requireComputed("MSERComputer::descendantInStabilityWindow");
268 return this->descendants[node];
269 }
270
276 [[nodiscard]] std::vector<Real>& getVariations() {
277 requireComputed("MSERComputer::getVariations");
278 return this->variation;
279 }
280
286 [[nodiscard]] int numNodes() {
287 requireComputed("MSERComputer::numNodes");
288 return this->num;
289 }
290
296 void setMaxVariation(Real maxVariation) { this->maxVariation = maxVariation; }
302 void setMinAttribute(Real minAttr) { this->minAttr = minAttr; }
308 void setMaxAttribute(Real maxAttr) { this->maxAttr = maxAttr; }
309};
310
311} // namespace mmcfilters
typename detail::AltitudeDifferenceSelector< T >::type AltitudeDifference
Arithmetic result type for altitude differences.
Definition Altitude.hpp:72
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 MSER-like nodes from a monotone increasing attribute defined on the hierarchy.
int numNodes()
Returns the number of nodes selected as MSER-like in the last run.
std::vector< uint8_t > computeMSER(AltitudeDifference< T > altitudeWindowRadius)
Computes the MSER indicator vector for an altitude-window radius.
MSERComputer(const ValuedMorphologicalTree< T > &valuedTree)
Creates an MSER detector that lazily falls back to AREA.
Real getVariation(NodeId node)
Returns the variation score currently associated with a node.
MSERComputer(const ValuedMorphologicalTree< T > &valuedTree, std::vector< Real > attr_increasing)
Creates an MSER detector backed by an owned attribute buffer.
NodeId descendantInStabilityWindow(NodeId node) const
Returns the descendant used in the current stability window.
MSERComputer(const MSERComputer &)=default
Copies the evaluator while preserving owned-buffer safety.
NodeId nodeWithMinimumVariationInWindow(NodeId node)
Returns the node with minimum variation among the current node and its altitude-window neighbours.
void setMaxVariation(Real maxVariation)
Sets the maximum accepted variation value.
void setMaxAttribute(Real maxAttr)
Sets the upper bound of the accepted attribute interval.
NodeId ancestorInStabilityWindow(NodeId node) const
Returns the ancestor used in the current stability window.
Real variation_value_type
Floating-point type used to store variation scores.
std::vector< Real > & getVariations()
Returns the current variation array, indexed by node slot.
MSERComputer(MSERComputer &&) noexcept=default
Moves the evaluator while preserving its referenced tree.
void setMinAttribute(Real minAttr)
Sets the lower bound of the accepted attribute interval.
Real getAttrMSER(NodeId node)
Returns the attribute used by the MSER stability measure, lazily computing AREA when no external buff...
MSERComputer(const ValuedMorphologicalTree< T > &valuedTree, const Real *attr_increasing)
Creates an MSER detector backed by a non-owning attribute view.
Mutable connected-subset tree on a finite pixel domain.
static void validateNodeAltitudeBufferShape(const MorphologicalTree &tree, std::span< const T > altitude)
Validates that an altitude buffer covers the dense internal-node domain.
Owning result for one computed scalar attribute layout and buffer.
std::vector< Real > second
Flat per-node attribute buffer indexed through first.