shinestacker 0.2.0.post1.dev1__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 shinestacker might be problematic. Click here for more details.

Files changed (163) hide show
  1. shinestacker-0.2.0.post1.dev1/.flake8 +4 -0
  2. shinestacker-0.2.0.post1.dev1/.github/workflows/ci-multiplatform.yml +39 -0
  3. shinestacker-0.2.0.post1.dev1/.github/workflows/release.yml +73 -0
  4. shinestacker-0.2.0.post1.dev1/.gitignore +23 -0
  5. shinestacker-0.2.0.post1.dev1/CHANGELOG.md +55 -0
  6. shinestacker-0.2.0.post1.dev1/LICENSE +1 -0
  7. shinestacker-0.2.0.post1.dev1/PKG-INFO +55 -0
  8. shinestacker-0.2.0.post1.dev1/README.md +26 -0
  9. shinestacker-0.2.0.post1.dev1/docs/alignment.md +74 -0
  10. shinestacker-0.2.0.post1.dev1/docs/balancing.md +25 -0
  11. shinestacker-0.2.0.post1.dev1/docs/focus_stacking.md +54 -0
  12. shinestacker-0.2.0.post1.dev1/docs/gui.md +131 -0
  13. shinestacker-0.2.0.post1.dev1/docs/job.md +33 -0
  14. shinestacker-0.2.0.post1.dev1/docs/main.md +116 -0
  15. shinestacker-0.2.0.post1.dev1/docs/multilayer.md +13 -0
  16. shinestacker-0.2.0.post1.dev1/docs/noise.md +47 -0
  17. shinestacker-0.2.0.post1.dev1/docs/vignetting.md +20 -0
  18. shinestacker-0.2.0.post1.dev1/examples/balance-only.fsp +1 -0
  19. shinestacker-0.2.0.post1.dev1/examples/complete-project.fsp +1 -0
  20. shinestacker-0.2.0.post1.dev1/examples/focus-stack-1.ipynb +163 -0
  21. shinestacker-0.2.0.post1.dev1/examples/focus-stack-2.ipynb +174 -0
  22. shinestacker-0.2.0.post1.dev1/examples/input/img-jpg/0000.jpg +0 -0
  23. shinestacker-0.2.0.post1.dev1/examples/input/img-jpg/0001.jpg +0 -0
  24. shinestacker-0.2.0.post1.dev1/examples/input/img-jpg/0002.jpg +0 -0
  25. shinestacker-0.2.0.post1.dev1/examples/input/img-jpg/0003.jpg +0 -0
  26. shinestacker-0.2.0.post1.dev1/examples/input/img-jpg/0004.jpg +0 -0
  27. shinestacker-0.2.0.post1.dev1/examples/input/img-jpg/0005.jpg +0 -0
  28. shinestacker-0.2.0.post1.dev1/examples/input/img-noise/0001.jpg +0 -0
  29. shinestacker-0.2.0.post1.dev1/examples/input/img-noise/0002.jpg +0 -0
  30. shinestacker-0.2.0.post1.dev1/examples/input/img-noise/0003.jpg +0 -0
  31. shinestacker-0.2.0.post1.dev1/examples/input/img-noise/0004.jpg +0 -0
  32. shinestacker-0.2.0.post1.dev1/examples/input/img-noise/0005.jpg +0 -0
  33. shinestacker-0.2.0.post1.dev1/examples/input/img-noise/0006.jpg +0 -0
  34. shinestacker-0.2.0.post1.dev1/examples/input/img-tif/0000.tif +0 -0
  35. shinestacker-0.2.0.post1.dev1/examples/input/img-tif/0001.tif +0 -0
  36. shinestacker-0.2.0.post1.dev1/examples/input/img-tif/0002.tif +0 -0
  37. shinestacker-0.2.0.post1.dev1/examples/input/img-tif/0003.tif +0 -0
  38. shinestacker-0.2.0.post1.dev1/examples/input/img-tif/0004.tif +0 -0
  39. shinestacker-0.2.0.post1.dev1/examples/input/img-tif/0005.tif +0 -0
  40. shinestacker-0.2.0.post1.dev1/examples/input/img-vignetted/vig-0000.jpg +0 -0
  41. shinestacker-0.2.0.post1.dev1/examples/input/img-vignetted/vig-0001.jpg +0 -0
  42. shinestacker-0.2.0.post1.dev1/examples/input/img-vignetted/vig-0002.jpg +0 -0
  43. shinestacker-0.2.0.post1.dev1/examples/input/img-vignetted/vig-0003.jpg +0 -0
  44. shinestacker-0.2.0.post1.dev1/examples/stack-comparison.fsp +1 -0
  45. shinestacker-0.2.0.post1.dev1/examples/stack-from-frames.fsp +1 -0
  46. shinestacker-0.2.0.post1.dev1/examples/vignetting.fsp +1 -0
  47. shinestacker-0.2.0.post1.dev1/ico/focus_stack_bkg.png +0 -0
  48. shinestacker-0.2.0.post1.dev1/ico/shinestacker.icns +0 -0
  49. shinestacker-0.2.0.post1.dev1/ico/shinestacker.ico +0 -0
  50. shinestacker-0.2.0.post1.dev1/ico/shinestacker.png +0 -0
  51. shinestacker-0.2.0.post1.dev1/img/flies.gif +0 -0
  52. shinestacker-0.2.0.post1.dev1/img/flies_stack.jpg +0 -0
  53. shinestacker-0.2.0.post1.dev1/img/flow-diagram.png +0 -0
  54. shinestacker-0.2.0.post1.dev1/img/gui-finder.png +0 -0
  55. shinestacker-0.2.0.post1.dev1/img/gui-project-new.png +0 -0
  56. shinestacker-0.2.0.post1.dev1/img/gui-project-run.png +0 -0
  57. shinestacker-0.2.0.post1.dev1/img/gui-retouch.png +0 -0
  58. shinestacker-0.2.0.post1.dev1/pyproject.toml +65 -0
  59. shinestacker-0.2.0.post1.dev1/sandbox/pypi-publish.yml +37 -0
  60. shinestacker-0.2.0.post1.dev1/sandbox/test_alignment_multiple.py +124 -0
  61. shinestacker-0.2.0.post1.dev1/scripts/build_release.py +49 -0
  62. shinestacker-0.2.0.post1.dev1/scripts/validate-tomli.py +20 -0
  63. shinestacker-0.2.0.post1.dev1/setup.cfg +4 -0
  64. shinestacker-0.2.0.post1.dev1/src/shinestacker/__init__.py +3 -0
  65. shinestacker-0.2.0.post1.dev1/src/shinestacker/_version.py +1 -0
  66. shinestacker-0.2.0.post1.dev1/src/shinestacker/algorithms/__init__.py +14 -0
  67. shinestacker-0.2.0.post1.dev1/src/shinestacker/algorithms/align.py +307 -0
  68. shinestacker-0.2.0.post1.dev1/src/shinestacker/algorithms/balance.py +367 -0
  69. shinestacker-0.2.0.post1.dev1/src/shinestacker/algorithms/core_utils.py +22 -0
  70. shinestacker-0.2.0.post1.dev1/src/shinestacker/algorithms/depth_map.py +164 -0
  71. shinestacker-0.2.0.post1.dev1/src/shinestacker/algorithms/exif.py +238 -0
  72. shinestacker-0.2.0.post1.dev1/src/shinestacker/algorithms/multilayer.py +187 -0
  73. shinestacker-0.2.0.post1.dev1/src/shinestacker/algorithms/noise_detection.py +182 -0
  74. shinestacker-0.2.0.post1.dev1/src/shinestacker/algorithms/pyramid.py +176 -0
  75. shinestacker-0.2.0.post1.dev1/src/shinestacker/algorithms/stack.py +112 -0
  76. shinestacker-0.2.0.post1.dev1/src/shinestacker/algorithms/stack_framework.py +248 -0
  77. shinestacker-0.2.0.post1.dev1/src/shinestacker/algorithms/utils.py +71 -0
  78. shinestacker-0.2.0.post1.dev1/src/shinestacker/algorithms/vignetting.py +137 -0
  79. shinestacker-0.2.0.post1.dev1/src/shinestacker/app/__init__.py +0 -0
  80. shinestacker-0.2.0.post1.dev1/src/shinestacker/app/about_dialog.py +24 -0
  81. shinestacker-0.2.0.post1.dev1/src/shinestacker/app/app_config.py +39 -0
  82. shinestacker-0.2.0.post1.dev1/src/shinestacker/app/gui_utils.py +35 -0
  83. shinestacker-0.2.0.post1.dev1/src/shinestacker/app/help_menu.py +16 -0
  84. shinestacker-0.2.0.post1.dev1/src/shinestacker/app/main.py +176 -0
  85. shinestacker-0.2.0.post1.dev1/src/shinestacker/app/open_frames.py +39 -0
  86. shinestacker-0.2.0.post1.dev1/src/shinestacker/app/project.py +91 -0
  87. shinestacker-0.2.0.post1.dev1/src/shinestacker/app/retouch.py +82 -0
  88. shinestacker-0.2.0.post1.dev1/src/shinestacker/config/__init__.py +4 -0
  89. shinestacker-0.2.0.post1.dev1/src/shinestacker/config/config.py +53 -0
  90. shinestacker-0.2.0.post1.dev1/src/shinestacker/config/constants.py +174 -0
  91. shinestacker-0.2.0.post1.dev1/src/shinestacker/config/gui_constants.py +85 -0
  92. shinestacker-0.2.0.post1.dev1/src/shinestacker/core/__init__.py +5 -0
  93. shinestacker-0.2.0.post1.dev1/src/shinestacker/core/colors.py +60 -0
  94. shinestacker-0.2.0.post1.dev1/src/shinestacker/core/core_utils.py +52 -0
  95. shinestacker-0.2.0.post1.dev1/src/shinestacker/core/exceptions.py +50 -0
  96. shinestacker-0.2.0.post1.dev1/src/shinestacker/core/framework.py +210 -0
  97. shinestacker-0.2.0.post1.dev1/src/shinestacker/core/logging.py +89 -0
  98. shinestacker-0.2.0.post1.dev1/src/shinestacker/gui/__init__.py +0 -0
  99. shinestacker-0.2.0.post1.dev1/src/shinestacker/gui/action_config.py +879 -0
  100. shinestacker-0.2.0.post1.dev1/src/shinestacker/gui/actions_window.py +283 -0
  101. shinestacker-0.2.0.post1.dev1/src/shinestacker/gui/colors.py +57 -0
  102. shinestacker-0.2.0.post1.dev1/src/shinestacker/gui/gui_images.py +152 -0
  103. shinestacker-0.2.0.post1.dev1/src/shinestacker/gui/gui_logging.py +213 -0
  104. shinestacker-0.2.0.post1.dev1/src/shinestacker/gui/gui_run.py +393 -0
  105. shinestacker-0.2.0.post1.dev1/src/shinestacker/gui/img/close-round-line-icon.png +0 -0
  106. shinestacker-0.2.0.post1.dev1/src/shinestacker/gui/img/forward-button-icon.png +0 -0
  107. shinestacker-0.2.0.post1.dev1/src/shinestacker/gui/img/play-button-round-icon.png +0 -0
  108. shinestacker-0.2.0.post1.dev1/src/shinestacker/gui/img/plus-round-line-icon.png +0 -0
  109. shinestacker-0.2.0.post1.dev1/src/shinestacker/gui/main_window.py +599 -0
  110. shinestacker-0.2.0.post1.dev1/src/shinestacker/gui/new_project.py +170 -0
  111. shinestacker-0.2.0.post1.dev1/src/shinestacker/gui/project_converter.py +148 -0
  112. shinestacker-0.2.0.post1.dev1/src/shinestacker/gui/project_editor.py +539 -0
  113. shinestacker-0.2.0.post1.dev1/src/shinestacker/gui/project_model.py +138 -0
  114. shinestacker-0.2.0.post1.dev1/src/shinestacker/retouch/__init__.py +0 -0
  115. shinestacker-0.2.0.post1.dev1/src/shinestacker/retouch/brush.py +9 -0
  116. shinestacker-0.2.0.post1.dev1/src/shinestacker/retouch/brush_controller.py +57 -0
  117. shinestacker-0.2.0.post1.dev1/src/shinestacker/retouch/brush_preview.py +126 -0
  118. shinestacker-0.2.0.post1.dev1/src/shinestacker/retouch/exif_data.py +65 -0
  119. shinestacker-0.2.0.post1.dev1/src/shinestacker/retouch/file_loader.py +104 -0
  120. shinestacker-0.2.0.post1.dev1/src/shinestacker/retouch/image_editor.py +651 -0
  121. shinestacker-0.2.0.post1.dev1/src/shinestacker/retouch/image_editor_ui.py +380 -0
  122. shinestacker-0.2.0.post1.dev1/src/shinestacker/retouch/image_viewer.py +356 -0
  123. shinestacker-0.2.0.post1.dev1/src/shinestacker/retouch/shortcuts_help.py +98 -0
  124. shinestacker-0.2.0.post1.dev1/src/shinestacker/retouch/undo_manager.py +38 -0
  125. shinestacker-0.2.0.post1.dev1/src/shinestacker.egg-info/PKG-INFO +55 -0
  126. shinestacker-0.2.0.post1.dev1/src/shinestacker.egg-info/SOURCES.txt +161 -0
  127. shinestacker-0.2.0.post1.dev1/src/shinestacker.egg-info/dependency_links.txt +1 -0
  128. shinestacker-0.2.0.post1.dev1/src/shinestacker.egg-info/entry_points.txt +4 -0
  129. shinestacker-0.2.0.post1.dev1/src/shinestacker.egg-info/requires.txt +17 -0
  130. shinestacker-0.2.0.post1.dev1/src/shinestacker.egg-info/top_level.txt +1 -0
  131. shinestacker-0.2.0.post1.dev1/tests/test-align-balance.ipynb +282 -0
  132. shinestacker-0.2.0.post1.dev1/tests/test-align.ipynb +242 -0
  133. shinestacker-0.2.0.post1.dev1/tests/test-balance.ipynb +918 -0
  134. shinestacker-0.2.0.post1.dev1/tests/test-exif.ipynb +121 -0
  135. shinestacker-0.2.0.post1.dev1/tests/test-job.ipynb +79 -0
  136. shinestacker-0.2.0.post1.dev1/tests/test-logging.ipynb +93 -0
  137. shinestacker-0.2.0.post1.dev1/tests/test-multilayer.ipynb +72 -0
  138. shinestacker-0.2.0.post1.dev1/tests/test-noise-detection.ipynb +110 -0
  139. shinestacker-0.2.0.post1.dev1/tests/test-stack.ipynb +97 -0
  140. shinestacker-0.2.0.post1.dev1/tests/test-vignetting.ipynb +154 -0
  141. shinestacker-0.2.0.post1.dev1/tests/test_0000_logging.py +66 -0
  142. shinestacker-0.2.0.post1.dev1/tests/test_0001_colors.py +32 -0
  143. shinestacker-0.2.0.post1.dev1/tests/test_0005_make_test_img.py +18 -0
  144. shinestacker-0.2.0.post1.dev1/tests/test_0010_job.py +49 -0
  145. shinestacker-0.2.0.post1.dev1/tests/test_0020_noise_detection.py +61 -0
  146. shinestacker-0.2.0.post1.dev1/tests/test_0030_align.py +62 -0
  147. shinestacker-0.2.0.post1.dev1/tests/test_0031_align_precision.py +111 -0
  148. shinestacker-0.2.0.post1.dev1/tests/test_0032_align_methods.py +60 -0
  149. shinestacker-0.2.0.post1.dev1/tests/test_0040_balance.py +90 -0
  150. shinestacker-0.2.0.post1.dev1/tests/test_0050_align_balance.py +59 -0
  151. shinestacker-0.2.0.post1.dev1/tests/test_0060_stack.py +51 -0
  152. shinestacker-0.2.0.post1.dev1/tests/test_0070_multilayer.py +60 -0
  153. shinestacker-0.2.0.post1.dev1/tests/test_0080_exif.py +90 -0
  154. shinestacker-0.2.0.post1.dev1/tests/test_0090_vignetting.py +17 -0
  155. shinestacker-0.2.0.post1.dev1/tests/test_1000_brush_mask.py +13 -0
  156. shinestacker-0.2.0.post1.dev1/tests/test_1010_gui.py +42 -0
  157. shinestacker-0.2.0.post1.dev1/tests/test_1020_gui_images.py +128 -0
  158. shinestacker-0.2.0.post1.dev1/tests/test_1030_gui_logging.py +118 -0
  159. shinestacker-0.2.0.post1.dev1/tests/test_1040_action_config.py +120 -0
  160. shinestacker-0.2.0.post1.dev1/tests/test_1050_project_converter.py +157 -0
  161. shinestacker-0.2.0.post1.dev1/tests/test_1060_gui_run.py +136 -0
  162. shinestacker-0.2.0.post1.dev1/tests/test_1070_project_editor.py +180 -0
  163. shinestacker-0.2.0.post1.dev1/tests/test_1080_actions_window.py +138 -0
