Library for connected image filtering based on morphological trees
Project description
MorphologicalAttributeFilters
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
NodeIdvalues; - direct proper-part ownership and image-domain topology queries;
- dynamic
MorphologicalTreeoperations 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
MorphologicalTreeuse cases andWeightedMorphologicalTreeworkflows 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
NodeIdvalues; - 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:
WeightedMorphologicalTreeowns the dense node-altitude buffer;WeightedMorphologicalTreeencapsulates its topology and exposes it only asconst 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 onWeightedMorphologicalTree; - attribute computation still runs first in the internal
MorphologicalTreenode-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, andgetProperParts; - safe public mutators,
pruneNodeandmergeNodeIntoParent, on both topology-only and weighted trees; - staged structural edits through
MorphologicalTree::edit()/TreeEditorandWeightedMorphologicalTree::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:
getRootgetAliveNodeIdsgetChildrengetProperPartsgetNodeParentgetPathBetweenNodesgetSmallestComponentgetConnectedComponentgetIteratorBreadthFirstTraversalgetNodeSubtree
Repository guide
Use this map to find the right entry point quickly:
- Core C++: mmcfilters/
- Python interface: pybinds/mmcfilters.cpp and python/
- Tests: unit-tests/
- Examples and notebooks: examples/ and notebooks/README.md
- Design notes: docs/editing-api.md and docs/contours.md
- Build and packaging: CMakeLists.txt and pyproject.toml
Release process
Releases are automated by GitHub Actions. For a production release:
- Make sure the
CIworkflow is green onmain. - Create and push a semantic version tag, for example
v0.1.26. - The
Releaseworkflow 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3dc4ecd0df66453706c57f91e14467f797b44d8bbf52847e4387cef9ddce2fab
|
|
| MD5 |
6d824849caf6d6d3cf5db6101cd493fe
|
|
| BLAKE2b-256 |
d4da86af5af40ca109677536ef955994ab73b243ed6450b54362f33fb724b9f4
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b6f3422aa4afb6c920b09d8eaa2fa73056004451ae01cdbfa51d6d99ed71a3be
|
|
| MD5 |
6b53327f53cc00dc7d662f4cf888e86f
|
|
| BLAKE2b-256 |
be6510088711961a5dcdc3d72a0adc6f9d7f00acf4bfd089ca3c64a100213bef
|
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
- Download URL: mmcfilters-1.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 687.7 kB
- Tags: CPython 3.13, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
32b6f4b34a41f8d9ec981acb5a7dc6a326facdfb4320543131321f4a2c6767d6
|
|
| MD5 |
325f8ea3bde7bedbb5f1b116a0684e05
|
|
| BLAKE2b-256 |
4d6a8ddb2394cb78d6dd963b4b2b3ba818fccc3bace1f2de2788af0fd77e27ec
|
File details
Details for the file mmcfilters-1.0.0-cp313-cp313-macosx_11_0_arm64.whl.
File metadata
- Download URL: mmcfilters-1.0.0-cp313-cp313-macosx_11_0_arm64.whl
- Upload date:
- Size: 588.0 kB
- Tags: CPython 3.13, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30a95c4a4bc47077703502dddb6d3802c981535b6664b95e34bb7fc14ab56f72
|
|
| MD5 |
557322d08ce23de247bf83adbdc08a75
|
|
| BLAKE2b-256 |
db57663ea8110224f590e3cd79a00e59c611f0ad270a1a89c47d8f48e15ccbc6
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5f4231ad448d9d220dd020e46e58d10b652ceedd0f259226eabe402cfd9c2bad
|
|
| MD5 |
073c205eabe91959de74a5c031e9bb58
|
|
| BLAKE2b-256 |
9f59fbefb43f892b8afc060d9214f0ddaa8cb49d67bfc6b7f13ad7b476d047c8
|
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
- Download URL: mmcfilters-1.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 687.4 kB
- Tags: CPython 3.12, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ee887273011b10431964fa6288492e7a9d549a852580bb10c187ccf872b30a00
|
|
| MD5 |
492d305f4e8b390a83c0353c0ea43014
|
|
| BLAKE2b-256 |
ebd5b6f6da7ba8b36223692334b1acc1085835f547db4d943ca3ccdb51ee0679
|
File details
Details for the file mmcfilters-1.0.0-cp312-cp312-macosx_11_0_arm64.whl.
File metadata
- Download URL: mmcfilters-1.0.0-cp312-cp312-macosx_11_0_arm64.whl
- Upload date:
- Size: 588.0 kB
- Tags: CPython 3.12, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9380f1ec2937ba36c3539c11ab6e78df9849d849672f3a3c8502a96e96a7226e
|
|
| MD5 |
e4f42cc754e05d2aa8771d528cd546c9
|
|
| BLAKE2b-256 |
7e0ffe3b3b78ccd95706f96797d44a54535f6e490b0cad19e1618314ea54a9f9
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d55b18b6c7272bf142b35bfb0bfa12891922313baaa2becff1565302f45da663
|
|
| MD5 |
975dbfaf9b12a1c4c7d360cd32be5379
|
|
| BLAKE2b-256 |
7af595189d718dff3bcf4ee776a838b37ca45127831a0d1be91375f13be410bc
|
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
- Download URL: mmcfilters-1.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 689.1 kB
- Tags: CPython 3.11, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cd11e7bc4ac4f49e2809b9d1e0e46e45486664563462d329bab1673270c944dd
|
|
| MD5 |
d3302477ec44b023cb4b3e450e8f2ec2
|
|
| BLAKE2b-256 |
081cd720dbb1bbd392f2af87c4c510a245f6a38702835e9bdd8c6e54ada2b202
|
File details
Details for the file mmcfilters-1.0.0-cp311-cp311-macosx_11_0_arm64.whl.
File metadata
- Download URL: mmcfilters-1.0.0-cp311-cp311-macosx_11_0_arm64.whl
- Upload date:
- Size: 586.3 kB
- Tags: CPython 3.11, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8eb02661ba6b84f385daf851794266b88b89d2a9cee14db1ffa6bf8c23704bb4
|
|
| MD5 |
6c6c79d43595a53718952d0acdcecab7
|
|
| BLAKE2b-256 |
b7c13e74c2237466b1923c76362660a1b84db4d5769302a0219e189b23851181
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
710b41a223ea6e25704a17ac2256d0e28e744eceb7fed6744dd395265aab433f
|
|
| MD5 |
92d241caf5bab34cbc3b351f8452f944
|
|
| BLAKE2b-256 |
d7b5ef0006e973994b3820411d9f93dfcc8c4d09396b5465e6a10f0459a43995
|
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
- Download URL: mmcfilters-1.0.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 687.4 kB
- Tags: CPython 3.10, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e9809802174cc54600b3ae0cd10b2efdd3be32552f7fcb7a00330d2fb6ce60df
|
|
| MD5 |
8b223c212c56ba614faca0a452fe2974
|
|
| BLAKE2b-256 |
6396ff2b92eb809f83e37e9874be3a9c3c301343862f4ceae48c76a261cb5213
|
File details
Details for the file mmcfilters-1.0.0-cp310-cp310-macosx_11_0_arm64.whl.
File metadata
- Download URL: mmcfilters-1.0.0-cp310-cp310-macosx_11_0_arm64.whl
- Upload date:
- Size: 584.5 kB
- Tags: CPython 3.10, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aae476f63a31564b85dce75b0510b9a8c1de1707d33031f62080bae0c237b561
|
|
| MD5 |
ae4d548b78e1982d9d9e2091b53586e1
|
|
| BLAKE2b-256 |
998afca70aea151b32460425c77a893326d278a7194ee4233cc7428f07973c46
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
551427ffe082014790d7289d702e5b5459254ca103772a7b52c38e88b1a24c45
|
|
| MD5 |
f3cde51923d528a7b6748fe26dd57f56
|
|
| BLAKE2b-256 |
22eb92eab63abda49ce53cbc1c1a7fdc72151fbe1324f3e1ba09c58b01d85be4
|
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
- Download URL: mmcfilters-1.0.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 687.6 kB
- Tags: CPython 3.9, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b32cbe4eb411cbb118c9e2462aa732eaed84b26daf2dc1e484ad7d8136ed67a1
|
|
| MD5 |
81b4a522ea44783ceb2c3357d1a00748
|
|
| BLAKE2b-256 |
b4f32b4ba0b235235c8773e11f400f45a4a32e18d4021bc2dd2f7fa86721367e
|
File details
Details for the file mmcfilters-1.0.0-cp39-cp39-macosx_11_0_arm64.whl.
File metadata
- Download URL: mmcfilters-1.0.0-cp39-cp39-macosx_11_0_arm64.whl
- Upload date:
- Size: 584.9 kB
- Tags: CPython 3.9, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e8c09b8be8618fed68e23dc4d8f81145ec4a49c5b30cf7cd066a9044c6b5d1a
|
|
| MD5 |
fde85fa96144f4fd369be6e30f8acad5
|
|
| BLAKE2b-256 |
7984682f3a3c500decb9c939cadc29d990512741648336af995492b18138aa60
|