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.
- morphotreeadjust-0.4.0/.gitignore +37 -0
- morphotreeadjust-0.4.0/.release-please-manifest.json +3 -0
- morphotreeadjust-0.4.0/CHANGELOG.md +9 -0
- morphotreeadjust-0.4.0/CMakeLists.txt +109 -0
- morphotreeadjust-0.4.0/PKG-INFO +240 -0
- morphotreeadjust-0.4.0/README.md +222 -0
- morphotreeadjust-0.4.0/cmake/AppleSdkFix.cmake +20 -0
- morphotreeadjust-0.4.0/dat/cameraman.pgm +1265 -1
- morphotreeadjust-0.4.0/dat/imgPassat.png +0 -0
- morphotreeadjust-0.4.0/dat/imgTeste.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/4.1.01.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/4.1.02.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/4.1.03.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/4.1.04.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/4.1.05.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/4.1.06.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/4.1.07.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/4.1.08.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/4.2.01.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/4.2.03.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/4.2.05.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/4.2.06.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/4.2.07.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/5.1.09.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/5.1.10.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/5.1.11.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/5.1.12.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/5.1.13.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/5.1.14.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/5.2.08.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/5.2.09.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/5.2.10.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/5.3.01.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/5.3.02.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/7.1.01.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/7.1.02.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/7.1.03.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/7.1.04.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/7.1.05.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/7.1.06.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/7.1.07.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/7.1.08.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/7.1.09.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/7.1.10.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/7.2.01.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/boat.512.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/gray21.512.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/house.png +0 -0
- morphotreeadjust-0.4.0/dat/misc256/ruler.512.png +0 -0
- morphotreeadjust-0.4.0/morphoTreeAdjust/include/AdjacencyRelation.hpp +444 -0
- morphotreeadjust-0.4.0/morphoTreeAdjust/include/AttributeComputer.hpp +819 -0
- morphotreeadjust-0.4.0/morphoTreeAdjust/include/Common.hpp +323 -0
- morphotreeadjust-0.4.0/morphoTreeAdjust/include/ComponentTreeCasf.hpp +203 -0
- morphotreeadjust-0.4.0/morphoTreeAdjust/include/DynamicComponentTree.hpp +1217 -0
- morphotreeadjust-0.4.0/morphoTreeAdjust/include/DynamicComponentTreeAdjustment.hpp +1402 -0
- morphotreeadjust-0.4.0/morphoTreeAdjust/include/DynamicComponentTreeAdjustmentInstrumented.hpp +1662 -0
- morphotreeadjust-0.4.0/morphoTreeAdjust/include/DynamicComponentTreeAdjustmentLeaf.hpp +948 -0
- morphotreeadjust-0.4.0/morphoTreeAdjust/include/MorphoTreeAdjust.hpp +22 -0
- morphotreeadjust-0.4.0/morphoTreeAdjust/morphoTreeAdjust.cpp +356 -0
- {morphotreeadjust-0.2 → morphotreeadjust-0.4.0}/morphoTreeAdjust/pybind/PybindUtils.hpp +3 -6
- {morphotreeadjust-0.2 → morphotreeadjust-0.4.0}/pybind11.cmake +1 -0
- morphotreeadjust-0.4.0/pyproject.toml +55 -0
- morphotreeadjust-0.4.0/python/morphoTreeAdjust/__init__.py +18 -0
- {morphotreeadjust-0.2 → morphotreeadjust-0.4.0}/python/morphoTreeAdjust/utils.py +183 -22
- morphotreeadjust-0.4.0/release-please-config.json +11 -0
- morphotreeadjust-0.2/CMakeLists.txt +0 -51
- morphotreeadjust-0.2/MANIFEST.in +0 -3
- morphotreeadjust-0.2/PKG-INFO +0 -27
- morphotreeadjust-0.2/README.md +0 -19
- morphotreeadjust-0.2/morphoTreeAdjust/include/AdjacencyRelation.hpp +0 -147
- morphotreeadjust-0.2/morphoTreeAdjust/include/Common.hpp +0 -1065
- morphotreeadjust-0.2/morphoTreeAdjust/include/ComponentTree.hpp +0 -778
- morphotreeadjust-0.2/morphoTreeAdjust/include/ComponentTree.tpp +0 -834
- morphotreeadjust-0.2/morphoTreeAdjust/include/ComponentTreeAdjustment.hpp +0 -440
- morphotreeadjust-0.2/morphoTreeAdjust/include/ComponentTreeAdjustmentByAnyNode.hpp +0 -71
- morphotreeadjust-0.2/morphoTreeAdjust/include/ComponentTreeAdjustmentByFlatzone.hpp +0 -64
- morphotreeadjust-0.2/morphoTreeAdjust/include/ComponentTreeAdjustmentByLeaf.hpp +0 -64
- morphotreeadjust-0.2/morphoTreeAdjust/include/ComponentTreeAdjustmentBySubtree.hpp +0 -203
- morphotreeadjust-0.2/morphoTreeAdjust/include/FlatZonesGraph.hpp +0 -499
- morphotreeadjust-0.2/morphoTreeAdjust/include/NodeCT.hpp +0 -502
- morphotreeadjust-0.2/morphoTreeAdjust/include/NodeCT.tpp +0 -58
- morphotreeadjust-0.2/morphoTreeAdjust/morphoTreeAdjust.cpp +0 -216
- morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTree.hpp +0 -49
- morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTree.tpp +0 -45
- morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTreeAdjustmentByAnyNode.cpp +0 -29
- morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTreeAdjustmentByAnyNode.hpp +0 -35
- morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTreeAdjustmentByFlatzone.cpp +0 -25
- morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTreeAdjustmentByFlatzone.hpp +0 -35
- morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTreeAdjustmentByLeaf.cpp +0 -35
- morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTreeAdjustmentByLeaf.hpp +0 -35
- morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTreeAdjustmentBySubtree.cpp +0 -35
- morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindComponentTreeAdjustmentBySubtree.hpp +0 -35
- morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindFlatZonesGraph.cpp +0 -10
- morphotreeadjust-0.2/morphoTreeAdjust/pybind/PyBindFlatZonesGraph.hpp +0 -29
- morphotreeadjust-0.2/morphoTreeAdjust/src/AdjacencyRelation.cpp +0 -232
- morphotreeadjust-0.2/morphoTreeAdjust/src/ComponentTreeAdjustmentByAnyNode.cpp +0 -40
- morphotreeadjust-0.2/morphoTreeAdjust/src/ComponentTreeAdjustmentByFlatzone.cpp +0 -172
- morphotreeadjust-0.2/morphoTreeAdjust/src/ComponentTreeAdjustmentByLeaf.cpp +0 -157
- morphotreeadjust-0.2/morphoTreeAdjust/src/ComponentTreeAdjustmentBySubtree.cpp +0 -250
- morphotreeadjust-0.2/pyproject.toml +0 -9
- morphotreeadjust-0.2/python/morphoTreeAdjust/__init__.py +0 -13
- morphotreeadjust-0.2/python/morphoTreeAdjust.egg-info/PKG-INFO +0 -27
- morphotreeadjust-0.2/python/morphoTreeAdjust.egg-info/SOURCES.txt +0 -46
- morphotreeadjust-0.2/python/morphoTreeAdjust.egg-info/dependency_links.txt +0 -1
- morphotreeadjust-0.2/python/morphoTreeAdjust.egg-info/not-zip-safe +0 -1
- morphotreeadjust-0.2/python/morphoTreeAdjust.egg-info/requires.txt +0 -4
- morphotreeadjust-0.2/python/morphoTreeAdjust.egg-info/top_level.txt +0 -1
- morphotreeadjust-0.2/setup.cfg +0 -4
- morphotreeadjust-0.2/setup.py +0 -147
- {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,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
|
+
[](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
|
+
[](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()
|