3#include "HierarchySaliencyMap.hpp"
4#include "../MorphologicalTreeFactory.hpp"
5#include "../TreeAltitudeAlgorithms.hpp"
6#include "../ValuedMorphologicalTreeView.hpp"
7#include "../detail/HierarchyCapabilityValidation.hpp"
54 std::vector<NodeId> parent_;
56 std::vector<int> size_;
64 explicit DisjointSet(
int count) : parent_(
static_cast<std::size_t
>(
count)), size_(
static_cast<std::size_t
>(
count), 1) {
65 std::iota(parent_.begin(), parent_.end(),
NodeId{0});
76 while (parent_[
static_cast<std::size_t
>(root)] != root) {
77 root = parent_[
static_cast<std::size_t
>(root)];
79 while (parent_[
static_cast<std::size_t
>(
id)] != id) {
80 const NodeId next = parent_[
static_cast<std::size_t
>(id)];
81 parent_[
static_cast<std::size_t
>(id)] = root;
100 if (size_[
static_cast<std::size_t
>(
lhs)] < size_[
static_cast<std::size_t
>(
rhs)]) {
103 parent_[
static_cast<std::size_t
>(
rhs)] =
lhs;
104 size_[
static_cast<std::size_t
>(
lhs)] += size_[
static_cast<std::size_t
>(
rhs)];
110 template <AltitudeValue T>
struct OrderedGraphEdge {
120 bool finestRegionEdge =
false;
122 std::size_t order = 0;
126 template <AltitudeValue T, std::
floating_po
int Real>
struct PersistenceEdge {
130 Real persistence = Real{0};
146 if (
lhs.finestRegionEdge !=
rhs.finestRegionEdge) {
147 return lhs.finestRegionEdge;
149 if (
lhs.altitude !=
rhs.altitude) {
150 if (nodeAltitudeOrder == NodeAltitudeOrder::Increasing) {
151 return rhs.altitude <
lhs.altitude;
153 return lhs.altitude <
rhs.altitude;
155 if (
lhs.source !=
rhs.source) {
156 return lhs.source <
rhs.source;
158 return lhs.target <
rhs.target;
174 template <std::
floating_po
int Real>
177 throw std::invalid_argument(std::string(
context) +
" requires one extinction slot per internal NodeId.");
180 const Real value =
leafExtinction[
static_cast<std::size_t
>(leaf)];
181 if (!std::isfinite(value) || value < Real{0}) {
182 throw std::invalid_argument(std::string(
context) +
" requires finite non-negative leaf extinction values.");
197 template <AltitudeValue T>
201 std::vector<OrderedGraphEdge<T>>
edges;
202 std::size_t order = 0;
211 throw std::runtime_error(std::string(
context) +
" could not find a live LCA for an adjacency edge.");
217 std::stable_sort(
edges.begin(),
edges.end(), [nodeAltitudeOrder](
const auto&
lhs,
const auto&
rhs) { return edgePrecedes(lhs, rhs, nodeAltitudeOrder); });
231 template <AltitudeValue T>
234 std::vector<OrderedGraphEdge<T>>
mst;
235 mst.reserve(
static_cast<std::size_t
>(std::max(0,
numVertices - 1)));
247 throw std::invalid_argument(std::string(
context) +
" requires a connected projection graph.");
266 template <AltitudeValue T, std::
floating_po
int Real>
275 throw std::invalid_argument(
"HierarchicalWatershedSaliency requires every component-tree leaf to own a proper part.");
308 template <AltitudeValue T, std::
floating_po
int Real>
313 if (lhs.persistence != rhs.persistence) {
314 return lhs.persistence < rhs.persistence;
316 return lhs.graphEdge.order <
rhs.graphEdge.order;
320 std::vector<NodeId> parent(
static_cast<std::size_t
>(numNodes),
InvalidNode);
322 std::vector<Real> altitude(
static_cast<std::size_t
>(numNodes), Real{0});
324 parent[
static_cast<std::size_t
>(pixel)] = pixel;
325 smallestNodeMap[
static_cast<std::size_t
>(pixel)] = pixel;
340 altitude[
static_cast<std::size_t
>(
nextNode)] =
edge.persistence;
350 std::span<const Real>(altitude), root, rows, columns, std::move(semantics));
378 template <AltitudeValue T, std::
floating_po
int Real>
381 constexpr const char*
context =
"HierarchicalWatershedSaliency::compute";
384 detail::validateGlobalMonotoneAltitudeOrder(tree,
context);
396 HierarchyValuationPolicy::AllowLevelCollapse, HierarchyLevelConvention::EdgeSaliencyValue,
397 HierarchyConnectivityPolicy::AssumeConnected);
413 template <AltitudeValue T, std::
floating_po
int Real>
constexpr NodeId InvalidNode
Sentinel value used to denote an invalid node identifier.
NodeAltitudeOrder
Global ordering constraint of node altitudes along parent-child arcs.
Builds Cousty-style hierarchical-watershed saliency from extinctions.
static EdgeSaliencyMap< Real > compute(const ValuedMorphologicalTreeView< T > &valuedTree, std::span< const Real > leafExtinction, const RegularGridAdjacency2D &adjacency)
Computes the full-graph extinction hierarchical-watershed saliency.
static EdgeSaliencyMap< int > computeRanked(const ValuedMorphologicalTreeView< T > &valuedTree, std::span< const Real > leafExtinction, const RegularGridAdjacency2D &adjacency)
Computes the canonical dense rank scale of compute.
static void validateHierarchyConnectivity(const MorphologicalTree &tree, const RegularGridAdjacency2D &adjacency, const char *context="HierarchySaliencyMapValidation::validateHierarchyConnectivity")
Validates that every hierarchy support is connected in adjacency.
static EdgeSaliencyMap< int > rankEdgeSaliencyMap(const EdgeSaliencyMap< Value > &edgeMap)
Densely ranks the values already present in an edge saliency map.
static EdgeSaliencyMap< Value > computeSaliencyEdgeMap(const MorphologicalTree &tree, const RegularGridAdjacency2D &adjacency, std::span< const Value > valuation, HierarchyValuationPolicy policy=HierarchyValuationPolicy::AllowLevelCollapse, HierarchyLevelConvention levelConvention=HierarchyLevelConvention::EdgeSaliencyValue, HierarchyConnectivityPolicy connectivityPolicy=HierarchyConnectivityPolicy::ValidateConnected)
Computes the formal edge-indexed saliency map induced by a valuation.
static ValuedMorphologicalTree< T > createFromNativeTopology(std::span< const NodeId > parent, std::span< const NodeId > smallestNodeMap, std::span< const T > nodeAltitudes, NodeId root, MorphologicalTreeSemantics semantics)
Imports a valued connected-subset tree from native buffers.
Mutable connected-subset tree on a finite pixel domain.
int numRows() const
Returns the number of rows in the regular 2D pixel domain.
ProperPartRange properPart(NodeId nodeId) const
Returns a fail-fast range over the pixels in the proper part of nodeId.
int numInternalNodeSlots() const
Returns the size of the dense internal-node id domain.
bool isAlive(NodeId nodeId) const
Tests whether a node slot currently represents a live node.
NodeAltitudeOrder nodeAltitudeOrder() const noexcept
Returns the global parent-to-child altitude ordering constraint.
int numPixels() const
Returns the cardinality of the pixel domain.
std::vector< NodeId > leaves() const
Returns all live leaf nodes in the current hierarchy.
NodeId smallestNode(PixelId pixel) const
Returns the inclusion-smallest node containing pixel.
NodeId lowestCommonAncestor(NodeId u, NodeId v) const
Returns the lowest common ancestor of u and v.
int numColumns() const
Returns the number of columns in the regular 2D pixel domain.
Immutable regular-grid 2D adjacency with allocation-free traversal.
ForwardNeighborIndexRange getForwardNeighborIndices(int row, int column) const
Returns the directed positive half of the neighbourhood.
static void validateMonotoneNodeAltitudes(const MorphologicalTree &tree, std::span< const T > altitude)
Validates the hierarchy's declared global altitude order.
static void validateFiniteAltitudeValues(std::span< const T > altitude, const char *context)
Rejects non-finite floating-point altitudes in a contiguous input range.
Owning result for one computed scalar attribute layout and buffer.
Immutable scientific interpretation attached to one morphological tree.
Records one adjacency shared by both construction polarities.