Skip to main content

Library for connected image filtering based on morphological trees

Project description

MorphologicalAttributeFilters

CI Release

Project status: transitional research library.

This repository exists to support experiments around dynamic morphological trees, including component trees, trees of shapes, mutable tree topologies, converters, and incremental attribute computation. It is not intended to be a long-term general-purpose replacement for Higra, and this package may change substantially or stop existing in the future.

For general-purpose hierarchical image analysis, production workflows, and stable APIs, prefer Higra. Use this library when you specifically need dynamic tree operations, topology/proper-part experiments, interoperability with Higra-style hierarchies, or the incremental attribute framework provided here.

The current codebase is organised around a dense NodeId API, direct proper-part ownership, incremental attribute computation, and Python bindings for interactive work.

Relationship with Higra

Higra should be preferred for stable, general-purpose component-tree and hierarchical image-analysis workflows. This repository is mainly useful as an experimental bridge for cases where the current Higra model is not the most convenient fit, especially dynamic tree topology changes and project-specific incremental attribute machinery.

Current scope

This library currently concentrates code for:

  • building max-trees, min-trees, and trees of shapes from images;
  • representing trees with dense internal NodeId values;
  • direct proper-part ownership and image-domain topology queries;
  • dynamic MorphologicalTree operations and staged structural edits;
  • incremental computation of geometric, statistical, topological, moment-based, bit-quads, and max-distance attributes;
  • attribute filters, extinction values, contours, and Ultimate Attribute Opening;
  • a C++ core that is effectively header-only, plus a pybind11 module for Python.

Interoperability and converters

Although this project is not intended to replace Higra, it provides converters that make it useful as an experimental interoperability layer.

The library can:

  • build max-trees, min-trees, and trees of shapes directly from images;
  • import static Higra-style hierarchies through (parent, altitude) arrays;
  • preserve imported Higra node ids while the topology remains unedited;
  • export the current live tree back to a compact Higra-style representation;
  • move between topology-only MorphologicalTree use cases and WeightedMorphologicalTree workflows when explicit node altitudes are required;
  • prototype dynamic tree edits and incremental attributes here, then export the resulting hierarchy for use elsewhere.

Imported Higra node ids are preserved only while the topology is not edited. After edits, exportHigraHierarchy() creates a new compact hierarchy.

Installation

From PyPI:

pip install mmcfilters

From source:

cmake -S . -B build -DMMCFILTERS_BUILD_PYTHON=ON
cmake --build build

Installed C++ package:

find_package(mmcfilters CONFIG REQUIRED)
target_link_libraries(my_target PRIVATE mmcfilters::core)

To enable the regression suite or examples:

cmake -S . -B build \
  -DMMCFILTERS_BUILD_PYTHON=ON \
  -DMMCFILTERS_BUILD_TESTS=ON \
  -DMMCFILTERS_BUILD_EXAMPLES=ON
cmake --build build
ctest --test-dir build --output-on-failure

Quick Python example

import numpy as np
import mmcfilters

img = np.array(
    [
        [3, 3, 2, 2],
        [3, 4, 4, 2],
        [1, 4, 5, 2],
        [1, 1, 5, 0],
    ],
    dtype=np.uint8,
)

# radius=1.5 selects the 8-neighbourhood on a 2D square grid.
# Use radius=1.0 for 4-connectivity.
adjacency_radius = 1.5

# Case 1: build a topology-only max-tree for structural queries.
topology_tree = mmcfilters.MorphologicalTree.createMaxTree(
    img,
    radius=adjacency_radius,
)
root_node_id = topology_tree.getRoot()
root_children = topology_tree.getChildren(root_node_id)
root_direct_proper_parts = topology_tree.getProperParts(root_node_id)

# Case 2: inspect the component that owns one image pixel.
pixel_index = 10
pixel_component_id = topology_tree.getSmallestComponent(pixel_index)
pixel_component_pixels = list(topology_tree.connected_component_of(pixel_component_id))
pixel_component_mask = topology_tree.reconstructNode(pixel_component_id)

# Case 3: compute attributes that depend only on tree topology/support.
area_by_node = mmcfilters.Attribute.computeSingleAttribute(
    topology_tree,
    mmcfilters.Attribute.Type.AREA,
)