@@ -0,0 +1,4 @@
1
+ [flake8]
2
+ exclude = */.ipynb_checkpoints/*,src/focusstack/_version.py
3
+ max-line-length = 160
4
+ ignore = E402
@@ -0,0 +1,39 @@
1
+ ---
2
+
3
+ name: CI multiplatform
4
+
5
+ on:
6
+ push:
7
+ branches: [main]
8
+ pull_request:
9
+ branches: [main]
10
+
11
+ jobs:
12
+ build-and-test:
13
+ permissions:
14
+ contents: read
15
+ pull-requests: write
16
+ runs-on: ${{ matrix.os }}
17
+ strategy:
18
+ matrix:
19
+ os: [ubuntu-latest, windows-latest, macos-latest]
20
+ python-version: ["3.12"]
21
+
22
+ steps:
23
+ - name: Checkout repo
24
+ uses: actions/checkout@v4
25
+
26
+ - name: Set up Python
27
+ uses: actions/setup-python@v5
28
+ with:
29
+ python-version: "3.12"
30
+
31
+ - name: Install dependencies
32
+ run: |
33
+ python -m pip install --upgrade pip setuptools
34
+ pip install -e .[dev]
35
+
36
+ - name: Run non-GUI tests (test_00*.py)
37
+ working-directory: tests
38
+ run: >
39
+ python3 -c "import glob, pytest, sys; sys.exit(pytest.main(glob.glob('test_00*.py') + ['-v', '--disable-warnings']))"
@@ -0,0 +1,73 @@
1
+ ---
2
+
3
+ name: Create new release
4
+
5
+ permissions:
6
+ contents: write
7
+ packages: write
8
+ pull-requests: write
9
+
10
+ on:
11
+ push:
12
+ tags:
13
+ - v**
14
+
15
+ jobs:
16
+ publish-release:
17
+ runs-on: ${{ matrix.os }}
18
+ strategy:
19
+ matrix:
20
+ os: [ubuntu-latest, windows-latest, macos-latest]
21
+ python-version: ["3.12"]
22
+
23
+ steps:
24
+ - name: Checkout repo
25
+ uses: actions/checkout@v4
26
+
27
+ - name: Set up Python
28
+ uses: actions/setup-python@v5
29
+ with:
30
+ python-version: "3.12"
31
+
32
+ - name: Install dependencies
33
+ run: |
34
+ python -m pip install --upgrade pip
35
+ pip install pyinstaller
36
+ pip install -e .[dev]
37
+
38
+ - name: Build and package release
39
+ working-directory: scripts
40
+ run: |
41
+ python build_release.py
42
+
43
+ - name: Upload artifact
44
+ uses: actions/upload-artifact@v4
45
+ with:
46
+ name: shinestacker-${{ matrix.os }}
47
+ path: dist/shinestacker-release.zip
48
+
49
+ create-release:
50
+ needs: publish-release
51
+ runs-on: ubuntu-latest
52
+ steps:
53
+ - name: Download all artifacts
54
+ uses: actions/download-artifact@v4
55
+ with:
56
+ path: artifacts
57
+
58
+ - name: Prepare release assets
59
+ run: |
60
+ mkdir -p release_assets
61
+ cp artifacts/shinestacker-ubuntu-latest/shinestacker-release.zip release_assets/shinestacker-ubuntu.zip
62
+ cp artifacts/shinestacker-windows-latest/shinestacker-release.zip release_assets/shinestacker-windows.zip
63
+ cp artifacts/shinestacker-macos-latest/shinestacker-release.zip release_assets/shinestacker-macos.zip
64
+ ls -la release_assets/
65
+
66
+ - name: Create release
67
+ uses: softprops/action-gh-release@v1
68
+ with:
69
+ draft: true
70
+ files: |
71
+ release_assets/shinestacker-ubuntu.zip
72
+ release_assets/shinestacker-windows.zip
73
+ release_assets/shinestacker-macos.zip
@@ -0,0 +1,23 @@
1
+ __pycache__/*
2
+ */__pycache__/*
3
+ *.pyc
4
+ .ipynb_checkpoints/*
5
+ */.ipynb_checkpoints/*
6
+ */*/.ipynb_checkpoints/*
7
+ */*/*/.ipynb_checkpoints/*
8
+ anaconda_projects
9
+ tests/output/*
10
+ tests/plots/*
11
+ tests/noise-map/*
12
+ sandbox/img-test/*
13
+ */logs/*
14
+ .DS_Store
15
+ .virtual_documents
16
+ *.egg-info/
17
+ build/
18
+ dist/
19
+ .eggs/
20
+ src/focusstack/_version.py
21
+ *~
22
+ *.spec
23
+ logs
@@ -0,0 +1,55 @@
1
+ # Changelog
2
+
3
+ This page reports the main releases only and the main changes therein.
4
+
5
+ ---
6
+
7
+ ## [v0.2.0] - 2025-07-27
8
+ **Stability improvements and new package name**
9
+
10
+ ### Changes
11
+
12
+ * first release with new name ShineStacker
13
+ * added BRISK detector/descriptor alignment method
14
+ * improved stability by adding more validation controls to alignment configuration
15
+ * some bug fixes
16
+ * minor restyling
17
+
18
+ ---
19
+
20
+ ## [v0.1.4] - 2025-07-23
21
+ **Bug fixes and alignment improvements**
22
+
23
+ ### Changes
24
+
25
+ * fixed recently introduced bugs in the alignment module
26
+ * disabled ECC refinement, too unstable
27
+ * improvement rigid alignment with more precise matrix
28
+ * some minor bug fixes
29
+ * removed dependence on termcolor external module
30
+ * some internal code cleanup
31
+
32
+ ---
33
+
34
+ ## [v0.1.1] - 2025-07-20
35
+ **Optimized image alignment**
36
+
37
+ ### Changes
38
+
39
+ * Faster alignment with image subsample enables
40
+ * Alignment refinement via ECC transform enabled
41
+ * GUI opens new project dialog at startup
42
+ * fixed color logging for windowed app
43
+ * bug fixes
44
+
45
+ ---
46
+
47
+ ## [v0.1.0] - 2025-07-19
48
+ **First relatively stable and usable GUI release**
49
+
50
+ ### Changes
51
+ - several stability improvements
52
+ - several bug fixes
53
+
54
+
55
+ ---
@@ -0,0 +1 @@
1
+ The software is provided as is under the GNU Lesser General Public License v3.0.
@@ -0,0 +1,55 @@
1
+ Metadata-Version: 2.4
2
+ Name: shinestacker
3
+ Version: 0.2.0.post1.dev1
4
+ Summary: ShineStacker
5
+ Author-email: Luca Lista <luka.lista@gmail.com>
6
+ License-Expression: LGPL-3.0
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Operating System :: OS Independent
9
+ Requires-Python: >=3.12
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: argparse
13
+ Requires-Dist: imagecodecs
14
+ Requires-Dist: ipywidgets
15
+ Requires-Dist: jsonpickle
16
+ Requires-Dist: matplotlib
17
+ Requires-Dist: numpy
18
+ Requires-Dist: opencv_python
19
+ Requires-Dist: pillow
20
+ Requires-Dist: psdtags
21
+ Requires-Dist: PySide6
22
+ Requires-Dist: scipy
23
+ Requires-Dist: tifffile
24
+ Requires-Dist: tqdm
25
+ Requires-Dist: setuptools-scm
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest; extra == "dev"
28
+ Dynamic: license-file
29
+
30
+ # Shine Stacker Processing Framework
31
+
32
+ [![CI multiplatform](https://github.com/lucalista/shinestacker/actions/workflows/ci-multiplatform.yml/badge.svg)](https://github.com/lucalista/shinestacker/actions/workflows/ci-multiplatform.yml)
33
+
34
+ <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/flies.gif' width="400"> <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/flies_stack.jpg' width="400">
35
+
36
+ ## Documentation
37
+
38
+ 📖 [Main documentation](https://github.com/lucalista/shinestacker/blob/main/docs/main.md) • 📝 [Changelog](https://github.com/lucalista/shinestacker/blob/main/CHANGELOG.md)
39
+
40
+
41
+ # Credits:
42
+
43
+ The main pyramid stack algorithm was inspired by the [Laplacian pyramids method](https://github.com/sjawhar/focus-stacking) implementation by Sami Jawhar. The latest implementation was rewritten from the original code that was used under permission of the author for initial versions of this package.
44
+
45
+ # Resources
46
+
47
+ * [Pyramid Methods in Image Processing](https://www.researchgate.net/publication/246727904_Pyramid_Methods_in_Image_Processing), E. H. Adelson, C. H. Anderson, J. R. Bergen, P. J. Burt, J. M. Ogden, RCA Engineer, 29-6, Nov/Dec 1984
48
+ Pyramid methods in image processing
49
+ * [A Multi-focus Image Fusion Method Based on Laplacian Pyramid](http://www.jcomputers.us/vol6/jcp0612-07.pdf), Wencheng Wang, Faliang Chang, Journal of Computers 6 (12), 2559, December 2011
50
+ * Another [original implementation on GitHub](https://github.com/bznick98/Focus_Stacking) by Zongnan Bao
51
+
52
+ # License
53
+
54
+ The software is provided as is under the [GNU Lesser General Public License v3.0](https://choosealicense.com/licenses/lgpl-3.0/).
55
+
@@ -0,0 +1,26 @@
1
+ # Shine Stacker Processing Framework
2
+
3
+ [![CI multiplatform](https://github.com/lucalista/shinestacker/actions/workflows/ci-multiplatform.yml/badge.svg)](https://github.com/lucalista/shinestacker/actions/workflows/ci-multiplatform.yml)
4
+
5
+ <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/flies.gif' width="400"> <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/flies_stack.jpg' width="400">
6
+
7
+ ## Documentation
8
+
9
+ 📖 [Main documentation](https://github.com/lucalista/shinestacker/blob/main/docs/main.md) • 📝 [Changelog](https://github.com/lucalista/shinestacker/blob/main/CHANGELOG.md)
10
+
11
+
12
+ # Credits:
13
+
14
+ The main pyramid stack algorithm was inspired by the [Laplacian pyramids method](https://github.com/sjawhar/focus-stacking) implementation by Sami Jawhar. The latest implementation was rewritten from the original code that was used under permission of the author for initial versions of this package.
15
+
16
+ # Resources
17
+
18
+ * [Pyramid Methods in Image Processing](https://www.researchgate.net/publication/246727904_Pyramid_Methods_in_Image_Processing), E. H. Adelson, C. H. Anderson, J. R. Bergen, P. J. Burt, J. M. Ogden, RCA Engineer, 29-6, Nov/Dec 1984
19
+ Pyramid methods in image processing
20
+ * [A Multi-focus Image Fusion Method Based on Laplacian Pyramid](http://www.jcomputers.us/vol6/jcp0612-07.pdf), Wencheng Wang, Faliang Chang, Journal of Computers 6 (12), 2559, December 2011
21
+ * Another [original implementation on GitHub](https://github.com/bznick98/Focus_Stacking) by Zongnan Bao
22
+
23
+ # License
24
+
25
+ The software is provided as is under the [GNU Lesser General Public License v3.0](https://choosealicense.com/licenses/lgpl-3.0/).
26
+
@@ -0,0 +1,74 @@
1
+ # Alignment and registration: scale, tanslation and rotation correction, or full perspective correction
2
+
3
+ ```python
4
+ job.add_action(Actions("align", [AlignFrames(*options)])
5
+ ```
6
+ Arguments for the constructor ```AlignFrames``` of are:
7
+ * ```feature_config``` (optional, default: ```None```): a dictionary specifying the following parameters, with the corresponding default values:
8
+ ```python
9
+ {
10
+ 'detector': DETECTOR_SIFT,
11
+ 'descriptor': DESCRIPTOR_SIFT
12
+ }
13
+ ```
14
+ * ```detector``` (optional): the feature detector is used to find matches. See [Feature Detection and Description](https://docs.opencv.org/4.x/db/d27/tutorial_py_table_of_contents_feature2d.html) for more details. Possible values are:
15
+ * ```DETECTOR_SIFT``` (default): [Scale-Invariant Feature Transform](https://docs.opencv.org/4.x/da/df5/tutorial_py_sift_intro.html)]
16
+ * ```DETECTOR_ORB```: [Oriented FAST and Rotated BRIEF](https://docs.opencv.org/4.x/d1/d89/tutorial_py_orb.html)
17
+ * ```DETECTOR_SURF```: [Speeded-Up Robust Features](https://docs.opencv.org/3.4/df/dd2/tutorial_py_surf_intro.html)
18
+ * ```DETECTOR_AKAZE```: [AKAZE local features matching](https://docs.opencv.org/3.4/db/d70/tutorial_akaze_matching.html)
19
+ * ```DETECTOR_BRISK```: [Binary Robust Invariant Scalable Keypoints](https://medium.com/analytics-vidhya/feature-matching-using-brisk-277c47539e8)
20
+ * ```descriptor``` (optional): the feature descriptor is used to find matches. Possible values are:
21
+ * ```DESCRIPTOR_SIFT``` (default)
22
+ * ```DESCRIPTOR_ORB```
23
+ * ```DESCRIPTOR_AKAZE```
24
+ * ```DESCRIPTPR_BRISK```
25
+
26
+ For a more quantitative comparison of performances of the different methods, consult the publication: [S. A. K. Tareen and Z. Saleem, "A comparative analysis of SIFT, SURF, KAZE, AKAZE, ORB, and BRISK", doi:10.1109/ICOMET.2018.8346440](https://ieeexplore.ieee.org/document/8346440)
27
+
28
+ ```matching_config``` (optional, default; ```None```): a dictionary specifying the following parameters, with the corresponding default values:
29
+ ```python
30
+ {
31
+ 'match_method': MATCHING_KNN,
32
+ 'flann_idx_kdtree': 2,
33
+ 'flann_trees': 5,
34
+ 'flann_checks': 50,
35
+ 'threshold': 0.75
36
+ }
37
+ ```
38
+ * ```match_method``` (optional): the method used to find matches. See [Feature Matching](https://docs.opencv.org/4.x/dc/dc3/tutorial_py_matcher.html) for more details. Possible values are:
39
+ * ```MATCHING_KNN``` (default): [Feature Matching with FLANN](https://docs.opencv.org/3.4/d5/d6f/tutorial_feature_flann_matcher.html)
40
+ * ```MATCHING_NORM_HAMMING```: [Use Hamming distance](https://docs.opencv.org/4.x/d2/de8/group__core__array.html#ggad12cefbcb5291cf958a85b4b67b6149fa4b063afd04aebb8dd07085a1207da727)
41
+ * ```flann_idx_kdtree``` (optional, default: 2): parameter used by the FLANN matching algorithm.
42
+ * ```flann_tree``` (optional, default: 5): parameter used by the FLANN matching algorithm.
43
+ * ```flann_checks``` (optional, default: 50): parameter used by the FLANN matching algorithm.
44
+ * ```threshold``` (optional, default: 0.75): parameter used to select good matches. See [Feature Matching](https://docs.opencv.org/4.x/dc/dc3/tutorial_py_matcher.html) for more details.
45
+
46
+ * ```alignment_config``` (optional, default; ```None```): a dictionary specifying the following parameters, with the corresponding default values:
47
+ ```python
48
+ {
49
+ 'transform': ALIGN_RIGID,
50
+ 'align_methid': RANSAC,
51
+ 'rans_threshold': 5.0,
52
+ 'border_mode': BORDER_REPLICATE_BLUR,
53
+ 'border_value': (0, 0, 0, 0),
54
+ 'border_blur': 50
55
+ }
56
+ ```
57
+ * ```transform``` (optional): the transformation applied to register images. Possible values are:
58
+ * ```ALIGN_RIGID``` (default): allow scale, tanslation and rotation correction. This should be used for image acquired with tripode or microscope.
59
+ * ```ALIGN_HOMOGRAPHY```: allow full perspective correction. This should be used for images taken with hand camera.
60
+ * ```align_method``` (optional): the method used to find matches. Valid options are:
61
+ * ```RANSAC``` (*Random Sample Consensus*)
62
+ * ```LMEDS``` (*Least Medians of Squares*)
63
+ * ```rans_threshold``` (optional, default: 5.0): parameter used if ```ALIGN_HOMOGRAPHY``` is choosen as tansformation, see [Feature Matching + Homography to find Objects](https://docs.opencv.org/3.4/d1/de0/tutorial_py_feature_homography.html) for more details.
64
+ * ```subsample``` (optional, default: 4): subsample image for faster alignment. Faster, but alignment could be less accurate.
65
+ * ```fast_subsampling``` (optiona, default: ```False```): perform fast image subsampling without interpolation. Used if ```subsample``` is set to ```True```.
66
+ * ```border_mode``` (optional, default: ```BORDER_REPLICATE_BLUR```): border mode. See [Adding borders to your images](https://docs.opencv.org/3.4/dc/da3/tutorial_copyMakeBorder.html) for more details. Possible values are:
67
+ * ```BORDER_CONSTANT```: pad the image with a constant value. The border value is specified with the parameter ```border_value```.
68
+ * ```BORDER_REPLICATE```: the rows and columns at the very edge of the original are replicated to the extra border.
69
+ * ```BORDER_REPLICATE_BLUR``` (default): same as above, but the border is blurred. The amount of blurring is specified by the parameter ```border_blur```.
70
+ * ```border_value``` (optional, default: ```(0, 0, 0, 0)```): border value. See [Adding borders to your images](https://docs.opencv.org/3.4/dc/da3/tutorial_copyMakeBorder.html) for more details.
71
+ * ```border_blur``` (optional, default: ```50```): amount of border blurring, in pixels. Only applied if ```border_mode``` is set to ```BORDER_REPLICATE_BLUR```, which is the default option.
72
+ * ```plot_summary``` (optional, default: ```False```): if ```True```, plot a summary histogram with number of matches in each frame. May be useful for inspection and debugging.
73
+ * ```plot_matches``` (optional, default: ```False```): if ```True```, for each image matches with reference frame are drawn. May be useful for inspection and debugging.
74
+ * ```enabled``` (optional, default: ```True```): allows to switch on and off this module.
@@ -0,0 +1,25 @@
1
+ # Luminosity and color balance
2
+
3
+ ```python
4
+ job.add_action(Actions("balance", [BalanceFrames(*options)])
5
+ ```
6
+
7
+ Arguments for the constructor of ```BalanceFrames``` are:
8
+ *```channel``` (optional, default: BALANCE_LUMI): channels to be balanced. Possible values are: ```BALANCE_LUMI``` (default): balance equally for R, G and B channels, should be reasonably fine for most of the cases; ```BALANCE_RGB```: balance luminosity separately for R, G and B channels, it may be needed if some but not all of the images have a undesired color dominance; ```BALANCE_HSV```: balance saturation a luminosity value in the HSV (Hue, Saturation, brightness Value) representation, it may be needed in cases of extreme luminosity variation that affects saturation; ```BALANCE_HLS```: balance saturation a luminosity value in the HLS (Hue, Lightness, Saturation) representation, it may be needed in cases of extreme luminosity variation that affects saturation. Note that ```BALANCE_HSV``` and ```BALANCE_HLS``` are only supported for 8-bit images.
9
+ * ```mask_size``` (optional): if specified, luminosity and color balance is only applied to pixels within a circle of radius equal to the minimum between the image width and height times ```mask_size```, i.e: 0.8 means 80% of a portrait image width or landscape image height. It may beuseful for images with vignetting, in order to avoid including in the balance processing the outer darker pixels.
10
+ * ```intensity_interval``` (optional): if specifies, only pixels with intensity within the specified range are used. It may be useful to remove very dark areas or very light areas. Not used if ```MATCH_HIST``` is specified as value for ```corr_map```. The argument has to be a dictionary where one or both values corresponding to the keys ```min``` and ```max``` can be specified. The default values are:
11
+ ```python
12
+ {
13
+ 'min': 0,
14
+ 'max': -1
15
+ }
16
+ ```
17
+ Note that for 8-bit images the maximum intensity is 255, while for 16-bit images the maximum intensity is 65536.
18
+ * ```subsample``` (optional, default: 8): extracts intensity histogram using every n-th pixel in each dimension in order to reduce processing time. By default, it takes one every 8 pixels in horizontal and vertical directions, i.e.: one every 100 pixels in total. This option is not ised if ```corr_map``` is equal to ```BALANCE_MATCH_HIST```.
19
+ * ```corr_map``` (optional, default: ```BALANCE_LINEAR```, possible values: ```BALANCE_LINEAR```, ```BALANCE_GAMMA``` and ```MATCH_HIST```): specifies the type of intensity correction.
20
+ * ```BALANCE_LINEAR```: a linear correction is applied in order to balance the average intensity of the corrected images to the reference image in the specified channels.
21
+ * ```BALANCE_GAMMA```: a gamma correction, i.e.: a power law, is applied in order to balance the average intensity of the corrected images to reference image in the specified channels. The gamma correction avoids saturation of low or high intensity pixels which may occur for a linear coorection, but may introduce more distortion than a linear mapping.
22
+ * ```BALANCE_MATCH_HIST```: the intensity histogram of the corrected image matches the histogram of the reference image in the specified channels. This options shoudl better be used with the value ```BALANCE_RGB``` for the ```channel``` option. If this option is specified, the options ```intensity_interval``` and ```subsample```are not used. This option may be somewhat slow for 16-bit images.
23
+ * ```plot_histograms``` (optional, default: ```False```): if ```True```, plot hisograms for each image and for the reference frame.
24
+ * ```plot_summary``` (optional, default: ```False```): if ```True```, plot a summary of the corrections.
25
+ * ```enabled``` (optional, default: ```True```): allows to switch on and off this module.
@@ -0,0 +1,54 @@
1
+ # Focus Stacking
2
+
3
+ ```python
4
+ job.add_action(FocusStack(name, stacker, *options))
5
+ ```
6
+ Arguments for the constructor of ```FocusStack``` are:
7
+ * ```name```: the name of the action, used for printout, and possibly for output path
8
+ * ```stacker```: an object defining the focus stacking algorithm. Can be ```PyramidStack```, ```PyramidBlock``` or ```DepthMapStack```, see below for possible algorithms.
9
+ * ```input_path``` (optional): the subdirectory within ```working_path``` that contains input images to be processed. If not specified, the last output path is used, or, if this is the first action, the ```input_path``` specified with the ```StackJob``` construction is used. If the ```StackJob``` specifies no ```input_path```, at least the first action must specify an ```input_path```.
10
+ * ```output_path``` (optional): the subdirectory within ```working_path``` where aligned images are written. If not specified, it is equal to ```name```.
11
+ * ```working_path```: the directory that contains input and output image subdirectories. If not specified, it is the same as ```job.working_path```.
12
+ * ```exif_path``` (optional): if specified, EXIF data are copied to the output file from file in the specified directory. If not specified, it is the source directory used as input for the first action. If set equal to ```''``` no EXIF data is saved.
13
+ * ```denoise``` (optoinal): if specified, a denois algorithm is applied. A value of 0.75 to 1.00 does not reduce details in an appreciable way, and is suitable for modest noise reduction. denoise may be useful for 8-bit images, or for images taken at large ISO. 16-bits images at low ISO usually don't require denoise. See [Image Denoising](https://docs.opencv.org/3.4/d5/d69/tutorial_py_non_local_means.html) for more details.
14
+ * ```prefix``` (optional): if specified, the specified string is pre-pended to the file name. May be useful if more algorithms are ran, and different file names are used for the output of different algorithms.
15
+ * ```enabled``` (optional, default: ``True```): allows to switch on and off this module.
16
+
17
+ ## Focus Stacking in bunches of frames
18
+
19
+ ```python
20
+ job.add_action(FocusStackBunch(name, stacker, *options))
21
+ ```
22
+ Arguments for the constructor of ```FocusStackBunch``` are:
23
+ * ```name```: the name of the action, used for printout, and possibly for output path
24
+ * ```stacker```: an object defining the focus stacking algorithm. Can be ```PyramidStack```, ```PyramidStack``` or ```DepthMapStack```, see below for possible algorithms.
25
+ * ```input_path``` (optional): the subdirectory within ```working_path``` that contains input images to be processed. If not specified, the last output path is used, or, if this is the first action, the ```input_path``` specified with the ```StackJob``` construction is used. If the ```StackJob``` specifies no ```input_path```, at least the first action must specify an ```input_path```.
26
+ * * ```output_path``` (optional): the subdirectory within ```working_path``` where aligned images are written. If not specified, it is equal to ```name```.
27
+ * ```working_path```: the directory that contains input and output image subdirectories. If not specified, it is the same as ```job.working_path```.
28
+ * ```exif_path``` (optional): if specified, EXIF data are copied to the output file from file in the specified directory. If not specified, it is the source directory used as * ```frames``` (optional, default: 10): the number of frames in each bunch that are stacked together.
29
+ * ```frames``` (optional, default: 10): the number of frames that are fused together.
30
+ * ```overlap``` (optional, default: 0): the number of overlapping frames between a bunch and the following one.
31
+ * ```denoise``` (optoinal): if specified, a denois algorithm is applied. A value of 0.75 to 1.00 does not reduce details in an appreciable way, and is suitable for modest noise reduction. See [Image Denoising](https://docs.opencv.org/3.4/d5/d69/tutorial_py_non_local_means.html) for more details
32
+ * ```prefix``` (optional): if specified, the specified string is pre-pended to the file name. May be useful if more algorithms are ran, and different file names are used for the output of different algorithms.
33
+ * ```enabled``` (optional, default: ```True```): allows to switch on and off this module.
34
+
35
+ ## Stack algorithms
36
+
37
+ ```PyramidStack```, Laplacian pyramid focus stacking algorithm, optimized implementation
38
+
39
+ Arguments for the constructor are:
40
+ * ```pyramid_min_size``` (optional, default: 32)
41
+ * ```kernel_size``` (optional, default: 5)
42
+ * ```gen_kernel``` (optional, default: 0.4)
43
+ * ```float_type``` (optional, default: ```FLOAT_32```, possible values: ```FLOAT_32```, ```FLOAT_64```): precision for internal image representation
44
+
45
+ ```DepthMapStack```, Depth map focus stacking algorithm
46
+
47
+ Arguments for the constructor are:
48
+ * ```map_type``` (optional), possible values are ```MAP_MAX``` (default) and ```MAP_AVERAGE```. ```MAP_MAX``` select for wach pixel the layer which has the best focus. ```MAP_AVERAGE``` performs for each pixel an average of all layers weighted by the quality of focus.
49
+ * ```energy``` (optional), possible values are ```ENERGY_LAPLACIAN``` (default) and ```ENERGY_SOBEL```.
50
+ * ```kernel_size``` (optional, default: 5) size in pixels of Laplacian kernel.
51
+ * ```blur_size``` (optional, default: 5) size in pixels of the pre-Laplacian Gaussian blur.
52
+ * ```smooth_size``` (optional, default: 15) size of energy smoothing.
53
+ * ```temperature``` (optional, default: 0.1) controls fision transition: lower value means sharper transitions.
54
+ * ```levels``` (optional, defauls: 3) number of levels for the Laplacian pyramid.
@@ -0,0 +1,131 @@
1
+ # Graphical User Interface
2
+
3
+ ## Introduction
4
+ FocusStack processes focus-bracketed images in two phases:
5
+ * **Project**: Batch processing (alignment/balancing/stacking)
6
+ * **Retouch**: Layer-based refinement
7
+ > [!NOTE]
8
+ > Advanced processing details in [main documentation](main.md).
9
+
10
+ The batch processing supports image alignment, color and luminosity balance, vignetting removal,
11
+ noisy pixel masking.
12
+
13
+ ## Starting
14
+
15
+ * If the python package is donwloaded and installed, the GUI can start either from a console command line :
16
+
17
+ ```console
18
+ > focusstack
19
+ ```
20
+
21
+ * If the app is dowloaded from the [releases page](https://github.com/lucalista/focusstack/releases), after the ```zip``` archive is uncompressed, just double-click the app icon.
22
+
23
+ <img src='../img/gui-finder.png' width="300">
24
+
25
+ **Platform Tip**: Windows apps are inside `/focusstack/`, macOS/Linux apps are directly in the uncompressed folder.
26
+
27
+ The GUI has two main working areas:
28
+
29
+ * *Project*
30
+ * *Retouch*
31
+
32
+ Switching from *Project* to *Retouch* can be done from the *FocusStack* main menu.
33
+
34
+ ## Project area
35
+
36
+ When the app starts, it proposes to create a new project.
37
+
38
+ <img src='../img/gui-project-new.png' width="600">
39
+
40
+ ### Creating Projects
41
+ 1. Select source folder (JPEG/TIFF 8/16-bit)
42
+ 2. Configure job actions (auto-saved in project file)
43
+ 3. Run processing:
44
+ - Real-time logs & progress bar
45
+ - Thumbnail previews for each stage
46
+
47
+ <img src='../img/flow-diagram.png' width="900" alt="FocusStack workflow: Source images → Alignment → Balancing → Stacking">
48
+
49
+ > **Large Set Tip**: For 100+ images:
50
+ > - Split into 10-15 image "bunches"
51
+ > - Set frame overlap (default: 2 frames)
52
+ > - Combine intermediate results later
53
+
54
+ > 💡 **RAM Warning**: >15 images may need 16GB+ RAM. Use smaller batches if needed.
55
+
56
+ The newly created project consists of a single job that contains more actions.
57
+ Each action produces a folder as output that has, by default, the action's name.
58
+ Some actions can be combined in order to produce a single intermediate output (alignment, balancing, etc.).
59
+
60
+ **Action Outputs**: 📁 `aligned-balanced/` | 📁 `bunches/` | 📁 `stacked/`
61
+
62
+ > **Pro Tip**: Duplicate jobs when processing similar image sets to save configuration time. You can run multiple jobs in sequence.
63
+
64
+ It is possible to run a single job, or all jobs within a project.
65
+
66
+ <img src='../img/gui-project-run.png' width="600">
67
+
68
+ ### Project Run Tabs
69
+
70
+ 1. Job progress bar
71
+ 2. Real-time log viewer
72
+ 3. Retouch button (enabled after processing)
73
+
74
+ When the job finishes, a *Retouch* button is enabled, which opens the output image into the retouch area.
75
+
76
+ ## Retouch area
77
+
78
+ <img src='../img/gui-retouch.png' width="600">
79
+
80
+ ### Brush Properties
81
+ Adjust in the top toolbar:
82
+ - **Size**: Brush diameter (px)
83
+ - **Hardness**: Edge softness (0-100%)
84
+ - **Opacity**: Paint transparency
85
+ - **Flow**: Paint accumulation rate
86
+
87
+ > 💡 Pro Tip: Use low opacity/flow (20-40%) for subtle corrections
88
+
89
+ ### Retouch Workflow
90
+
91
+ 1. **Navigate**:
92
+ - Zoom/pan to defect area
93
+ - Toggle between master/source (`X`)
94
+ 2. **Correct defects/artifacts**:**:
95
+ - Select source layer with clean area
96
+ - Adjust brush properties (size/hardness/opacity)
97
+ - Paint over defects
98
+ - Use `Ctrl+Z` to undo strokes
99
+ 3. **Verify**:
100
+ - Toggle master view (`M`) to check results
101
+ - Compare before/after with `L`/`M` toggle
102
+ 3. **Export**:
103
+ - ✅ Final image: Single TIFF/JPEG
104
+ - 🗂️ Editable: Multilayer TIFF (large)
105
+
106
+ | Action | Shortcut |
107
+ |---------------------|---------------------------|
108
+ | Zoom in/out | `Ctrl` + `+`/`- or mouse wheel |
109
+ | Reset view | `Ctrl` + `0` |
110
+ | Pan | `Space` + mouse drag |
111
+ | Prev./next layer | `Up`/`Down` arrows |
112
+ | View master layer | `M` |
113
+ | View source layer | `L` |
114
+ | Toggle master ↔ source | `X` |
115
+
116
+ See help menu for complete list of shortcuts.
117
+
118
+ **Export Formats**:
119
+ - Single TIFF: Final image (highest quality)
120
+ - Single JPEG: For web and quick preview (lower quality)
121
+ - Multilayer TIFF: Preserves all layers (large file)
122
+
123
+ **EXIF metadata**:
124
+ * EXIF data can be imported from source images and saved with final file.
125
+
126
+ ## Final retouch
127
+
128
+ The final retouch, including color and luminosity balance, sharpness enhancement and
129
+ so on can be applied with your favorite image processing application, like [GIMP](https://www.gimp.org/)
130
+ or other.
131
+
@@ -0,0 +1,33 @@
1
+ # Job creation
2
+
3
+ Create a job, then schedule the desired actions in a job, then run the job.
4
+
5
+ ```python
6
+ job = StackJob(name, working_path [, input_path])
7
+ ```
8
+
9
+ Arguments are:
10
+ * ```working_path```: the directory that contains input and output images, organized in subdirectories as specified by each action
11
+ * ```name```: the name of the job, used for printout
12
+ * ```input_path``` (optional): the subdirectory within ```working_path``` that contains input images for subsequent action. If not specified, at least the first action must specify an ```input_path```.
13
+ * ```callbacks``` (optional, default: ```None```): dictionary of callback functions for internal use. If equal to ```'tqdm'```, a progress bar is shown in either text mode or jupyter notebook.
14
+ * ```enabled``` (optional, default: ```True```): allows to switch on and off all actions within a job.
15
+
16
+ # Schedule multiple actions based on a reference image: align and/or balance images
17
+
18
+ The class ```CombinedActions``` runs multiple actions on each of the frames appearing in a path.
19
+
20
+ ```python
21
+ job.add_action(CombinedActions(name, [...], *options))
22
+ ```
23
+ Arguments for the constructor of ```CombinedActions``` are for the :
24
+ * ```name```: the name of the action, used for printout, and possibly for output path.
25
+ * ```actions```: array of action object to be applied in cascade.
26
+ * ```input_path``` (optional): the subdirectory within ```working_path``` that contains input images to be processed. If not specified, the last output path is used, or, if this is the first action, the ```input_path``` specified with the ```StackJob``` construction is used. If the ```StackJob``` specifies no ```input_path```, at least the first action must specify an ```input_path```.
27
+ * ```output_path``` (optional): the subdirectory within ```working_path``` where aligned images are written. If not specified, it is equal to ```name```.
28
+ * ```working_path``` (optional): the directory that contains input and output image subdirectories. If not specified, it is the same as ```job.working_path```.
29
+ * ```plot_path``` (optional, default: ```plots```): the directory within ```working_path``` that contains plots produced by the different actions.
30
+ * ```resample``` (optional, default: 1): take every *n*<sup>th</sup> frame in the selected directory. Default: take all frames.
31
+ * ```ref_idx``` (optional): the index of the image used as reference. Images are numbered starting from zero. If not specified, it is the index of the middle image.
32
+ * ```step_process``` (optional): if equal to ```True``` (default), each image is processed with respect to the previous or next image, depending if its file is placed in alphabetic order after or befor the reference image.
33
+ * ```enabled``` (optional, default: ```True```): allows to switch on and off this module.