MorphologicalAttributeFilters
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/TreeKindValidation.hpp"
6#include "../trees/MorphologicalTree.hpp"
7#include "../trees/TreeAltitudeAlgorithms.hpp"
8#include "../trees/WeightedMorphologicalTree.hpp"
9#include "../utils/Common.hpp"
10#include "detail/VariationMeasure.hpp"
11
12#include <cassert>
13#include <cmath>
14#include <concepts>
15#include <limits>
16#include <memory>
17#include <span>
18#include <stdexcept>
19#include <utility>
20#include <vector>
21
22namespace mmcfilters {
23
55template<AltitudeValue T, std::floating_point Real = float>
57public:
60
61private:
62 const WeightedMorphologicalTree<T>& weighted_;
63 const MorphologicalTree& tree;
64 const std::vector<T>& altitude_;
65 const Real* attrMserView_;
66 std::vector<Real> ownedAttrMser_;
67 Real maxVariation;
68 Real minAttr;
69 Real maxAttr;
70 int num;
71 std::vector<Real> variation;
72 std::vector<NodeId> ascendants;
73 std::vector<NodeId> descendants;
74
75 static void validateOwnedAttributeSize(const MorphologicalTree& tree, const std::vector<Real>& attr) {
76 if (attr.size() != static_cast<std::size_t>(tree.getNumInternalNodeSlots())) {
77 throw std::invalid_argument("MSERComputer attribute size must match the internal node slot count.");
78 }
79 }
80
82 : weighted_(weighted),
83 tree(weighted.topology()),
84 altitude_(weighted.getAltitudeBuffer()),
85 attrMserView_(nullptr),
86 ownedAttrMser_(std::move(ownedAttr)),
87 maxVariation(Real{10}),
88 minAttr(Real{0}),
89 maxAttr(static_cast<Real>(this->tree.getNumColsOfImage() * this->tree.getNumRowsOfImage())) {
90 TreeAltitudeAlgorithms::validateAltitudeBufferShape(this->tree, std::span<const T>(this->altitude_));
91 detail::validateComponentTreeKind(this->tree, "MSERComputer");
92 this->attrMserView_ = this->ownedAttrMser_.empty() ? attr_increasing : this->ownedAttrMser_.data();
93 }
94
95public:
100 : MSERComputer(weighted, nullptr, [&]() {
101 validateOwnedAttributeSize(weighted.topology(), attr_increasing);
102 return std::move(attr_increasing);
103 }()) {}
104
112 if (attr_increasing == nullptr) {
113 throw std::invalid_argument("MSERComputer requires a non-null attribute buffer for the raw-pointer constructor.");
114 }
115 }
116
122
123 ~MSERComputer() = default;
124
131 [[nodiscard]] std::vector<uint8_t> computeMSER(AltitudeDiff<T> delta){
132 detail::StabilityNeighborhood neighborhood =
133 detail::computeAltitudeStabilityNeighborhood(
134 tree,
135 std::span<const T>(altitude_),
136 delta);
137 this->ascendants = std::move(neighborhood.ascendants);
138 this->descendants = std::move(neighborhood.descendants);
139
140 auto attrAt = [this](NodeId node) -> Real {
141 return this->getAttrMSER(node);
142 };
143 this->variation =
144 detail::computeVariationsFromNeighborhood<Real>(
145 this->tree,
146 this->ascendants,
147 this->descendants,
148 attrAt);
149 return detail::selectStrictVariationMinima<Real>(
150 this->tree,
151 this->variation,
152 this->ascendants,
153 this->descendants,
154 attrAt,
155 this->maxVariation,
156 this->minAttr,
157 this->maxAttr,
158 this->num);
159 }
160
161
166 detail::validateStabilityNeighborhoodShape(
167 this->tree,
168 this->ascendants,
169 this->descendants,
170 "MSERComputer::getVariation");
171 if (this->variation.size() != static_cast<std::size_t>(this->tree.getNumInternalNodeSlots())) {
172 throw std::logic_error("MSERComputer::getVariation requires computeMSER to run first.");
173 }
174 auto attrAt = [this](NodeId nodeId) -> Real {
175 return this->getAttrMSER(nodeId);
176 };
177 return detail::computeVariationValue<Real>(
178 node,
179 this->ascendants,
180 this->descendants,
181 attrAt);
182 }
183
189 if(attrMserView_ == nullptr) {
190 auto area = AttributeComputation::computeSingleAttribute<Real>(weighted_, AREA);
191 ownedAttrMser_ = std::move(area.second);
192 attrMserView_ = ownedAttrMser_.data();
193 }
194 if(attrMserView_ == nullptr)
195 return Real{0};
196 else
197 return this->attrMserView_[node];
198 }
199
205 detail::validateStabilityNeighborhoodShape(
206 this->tree,
207 this->ascendants,
208 this->descendants,
209 "MSERComputer::nodeWithMinimumVariationInWindow");
210 if (this->variation.size() != static_cast<std::size_t>(this->tree.getNumInternalNodeSlots())) {
211 throw std::logic_error("MSERComputer::nodeWithMinimumVariationInWindow requires computeMSER to run first.");
212 }
213 return detail::nodeWithMinimumVariationInWindow<Real>(
214 node,
215 this->variation,
216 this->ascendants,
217 this->descendants);
218 }
219
223 [[nodiscard]] NodeId ascendantInStabilityWindow(NodeId node) const { return this->ascendants[node];}
227 [[nodiscard]] NodeId descendantInStabilityWindow(NodeId node) const { return descendants[node];}
231 std::vector<Real>& getVariations() { return variation; }
235 [[nodiscard]] int getNumNodes() {return num;}
239 void setMaxVariation(Real maxVariation) { this->maxVariation = maxVariation; }
243 void setMinAttribute(Real minAttr) { this->minAttr = minAttr; }
247 void setMaxAttribute(Real maxAttr) { this->maxAttr = maxAttr; }
248};
249
250
251} // namespace mmcfilters
int NodeId
Node identifier type used throughout the project.
Definition Common.hpp:17
Detects MSER-like nodes from a monotone increasing attribute defined on the hierarchy.
MSERComputer(const WeightedMorphologicalTree< T > &weighted)
Creates an MSER detector that lazily falls back to AREA.
int getNumNodes()
Returns the number of nodes selected as MSER-like in the last run.
MSERComputer(const WeightedMorphologicalTree< T > &weighted, const Real *attr_increasing)
Creates an MSER detector backed by a non-owning attribute view.
Real getVariation(NodeId node)
Returns the variation score currently associated with a node.
std::vector< uint8_t > computeMSER(AltitudeDiff< T > delta)
Computes the MSER indicator vector for the given delta.
NodeId descendantInStabilityWindow(NodeId node) const
Returns the descendant used in the current stability window.
MSERComputer(const WeightedMorphologicalTree< T > &weighted, std::vector< Real > attr_increasing)
Creates an MSER detector backed by an owned attribute buffer.
NodeId nodeWithMinimumVariationInWindow(NodeId node)
Returns the node with minimum variation among the current node and its delta-linked 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 ascendantInStabilityWindow(NodeId node) const
Returns the ascendant used in the current stability window.
std::vector< Real > & getVariations()
Returns the current variation array, indexed by node slot.
void setMinAttribute(Real minAttr)
Sets the lower bound of the accepted attribute interval.
Real getAttrMSER(NodeId node)
Returns the attribute used by the MSER criterion, lazily computing AREA when no external buffer has b...
Mutable morphological tree built directly on proper parts and dense node ids.
int getNumInternalNodeSlots() const
Returns the size of the dense internal-node id domain.
static void validateAltitudeBufferShape(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.