morphoTreeAdjust 0.2__tar.gz → 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. morphotreeadjust-0.4.0/.gitignore +37 -0
  2. morphotreeadjust-0.4.0/.release-please-manifest.json +3 -0
  3. morphotreeadjust-0.4.0/CHANGELOG.md +9 -0
  4. morphotreeadjust-0.4.0/CMakeLists.txt +109 -0
  5. morphotreeadjust-0.4.0/PKG-INFO +240 -0
  6. morphotreeadjust-0.4.0/README.md +222 -0
  7. morphotreeadjust-0.4.0/cmake/AppleSdkFix.cmake +20 -0
  8. morphotreeadjust-0.4.0/dat/cameraman.pgm +1265 -1
  9. morphotreeadjust-0.4.0/dat/imgPassat.png +0 -0
  10. morphotreeadjust-0.4.0/dat/imgTeste.png +0 -0
  11. morphotreeadjust-0.4.0/dat/misc256/4.1.01.png +0 -0
  12. morphotreeadjust-0.4.0/dat/misc256/4.1.02.png +0 -0
  13. morphotreeadjust-0.4.0/dat/misc256/4.1.03.png +0 -0
  14. morphotreeadjust-0.4.0/dat/misc256/4.1.04.png +0 -0
  15. morphotreeadjust-0.4.0/dat/misc256/4.1.05.png +0 -0
  16. morphotreeadjust-0.4.0/dat/misc256/4.1.06.png +0 -0
  17. morphotreeadjust-0.4.0/dat/misc256/4.1.07.png +0 -0
  18. morphotreeadjust-0.4.0/dat/misc256/4.1.08.png +0 -0
  19. morphotreeadjust-0.4.0/dat/misc256/4.2.01.png +0 -0
  20. morphotreeadjust-0.4.0/dat/misc256/4.2.03.png +0 -0
  21. morphotreeadjust-0.4.0/dat/misc256/4.2.05.png +0 -0
  22. morphotreeadjust-0.4.0/dat/misc256/4.2.06.png +0 -0
  23. morphotreeadjust-0.4.0/dat/misc256/4.2.07.png +0 -0
  24. morphotreeadjust-0.4.0/dat/misc256/5.1.09.png +0 -0
  25. morphotreeadjust-0.4.0/dat/misc256/5.1.10.png +0 -0
  26. morphotreeadjust-0.4.0/dat/misc256/5.1.11.png +0 -0
  27. morphotreeadjust-0.4.0/dat/misc256/5.1.12.png +0 -0
  28. morphotreeadjust-0.4.0/dat/misc256/5.1.13.png +0 -0
  29. morphotreeadjust-0.4.0/dat/misc256/5.1.14.png +0 -0
  30. morphotreeadjust-0.4.0/dat/misc256/5.2.08.png +0 -0
  31. morphotreeadjust-0.4.0/dat/misc256/5.2.09.png +0 -0
  32. morphotreeadjust-0.4.0/dat/misc256/5.2.10.png +0 -0
  33. morphotreeadjust-0.4.0/dat/misc256/5.3.01.png +0 -0
  34. morphotreeadjust-0.4.0/dat/misc256/5.3.02.png +0 -0
  35. morphotreeadjust-0.4.0/dat/misc256/7.1.01.png +0 -0
  36. morphotreeadjust-0.4.0/dat/misc256/7.1.02.png +0 -0
  37. morphotreeadjust-0.4.0/dat/misc256/7.1.03.png +0 -0
  38. morphotreeadjust-0.4.0/dat/misc256/7.1.04.png +0 -0
  39. morphotreeadjust-0.4.0/dat/misc256/7.1.05.png +0 -0
  40. morphotreeadjust-0.4.0/dat/misc256/7.1.06.png +0 -0
  41. morphotreeadjust-0.4.0/dat/misc256/7.1.07.png +0 -0
  42. morphotreeadjust-0.4.0/dat/misc256/7.1.08.png +0 -0
  43. morphotreeadjust-0.4.0/dat/misc256/7.1.09.png +0 -0
  44. morphotreeadjust-0.4.0/dat/misc256/7.1.10.png +0 -0
  45. morphotreeadjust-0.4.0/dat/misc256/7.2.01.png +0 -0
  46. morphotreeadjust-0.4.0/dat/misc256/boat.512.png +0 -0
  47. morphotreeadjust-0.4.0/dat/misc256/gray21.512.png +0 -0
  48. morphotreeadjust-0.4.0/dat/misc256/house.png +0 -0
  49. morphotreeadjust-0.4.0/dat/misc256/ruler.512.png +0 -0
  50. morphotreeadjust-0.4.0/morphoTreeAdjust/include/AdjacencyRelation.hpp +444 -0
  51. morphotreeadjust-0.4.0/morphoTreeAdjust/include/AttributeComputer.hpp +819 -0
  52. morphotreeadjust-0.4.0/morphoTreeAdjust/include/Common.hpp +323 -0
  53. morphotreeadjust-0.4.0/morphoTreeAdjust/include/ComponentTreeCasf.hpp +203 -0
  54. morphotreeadjust-0.4.0/morphoTreeAdjust/include/DynamicComponentTree.hpp +1217 -0
  55. morphotreeadjust-0.4.0/morphoTreeAdjust/include/DynamicComponentTreeAdjustment.hpp +1402 -0
  56. morphotreeadjust-0.4.0/morphoTreeAdjust/include/DynamicComponentTreeAdjustmentInstrumented.hpp +1662 -0
  57. morphotreeadjust-0.4.0/morphoTreeAdjust/include/DynamicComponentTreeAdjustmentLeaf.hpp +948 -0
  58. morphotreeadjust-0.4.0/morphoTreeAdjust/include/MorphoTreeAdjust.hpp +22 -0
  59. morphotreeadjust-0.4.0/morphoTreeAdjust/morphoTreeAdjust.cpp +356 -0
  60. {morphotreeadjust-0.2 → morphotreeadjust-0.4.0}/morphoTreeAdjust/pybind/PybindUtils.hpp +3 -6
  61. {morphotreeadjust-0.2 → morphotreeadjust-0.4.0}/pybind11.cmake +1 -0
  62. morphotreeadjust-0.4.0/pyproject.toml +55 -0
  63. morphotreeadjust-0.4.0/python/morphoTreeAdjust/__init__.py +18 -0
  64. {morphotreeadjust-0.2 → morphotreeadjust-0.4.0}/python/morphoTreeAdjust/utils.py +183 -22
  65. morphotreeadjust-0.4.0/release-please-config.json +11 -0
  66. morphotreeadjust-0.2/CMakeLists.txt +0 -51
  67. morphotreeadjust-0.2/MANIFEST.in +0 -3
  68. morphotreeadjust-0.2/PKG-INFO +0 -27
  69. morphotreeadjust-0.2/README.md +0 -19
  70. morphotreeadjust-0.2/morphoTreeAdjust/include/AdjacencyRelation.hpp +0 -147
  71. morphotreeadjust-0.2/morphoTreeAdjust/include/Common.hpp +0 -1065
  72. morphotreeadjust-0.2/morphoTreeAdjust/include/ComponentTree.hpp +0 -778
  73. morphotreeadjust-0.2/morphoTreeAdjust/include/ComponentTree.tpp +0 -834
  74. morphotreeadjust-0.2/morphoTreeAdjust/include/ComponentTreeAdjustment.hpp +0 -440
  75. morphotreeadjust-0.2/morphoTreeAdjust/include/ComponentTreeAdjustmentByAnyNode.hpp +0 -71
  76. morphotreeadjust-0.2/morphoTreeAdjust/include/ComponentTreeAdjustmentByFlatzone.hpp +0 -64
  77. morphotreeadjust-0.2/morphoTreeAdjust/include/ComponentTreeAdjustmentByLeaf.hpp +0 -64
  78. morphotreeadjust-0.2/morphoTreeAdjust/include/ComponentTreeAdjustmentBySubtree.hpp +0 -203
  79. morphotreeadjust-0.2/morphoTreeAdjust/include/FlatZonesGraph.hpp +0 -499
  80. morphotreeadjust-0.2/morphoTreeAdjust/include/NodeCT.hpp +0 -502
  81. morphotreeadjust-0.2/morphoTreeAdjust/include/NodeCT.tpp +0 -58
  82. morphotreeadjust-0.2/morphoTreeAdjust/morphoTreeAdjust.cpp +0 -216
  83. morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTree.hpp +0 -49
  84. morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTree.tpp +0 -45
  85. morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTreeAdjustmentByAnyNode.cpp +0 -29
  86. morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTreeAdjustmentByAnyNode.hpp +0 -35
  87. morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTreeAdjustmentByFlatzone.cpp +0 -25
  88. morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTreeAdjustmentByFlatzone.hpp +0 -35
  89. morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTreeAdjustmentByLeaf.cpp +0 -35
  90. morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTreeAdjustmentByLeaf.hpp +0 -35
  91. morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTreeAdjustmentBySubtree.cpp +0 -35
  92. morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTreeAdjustmentBySubtree.hpp +0 -35
  93. morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindFlatZonesGraph.cpp +0 -10
  94. morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindFlatZonesGraph.hpp +0 -29
  95. morphotreeadjust-0.2/morphoTreeAdjust/src/AdjacencyRelation.cpp +0 -232
  96. morphotreeadjust-0.2/morphoTreeAdjust/src/ComponentTreeAdjustmentByAnyNode.cpp +0 -40
  97. morphotreeadjust-0.2/morphoTreeAdjust/src/ComponentTreeAdjustmentByFlatzone.cpp +0 -172
  98. morphotreeadjust-0.2/morphoTreeAdjust/src/ComponentTreeAdjustmentByLeaf.cpp +0 -157
  99. morphotreeadjust-0.2/morphoTreeAdjust/src/ComponentTreeAdjustmentBySubtree.cpp +0 -250
  100. morphotreeadjust-0.2/pyproject.toml +0 -9
  101. morphotreeadjust-0.2/python/morphoTreeAdjust/__init__.py +0 -13
  102. morphotreeadjust-0.2/python/morphoTreeAdjust.egg-info/PKG-INFO +0 -27
  103. morphotreeadjust-0.2/python/morphoTreeAdjust.egg-info/SOURCES.txt +0 -46
  104. morphotreeadjust-0.2/python/morphoTreeAdjust.egg-info/dependency_links.txt +0 -1
  105. morphotreeadjust-0.2/python/morphoTreeAdjust.egg-info/not-zip-safe +0 -1
  106. morphotreeadjust-0.2/python/morphoTreeAdjust.egg-info/requires.txt +0 -4
  107. morphotreeadjust-0.2/python/morphoTreeAdjust.egg-info/top_level.txt +0 -1
  108. morphotreeadjust-0.2/setup.cfg +0 -4
  109. morphotreeadjust-0.2/setup.py +0 -147
  110. {morphotreeadjust-0.2 → morphotreeadjust-0.4.0}/LICENSE +0 -0