# Case 4: reuse the same topology as a weighted tree when node altitudes are required.
weighted_tree = mmcfilters.WeightedMorphologicalTree.createFromTopology(
    topology_tree,
    img,
)
max_dist_by_node = mmcfilters.Attribute.computeSingleAttribute(
    weighted_tree,
    mmcfilters.Attribute.Type.MAX_DIST,
)
reconstructed_image = weighted_tree.reconstructionImage()

# Case 5: export/import a Higra-style hierarchy for interoperability.
higra_parent, higra_altitude = weighted_tree.exportHigraHierarchy()
max_dist_by_higra = weighted_tree.project_node_values_to_exported_higra(
    max_dist_by_node,
    mmcfilters.Attribute.Type.MAX_DIST,
)
roundtrip_weighted_tree = mmcfilters.WeightedMorphologicalTree.createFromHigraParent(
    higra_parent,
    higra_altitude,
    img.shape[0],
    img.shape[1],
    mmcfilters.WeightedMorphologicalTree.MAX_TREE,
    radius=adjacency_radius,
)

Current MorphologicalTree boundary

MorphologicalTree currently provides:

  • a dynamic hierarchy over dense internal NodeId values;
  • direct ownership of proper parts;
  • structural traversal and safe local mutation operations;
  • optional adjacency metadata plus explicit image-domain dimensions.

Weighted quantities are intentionally outside the topology-only tree:

  • WeightedMorphologicalTree owns the dense node-altitude buffer;
  • WeightedMorphologicalTree encapsulates its topology and exposes it only as const MorphologicalTree&;
  • WeightedMorphologicalTree.createFromTopology(...) clones an existing topology and infers altitudes from an image, avoiding a second tree reconstruction;
  • image reconstruction, node residues, and Higra (parent, altitude) export live on WeightedMorphologicalTree;
  • attribute computation still runs first in the internal MorphologicalTree node-id space and is projected only at API boundaries when requested.

The editing API has three levels:

  • read-only topology queries such as getRoot, getAliveNodeIds, getChildren, and getProperParts;
  • safe public mutators, pruneNode and mergeNodeIntoParent, on both topology-only and weighted trees;
  • staged structural edits through MorphologicalTree::edit() / TreeEditor and WeightedMorphologicalTree::edit() / WeightedTreeEditor.

Low-level topology rewiring is not public API. Full connected-tree validation and weighted monotone-altitude validation run at editor commit() time. See docs/editing-api.md for the detailed contract.

NodeIdSpace::HIGRA, getNumHigraNodes(), and getHigraNodeId() refer only to the original Higra node-id domain preserved by createFromHigraParent. Image-built trees and trees edited after import do not expose that domain. exportHigraHierarchy() always creates a new compact Higra representation of the current live rooted tree. Use projectNodeValuesToExportedHigra() / project_node_values_to_exported_higra() to project node-indexed attribute buffers to that exported compact layout without reimporting the tree; each AttributeComputer supplies the unit-component values for the exported leaves.

The main public C++/Python surface is centred on:

  • getRoot
  • getAliveNodeIds
  • getChildren
  • getProperParts
  • getNodeParent
  • getPathBetweenNodes
  • getSmallestComponent
  • getConnectedComponent
  • getIteratorBreadthFirstTraversal
  • getNodeSubtree

Repository guide

Use this map to find the right entry point quickly:

Release process

Releases are automated by GitHub Actions. For a production release:

  1. Make sure the CI workflow is green on main.
  2. Create and push a semantic version tag, for example v0.1.26.
  3. The Release workflow builds the source distribution and platform wheels, validates the package metadata, and attaches the artifacts to a GitHub Release.

PyPI publication is intentionally manual. Download the release artifacts from the GitHub Release or from the Release workflow run, then upload them with:

