mtlearn 0.1.2__tar.gz → 0.1.4__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.
Potentially problematic release.
This version of mtlearn might be problematic. Click here for more details.
- mtlearn-0.1.4/.DS_Store +0 -0
- mtlearn-0.1.4/.gitignore +12 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/PKG-INFO +6 -5
- {mtlearn-0.1.2 → mtlearn-0.1.4}/README.md +4 -3
- mtlearn-0.1.4/bindings/.ipynb_checkpoints/ConnectedFilterByJacobian-checkpoint.hpp +108 -0
- mtlearn-0.1.4/bindings/.ipynb_checkpoints/ConnectedFilterByMorphologicalTree-checkpoint.hpp +258 -0
- mtlearn-0.1.4/bindings/.ipynb_checkpoints/InfoTreePybind-checkpoint.hpp +54 -0
- mtlearn-0.1.4/bindings/.ipynb_checkpoints/module-checkpoint.cpp +128 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/bindings/CMakeLists.txt +24 -7
- mtlearn-0.1.4/bindings/ConnectedFilterByJacobian.hpp +108 -0
- mtlearn-0.1.4/bindings/ConnectedFilterByMorphologicalTree.hpp +260 -0
- mtlearn-0.1.4/bindings/InfoTreePybind.hpp +78 -0
- mtlearn-0.1.4/bindings/PybindTorchUtils.hpp +84 -0
- mtlearn-0.1.4/bindings/module.cpp +135 -0
- mtlearn-0.1.4/environment.yml +532 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/README.md +3 -3
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/attributes/ComputerAttributeBasedBitQuads.hpp +7 -6
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/filters/AttributeFilters.hpp +2 -8
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/trees/MorphologicalTree.hpp +2 -10
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/trees/NodeMTArena.hpp +3 -2
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/pybinds/mmcfilters.cpp +16 -16
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/tests/CMakeLists.txt +17 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/tests/TesteBitQuads.cpp +6 -4
- {mtlearn-0.1.2 → mtlearn-0.1.4}/pyproject.toml +8 -4
- mtlearn-0.1.4/python/mtlearn/.DS_Store +0 -0
- mtlearn-0.1.4/python/mtlearn/__init__.py +34 -0
- mtlearn-0.1.4/python/mtlearn/__pycache__/ConnectedFilterLayer.cpython-312.pyc +0 -0
- mtlearn-0.1.4/python/mtlearn/__pycache__/__init__.cpython-312.pyc +0 -0
- mtlearn-0.1.4/python/mtlearn/__pycache__/datasets.cpython-312.pyc +0 -0
- mtlearn-0.1.4/python/mtlearn/datasets.py +280 -0
- mtlearn-0.1.4/python/mtlearn/layers/.ipynb_checkpoints/ConnectedFilterLayerBySingleThreshold-checkpoint.py +347 -0
- mtlearn-0.1.4/python/mtlearn/layers/ConnectedFilterLayer copy.py +925 -0
- mtlearn-0.1.4/python/mtlearn/layers/ConnectedFilterLayer.py +630 -0
- mtlearn-0.1.4/python/mtlearn/layers/ConnectedFilterLayerBySingleThreshold.py +504 -0
- mtlearn-0.1.4/python/mtlearn/layers/ConnectedFilterLayerByThresholds copy.py +562 -0
- mtlearn-0.1.4/python/mtlearn/layers/ConnectedFilterLayerByThresholds.py +485 -0
- mtlearn-0.1.4/python/mtlearn/layers/ConnectedFilterLayerWithJacobian.py +639 -0
- mtlearn-0.1.4/python/mtlearn/layers/ConnectedFilterLayer_copy.py +529 -0
- mtlearn-0.1.4/python/mtlearn/layers/__init__.py +3 -0
- mtlearn-0.1.4/python/mtlearn/layers/__pycache__/ConnectedFilterLayer.cpython-312.pyc +0 -0
- mtlearn-0.1.4/python/mtlearn/layers/__pycache__/ConnectedFilterLayerBySingleThreshold.cpython-312.pyc +0 -0
- mtlearn-0.1.4/python/mtlearn/layers/__pycache__/ConnectedFilterLayerByThresholds.cpython-312.pyc +0 -0
- mtlearn-0.1.4/python/mtlearn/layers/__pycache__/ConnectedFilterLayerWithJacobian.cpython-312.pyc +0 -0
- mtlearn-0.1.4/python/mtlearn/layers/__pycache__/__init__.cpython-312.pyc +0 -0
- mtlearn-0.1.4/python/mtlearn/layers/__pycache__/_helpers.cpython-312.pyc +0 -0
- mtlearn-0.1.4/python/mtlearn/layers/_helpers.py +214 -0
- mtlearn-0.1.4/requirements.txt +0 -0
- mtlearn-0.1.2/.gitignore +0 -8
- mtlearn-0.1.2/bindings/module.cpp +0 -39
- mtlearn-0.1.2/bindings/module_stub.cpp +0 -34
- mtlearn-0.1.2/cmake/README.md +0 -1
- mtlearn-0.1.2/notebooks/.ipynb_checkpoints/Untitled-checkpoint.ipynb +0 -6
- mtlearn-0.1.2/notebooks/Untitled.ipynb +0 -64
- mtlearn-0.1.2/python/mtlearn/__init__.py +0 -24
- mtlearn-0.1.2/python/mtlearn/__pycache__/__init__.cpython-312.pyc +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/.gitmodules +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/CMakeLists.txt +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/Pipfile +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/.git +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/.gitignore +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/.vscode/c_cpp_properties.json +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/.vscode/extensions.json +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/.vscode/launch.json +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/.vscode/settings.json +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/.vscode/tasks.json +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/CMakeLists.txt +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/LICENSE +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/MANIFEST.in +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/article-2.png +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/attr.png +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/believe.pgm +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/brain2.pgm +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/cable.png +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/images/cameraman.tif +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/images/house.tif +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/images/jetplane.tif +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/images/lake.tif +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/images/lena_gray_512.tif +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/images/livingroom.tif +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/images/mandril_gray.tif +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/images/peppers_gray.tif +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/images/pirate.tif +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/images/walkbridge.tif +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/images/woman_blonde.tif +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/images/woman_darkhair.tif +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/imgObjetos.png +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/imgTeste-2.png +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/imgTeste-inv.png +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/imgTeste.png +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/imgTeste.txt +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/knee.pgm +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/lena.pgm +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/mesa-wonder.jpeg +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/mesa.png +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/synthetic.pgm +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/synthetic.png +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/val_000.png +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/dat/wrist.pgm +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/external/stb/stb_image.cpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/external/stb/stb_image.h +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/external/stb/stb_image_write.h +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/CMakeLists.txt +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/attributes/AreaComputer.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/attributes/AttributeComputedIncrementally.cpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/attributes/AttributeComputedIncrementally.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/attributes/AttributeComputer.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/attributes/AttributeFactory.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/attributes/AttributeNames.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/attributes/BitquadsComputer.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/attributes/BoundingBoxComputer.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/attributes/ComputerMSER.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/attributes/GrayLevelStatsComputer.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/attributes/MomentBasedAttributeComputer.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/attributes/TreeTopologyComputer.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/attributes/VolumeComputer.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/contours/ContoursComputedIncrementally.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/dataStructure/FastQueue.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/dataStructure/FastStack.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/filters/AttributeFilters.cpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/filters/AttributeOpeningPrimitivesFamily.cpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/filters/AttributeOpeningPrimitivesFamily.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/filters/ExtinctionValues.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/filters/UltimateAttributeOpening.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/trees/BuilderMorphologicalTreeByUnionFind.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/trees/MorphologicalTree.cpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/trees/MorphologicalTree.tpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/trees/NodeMT.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/trees/NodeRes.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/trees/ResidualTree.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/utils/AdjacencyRelation.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/utils/Common.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/utils/ComputerDerivatives.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/utils/Image.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/mmcfilters/utils/PixelSetManager.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/notebooks/Attribute_Filters.ipynb +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/notebooks/Exemplo_ToS_Contorno.ipynb +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/notebooks/Filter.ipynb +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/notebooks/SimpleExamples.ipynb +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/notebooks/SimpleExamples2.ipynb +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/notebooks/ToS.ipynb +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/notebooks/UAO_Exemplos.ipynb +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/old_setup.py +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/pybind11.cmake +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/pybinds/AttributeComputedIncrementallyPybind.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/pybinds/AttributeFiltersPybind.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/pybinds/AttributeOpeningPrimitivesFamilyPybind.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/pybinds/ContoursComputedIncrementallyPybind.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/pybinds/ExtinctionValuesPybind.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/pybinds/MorphologicalTreePybind.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/pybinds/PybindUtils.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/pybinds/ResidualTreePybind.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/pybinds/UltimateAttributeOpeningPybind.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/pyproject.toml +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/python/mmcfilters/__init__.py +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/python/mmcfilters/test.py +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/tests/TestMorphologicalTree.cpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/tests/TesteAdjacencyUC.cpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/tests/TesteContours.cpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/tests/TesteContours2.cpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/tests/TesteContours3.cpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/tests/Tests.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/tests/testeComputerAllAttributes.cpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/tests/testeComputerAttribute.cpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/tests/testeResidualTree.cpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/tests/testeTreeOfShapes.cpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/external/MorphologicalAttributeFilters/tmp/output_windows.txt +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/src/CMakeLists.txt +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/src/main.cpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/src/mtlearn/core.cpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/src/mtlearn/core.hpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/tests/CMakeLists.txt +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/tests/basic.cpp +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/tests/python/test_bindings.py +0 -0
- {mtlearn-0.1.2 → mtlearn-0.1.4}/tests/test_interpreter.cpp +0 -0
mtlearn-0.1.4/.DS_Store
ADDED
|
Binary file
|
mtlearn-0.1.4/.gitignore
ADDED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: mtlearn
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Morphological tree learning utilities built on top of mmcfilters
|
|
5
5
|
Author-Email: Wonder Alexandre Luz Alves <worderalexandre@gmail.com>
|
|
6
6
|
Classifier: Programming Language :: Python
|
|
@@ -10,7 +10,7 @@ Classifier: Operating System :: MacOS
|
|
|
10
10
|
Classifier: Operating System :: Microsoft :: Windows
|
|
11
11
|
Classifier: Operating System :: POSIX :: Linux
|
|
12
12
|
Requires-Python: >=3.9
|
|
13
|
-
Requires-Dist: mmcfilters>=0.1.
|
|
13
|
+
Requires-Dist: mmcfilters>=0.1.23
|
|
14
14
|
Provides-Extra: torch
|
|
15
15
|
Requires-Dist: torch>=2.0; extra == "torch"
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
@@ -58,9 +58,10 @@ cmake --build build
|
|
|
58
58
|
Para rodar o teste com interpretador embutido:
|
|
59
59
|
|
|
60
60
|
```bash
|
|
61
|
-
cmake -S . -B build -DMTLEARN_BUILD_TESTS=ON -DMTLEARN_ENABLE_EMBED=ON \
|
|
62
|
-
-DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") \
|
|
63
|
-
-DPYTHON_LIBRARY_DIR=$(python3 -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))")
|
|
61
|
+
#cmake -S . -B build -DMTLEARN_BUILD_TESTS=ON -DMTLEARN_ENABLE_EMBED=ON \
|
|
62
|
+
# -DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") \
|
|
63
|
+
# -DPYTHON_LIBRARY_DIR=$(python3 -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))")
|
|
64
|
+
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=$(python -c "import site; print(site.getsitepackages()[0])")
|
|
64
65
|
cmake --build build
|
|
65
66
|
ctest --test-dir build -R mtl_interpreter_test --output-on-failure
|
|
66
67
|
```
|
|
@@ -41,9 +41,10 @@ cmake --build build
|
|
|
41
41
|
Para rodar o teste com interpretador embutido:
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
|
-
cmake -S . -B build -DMTLEARN_BUILD_TESTS=ON -DMTLEARN_ENABLE_EMBED=ON \
|
|
45
|
-
-DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") \
|
|
46
|
-
-DPYTHON_LIBRARY_DIR=$(python3 -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))")
|
|
44
|
+
#cmake -S . -B build -DMTLEARN_BUILD_TESTS=ON -DMTLEARN_ENABLE_EMBED=ON \
|
|
45
|
+
# -DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") \
|
|
46
|
+
# -DPYTHON_LIBRARY_DIR=$(python3 -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))")
|
|
47
|
+
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=$(python -c "import site; print(site.getsitepackages()[0])")
|
|
47
48
|
cmake --build build
|
|
48
49
|
ctest --test-dir build -R mtl_interpreter_test --output-on-failure
|
|
49
50
|
```
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
#include <mmcfilters/attributes/AttributeComputedIncrementally.hpp>
|
|
5
|
+
#include <mmcfilters/trees/NodeMT.hpp>
|
|
6
|
+
#include <mmcfilters/trees/MorphologicalTree.hpp>
|
|
7
|
+
#include <mmcfilters/utils/Common.hpp>
|
|
8
|
+
|
|
9
|
+
#include "MorphologicalTreePybind.hpp"
|
|
10
|
+
#include "PybindTorchUtils.hpp"
|
|
11
|
+
|
|
12
|
+
#include <memory>
|
|
13
|
+
#include <vector>
|
|
14
|
+
#include <tuple>
|
|
15
|
+
|
|
16
|
+
#include <pybind11/pybind11.h>
|
|
17
|
+
#include <torch/extension.h>
|
|
18
|
+
#include <ATen/ops/_sparse_mm.h>
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
namespace mtlearn {
|
|
23
|
+
|
|
24
|
+
namespace py = pybind11;
|
|
25
|
+
|
|
26
|
+
using mmcfilters::AttributeComputedIncrementally;
|
|
27
|
+
using mmcfilters::InvalidNode;
|
|
28
|
+
using mmcfilters::MorphologicalTreePybindPtr;
|
|
29
|
+
using mmcfilters::NodeId;
|
|
30
|
+
|
|
31
|
+
class ConnectedFilterByJacobian {
|
|
32
|
+
public:
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
static torch::Tensor filtering(
|
|
36
|
+
const torch::Tensor& pixel_to_node, // [N_pixels]
|
|
37
|
+
const torch::Tensor& residues, // [N_nodes]
|
|
38
|
+
const torch::Tensor& sigmoid // [N_nodes]
|
|
39
|
+
) {
|
|
40
|
+
|
|
41
|
+
auto node_filter = residues * sigmoid; // [N_nodes]
|
|
42
|
+
return node_filter.index_select(0, pixel_to_node); // [N_pixels]
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
static py::tuple gradients(const torch::Tensor& jacobian,
|
|
47
|
+
const torch::Tensor& residues,
|
|
48
|
+
const torch::Tensor& attributes,
|
|
49
|
+
const torch::Tensor& sigmoid,
|
|
50
|
+
const torch::Tensor& grad_output) {
|
|
51
|
+
|
|
52
|
+
// 1. Gradiente da sigmoide
|
|
53
|
+
auto d_sigmoid = sigmoid * (1 - sigmoid); // Element-wise, Shape: [N_nodes]
|
|
54
|
+
|
|
55
|
+
// 2. Gradientes para os nós
|
|
56
|
+
auto grad_filter = residues * d_sigmoid; // Shape: [N_nodes]
|
|
57
|
+
auto grad_bias_nodes = grad_filter.unsqueeze(1); // Shape: [N_nodes, 1]
|
|
58
|
+
auto grad_weight_nodes = grad_bias_nodes * attributes; // Shape: [N_nodes, D_attributes]
|
|
59
|
+
|
|
60
|
+
// 3. Projeção com Jacobiana
|
|
61
|
+
auto grad_bias_pixels = at::_sparse_mm(jacobian.t(), grad_bias_nodes); // [N_pixels, 1]
|
|
62
|
+
auto grad_weight_pixels = at::_sparse_mm(jacobian.t(), grad_weight_nodes); // [N_pixels, D_attributes]
|
|
63
|
+
|
|
64
|
+
// 4. Gradientes finais
|
|
65
|
+
auto grad_bias = grad_output.t().matmul(grad_bias_pixels); // Scalar [1]
|
|
66
|
+
auto grad_weight = grad_output.t().matmul(grad_weight_pixels).reshape({-1, 1}); // Shape: [D_attributes, 1]; // [1, D_attributes]
|
|
67
|
+
|
|
68
|
+
return py::make_tuple(grad_bias, grad_weight);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
static py::tuple computeGradientsEfficient(
|
|
77
|
+
const torch::Tensor& pixel_to_node, // [N_pixels]
|
|
78
|
+
const torch::Tensor& residues, // [N_nodes]
|
|
79
|
+
const torch::Tensor& sigmoid, // [N_nodes]
|
|
80
|
+
const torch::Tensor& attributes, // [N_nodes, D]
|
|
81
|
+
const torch::Tensor& grad_output // [N_pixels]
|
|
82
|
+
) {
|
|
83
|
+
// 1. Derivada da sigmoide
|
|
84
|
+
auto d_sigmoid = sigmoid * (1 - sigmoid); // [N_nodes]
|
|
85
|
+
|
|
86
|
+
// 2. Gradiente do filtro por nó
|
|
87
|
+
auto node_filter_grad = residues * d_sigmoid; // [N_nodes]
|
|
88
|
+
|
|
89
|
+
// 3. Gradiente da saída dos pixels: para cada pixel, obter o gradiente do nó correspondente
|
|
90
|
+
auto node_grad_per_pixel = node_filter_grad.index_select(0, pixel_to_node); // [N_pixels]
|
|
91
|
+
|
|
92
|
+
// 4. Gradientes por pixel
|
|
93
|
+
auto grad_bias_pixels = node_grad_per_pixel; // [N_pixels]
|
|
94
|
+
auto grad_weight_pixels = grad_bias_pixels.unsqueeze(1) * attributes.index_select(0, pixel_to_node); // [N_pixels, D]
|
|
95
|
+
|
|
96
|
+
// 5. Projeção final (produto com grad_output)
|
|
97
|
+
auto grad_bias = (grad_output * grad_bias_pixels).sum(); // Escalar
|
|
98
|
+
//auto grad_weight = (grad_output.unsqueeze(1) * grad_weight_pixels).sum(0); // [D]
|
|
99
|
+
auto grad_weight = (grad_output.unsqueeze(1) * grad_weight_pixels).sum(0).unsqueeze(1); // [D, 1]
|
|
100
|
+
|
|
101
|
+
return py::make_tuple(grad_weight, grad_bias.unsqueeze(0).unsqueeze(0));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
} // namespace mtlearn
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
#include <mmcfilters/attributes/AttributeComputedIncrementally.hpp>
|
|
5
|
+
#include <mmcfilters/trees/NodeMT.hpp>
|
|
6
|
+
#include <mmcfilters/trees/MorphologicalTree.hpp>
|
|
7
|
+
#include <mmcfilters/utils/Common.hpp>
|
|
8
|
+
|
|
9
|
+
#include "MorphologicalTreePybind.hpp"
|
|
10
|
+
#include "PybindTorchUtils.hpp"
|
|
11
|
+
|
|
12
|
+
#include <memory>
|
|
13
|
+
#include <vector>
|
|
14
|
+
#include <tuple>
|
|
15
|
+
|
|
16
|
+
#include <pybind11/pybind11.h>
|
|
17
|
+
#include <torch/extension.h>
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
namespace mtlearn {
|
|
22
|
+
|
|
23
|
+
namespace py = pybind11;
|
|
24
|
+
|
|
25
|
+
using mmcfilters::AttributeComputedIncrementally;
|
|
26
|
+
using mmcfilters::InvalidNode;
|
|
27
|
+
using mmcfilters::MorphologicalTreePybindPtr;
|
|
28
|
+
using mmcfilters::MorphologicalTreePybind;
|
|
29
|
+
using mmcfilters::NodeId;
|
|
30
|
+
|
|
31
|
+
class ConnectedFilterByMorphologicalTree {
|
|
32
|
+
public:
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
static torch::Tensor filtering(MorphologicalTreePybindPtr tree, torch::Tensor sigmoid) {
|
|
36
|
+
int numRows = tree->getNumRowsOfImage();
|
|
37
|
+
int numCols = tree->getNumColsOfImage();
|
|
38
|
+
int n = numRows * numCols;
|
|
39
|
+
float* sigmoid_ptr = sigmoid.data_ptr<float>();
|
|
40
|
+
|
|
41
|
+
std::unique_ptr<float[]> mapLevel(new float[tree->getNumNodes()]);
|
|
42
|
+
|
|
43
|
+
// The root is always kept
|
|
44
|
+
NodeId rootId = tree->getRootById();
|
|
45
|
+
mapLevel[rootId] = tree->getLevelById(rootId);
|
|
46
|
+
for (NodeId nodeId : tree->getNodeIds()) {
|
|
47
|
+
if (tree->getParentById(nodeId) != InvalidNode) {
|
|
48
|
+
float residue = static_cast<float>(tree->getResidueById(nodeId));
|
|
49
|
+
mapLevel[nodeId] = mapLevel[tree->getParentById(nodeId)] + (residue * sigmoid_ptr[nodeId]);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
auto out = torch::empty({numRows, numCols}, torch::kFloat32);
|
|
54
|
+
float* imgOutput = out.data_ptr<float>();
|
|
55
|
+
for (NodeId nodeId : tree->getNodeIds()) {
|
|
56
|
+
for (int pixel : tree->getCNPsById(nodeId)) {
|
|
57
|
+
imgOutput[pixel] = mapLevel[nodeId];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
static std::tuple<torch::Tensor, torch::Tensor> gradients(MorphologicalTreePybindPtr treePtr, torch::Tensor attrs, torch::Tensor sigmoid, torch::Tensor gradientOfLoss) {
|
|
66
|
+
float* attributes = attrs.data_ptr<float>();
|
|
67
|
+
float* sigmoid_ptr = sigmoid.data_ptr<float>();
|
|
68
|
+
MorphologicalTreePybind* tree = treePtr.get();
|
|
69
|
+
int rows = attrs.size(0); // numNodes
|
|
70
|
+
int cols = attrs.size(1); // numFeatures
|
|
71
|
+
torch::Tensor gradFilterWeights = torch::empty({rows * cols}, torch::kFloat32);
|
|
72
|
+
torch::Tensor gradFilterBias = torch::empty({rows}, torch::kFloat32);
|
|
73
|
+
|
|
74
|
+
float* gradFilterWeights_ptr = gradFilterWeights.data_ptr<float>();
|
|
75
|
+
float* gradFilterBias_ptr = gradFilterBias.data_ptr<float>();
|
|
76
|
+
|
|
77
|
+
std::unique_ptr<float[]> localDerivativeOfFilterOutput(new float[tree->getNumNodes()]);
|
|
78
|
+
for (NodeId nodeId : tree->getNodeIds()) {
|
|
79
|
+
float dSigmoid = sigmoid_ptr[nodeId] * (1 - sigmoid_ptr[nodeId]);
|
|
80
|
+
float residue = tree->getParentById(nodeId) != InvalidNode ? tree->getResidueById(nodeId) : 0;
|
|
81
|
+
|
|
82
|
+
// Calcula o gradiente local para cada nó
|
|
83
|
+
localDerivativeOfFilterOutput[nodeId] = residue * dSigmoid;
|
|
84
|
+
|
|
85
|
+
// Calcula o gradiente do filtro para os pesos e bias
|
|
86
|
+
gradFilterBias_ptr[nodeId] = localDerivativeOfFilterOutput[nodeId];
|
|
87
|
+
for (int j = 0; j < cols; j++) {
|
|
88
|
+
gradFilterWeights_ptr[nodeId * cols + j] = localDerivativeOfFilterOutput[nodeId] * attributes[nodeId * cols + j]; // row-major //attributes[j * rows + nodeId];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
torch::Tensor gradWeight = torch::zeros({cols}, torch::kFloat32);
|
|
93
|
+
torch::Tensor gradBias = torch::zeros({1}, torch::kFloat32);
|
|
94
|
+
|
|
95
|
+
float* gradWeight_ptr = gradWeight.data_ptr<float>();
|
|
96
|
+
float* gradBias_ptr = gradBias.data_ptr<float>();
|
|
97
|
+
float* gradLoss = gradientOfLoss.data_ptr<float>();
|
|
98
|
+
|
|
99
|
+
// Vamos somar os gradientes da loss de cada CC e acumular com o gradiente local.
|
|
100
|
+
std::unique_ptr<float[]> summationGrad_ptr(new float[tree->getNumNodes()]);
|
|
101
|
+
AttributeComputedIncrementally::computerAttribute(
|
|
102
|
+
tree,
|
|
103
|
+
tree->getRootById(),
|
|
104
|
+
[&](NodeId nodeId) -> void { // pre-processing
|
|
105
|
+
summationGrad_ptr[nodeId] = 0;
|
|
106
|
+
for (int p : tree->getCNPsById(nodeId)) {
|
|
107
|
+
summationGrad_ptr[nodeId] += gradLoss[p];
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
[&summationGrad_ptr](NodeId parent, NodeId child) -> void { // merge-processing
|
|
111
|
+
summationGrad_ptr[parent] += summationGrad_ptr[child];
|
|
112
|
+
},
|
|
113
|
+
[&](NodeId nodeId) -> void { // post-processing
|
|
114
|
+
gradBias_ptr[0] += summationGrad_ptr[nodeId] * gradFilterBias_ptr[nodeId];
|
|
115
|
+
for (int j = 0; j < cols; j++) {
|
|
116
|
+
gradWeight_ptr[j] += summationGrad_ptr[nodeId] * gradFilterWeights_ptr[nodeId * cols + j];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
return std::make_tuple(gradWeight, gradBias);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Gradiente apenas para o parâmetro escalar "threshold".
|
|
128
|
+
*
|
|
129
|
+
* Assumimos que o forward foi:
|
|
130
|
+
* logits_i = attribute_i - threshold
|
|
131
|
+
* sigmoid_i = 1 / (1 + exp(-logits_i))
|
|
132
|
+
* y = filtering(tree, sigmoid)
|
|
133
|
+
*
|
|
134
|
+
* Então:
|
|
135
|
+
* d(sigmoid_i)/d(threshold) = - sigmoid_i * (1 - sigmoid_i)
|
|
136
|
+
* d(y)/d(sigmoid_i) = residue_i
|
|
137
|
+
* dLoss/dthreshold = sum_nodes [ sum_pixels_in_CC( dLoss/dy[p] ) * residue_i * d(sigmoid_i)/d(threshold) ]
|
|
138
|
+
*
|
|
139
|
+
* Parâmetros:
|
|
140
|
+
* - treePtr: árvore
|
|
141
|
+
* - sigmoid: tensor 1D (numNodes) float32
|
|
142
|
+
* - gradientOfLoss: gradiente da loss no domínio da imagem (H x W), float32
|
|
143
|
+
*
|
|
144
|
+
* Retorno:
|
|
145
|
+
* - gradThreshold: tensor (1,) float32
|
|
146
|
+
*/
|
|
147
|
+
static torch::Tensor gradientsOfThreshold(MorphologicalTreePybindPtr treePtr, torch::Tensor sigmoid, float beta, torch::Tensor gradientOfLoss) {
|
|
148
|
+
MorphologicalTreePybind* tree = treePtr.get();
|
|
149
|
+
float* sigmoid_ptr = sigmoid.data_ptr<float>();
|
|
150
|
+
float* gradLoss = gradientOfLoss.data_ptr<float>();
|
|
151
|
+
|
|
152
|
+
// Derivada local d y / d threshold por nó
|
|
153
|
+
std::unique_ptr<float[]> localDerivativeOfFilterOutput(new float[tree->getNumNodes()]);
|
|
154
|
+
|
|
155
|
+
// Primeiro, computamos a derivada local:
|
|
156
|
+
// localDerivativeOfFilterOutput[node] = residue(node) * d(sigmoid)/d(threshold)
|
|
157
|
+
// d(sigmoid)/d(threshold) = -beta * sigmoid * (1 - sigmoid)
|
|
158
|
+
for (NodeId nodeId : tree->getNodeIds()) {
|
|
159
|
+
float residue = (tree->getParentById(nodeId) != InvalidNode) ? static_cast<float>(tree->getResidueById(nodeId)) : 0.0f;
|
|
160
|
+
float dSigmoid = -beta * sigmoid_ptr[nodeId] * (1 - sigmoid_ptr[nodeId]);
|
|
161
|
+
localDerivativeOfFilterOutput[nodeId] = residue * dSigmoid;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
torch::Tensor gradThreshold = torch::zeros({1}, torch::kFloat32);
|
|
165
|
+
float* gthr = gradThreshold.data_ptr<float>();
|
|
166
|
+
gthr[0] = 0.0f;
|
|
167
|
+
|
|
168
|
+
// Agora, somamos dLoss/dy(p) por nó (somando nos pixels pertencentes à CC do nó)
|
|
169
|
+
std::unique_ptr<float[]> sumGradPerNode(new float[tree->getNumNodes()]);
|
|
170
|
+
AttributeComputedIncrementally::computerAttribute(
|
|
171
|
+
tree,
|
|
172
|
+
tree->getRootById(),
|
|
173
|
+
[&](NodeId nodeId) -> void { // pre-processing
|
|
174
|
+
sumGradPerNode[nodeId] = 0.0f;
|
|
175
|
+
for (int p : tree->getCNPsById(nodeId)) {
|
|
176
|
+
sumGradPerNode[nodeId] += gradLoss[p];
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
[&](NodeId parent, NodeId child) -> void { // merge-processing
|
|
180
|
+
sumGradPerNode[parent] += sumGradPerNode[child];
|
|
181
|
+
},
|
|
182
|
+
[&](NodeId nodeId) -> void {
|
|
183
|
+
gthr[0] += sumGradPerNode[nodeId] * localDerivativeOfFilterOutput[nodeId];
|
|
184
|
+
}
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
return gradThreshold;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Gradiente para K parâmetros (um threshold por atributo do grupo).
|
|
191
|
+
// Entradas:
|
|
192
|
+
// - sigmoids2d: tensor 2D (numNodes, K) float32 com σ_{ik} do forward
|
|
193
|
+
// - gradientOfLoss: tensor 2D (H, W) float32 com dLoss/dy
|
|
194
|
+
// Saída:
|
|
195
|
+
// - gradThresholds: tensor 1D (K,) float32 com dLoss/dτ_k
|
|
196
|
+
static torch::Tensor gradientsOfThresholds(MorphologicalTreePybindPtr treePtr, torch::Tensor sigmoids2d, float beta, torch::Tensor gradientOfLoss) {
|
|
197
|
+
MorphologicalTreePybind* tree = treePtr.get();
|
|
198
|
+
|
|
199
|
+
//--- checagens básicas ---
|
|
200
|
+
TORCH_CHECK(sigmoids2d.dim() == 2, "sigmoids2d deve ter shape (numNodes, K).");
|
|
201
|
+
TORCH_CHECK(sigmoids2d.dtype() == torch::kFloat32, "sigmoids2d deve ser float32.");
|
|
202
|
+
TORCH_CHECK(gradientOfLoss.dim() == 2, "gradientOfLoss deve ter shape (H, W).");
|
|
203
|
+
TORCH_CHECK(gradientOfLoss.dtype() == torch::kFloat32, "gradientOfLoss deve ser float32.");
|
|
204
|
+
|
|
205
|
+
const int64_t numNodes = sigmoids2d.size(0);
|
|
206
|
+
const int64_t K = sigmoids2d.size(1);
|
|
207
|
+
const float* sigmoids2d_ptr = sigmoids2d.data_ptr<float>();
|
|
208
|
+
|
|
209
|
+
// 1) Derivada local por nó e por parâmetro:
|
|
210
|
+
// localDerivativeOfFilterOutput[i,k] = residue_i * ( - s_i * (1 - s_i) )
|
|
211
|
+
const size_t localSize = static_cast<size_t>(numNodes) * static_cast<size_t>(K);
|
|
212
|
+
std::unique_ptr<float[]> localDerivativeOfFilterOutput(new float[localSize]);
|
|
213
|
+
float* localDerivativeOfFilterOutput_ptr = localDerivativeOfFilterOutput.get();
|
|
214
|
+
|
|
215
|
+
for (NodeId nodeId : tree->getNodeIds()) {
|
|
216
|
+
float residue = (tree->getParentById(nodeId) != InvalidNode) ? static_cast<float>(tree->getResidueById(nodeId)) : 0.0f;
|
|
217
|
+
float* dst = localDerivativeOfFilterOutput_ptr + static_cast<int64_t>(nodeId) * K;
|
|
218
|
+
const float* sigmoids_nodeId = sigmoids2d_ptr + static_cast<int64_t>(nodeId) * K;
|
|
219
|
+
for (int64_t k = 0; k < K; ++k) {
|
|
220
|
+
dst[k] = residue * (-beta * sigmoids_nodeId[k] * (1.0f - sigmoids_nodeId[k]) );
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// 2) Somatório de dLoss/dy por CC e agregação final
|
|
225
|
+
float* gradLoss = gradientOfLoss.data_ptr<float>();
|
|
226
|
+
std::unique_ptr<float[]> sumGradPerNode(new float[static_cast<size_t>(numNodes)]);
|
|
227
|
+
auto gradThresholds = torch::zeros({K}, torch::kFloat32);
|
|
228
|
+
float* gthr = gradThresholds.data_ptr<float>();
|
|
229
|
+
|
|
230
|
+
AttributeComputedIncrementally::computerAttribute(
|
|
231
|
+
tree,
|
|
232
|
+
tree->getRootById(),
|
|
233
|
+
[&](NodeId nodeId) -> void { // pre-processing
|
|
234
|
+
sumGradPerNode[nodeId] = 0.0f;
|
|
235
|
+
for (int p : tree->getCNPsById(nodeId)) {
|
|
236
|
+
sumGradPerNode[nodeId] += gradLoss[p];
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
[&](NodeId parent, NodeId child) -> void { // merge-processing
|
|
240
|
+
sumGradPerNode[parent] += sumGradPerNode[child];
|
|
241
|
+
},
|
|
242
|
+
[&](NodeId nodeId) -> void { // post-processing
|
|
243
|
+
const float acc = sumGradPerNode[nodeId]; // dL/dy somado nos pixels do nó/CC
|
|
244
|
+
const float* loc = localDerivativeOfFilterOutput_ptr + static_cast<int64_t>(nodeId) * K;
|
|
245
|
+
for (int64_t k = 0; k < K; ++k) {
|
|
246
|
+
gthr[k] += acc * loc[k];
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
return gradThresholds; // (K,)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
} // namespace mtlearn
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
#include <mmcfilters/attributes/AttributeComputedIncrementally.hpp>
|
|
5
|
+
#include <mmcfilters/trees/NodeMT.hpp>
|
|
6
|
+
#include <mmcfilters/trees/MorphologicalTree.hpp>
|
|
7
|
+
#include <mmcfilters/utils/Common.hpp>
|
|
8
|
+
|
|
9
|
+
#include "MorphologicalTreePybind.hpp"
|
|
10
|
+
#include "PybindTorchUtils.hpp"
|
|
11
|
+
|
|
12
|
+
#include <memory>
|
|
13
|
+
#include <vector>
|
|
14
|
+
#include <tuple>
|
|
15
|
+
|
|
16
|
+
#include <pybind11/pybind11.h>
|
|
17
|
+
#include <torch/extension.h>
|
|
18
|
+
#include <ATen/ops/_sparse_mm.h>
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
namespace mtlearn {
|
|
23
|
+
|
|
24
|
+
namespace py = pybind11;
|
|
25
|
+
|
|
26
|
+
using mmcfilters::AttributeComputedIncrementally;
|
|
27
|
+
using mmcfilters::InvalidNode;
|
|
28
|
+
using mmcfilters::MorphologicalTreePybindPtr;
|
|
29
|
+
using mmcfilters::NodeId;
|
|
30
|
+
|
|
31
|
+
class InfoTreePybind {
|
|
32
|
+
public:
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
static torch::Tensor getResidues(MorphologicalTreePybindPtr tree) {
|
|
36
|
+
if (!tree) {
|
|
37
|
+
throw py::value_error("MorphologicalTreePybindPtr inválido");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
int numNodes = tree->getNumNodes();
|
|
41
|
+
float* residues = new float[numNodes];
|
|
42
|
+
|
|
43
|
+
for (NodeId nodeId : tree->getNodeIds()) {
|
|
44
|
+
residues[nodeId] = static_cast<float>(tree->getResidueById(nodeId));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return PybindTorchUtils::toTensor(residues, numNodes);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
} // namespace mtlearn
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#include <pybind11/pybind11.h>
|
|
2
|
+
#include <pybind11/stl.h>
|
|
3
|
+
#include <torch/extension.h>
|
|
4
|
+
|
|
5
|
+
#include "mtlearn/core.hpp"
|
|
6
|
+
#include "ConnectedFilterByJacobian.hpp"
|
|
7
|
+
#include "ConnectedFilterByMorphologicalTree.hpp"
|
|
8
|
+
#include "InfoTreePybind.hpp"
|
|
9
|
+
|
|
10
|
+
namespace py = pybind11;
|
|
11
|
+
|
|
12
|
+
void init_ComputerDerivative(py::module& m){
|
|
13
|
+
|
|
14
|
+
py::class_<mtlearn::ConnectedFilterByJacobian>(m, "ConnectedFilterByJacobian")
|
|
15
|
+
.def_static(
|
|
16
|
+
"gradients",
|
|
17
|
+
&mtlearn::ConnectedFilterByJacobian::gradients,
|
|
18
|
+
py::arg("jacobian"),
|
|
19
|
+
py::arg("residues"),
|
|
20
|
+
py::arg("attributes"),
|
|
21
|
+
py::arg("sigmoid"),
|
|
22
|
+
py::arg("grad_output"),
|
|
23
|
+
"Aplica a jacobiana esparsa para projetar gradientes de nós para pixels.")
|
|
24
|
+
.def_static(
|
|
25
|
+
"filtering",
|
|
26
|
+
&mtlearn::ConnectedFilterByJacobian::filtering,
|
|
27
|
+
py::arg("pixel_to_node"),
|
|
28
|
+
py::arg("residues"),
|
|
29
|
+
py::arg("sigmoid"),
|
|
30
|
+
"Reconstrói a saída por pixel sem depender da árvore C++ completa.")
|
|
31
|
+
.def_static(
|
|
32
|
+
"compute_gradients_efficient",
|
|
33
|
+
&mtlearn::ConnectedFilterByJacobian::computeGradientsEfficient,
|
|
34
|
+
py::arg("pixel_to_node"),
|
|
35
|
+
py::arg("residues"),
|
|
36
|
+
py::arg("sigmoid"),
|
|
37
|
+
py::arg("attributes"),
|
|
38
|
+
py::arg("grad_output"),
|
|
39
|
+
"Gradientes otimizados usando apenas vetores auxiliares no PyTorch.");
|
|
40
|
+
|
|
41
|
+
py::class_<mtlearn::ConnectedFilterByMorphologicalTree>(m, "ConnectedFilterByMorphologicalTree")
|
|
42
|
+
.def_static(
|
|
43
|
+
"filtering",
|
|
44
|
+
&mtlearn::ConnectedFilterByMorphologicalTree::filtering,
|
|
45
|
+
py::arg("tree"),
|
|
46
|
+
py::arg("sigmoid"),
|
|
47
|
+
"Reconstrói a imagem filtrada.")
|
|
48
|
+
// --- gradientes p/ pesos e bias (assinatura antiga, 4 args) ---
|
|
49
|
+
.def_static(
|
|
50
|
+
"gradients",
|
|
51
|
+
&mtlearn::ConnectedFilterByMorphologicalTree::gradients,
|
|
52
|
+
py::arg("tree"),
|
|
53
|
+
py::arg("attributes"),
|
|
54
|
+
py::arg("sigmoid"),
|
|
55
|
+
py::arg("grad_output"),
|
|
56
|
+
"Calcula gradientes de weight e bias a partir da estrutura da árvore."
|
|
57
|
+
)
|
|
58
|
+
// --- gradiente p/ thresholds
|
|
59
|
+
.def_static(
|
|
60
|
+
"gradientsOfThresholds",
|
|
61
|
+
&mtlearn::ConnectedFilterByMorphologicalTree::gradientsOfThresholds,
|
|
62
|
+
py::arg("tree"),
|
|
63
|
+
py::arg("sigmoid"),
|
|
64
|
+
py::arg("beta"),
|
|
65
|
+
py::arg("grad_output"),
|
|
66
|
+
"Calcula gradiente dos thresholds (logits = attributes - thresholds)."
|
|
67
|
+
)
|
|
68
|
+
// --- gradiente p/ 1 threshold
|
|
69
|
+
.def_static(
|
|
70
|
+
"gradientsOfThreshold",
|
|
71
|
+
&mtlearn::ConnectedFilterByMorphologicalTree::gradientsOfThreshold,
|
|
72
|
+
py::arg("tree"),
|
|
73
|
+
py::arg("sigmoid"),
|
|
74
|
+
py::arg("beta"),
|
|
75
|
+
py::arg("grad_output"),
|
|
76
|
+
"Calcula gradiente apenas de um threshold (logits = attribute - threshold)."
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
void init_InfoTree(py::module& m)
|
|
81
|
+
{
|
|
82
|
+
|
|
83
|
+
py::class_<mtlearn::InfoTreePybind>(m, "InfoTree")
|
|
84
|
+
.def_static(
|
|
85
|
+
"get_residues",
|
|
86
|
+
&mtlearn::InfoTreePybind::getResidues,
|
|
87
|
+
py::arg("tree"),
|
|
88
|
+
"Obtém os resíduos de todos os nós da árvore como um tensor.");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
void init_tests(py::module& m)
|
|
92
|
+
{
|
|
93
|
+
py::class_<mtlearn::TreeStats>(m, "TreeStats")
|
|
94
|
+
.def(py::init<>())
|
|
95
|
+
.def_readwrite("num_nodes", &mtlearn::TreeStats::numNodes)
|
|
96
|
+
.def("describe", [](const mtlearn::TreeStats& stats) {
|
|
97
|
+
return mtlearn::describeTree(stats);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
m.def(
|
|
101
|
+
"make_tree_stats",
|
|
102
|
+
[](int numNodes) {
|
|
103
|
+
return mtlearn::makeTreeStats(numNodes);
|
|
104
|
+
},
|
|
105
|
+
py::arg("num_nodes"),
|
|
106
|
+
"Create a simple TreeStats instance using a node count.");
|
|
107
|
+
|
|
108
|
+
m.def(
|
|
109
|
+
"make_tree_tensor",
|
|
110
|
+
[](int numNodes) {
|
|
111
|
+
auto stats = mtlearn::makeTreeStats(numNodes);
|
|
112
|
+
auto tensor = torch::arange(numNodes, torch::dtype(torch::kFloat32));
|
|
113
|
+
return py::make_tuple(stats, tensor);
|
|
114
|
+
},
|
|
115
|
+
py::arg("num_nodes"),
|
|
116
|
+
"Return TreeStats and a torch tensor with a simple range.");
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
PYBIND11_MODULE(_mtlearn, m)
|
|
122
|
+
{
|
|
123
|
+
m.doc() = "Python bindings for MTLearn built on top of mmcfilters";
|
|
124
|
+
m.attr("WITH_TORCH") = true;
|
|
125
|
+
init_ComputerDerivative(m);
|
|
126
|
+
init_InfoTree(m);
|
|
127
|
+
init_tests(m);
|
|
128
|
+
}
|
|
@@ -19,14 +19,31 @@ find_package(Python3 COMPONENTS Interpreter QUIET)
|
|
|
19
19
|
if(MTLEARN_WITH_TORCH)
|
|
20
20
|
find_package(Torch REQUIRED)
|
|
21
21
|
pybind11_add_module(_mtlearn module.cpp)
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
# Filtra libs não encontradas do Torch antes de linkar
|
|
23
|
+
if(UNIX AND NOT APPLE)
|
|
24
|
+
set(FILTERED_TORCH_LIBRARIES "")
|
|
25
|
+
foreach(lib ${TORCH_LIBRARIES})
|
|
26
|
+
if(NOT lib MATCHES "-NOTFOUND$")
|
|
27
|
+
list(APPEND FILTERED_TORCH_LIBRARIES ${lib})
|
|
28
|
+
endif()
|
|
29
|
+
endforeach()
|
|
30
|
+
target_link_libraries(_mtlearn PRIVATE mtlearn::core mmcfilters::core ${FILTERED_TORCH_LIBRARIES})
|
|
31
|
+
elseif(APPLE)
|
|
32
|
+
target_link_libraries(_mtlearn PRIVATE mtlearn::core mmcfilters::core ${TORCH_LIBRARIES})
|
|
33
|
+
endif()
|
|
34
|
+
|
|
35
|
+
get_filename_component(_torch_root "${TORCH_LIBRARY}" DIRECTORY)
|
|
36
|
+
find_library(TORCH_PYTHON_LIBRARY torch_python
|
|
37
|
+
HINTS "${_torch_root}" "${_torch_root}/.." "${_torch_root}/../.."
|
|
38
|
+
PATH_SUFFIXES lib)
|
|
39
|
+
if(TORCH_PYTHON_LIBRARY)
|
|
40
|
+
target_link_libraries(_mtlearn PRIVATE "${TORCH_PYTHON_LIBRARY}")
|
|
41
|
+
endif()
|
|
42
|
+
target_include_directories(_mtlearn PRIVATE
|
|
43
|
+
${CMAKE_CURRENT_SOURCE_DIR}/../src
|
|
44
|
+
${TORCH_INCLUDE_DIRS}
|
|
45
|
+
${CMAKE_SOURCE_DIR}/external/MorphologicalAttributeFilters/pybinds)
|
|
24
46
|
target_compile_definitions(_mtlearn PRIVATE MTLEARN_WITH_TORCH=1)
|
|
25
|
-
else()
|
|
26
|
-
pybind11_add_module(_mtlearn module_stub.cpp)
|
|
27
|
-
target_link_libraries(_mtlearn PRIVATE mtlearn::core)
|
|
28
|
-
target_include_directories(_mtlearn PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../src)
|
|
29
|
-
target_compile_definitions(_mtlearn PRIVATE MTLEARN_WITH_TORCH=0)
|
|
30
47
|
endif()
|
|
31
48
|
|
|
32
49
|
set_target_properties(_mtlearn PROPERTIES OUTPUT_NAME "_mtlearn")
|