@@ -0,0 +1,37 @@
1
+ /build/
2
+ /build-root-check/
3
+ /build-tests/
4
+ /benchmark/build*/
5
+ /dev-tools/build*/
6
+ /tests/build*/
7
+ /dist/
8
+ /.eggs/
9
+ /anaconda_projects/
10
+ /.vscode/
11
+
12
+ *.d
13
+ *.o
14
+ *.pyc
15
+ *.pyo
16
+ *.so
17
+ .DS_Store
18
+ Pipfile
19
+
20
+ __pycache__/
21
+ /dev-tools/**/__pycache__/
22
+
23
+ /morphoTreeAdjust.egg-info/
24
+ /python/morphoTreeAdjust.egg-info/
25
+ /python/casfInducedTree.egg-info/
26
+
27
+ /notebooks/.ipynb_checkpoints/
28
+ /notebooks/anaconda_projects/
29
+
30
+ /tests/dat/icdar_val
31
+ /tests/dat/icdar_resized
32
+ /tests/dat/icdar
33
+ /tests/dat/dataset-icdar2024_occluded
34
+ /tests/dat/icdar_1024p
35
+ /tests/dat/icdar_360p
36
+ /tests/dat/icdar_480p
37
+ /tests/dat/icdar_720p
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.3.0"
3
+ }
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [0.3.0] - 2026-04-15
6
+
7
+ ### Internal
8
+
9
+ - Bootstrap release-please from the current refactored repository state.
@@ -0,0 +1,109 @@
1
+ cmake_minimum_required(VERSION 3.15)
2
+ include("${CMAKE_CURRENT_LIST_DIR}/cmake/AppleSdkFix.cmake")
3
+
4
+ if(SKBUILD)
5
+ project(${SKBUILD_PROJECT_NAME} VERSION ${SKBUILD_PROJECT_VERSION} LANGUAGES CXX)
6
+ else()
7
+ project(MorphoTreeAdjust LANGUAGES CXX)
8
+ endif()
9
+ include(GNUInstallDirs)
10
+
11
+ # C++20 without compiler-specific extensions
12
+ set(CMAKE_CXX_STANDARD 20)
13
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
14
+ set(CMAKE_CXX_EXTENSIONS OFF)
15
+ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
16
+
17
+ # Define the default build type if none is specified
18
+ if(NOT CMAKE_BUILD_TYPE)
19
+ set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
20
+ endif()
21
+
22
+ if(MSVC)
23
+ add_compile_options(/W4)
24
+ else()
25
+ add_compile_options(-Wall -Wextra -Wpedantic)
26
+ endif()
27
+
28
+ # Helpful status messages
29
+ message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
30
+ message(STATUS "Compiler: ${CMAKE_CXX_COMPILER}")
31
+ message(STATUS "C++ Standard: C++${CMAKE_CXX_STANDARD}")
32
+
33
+ option(MTA_INSTALL_PUBLIC_CORE_HEADERS "Install only the public C++ core headers." ON)
34
+ if(SKBUILD)
35
+ set(MTA_PYTHON_PACKAGE_INSTALL_DIR "morphoTreeAdjust" CACHE PATH
36
+ "Install directory for the Python package relative to the install prefix.")
37
+ else()
38
+ set(MTA_PYTHON_PACKAGE_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/morphoTreeAdjust" CACHE PATH
39
+ "Install directory for the Python package relative to the install prefix.")
40
+ endif()
41
+
42
+ include_directories("${CMAKE_SOURCE_DIR}/python")
43
+
44
+ file (GLOB SOURCE_FILES "morphoTreeAdjust/src/*.cpp")
45
+ file (GLOB HEADER_FILES "morphoTreeAdjust/include/*.hpp" "morphoTreeAdjust/include/*.tpp")
46
+ set(PYTHON_FILES "morphoTreeAdjust/morphoTreeAdjust.cpp")
47
+ set(MTA_PYTHON_PACKAGE_FILES
48
+ "${CMAKE_CURRENT_SOURCE_DIR}/python/morphoTreeAdjust/__init__.py"
49
+ "${CMAKE_CURRENT_SOURCE_DIR}/python/morphoTreeAdjust/utils.py"
50
+ )
51
+
52
+ set(MTA_PUBLIC_CORE_HEADER_FILES
53
+ "${CMAKE_CURRENT_SOURCE_DIR}/morphoTreeAdjust/include/MorphoTreeAdjust.hpp"
54
+ "${CMAKE_CURRENT_SOURCE_DIR}/morphoTreeAdjust/include/AdjacencyRelation.hpp"
55
+ "${CMAKE_CURRENT_SOURCE_DIR}/morphoTreeAdjust/include/AttributeComputer.hpp"
56
+ "${CMAKE_CURRENT_SOURCE_DIR}/morphoTreeAdjust/include/Common.hpp"
57
+ "${CMAKE_CURRENT_SOURCE_DIR}/morphoTreeAdjust/include/ComponentTreeCasf.hpp"
58
+ "${CMAKE_CURRENT_SOURCE_DIR}/morphoTreeAdjust/include/DynamicComponentTree.hpp"
59
+ "${CMAKE_CURRENT_SOURCE_DIR}/morphoTreeAdjust/include/DynamicComponentTreeAdjustment.hpp"
60
+ "${CMAKE_CURRENT_SOURCE_DIR}/morphoTreeAdjust/include/DynamicComponentTreeAdjustmentLeaf.hpp"
61
+ )
62
+
63
+ # Set up such that XCode organizes the files
64
+ source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCE_FILES} ${HEADER_FILES} ${PYTHON_FILES} )
65
+
66
+ if(SKBUILD)
67
+ set(PYBIND11_FINDPYTHON ON)
68
+ find_package(pybind11 CONFIG REQUIRED)
69
+ else()
70
+ include(pybind11.cmake)
71
+ endif()
72
+ pybind11_add_module(morphoTreeAdjust
73
+ ${SOURCE_FILES}
74
+ ${HEADER_FILES}
75
+ ${PYTHON_FILES}
76
+ )
77
+
78
+ target_include_directories(morphoTreeAdjust PUBLIC
79
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/morphoTreeAdjust/include>
80
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/MorphoTreeAdjust>
81
+ )
82
+
83
+ target_link_libraries(morphoTreeAdjust PUBLIC)
84
+
85
+ message(STATUS
86
+ "MorphoTreeAdjust install surface:"
87
+ " python-package-dir=${MTA_PYTHON_PACKAGE_INSTALL_DIR}"
88
+ " public-core-headers=${MTA_INSTALL_PUBLIC_CORE_HEADERS}"
89
+ " transitional-headers=OFF"
90
+ )
91
+
92
+ install(TARGETS morphoTreeAdjust
93
+ COMPONENT python
94
+ LIBRARY DESTINATION "${MTA_PYTHON_PACKAGE_INSTALL_DIR}"
95
+ )
96
+
97
+ if(NOT SKBUILD)
98
+ install(FILES ${MTA_PYTHON_PACKAGE_FILES}
99
+ COMPONENT python
100
+ DESTINATION "${MTA_PYTHON_PACKAGE_INSTALL_DIR}"
101
+ )
102
+ endif()
103
+
104
+ if(MTA_INSTALL_PUBLIC_CORE_HEADERS)
105
+ install(FILES ${MTA_PUBLIC_CORE_HEADER_FILES}
106
+ COMPONENT core_headers
107
+ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/MorphoTreeAdjust"
108
+ )
109
+ endif()
@@ -0,0 +1,240 @@
1
+ Metadata-Version: 2.2
2
+ Name: morphoTreeAdjust
3
+ Version: 0.4.0
4
+ Summary: Core C++/Python implementation of MorphoTreeAdjust for dynamic component-tree adjustment.
5
+ Keywords: machine learning,morphological trees,mathematical morphology
6
+ Author-Email: Wonder Alexandre Luz Alves <worderalexandre@gmail.com>
7
+ License: GPL-3.0
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Science/Research
10
+ Classifier: Topic :: Scientific/Engineering :: Image Processing
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Programming Language :: C++
13
+ Project-URL: Homepage, https://github.com/wonderalexandre/MorphoTreeAdjust
14
+ Provides-Extra: viz
15
+ Requires-Dist: numpy; extra == "viz"
16
+ Requires-Dist: matplotlib; extra == "viz"
17
+ Description-Content-Type: text/markdown
18
+
19
+ # MorphoTreeAdjust
20
+
21
+ [![CI](https://github.com/wonderalexandre/MorphoTreeAdjust/actions/workflows/unit-tests.yml/badge.svg?branch=main)](https://github.com/wonderalexandre/MorphoTreeAdjust/actions/workflows/unit-tests.yml)
22
+
23
+ MorphoTreeAdjust provides the core C++ and Python implementation for dynamic
24
+ updates of component trees and connected alternating sequential filters (CASF).
25
+ The repository is organized around a small public API, example programs, and
26
+ developer tools for experiments, validation, and benchmarks.
27
+
28
+ ## Research Context
29
+
30
+ The repository is centered on dynamic update problems for component trees.
31
+
32
+ Let `f` be an image, and let `T_f^min` and `T_f^max` be the min-tree and
33
+ max-tree of `f`.
34
+
35
+ We set:
36
+
37
+ - `S`: a subtree in `T_f^min`
38
+ - `T_g^min`: the min-tree obtained after pruning `S` from `T_f^min`
39
+ - `g`: the image reconstructed from `T_g^min`
40
+ - `T_g^max`: the max-tree of `g`
41
+
42
+ The central question is:
43
+
44
+ > How to modify `T_f^max` to obtain `T_g^max`?
45
+
46
+ This is the basis for the dynamic primal/dual adjustment work and for CASF
47
+ implementations derived from those structures.
48
+
49
+ Related papers:
50
+
51
+ - Wonder Alves, Nicolas Passat, Dênnis José da Silva, Alexandre Morimitsu,
52
+ Ronaldo F. Hashimoto. *Efficient connected alternating sequential filters
53
+ based on component trees*. International Conference on Discrete Geometry and
54
+ Mathematical Morphology (DGMM), November 2025, Groningen, Netherlands.
55
+ [hal-05163556](https://hal.science/hal-05163556/)
56
+ - Wonder Alves, Nicolas Passat, Dênnis José da Silva, Alexandre Morimitsu,
57
+ Ronaldo F. Hashimoto. *Component tree: Update rather than rebuild*. Journal
58
+ of Mathematical Imaging and Vision (under review), 2026.
59
+
60
+ ## Quick Start
61
+
62
+ If you want the Python surface first, install it from PyPI:
63
+
64
+ ```sh
65
+ python -m pip install morphoTreeAdjust
66
+ ```
67
+
68
+ If you want the current repository version instead, install it from the
69
+ repository root:
70
+
71
+ ```sh
72
+ python -m pip install .
73
+ ```
74
+
75
+ The package build is `pyproject.toml`-driven and uses `scikit-build-core`
76
+ with CMake for the native extension.
77
+
78
+ Then use the public module:
79
+
80
+ ```python
81
+ import numpy as np
82
+ import morphoTreeAdjust as mta
83
+
84
+ image = np.array(
85
+ [
86
+ [4, 4, 2, 1],
87
+ [4, 3, 2, 1],
88
+ [5, 5, 2, 0],
89
+ [5, 6, 6, 0],
90
+ ],
91
+ dtype=np.uint8,
92
+ )
93
+
94
+ adj = mta.AdjacencyRelation(image.shape[0], image.shape[1], 1.5)
95
+ maxtree = mta.DynamicComponentTree(image, True, adj)
96
+ mintree = mta.DynamicComponentTree(image, False, adj)
97
+
98
+ adjust = mta.DynamicComponentTreeAdjustment(mintree, maxtree)
99
+ adjust.refreshAttributes()
100
+
101
+ casf = mta.ComponentTreeCasf(image, "area", adj)
102
+ filtered = casf.filter([1, 2])
103
+ ```
104
+
105
+ For a complete runnable script, see
106
+ [examples/core_python_api_example.py](./examples/core_python_api_example.py).
107
+
108
+ If you want a developer build with benchmarks and tools:
109
+
110
+ ```sh
111
+ cmake -S dev-tools -B ../build/MorphoTreeAdjust/dev-tools
112
+ cmake --build ../build/MorphoTreeAdjust/dev-tools
113
+ ```
114
+
115
+ If you want the install surface from the root project:
116
+
117
+ ```sh
118
+ cmake -S . -B ../build/MorphoTreeAdjust/install \
119
+ -DPYTHON_EXECUTABLE="$(python -c 'import sys; print(sys.executable)')"
120
+ cmake --build ../build/MorphoTreeAdjust/install
121
+ cmake --install ../build/MorphoTreeAdjust/install --prefix /tmp/mta-install
122
+ ```
123
+
124
+ `cmake --install` publishes:
125
+
126
+ - the Python package under `lib/morphoTreeAdjust`;
127
+ - the public C++ headers under `include/MorphoTreeAdjust` when
128
+ `MTA_INSTALL_PUBLIC_CORE_HEADERS=ON`.
129
+
130
+ ## Repository Layout
131
+
132
+ - Public C++ entrypoint:
133
+ [morphoTreeAdjust/include/MorphoTreeAdjust.hpp](./morphoTreeAdjust/include/MorphoTreeAdjust.hpp)
134
+ - Core headers:
135
+ [morphoTreeAdjust/include](./morphoTreeAdjust/include)
136
+ - Python bindings:
137
+ [morphoTreeAdjust/morphoTreeAdjust.cpp](./morphoTreeAdjust/morphoTreeAdjust.cpp)
138
+ - Examples:
139
+ [examples](./examples)
140
+ - Notebooks:
141
+ [notebooks](./notebooks)
142
+ - Documentation:
143
+ [docs](./docs)
144
+ - Developer tools and benchmarks:
145
+ [dev-tools](./dev-tools)
146
+
147
+ Recommended documentation entry points:
148
+
149
+ - [docs/README.md](./docs/README.md)
150
+ - [docs/public_core_api.md](./docs/public_core_api.md)
151
+ - [docs/tree_code_overview.md](./docs/tree_code_overview.md)
152
+
153
+ ## Developer Tools
154
+
155
+ Ad hoc debug binaries under `dev-tools/tools/debug_*.cpp` are excluded from the
156
+ default developer build. Enable them explicitly when needed:
157
+
158
+ ```sh
159
+ cmake -S dev-tools -B ../build/MorphoTreeAdjust/dev-tools \
160
+ -DMTA_BUILD_DEBUG_TOOLS=ON
161
+ cmake --build ../build/MorphoTreeAdjust/dev-tools
162
+ ```
163
+
164
+ Core benchmark example:
165
+
166
+ ```sh
167
+ ../build/MorphoTreeAdjust/dev-tools/benchmarks/jmiv2026_benchmark \
168
+ --repeat 5 --warmup 1 --json --no-validate image1.png image2.png
169
+ ```
170
+
171
+ ### `dynamic_casf_apply`
172
+
173
+ `dynamic_casf_apply` applies connected alternating sequential filters on
174
+ grayscale images and compares the dynamic implementations against the naive
175
+ rebuild-based baseline.
176
+
177
+ After building `dev-tools`, the executable is available at:
178
+
179
+ ```sh
180
+ ../build/MorphoTreeAdjust/dev-tools/tools/dynamic_casf_apply
181
+ ```
182
+
183
+ Usage:
184
+
185
+ ```sh
186
+ ../build/MorphoTreeAdjust/dev-tools/tools/dynamic_casf_apply \
187
+ [--mode dynamic-subtree|dynamic-leaf|naive|compare] \
188
+ [--attribute area|bbox_width|bbox_height|bbox_diagonal] \
189
+ [--radio-adj <radius>] \
190
+ [--iter-timing] \
191
+ [--no-output] \
192
+ <input.png> [<output.png>] <threshold1> [threshold2 ...]
193
+ ```
194
+
195
+ Modes:
196
+
197
+ - `dynamic-subtree`: CASF with dynamic subtree-based updates;
198
+ - `dynamic-leaf`: CASF with dynamic leaf-based updates;
199
+ - `naive`: CASF by rebuilding the trees at every threshold;
200
+ - `compare`: runs `dynamic-subtree`, `dynamic-leaf`, and `naive`, checks that
201
+ outputs match, and prints a timing summary.
202
+
203
+ Attributes:
204
+
205
+ - `area`
206
+ - `bbox_width`
207
+ - `bbox_height`
208
+ - `bbox_diagonal`
209
+
210
+ Examples:
211
+
212
+ ```sh
213
+ ../build/MorphoTreeAdjust/dev-tools/tools/dynamic_casf_apply \
214
+ --mode dynamic-subtree \
215
+ --attribute area \
216
+ cameraman.png cameraman_dynamic.png 64 128 256
217
+ ```
218
+
219
+ ```sh
220
+ ../build/MorphoTreeAdjust/dev-tools/tools/dynamic_casf_apply \
221
+ --mode compare \
222
+ --attribute bbox_diagonal \
223
+ --radio-adj 1.5 \
224
+ --no-output \
225
+ cameraman.png 64 128 256
226
+ ```
227
+
228
+ Timing output:
229
+
230
+ - `Initialization time`: dynamic setup cost before the threshold loop,
231
+ including adjacency creation, max-tree/min-tree construction, attribute
232
+ computer setup, initial attribute computation, and attribute binding;
233
+ - `Iteration time`: accumulated threshold-loop time, excluding initialization
234
+ and final reconstruction;
235
+ - `Reconstruction time`: final image reconstruction time;
236
+ - `Total time`: `Initialization time + Iteration time + Reconstruction time`.
237
+
238
+ For `naive`, `Total time` measures the full per-threshold rebuild-and-filter
239
+ work. In `compare` mode, the reported dynamic totals include initialization so
240
+ they are directly comparable to the naive baseline.
@@ -0,0 +1,222 @@
1
+ # MorphoTreeAdjust
2
+
3
+ [![CI](https://github.com/wonderalexandre/MorphoTreeAdjust/actions/workflows/unit-tests.yml/badge.svg?branch=main)](https://github.com/wonderalexandre/MorphoTreeAdjust/actions/workflows/unit-tests.yml)
4
+
5
+ MorphoTreeAdjust provides the core C++ and Python implementation for dynamic
6
+ updates of component trees and connected alternating sequential filters (CASF).
7
+ The repository is organized around a small public API, example programs, and
8
+ developer tools for experiments, validation, and benchmarks.
9
+
10
+ ## Research Context
11
+
12
+ The repository is centered on dynamic update problems for component trees.
13
+
14
+ Let `f` be an image, and let `T_f^min` and `T_f^max` be the min-tree and
15
+ max-tree of `f`.
16
+
17
+ We set:
18
+
19
+ - `S`: a subtree in `T_f^min`
20
+ - `T_g^min`: the min-tree obtained after pruning `S` from `T_f^min`
21
+ - `g`: the image reconstructed from `T_g^min`
22
+ - `T_g^max`: the max-tree of `g`
23
+
24
+ The central question is:
25
+
26
+ > How to modify `T_f^max` to obtain `T_g^max`?
27
+
28
+ This is the basis for the dynamic primal/dual adjustment work and for CASF
29
+ implementations derived from those structures.
30
+
31
+ Related papers:
32
+
33
+ - Wonder Alves, Nicolas Passat, Dênnis José da Silva, Alexandre Morimitsu,
34
+ Ronaldo F. Hashimoto. *Efficient connected alternating sequential filters
35
+ based on component trees*. International Conference on Discrete Geometry and
36
+ Mathematical Morphology (DGMM), November 2025, Groningen, Netherlands.
37
+ [hal-05163556](https://hal.science/hal-05163556/)
38
+ - Wonder Alves, Nicolas Passat, Dênnis José da Silva, Alexandre Morimitsu,
39
+ Ronaldo F. Hashimoto. *Component tree: Update rather than rebuild*. Journal
40
+ of Mathematical Imaging and Vision (under review), 2026.
41
+
42
+ ## Quick Start
43
+
44
+ If you want the Python surface first, install it from PyPI:
45
+
46
+ ```sh
47
+ python -m pip install morphoTreeAdjust
48
+ ```
49
+
50
+ If you want the current repository version instead, install it from the
51
+ repository root:
52
+
53
+ ```sh
54
+ python -m pip install .
55
+ ```
56
+
57
+ The package build is `pyproject.toml`-driven and uses `scikit-build-core`
58
+ with CMake for the native extension.
59
+
60
+ Then use the public module:
61
+
62
+ ```python
63
+ import numpy as np
64
+ import morphoTreeAdjust as mta
65
+
66
+ image = np.array(
67
+ [
68
+ [4, 4, 2, 1],
69
+ [4, 3, 2, 1],
70
+ [5, 5, 2, 0],
71
+ [5, 6, 6, 0],
72
+ ],
73
+ dtype=np.uint8,
74
+ )
75
+
76
+ adj = mta.AdjacencyRelation(image.shape[0], image.shape[1], 1.5)
77
+ maxtree = mta.DynamicComponentTree(image, True, adj)
78
+ mintree = mta.DynamicComponentTree(image, False, adj)
79
+
80
+ adjust = mta.DynamicComponentTreeAdjustment(mintree, maxtree)
81
+ adjust.refreshAttributes()
82
+
83
+ casf = mta.ComponentTreeCasf(image, "area", adj)
84
+ filtered = casf.filter([1, 2])
85
+ ```
86
+
87
+ For a complete runnable script, see
88
+ [examples/core_python_api_example.py](./examples/core_python_api_example.py).
89
+
90
+ If you want a developer build with benchmarks and tools:
91
+
92
+ ```sh
93
+ cmake -S dev-tools -B ../build/MorphoTreeAdjust/dev-tools
94
+ cmake --build ../build/MorphoTreeAdjust/dev-tools
95
+ ```
96
+
97
+ If you want the install surface from the root project:
98
+
99
+ ```sh
100
+ cmake -S . -B ../build/MorphoTreeAdjust/install \
101
+ -DPYTHON_EXECUTABLE="$(python -c 'import sys; print(sys.executable)')"
102
+ cmake --build ../build/MorphoTreeAdjust/install
103
+ cmake --install ../build/MorphoTreeAdjust/install --prefix /tmp/mta-install
104
+ ```
105
+
106
+ `cmake --install` publishes:
107
+
108
+ - the Python package under `lib/morphoTreeAdjust`;
109
+ - the public C++ headers under `include/MorphoTreeAdjust` when
110
+ `MTA_INSTALL_PUBLIC_CORE_HEADERS=ON`.
111
+
112
+ ## Repository Layout
113
+
114
+ - Public C++ entrypoint:
115
+ [morphoTreeAdjust/include/MorphoTreeAdjust.hpp](./morphoTreeAdjust/include/MorphoTreeAdjust.hpp)
116
+ - Core headers:
117
+ [morphoTreeAdjust/include](./morphoTreeAdjust/include)
118
+ - Python bindings:
119
+ [morphoTreeAdjust/morphoTreeAdjust.cpp](./morphoTreeAdjust/morphoTreeAdjust.cpp)
120
+ - Examples:
121
+ [examples](./examples)
122
+ - Notebooks:
123
+ [notebooks](./notebooks)
124
+ - Documentation:
125
+ [docs](./docs)
126
+ - Developer tools and benchmarks:
127
+ [dev-tools](./dev-tools)
128
+
129
+ Recommended documentation entry points:
130
+
131
+ - [docs/README.md](./docs/README.md)
132
+ - [docs/public_core_api.md](./docs/public_core_api.md)
133
+ - [docs/tree_code_overview.md](./docs/tree_code_overview.md)
134
+
135
+ ## Developer Tools
136
+
137
+ Ad hoc debug binaries under `dev-tools/tools/debug_*.cpp` are excluded from the
138
+ default developer build. Enable them explicitly when needed:
139
+
140
+ ```sh
141
+ cmake -S dev-tools -B ../build/MorphoTreeAdjust/dev-tools \
142
+ -DMTA_BUILD_DEBUG_TOOLS=ON
143
+ cmake --build ../build/MorphoTreeAdjust/dev-tools
144
+ ```
145
+
146
+ Core benchmark example:
147
+
148
+ ```sh
149
+ ../build/MorphoTreeAdjust/dev-tools/benchmarks/jmiv2026_benchmark \
150
+ --repeat 5 --warmup 1 --json --no-validate image1.png image2.png
151
+ ```
152
+
153
+ ### `dynamic_casf_apply`
154
+
155
+ `dynamic_casf_apply` applies connected alternating sequential filters on
156
+ grayscale images and compares the dynamic implementations against the naive
157
+ rebuild-based baseline.
158
+
159
+ After building `dev-tools`, the executable is available at:
160
+
161
+ ```sh
162
+ ../build/MorphoTreeAdjust/dev-tools/tools/dynamic_casf_apply
163
+ ```
164
+
165
+ Usage:
166
+
167
+ ```sh
168
+ ../build/MorphoTreeAdjust/dev-tools/tools/dynamic_casf_apply \
169
+ [--mode dynamic-subtree|dynamic-leaf|naive|compare] \
170
+ [--attribute area|bbox_width|bbox_height|bbox_diagonal] \
171
+ [--radio-adj <radius>] \
172
+ [--iter-timing] \
173
+ [--no-output] \
174
+ <input.png> [<output.png>] <threshold1> [threshold2 ...]
175
+ ```
176
+
177
+ Modes:
178
+
179
+ - `dynamic-subtree`: CASF with dynamic subtree-based updates;
180
+ - `dynamic-leaf`: CASF with dynamic leaf-based updates;
181
+ - `naive`: CASF by rebuilding the trees at every threshold;
182
+ - `compare`: runs `dynamic-subtree`, `dynamic-leaf`, and `naive`, checks that
183
+ outputs match, and prints a timing summary.
184
+
185
+ Attributes:
186
+
187
+ - `area`
188
+ - `bbox_width`
189
+ - `bbox_height`
190
+ - `bbox_diagonal`
191
+
192
+ Examples:
193
+
194
+ ```sh
195
+ ../build/MorphoTreeAdjust/dev-tools/tools/dynamic_casf_apply \
196
+ --mode dynamic-subtree \
197
+ --attribute area \
198
+ cameraman.png cameraman_dynamic.png 64 128 256
199
+ ```
200
+
201
+ ```sh
202
+ ../build/MorphoTreeAdjust/dev-tools/tools/dynamic_casf_apply \
203
+ --mode compare \
204
+ --attribute bbox_diagonal \
205
+ --radio-adj 1.5 \
206
+ --no-output \
207
+ cameraman.png 64 128 256
208
+ ```
209
+
210
+ Timing output:
211
+
212
+ - `Initialization time`: dynamic setup cost before the threshold loop,
213
+ including adjacency creation, max-tree/min-tree construction, attribute
214
+ computer setup, initial attribute computation, and attribute binding;
215
+ - `Iteration time`: accumulated threshold-loop time, excluding initialization
216
+ and final reconstruction;
217
+ - `Reconstruction time`: final image reconstruction time;
218
+ - `Total time`: `Initialization time + Iteration time + Reconstruction time`.
219
+
220
+ For `naive`, `Total time` measures the full per-threshold rebuild-and-filter
221
+ work. In `compare` mode, the reported dynamic totals include initialization so
222
+ they are directly comparable to the naive baseline.
@@ -0,0 +1,20 @@
1
+ if(APPLE AND CMAKE_OSX_SYSROOT AND NOT EXISTS "${CMAKE_OSX_SYSROOT}")
2
+ set(MTA_STALE_MACOS_SDK "${CMAKE_OSX_SYSROOT}")
3
+ execute_process(
4
+ COMMAND xcrun --sdk macosx --show-sdk-path
5
+ OUTPUT_VARIABLE MTA_ACTIVE_MACOS_SDK
6
+ OUTPUT_STRIP_TRAILING_WHITESPACE
7
+ ERROR_QUIET
8
+ )
9
+
10
+ if(EXISTS "${MTA_ACTIVE_MACOS_SDK}")
11
+ message(STATUS "Resetting stale CMAKE_OSX_SYSROOT from ${MTA_STALE_MACOS_SDK} to ${MTA_ACTIVE_MACOS_SDK}")
12
+ set(CMAKE_OSX_SYSROOT "${MTA_ACTIVE_MACOS_SDK}" CACHE PATH "The product will be built against the headers and libraries located inside the indicated SDK." FORCE)
13
+ else()
14
+ message(STATUS "Clearing stale CMAKE_OSX_SYSROOT ${MTA_STALE_MACOS_SDK}")
15
+ unset(CMAKE_OSX_SYSROOT CACHE)
16
+ endif()
17
+
18
+ unset(MTA_ACTIVE_MACOS_SDK)
19
+ unset(MTA_STALE_MACOS_SDK)
20
+ endif()