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));
382 template <AltitudeValue T, std::
floating_po
int Real>
385 constexpr const char*
context =
"HierarchicalWatershedSaliency::compute";
388 detail::validateGlobalMonotoneAltitudeOrder(tree,
context);
400 HierarchyValuationPolicy::AllowLevelCollapse, HierarchyLevelConvention::EdgeSaliencyValue,
401 HierarchyConnectivityPolicy::AssumeConnected);
417 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 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.