python -m pip install --upgrade twine
python -m twine upload dist/*

Manual runs of the Release workflow also build downloadable artifacts without creating a GitHub Release.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mmcfilters-1.0.0.tar.gz (12.8 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

mmcfilters-1.0.0-cp313-cp313-win_amd64.whl (546.9 kB view details)

Uploaded CPython 3.13Windows x86-64

mmcfilters-1.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (687.7 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

mmcfilters-1.0.0-cp313-cp313-macosx_11_0_arm64.whl (588.0 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

mmcfilters-1.0.0-cp312-cp312-win_amd64.whl (546.8 kB view details)

Uploaded CPython 3.12Windows x86-64

mmcfilters-1.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (687.4 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

mmcfilters-1.0.0-cp312-cp312-macosx_11_0_arm64.whl (588.0 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

mmcfilters-1.0.0-cp311-cp311-win_amd64.whl (544.0 kB view details)

Uploaded CPython 3.11Windows x86-64

mmcfilters-1.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (689.1 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

mmcfilters-1.0.0-cp311-cp311-macosx_11_0_arm64.whl (586.3 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

mmcfilters-1.0.0-cp310-cp310-win_amd64.whl (543.6 kB view details)

Uploaded CPython 3.10Windows x86-64

mmcfilters-1.0.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (687.4 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

mmcfilters-1.0.0-cp310-cp310-macosx_11_0_arm64.whl (584.5 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

mmcfilters-1.0.0-cp39-cp39-win_amd64.whl (568.9 kB view details)

Uploaded CPython 3.9Windows x86-64

mmcfilters-1.0.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (687.6 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

mmcfilters-1.0.0-cp39-cp39-macosx_11_0_arm64.whl (584.9 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

File details

Details for the file mmcfilters-1.0.0.tar.gz.

File metadata

  • Download URL: mmcfilters-1.0.0.tar.gz
  • Upload date:
  • Size: 12.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for mmcfilters-1.0.0.tar.gz
Algorithm Hash digest
SHA256 3dc4ecd0df66453706c57f91e14467f797b44d8bbf52847e4387cef9ddce2fab
MD5 6d824849caf6d6d3cf5db6101cd493fe
BLAKE2b-256 d4da86af5af40ca109677536ef955994ab73b243ed6450b54362f33fb724b9f4

See more details on using hashes here.

File details

Details for the file mmcfilters-1.0.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: mmcfilters-1.0.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 546.9 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for mmcfilters-1.0.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 b6f3422aa4afb6c920b09d8eaa2fa73056004451ae01cdbfa51d6d99ed71a3be
MD5 6b53327f53cc00dc7d662f4cf888e86f
BLAKE2b-256 be6510088711961a5dcdc3d72a0adc6f9d7f00acf4bfd089ca3c64a100213bef

See more details on using hashes here.

File details

Details for the file mmcfilters-1.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for mmcfilters-1.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 32b6f4b34a41f8d9ec981acb5a7dc6a326facdfb4320543131321f4a2c6767d6
MD5 325f8ea3bde7bedbb5f1b116a0684e05
BLAKE2b-256 4d6a8ddb2394cb78d6dd963b4b2b3ba818fccc3bace1f2de2788af0fd77e27ec

See more details on using hashes here.

File details

Details for the file mmcfilters-1.0.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for mmcfilters-1.0.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 30a95c4a4bc47077703502dddb6d3802c981535b6664b95e34bb7fc14ab56f72
MD5 557322d08ce23de247bf83adbdc08a75
BLAKE2b-256 db57663ea8110224f590e3cd79a00e59c611f0ad270a1a89c47d8f48e15ccbc6

See more details on using hashes here.

File details

Details for the file mmcfilters-1.0.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: mmcfilters-1.0.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 546.8 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for mmcfilters-1.0.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 5f4231ad448d9d220dd020e46e58d10b652ceedd0f259226eabe402cfd9c2bad
MD5 073c205eabe91959de74a5c031e9bb58
BLAKE2b-256 9f59fbefb43f892b8afc060d9214f0ddaa8cb49d67bfc6b7f13ad7b476d047c8

See more details on using hashes here.

File details

Details for the file mmcfilters-1.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for mmcfilters-1.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ee887273011b10431964fa6288492e7a9d549a852580bb10c187ccf872b30a00
MD5 492d305f4e8b390a83c0353c0ea43014
BLAKE2b-256 ebd5b6f6da7ba8b36223692334b1acc1085835f547db4d943ca3ccdb51ee0679

See more details on using hashes here.

File details

Details for the file mmcfilters-1.0.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for mmcfilters-1.0.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9380f1ec2937ba36c3539c11ab6e78df9849d849672f3a3c8502a96e96a7226e
MD5 e4f42cc754e05d2aa8771d528cd546c9
BLAKE2b-256 7e0ffe3b3b78ccd95706f96797d44a54535f6e490b0cad19e1618314ea54a9f9

See more details on using hashes here.

File details

Details for the file mmcfilters-1.0.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: mmcfilters-1.0.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 544.0 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for mmcfilters-1.0.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 d55b18b6c7272bf142b35bfb0bfa12891922313baaa2becff1565302f45da663
MD5 975dbfaf9b12a1c4c7d360cd32be5379
BLAKE2b-256 7af595189d718dff3bcf4ee776a838b37ca45127831a0d1be91375f13be410bc

See more details on using hashes here.

File details

Details for the file mmcfilters-1.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for mmcfilters-1.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 cd11e7bc4ac4f49e2809b9d1e0e46e45486664563462d329bab1673270c944dd
MD5 d3302477ec44b023cb4b3e450e8f2ec2
BLAKE2b-256 081cd720dbb1bbd392f2af87c4c510a245f6a38702835e9bdd8c6e54ada2b202

See more details on using hashes here.

File details

Details for the file mmcfilters-1.0.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for mmcfilters-1.0.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8eb02661ba6b84f385daf851794266b88b89d2a9cee14db1ffa6bf8c23704bb4
MD5 6c6c79d43595a53718952d0acdcecab7
BLAKE2b-256 b7c13e74c2237466b1923c76362660a1b84db4d5769302a0219e189b23851181

See more details on using hashes here.

File details

Details for the file mmcfilters-1.0.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: mmcfilters-1.0.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 543.6 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for mmcfilters-1.0.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 710b41a223ea6e25704a17ac2256d0e28e744eceb7fed6744dd395265aab433f
MD5 92d241caf5bab34cbc3b351f8452f944
BLAKE2b-256 d7b5ef0006e973994b3820411d9f93dfcc8c4d09396b5465e6a10f0459a43995

See more details on using hashes here.

File details

Details for the file mmcfilters-1.0.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for mmcfilters-1.0.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 e9809802174cc54600b3ae0cd10b2efdd3be32552f7fcb7a00330d2fb6ce60df
MD5 8b223c212c56ba614faca0a452fe2974
BLAKE2b-256 6396ff2b92eb809f83e37e9874be3a9c3c301343862f4ceae48c76a261cb5213

See more details on using hashes here.

File details

Details for the file mmcfilters-1.0.0-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for mmcfilters-1.0.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 aae476f63a31564b85dce75b0510b9a8c1de1707d33031f62080bae0c237b561
MD5 ae4d548b78e1982d9d9e2091b53586e1
BLAKE2b-256 998afca70aea151b32460425c77a893326d278a7194ee4233cc7428f07973c46

See more details on using hashes here.

File details

Details for the file mmcfilters-1.0.0-cp39-cp39-win_amd64.whl.

File metadata

  • Download URL: mmcfilters-1.0.0-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 568.9 kB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for mmcfilters-1.0.0-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 551427ffe082014790d7289d702e5b5459254ca103772a7b52c38e88b1a24c45
MD5 f3cde51923d528a7b6748fe26dd57f56
BLAKE2b-256 22eb92eab63abda49ce53cbc1c1a7fdc72151fbe1324f3e1ba09c58b01d85be4

See more details on using hashes here.

File details

Details for the file mmcfilters-1.0.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for mmcfilters-1.0.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b32cbe4eb411cbb118c9e2462aa732eaed84b26daf2dc1e484ad7d8136ed67a1
MD5 81b4a522ea44783ceb2c3357d1a00748
BLAKE2b-256 b4f32b4ba0b235235c8773e11f400f45a4a32e18d4021bc2dd2f7fa86721367e

See more details on using hashes here.

File details

Details for the file mmcfilters-1.0.0-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for mmcfilters-1.0.0-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0e8c09b8be8618fed68e23dc4d8f81145ec4a49c5b30cf7cd066a9044c6b5d1a
MD5 fde85fa96144f4fd369be6e30f8acad5
BLAKE2b-256 7984682f3a3c500decb9c939cadc29d990512741648336af995492b18138aa60

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page