3#include "../attributes/AttributeComputation.hpp"
4#include "../trees/detail/TreeNeighborhood.hpp"
5#include "../trees/MorphologicalTree.hpp"
6#include "../trees/TreeAltitudeAlgorithms.hpp"
7#include "../trees/ValuedMorphologicalTree.hpp"
8#include "../utils/Common.hpp"
9#include "../utils/Contract.hpp"
10#include "detail/VariationMeasure.hpp"
59template <AltitudeValue T, std::
floating_po
int Real =
float>
class MSERComputer {
70 const std::vector<T>& altitude_;
72 const Real* externalAttrMser_;
74 std::vector<Real> ownedAttrMser_;
84 bool hasComputed_ =
false;
86 std::vector<Real> variation;
88 std::vector<NodeId> ancestors;
90 std::vector<NodeId> descendants;
97 [[
nodiscard]]
const Real* attributeData()
const noexcept {
return ownedAttrMser_.empty() ? externalAttrMser_ : ownedAttrMser_.data(); }
104 void requireComputed(
const char*
context)
const {
114 static void validateOwnedAttributeSize(
const MorphologicalTree& tree,
const std::vector<Real>& attr) {
116 throw std::invalid_argument(
"MSERComputer attribute size must match the internal node slot count."));
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())) {
158 throw std::invalid_argument(
"MSERComputer requires a non-null attribute buffer for the raw-pointer constructor."));
191 if constexpr (std::is_floating_point_v<AltitudeDifference<T>>) {
193 throw std::invalid_argument(
"MSERComputer requires a finite altitude window radius."));
196 throw std::invalid_argument(
"MSERComputer requires a positive altitude window radius."));
200 this->descendants = std::move(
neighborhood.descendants);
203 this->variation = detail::computeVariationsFromNeighborhood<Real>(this->tree, this->ancestors, this->descendants,
attrAt);
204 std::vector<uint8_t>
selected = detail::selectStrictVariationMinima<Real>(this->tree, this->variation, this->ancestors, this->descendants,
attrAt,
205 this->maxVariation, this->minAttr, this->maxAttr, this->num);
206 this->hasComputed_ =
true;
217 requireComputed(
"MSERComputer::getVariation");
218 detail::validateStabilityNeighborhoodShape(this->tree, this->ancestors, this->descendants,
"MSERComputer::getVariation");
220 return detail::computeVariationValue<Real>(node, this->ancestors, this->descendants,
attrAt);
231 if (attributeData() ==
nullptr) {
232 auto area = AttributeComputation::computeSingleAttribute<Real>(valuedTree_, Area);
233 ownedAttrMser_ = std::move(area.second);
235 const Real* data = attributeData();
236 if (data ==
nullptr) {
237 throw std::logic_error(
"MSERComputer attribute storage is unavailable.");
250 requireComputed(
"MSERComputer::nodeWithMinimumVariationInWindow");
251 detail::validateStabilityNeighborhoodShape(this->tree, this->ancestors, this->descendants,
"MSERComputer::nodeWithMinimumVariationInWindow");
252 return detail::nodeWithMinimumVariationInWindow<Real>(node, this->variation, this->ancestors, this->descendants);
262 requireComputed(
"MSERComputer::ancestorInStabilityWindow");
263 return this->ancestors[
static_cast<std::size_t
>(node)];
273 requireComputed(
"MSERComputer::descendantInStabilityWindow");
274 return this->descendants[node];
283 requireComputed(
"MSERComputer::getVariations");
284 return this->variation;
293 requireComputed(
"MSERComputer::numNodes");
typename detail::AltitudeDifferenceSelector< T >::type AltitudeDifference
Arithmetic result type for altitude differences.
int NodeId
Node identifier type used throughout the project.
#define MMCFILTERS_CONTRACT_REQUIRE(condition,...)
Evaluates a caller precondition and its failure action only in checked builds.
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.
static void requireGlobalMonotoneAltitudeOrder(const MorphologicalTree &tree, const char *context)
Requires a declared globally monotone altitude order.
Owning result for one computed scalar attribute layout and buffer.