|
mmcfilters
Public API documentation
|
This guide documents the Higra-facing boundary of mmcfilters: importing a static hierarchy, preserving imported Higra node IDs, exporting the current tree, and projecting node attributes to exported layouts.
For the underlying tree model, see Morphological trees. For attribute-buffer layout, see Attributes.
The library exposes two distinct Higra-related domains:
| Domain | Created by | Edit-stable | Main use |
|---|---|---|---|
| Preserved imported Higra domain | createFromHigraParent(...) | No | Original imported node IDs |
| Exported compact Higra domain | exportHigraHierarchy() | Snapshot only | Current live tree export |
NodeIdSpace::Higra selects the original imported node IDs while that domain remains valid. Normal tree queries, filters, and contours use internal NodeIdSpace::MorphologicalTree indexing.
exportHigraHierarchy() always computes a new compact layout for the current live rooted tree. Use projectNodeValuesToExportedHigra(...) or Python project_node_values_to_exported_higra(...) when attributes must be aligned with that exported snapshot.
The compact Higra layout used by import and export is:
For an image domain with rows * columns pixels:
[0, rows * columns);[rows * columns, parent.size());Each pixel leaf represents one pixel. A tree node's proper part is the set of pixels mapped to that node; it may contain several pixels or be empty.
When exporting, pixel leaves are emitted in row-major order. Internal nodes are assigned compact node IDs from the live rooted tree. For max-trees and min-trees, the export order follows the tree altitude polarity with a deterministic post-order tie-breaker. Trees of shapes and other NodeAltitudeOrder::Unconstrained hierarchies use deterministic post-order directly. Consequently, every non-root internal node appears before its parent even when one branch increases in altitude and another decreases.
The exported altitude array has the same length as the exported parent array. Each pixel leaf receives the altitude of its smallest node.
This layout policy lives at the interoperability boundary. Import converts it to separate dense buffers for node parents and smallest nodes before generic tree materialization; MorphologicalTree does not parse Higra parent arrays. While the topology is unchanged, it retains only the affine external ID offset needed by the imported-ID queries below.
Use MorphologicalTreeFactory::createFromHigraParent(...) in C++:
C++ import is generic over the altitude type:
Python exposes the canonical 8-bit path:
Python altitude inputs must be integer sequences in [0, 255] or 1D C-contiguous np.uint8 arrays. C++ accepts any type satisfying the public AltitudeValue contract.
Max-tree and min-tree imports require adjacency metadata. In Python, pass radius; in C++, pass a RegularGridAdjacency2D. Tree-of-shapes imports can omit component-tree adjacency.
After import, the tree still uses the internal dense NodeId domain for normal tree operations. A preserved mapping from internal live nodes to the original Higra node IDs is available until the topology is edited:
For trees imported from the compact layout above, the internal slot associated with Higra internal node ID h starts as:
Do not rely on that arithmetic after edits. Safe public code should use getHigraNodeId(...) while the preserved domain is still valid.
Any topology mutation invalidates the preserved imported Higra domain. This includes safe mutators such as pruneNode(...) and mergeNodeIntoParent(...) and staged edit commits. After invalidation:
getNumHigraNodes() fails;NodeIdSpace::Higra attribute requests fail;getHigraNodeId(node) returns InvalidNode.Export still works after edits because it creates a new compact domain.
Attribute computation always runs internally in NodeIdSpace::MorphologicalTree. Projection to NodeIdSpace::Higra is an API-boundary step.
Use preserved Higra output space when a consumer needs rows indexed by the original imported node IDs:
Live internal-node rows receive the values computed in the internal MorphologicalTree node ID space. Rows for pixel leaves in the preserved imported Higra domain receive the same unit-component values used by compact Higra export.
Use exportHigraHierarchy() when a consumer needs the current live tree:
The exported layout is a fresh snapshot. It is valid for image-built trees, imported trees, and edited trees as long as the current topology is one rooted live component, no edit session is open, and the altitude buffer covers the internal node slots.
Dead internal slots are not exported. Export size is:
The exported parent and altitude arrays should be treated as a pair. If the tree is edited again, export again and reproject any attributes that must align with the new compact node IDs.
To align attributes with exportHigraHierarchy(), project a dense internal-node buffer:
Python exposes the same operation on ValuedMorphologicalTree:
For a single attribute:
The projection output follows the same [pixel leaves | live internal nodes] layout as the exported hierarchy. Internal-node rows are copied from the node-indexed input. Pixel rows are filled with unit-component values for the requested attributes.
Examples of values for a pixel leaf:
AREA: 1;MeanGrayLevel: the altitude of the smallest node;VOLUME: one pixel at the smallest node altitude;GrayLevelVariance, GrayLevelHeight, and MAX_DIST: 0;1.Projection fails if:
ValuedMorphologicalTreeView<T> became stale after topology mutation.A common interoperability round trip is:
area_exported and area_imported_space use the same compact node ID layout after the round trip. Both paths fill pixel rows with unit-component values.
NodeId, proper parts, altitude, and edits.