PyHoloscope 1.0.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.
- pyholoscope-1.0.0/PKG-INFO +94 -0
- pyholoscope-1.0.0/README.md +75 -0
- pyholoscope-1.0.0/pyproject.toml +32 -0
- pyholoscope-1.0.0/setup.cfg +4 -0
- pyholoscope-1.0.0/src/PyHoloscope.egg-info/PKG-INFO +94 -0
- pyholoscope-1.0.0/src/PyHoloscope.egg-info/SOURCES.txt +22 -0
- pyholoscope-1.0.0/src/PyHoloscope.egg-info/dependency_links.txt +1 -0
- pyholoscope-1.0.0/src/PyHoloscope.egg-info/requires.txt +6 -0
- pyholoscope-1.0.0/src/PyHoloscope.egg-info/top_level.txt +1 -0
- pyholoscope-1.0.0/src/pyholoscope/__init__.py +27 -0
- pyholoscope-1.0.0/src/pyholoscope/focus_shift.py +90 -0
- pyholoscope-1.0.0/src/pyholoscope/focus_stack.py +212 -0
- pyholoscope-1.0.0/src/pyholoscope/focusing.py +730 -0
- pyholoscope-1.0.0/src/pyholoscope/focusing_numba.py +105 -0
- pyholoscope-1.0.0/src/pyholoscope/general.py +246 -0
- pyholoscope-1.0.0/src/pyholoscope/holo_class.py +1091 -0
- pyholoscope-1.0.0/src/pyholoscope/off_axis.py +404 -0
- pyholoscope-1.0.0/src/pyholoscope/phase_proc.py +290 -0
- pyholoscope-1.0.0/src/pyholoscope/prop_lut.py +135 -0
- pyholoscope-1.0.0/src/pyholoscope/propagator.py +87 -0
- pyholoscope-1.0.0/src/pyholoscope/roi.py +101 -0
- pyholoscope-1.0.0/src/pyholoscope/sim.py +67 -0
- pyholoscope-1.0.0/src/pyholoscope/utils.py +325 -0
- pyholoscope-1.0.0/src/pyholoscope/windows.py +178 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: PyHoloscope
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python package for holographic microscopy.
|
|
5
|
+
Author-email: Michael Hughes <m.r.hughes@kent.ac.uk>
|
|
6
|
+
Project-URL: Homepage, https://github.com/MikeHughesKent/PyHoloscope/
|
|
7
|
+
Keywords: holographic,microscopy,microscopy,holography,inline holography,off-axis holography
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Programming Language :: Python
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
Requires-Dist: matplotlib>=3.3.4
|
|
14
|
+
Requires-Dist: numba>=0.55.1
|
|
15
|
+
Requires-Dist: numpy>=1.22
|
|
16
|
+
Requires-Dist: opencv_python>=4.5
|
|
17
|
+
Requires-Dist: Pillow>=9
|
|
18
|
+
Requires-Dist: scipy>=1.7
|
|
19
|
+
|
|
20
|
+

|
|
21
|
+
[](https://opensource.org/licenses/MIT)
|
|
22
|
+
|
|
23
|
+

|
|
24
|
+
# PyHololoscope: Fast Holographic Microscopy for Python
|
|
25
|
+
|
|
26
|
+
PyHoloscope is a Python package for holographic microscopy, providing perfomant reconstruction of inline and off-axis holograms.
|
|
27
|
+
|
|
28
|
+
It is currently pre-release, aiming for release 1.0.0 before end of 2025.
|
|
29
|
+
|
|
30
|
+
PyHoloscope is designed to be:
|
|
31
|
+
* Fast (for Python) - optmised for CPU using Numpy, Scipy and Numba, with GPU support via CuPy
|
|
32
|
+
* Easy to Use - a simple object-oriented API gives high performance without low-level tweaks
|
|
33
|
+
* Suitable for Live Imaging - can be used as the back-end of holographic microscopy GUIs as well as for offline processing
|
|
34
|
+
|
|
35
|
+
Full documentation is on [Read the docs](https://pyholoscope.readthedocs.io/en/latest/index.html).
|
|
36
|
+
|
|
37
|
+
Also see the examples in the [examples folder](https://github.com/MikeHughesKent/PyHoloscope/tree/main/examples).
|
|
38
|
+
|
|
39
|
+
Contributions to the package (new features, tests or documentation) as very welcome, please see the roadmap below and post in the discussion if you are working on something, or [get in touch](mailto:m.r.hughes@kent.ac.uk).
|
|
40
|
+
|
|
41
|
+
Development is co-ordinated by [Mike Hughes](https://research.kent.ac.uk/applied-optics/hughes/)' lab in the
|
|
42
|
+
[Applied Optics Group](https://research.kent.ac.uk/applied-optics), Physics & Astronomy, University of Kent.
|
|
43
|
+
|
|
44
|
+
If you are interested in academic applications we are happy to help, post in the discussion. If you would like help using PyHoloscope for commercial purposes, consultancy is available, please contact [Mike Hughes](mailto:m.r.hughes@kent.ac.uk) in the first instance.
|
|
45
|
+
|
|
46
|
+
## Features
|
|
47
|
+
|
|
48
|
+
### General
|
|
49
|
+
* Object-oriented interface
|
|
50
|
+
* Choice of single or double precision
|
|
51
|
+
* Support for CUDA compatible GPUs
|
|
52
|
+
* Optional use of Numba JIT compiler
|
|
53
|
+
* Supports non-square holograms
|
|
54
|
+
|
|
55
|
+
### Off Axis Holography
|
|
56
|
+
* Quantitatave phase and amplitude recovery from off-axis hologram
|
|
57
|
+
* Auto detect off-axis modulation frequency
|
|
58
|
+
* Predict tilt angle from modulation frequency
|
|
59
|
+
|
|
60
|
+
### Numerical Refocusing (Inline and Off-axis Holgoraphy)
|
|
61
|
+
* Refocus holograms or complex fields using the angular spectrum method
|
|
62
|
+
* Choice of cosine windows to reduce edge effects
|
|
63
|
+
* Generate stack of images at different refocus depths
|
|
64
|
+
* Apply focus metrics (Brenner, Sobel, Peak Intensity, DarkFocus, SobelVariance)
|
|
65
|
+
* Auto focus whole image or ROI by optimising focus metric, through fast bounded search and (optionally) initial coarse search to narrow search range.
|
|
66
|
+
* Generate LUT of propagators for faster auto-focus or repeated generation of focus stacks.
|
|
67
|
+
|
|
68
|
+
### Phase Visualation
|
|
69
|
+
* Remove background phase
|
|
70
|
+
* Remove phase tilt
|
|
71
|
+
* Show phase relative to region of interest
|
|
72
|
+
* Generate phase contrast image
|
|
73
|
+
* Generate synthetic DIC image
|
|
74
|
+
|
|
75
|
+
## Roadmap of Planned Developments (help welcome!)
|
|
76
|
+
|
|
77
|
+
- [ ] Phase recovery for inline holography
|
|
78
|
+
- [ ] Improved optimisation for speed/multiple back-ends
|
|
79
|
+
- [ ] Support phase-shifting holography
|
|
80
|
+
- [ ] Support coded aperture/multi-depth phase recovery
|
|
81
|
+
- [ ] Support forward scattering and inference
|
|
82
|
+
- [ ] Support particle tracking
|
|
83
|
+
- [ ] Deep learning for focusing
|
|
84
|
+
- [ ] Targeted support for edge computing (e.g. Raspberry Pi)
|
|
85
|
+
|
|
86
|
+
## Requirements
|
|
87
|
+
* Numpy
|
|
88
|
+
* Scipy
|
|
89
|
+
* PIL
|
|
90
|
+
* OpenCV
|
|
91
|
+
* Scikit-Image
|
|
92
|
+
* Matplotlib
|
|
93
|
+
* Numba (optional, for JIT acceleration)
|
|
94
|
+
* CuPy (optional, for GPU)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+

|
|
2
|
+
[](https://opensource.org/licenses/MIT)
|
|
3
|
+
|
|
4
|
+

|
|
5
|
+
# PyHololoscope: Fast Holographic Microscopy for Python
|
|
6
|
+
|
|
7
|
+
PyHoloscope is a Python package for holographic microscopy, providing perfomant reconstruction of inline and off-axis holograms.
|
|
8
|
+
|
|
9
|
+
It is currently pre-release, aiming for release 1.0.0 before end of 2025.
|
|
10
|
+
|
|
11
|
+
PyHoloscope is designed to be:
|
|
12
|
+
* Fast (for Python) - optmised for CPU using Numpy, Scipy and Numba, with GPU support via CuPy
|
|
13
|
+
* Easy to Use - a simple object-oriented API gives high performance without low-level tweaks
|
|
14
|
+
* Suitable for Live Imaging - can be used as the back-end of holographic microscopy GUIs as well as for offline processing
|
|
15
|
+
|
|
16
|
+
Full documentation is on [Read the docs](https://pyholoscope.readthedocs.io/en/latest/index.html).
|
|
17
|
+
|
|
18
|
+
Also see the examples in the [examples folder](https://github.com/MikeHughesKent/PyHoloscope/tree/main/examples).
|
|
19
|
+
|
|
20
|
+
Contributions to the package (new features, tests or documentation) as very welcome, please see the roadmap below and post in the discussion if you are working on something, or [get in touch](mailto:m.r.hughes@kent.ac.uk).
|
|
21
|
+
|
|
22
|
+
Development is co-ordinated by [Mike Hughes](https://research.kent.ac.uk/applied-optics/hughes/)' lab in the
|
|
23
|
+
[Applied Optics Group](https://research.kent.ac.uk/applied-optics), Physics & Astronomy, University of Kent.
|
|
24
|
+
|
|
25
|
+
If you are interested in academic applications we are happy to help, post in the discussion. If you would like help using PyHoloscope for commercial purposes, consultancy is available, please contact [Mike Hughes](mailto:m.r.hughes@kent.ac.uk) in the first instance.
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
### General
|
|
30
|
+
* Object-oriented interface
|
|
31
|
+
* Choice of single or double precision
|
|
32
|
+
* Support for CUDA compatible GPUs
|
|
33
|
+
* Optional use of Numba JIT compiler
|
|
34
|
+
* Supports non-square holograms
|
|
35
|
+
|
|
36
|
+
### Off Axis Holography
|
|
37
|
+
* Quantitatave phase and amplitude recovery from off-axis hologram
|
|
38
|
+
* Auto detect off-axis modulation frequency
|
|
39
|
+
* Predict tilt angle from modulation frequency
|
|
40
|
+
|
|
41
|
+
### Numerical Refocusing (Inline and Off-axis Holgoraphy)
|
|
42
|
+
* Refocus holograms or complex fields using the angular spectrum method
|
|
43
|
+
* Choice of cosine windows to reduce edge effects
|
|
44
|
+
* Generate stack of images at different refocus depths
|
|
45
|
+
* Apply focus metrics (Brenner, Sobel, Peak Intensity, DarkFocus, SobelVariance)
|
|
46
|
+
* Auto focus whole image or ROI by optimising focus metric, through fast bounded search and (optionally) initial coarse search to narrow search range.
|
|
47
|
+
* Generate LUT of propagators for faster auto-focus or repeated generation of focus stacks.
|
|
48
|
+
|
|
49
|
+
### Phase Visualation
|
|
50
|
+
* Remove background phase
|
|
51
|
+
* Remove phase tilt
|
|
52
|
+
* Show phase relative to region of interest
|
|
53
|
+
* Generate phase contrast image
|
|
54
|
+
* Generate synthetic DIC image
|
|
55
|
+
|
|
56
|
+
## Roadmap of Planned Developments (help welcome!)
|
|
57
|
+
|
|
58
|
+
- [ ] Phase recovery for inline holography
|
|
59
|
+
- [ ] Improved optimisation for speed/multiple back-ends
|
|
60
|
+
- [ ] Support phase-shifting holography
|
|
61
|
+
- [ ] Support coded aperture/multi-depth phase recovery
|
|
62
|
+
- [ ] Support forward scattering and inference
|
|
63
|
+
- [ ] Support particle tracking
|
|
64
|
+
- [ ] Deep learning for focusing
|
|
65
|
+
- [ ] Targeted support for edge computing (e.g. Raspberry Pi)
|
|
66
|
+
|
|
67
|
+
## Requirements
|
|
68
|
+
* Numpy
|
|
69
|
+
* Scipy
|
|
70
|
+
* PIL
|
|
71
|
+
* OpenCV
|
|
72
|
+
* Scikit-Image
|
|
73
|
+
* Matplotlib
|
|
74
|
+
* Numba (optional, for JIT acceleration)
|
|
75
|
+
* CuPy (optional, for GPU)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# pyproject.toml
|
|
2
|
+
|
|
3
|
+
[build-system]
|
|
4
|
+
requires = ["setuptools>=61.0.0", "wheel"]
|
|
5
|
+
build-backend = "setuptools.build_meta"
|
|
6
|
+
|
|
7
|
+
[project]
|
|
8
|
+
name = "PyHoloscope"
|
|
9
|
+
version = "1.0.0"
|
|
10
|
+
description = "Python package for holographic microscopy."
|
|
11
|
+
readme = "README.md"
|
|
12
|
+
authors = [{ name = "Michael Hughes", email = "m.r.hughes@kent.ac.uk" }]
|
|
13
|
+
license = { file = "LICENSE" }
|
|
14
|
+
classifiers = [
|
|
15
|
+
"License :: OSI Approved :: MIT License",
|
|
16
|
+
"Programming Language :: Python",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
]
|
|
19
|
+
keywords = ["holographic", "microscopy", "microscopy", "holography", "inline holography", "off-axis holography"]
|
|
20
|
+
dependencies = [
|
|
21
|
+
"matplotlib>=3.3.4",
|
|
22
|
+
"numba>=0.55.1",
|
|
23
|
+
"numpy >= 1.22",
|
|
24
|
+
"opencv_python>=4.5",
|
|
25
|
+
"Pillow>=9",
|
|
26
|
+
"scipy>=1.7"
|
|
27
|
+
]
|
|
28
|
+
requires-python = ">=3.8"
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
Homepage = "https://github.com/MikeHughesKent/PyHoloscope/"
|
|
32
|
+
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: PyHoloscope
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python package for holographic microscopy.
|
|
5
|
+
Author-email: Michael Hughes <m.r.hughes@kent.ac.uk>
|
|
6
|
+
Project-URL: Homepage, https://github.com/MikeHughesKent/PyHoloscope/
|
|
7
|
+
Keywords: holographic,microscopy,microscopy,holography,inline holography,off-axis holography
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Programming Language :: Python
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
Requires-Dist: matplotlib>=3.3.4
|
|
14
|
+
Requires-Dist: numba>=0.55.1
|
|
15
|
+
Requires-Dist: numpy>=1.22
|
|
16
|
+
Requires-Dist: opencv_python>=4.5
|
|
17
|
+
Requires-Dist: Pillow>=9
|
|
18
|
+
Requires-Dist: scipy>=1.7
|
|
19
|
+
|
|
20
|
+

|
|
21
|
+
[](https://opensource.org/licenses/MIT)
|
|
22
|
+
|
|
23
|
+

|
|
24
|
+
# PyHololoscope: Fast Holographic Microscopy for Python
|
|
25
|
+
|
|
26
|
+
PyHoloscope is a Python package for holographic microscopy, providing perfomant reconstruction of inline and off-axis holograms.
|
|
27
|
+
|
|
28
|
+
It is currently pre-release, aiming for release 1.0.0 before end of 2025.
|
|
29
|
+
|
|
30
|
+
PyHoloscope is designed to be:
|
|
31
|
+
* Fast (for Python) - optmised for CPU using Numpy, Scipy and Numba, with GPU support via CuPy
|
|
32
|
+
* Easy to Use - a simple object-oriented API gives high performance without low-level tweaks
|
|
33
|
+
* Suitable for Live Imaging - can be used as the back-end of holographic microscopy GUIs as well as for offline processing
|
|
34
|
+
|
|
35
|
+
Full documentation is on [Read the docs](https://pyholoscope.readthedocs.io/en/latest/index.html).
|
|
36
|
+
|
|
37
|
+
Also see the examples in the [examples folder](https://github.com/MikeHughesKent/PyHoloscope/tree/main/examples).
|
|
38
|
+
|
|
39
|
+
Contributions to the package (new features, tests or documentation) as very welcome, please see the roadmap below and post in the discussion if you are working on something, or [get in touch](mailto:m.r.hughes@kent.ac.uk).
|
|
40
|
+
|
|
41
|
+
Development is co-ordinated by [Mike Hughes](https://research.kent.ac.uk/applied-optics/hughes/)' lab in the
|
|
42
|
+
[Applied Optics Group](https://research.kent.ac.uk/applied-optics), Physics & Astronomy, University of Kent.
|
|
43
|
+
|
|
44
|
+
If you are interested in academic applications we are happy to help, post in the discussion. If you would like help using PyHoloscope for commercial purposes, consultancy is available, please contact [Mike Hughes](mailto:m.r.hughes@kent.ac.uk) in the first instance.
|
|
45
|
+
|
|
46
|
+
## Features
|
|
47
|
+
|
|
48
|
+
### General
|
|
49
|
+
* Object-oriented interface
|
|
50
|
+
* Choice of single or double precision
|
|
51
|
+
* Support for CUDA compatible GPUs
|
|
52
|
+
* Optional use of Numba JIT compiler
|
|
53
|
+
* Supports non-square holograms
|
|
54
|
+
|
|
55
|
+
### Off Axis Holography
|
|
56
|
+
* Quantitatave phase and amplitude recovery from off-axis hologram
|
|
57
|
+
* Auto detect off-axis modulation frequency
|
|
58
|
+
* Predict tilt angle from modulation frequency
|
|
59
|
+
|
|
60
|
+
### Numerical Refocusing (Inline and Off-axis Holgoraphy)
|
|
61
|
+
* Refocus holograms or complex fields using the angular spectrum method
|
|
62
|
+
* Choice of cosine windows to reduce edge effects
|
|
63
|
+
* Generate stack of images at different refocus depths
|
|
64
|
+
* Apply focus metrics (Brenner, Sobel, Peak Intensity, DarkFocus, SobelVariance)
|
|
65
|
+
* Auto focus whole image or ROI by optimising focus metric, through fast bounded search and (optionally) initial coarse search to narrow search range.
|
|
66
|
+
* Generate LUT of propagators for faster auto-focus or repeated generation of focus stacks.
|
|
67
|
+
|
|
68
|
+
### Phase Visualation
|
|
69
|
+
* Remove background phase
|
|
70
|
+
* Remove phase tilt
|
|
71
|
+
* Show phase relative to region of interest
|
|
72
|
+
* Generate phase contrast image
|
|
73
|
+
* Generate synthetic DIC image
|
|
74
|
+
|
|
75
|
+
## Roadmap of Planned Developments (help welcome!)
|
|
76
|
+
|
|
77
|
+
- [ ] Phase recovery for inline holography
|
|
78
|
+
- [ ] Improved optimisation for speed/multiple back-ends
|
|
79
|
+
- [ ] Support phase-shifting holography
|
|
80
|
+
- [ ] Support coded aperture/multi-depth phase recovery
|
|
81
|
+
- [ ] Support forward scattering and inference
|
|
82
|
+
- [ ] Support particle tracking
|
|
83
|
+
- [ ] Deep learning for focusing
|
|
84
|
+
- [ ] Targeted support for edge computing (e.g. Raspberry Pi)
|
|
85
|
+
|
|
86
|
+
## Requirements
|
|
87
|
+
* Numpy
|
|
88
|
+
* Scipy
|
|
89
|
+
* PIL
|
|
90
|
+
* OpenCV
|
|
91
|
+
* Scikit-Image
|
|
92
|
+
* Matplotlib
|
|
93
|
+
* Numba (optional, for JIT acceleration)
|
|
94
|
+
* CuPy (optional, for GPU)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/PyHoloscope.egg-info/PKG-INFO
|
|
4
|
+
src/PyHoloscope.egg-info/SOURCES.txt
|
|
5
|
+
src/PyHoloscope.egg-info/dependency_links.txt
|
|
6
|
+
src/PyHoloscope.egg-info/requires.txt
|
|
7
|
+
src/PyHoloscope.egg-info/top_level.txt
|
|
8
|
+
src/pyholoscope/__init__.py
|
|
9
|
+
src/pyholoscope/focus_shift.py
|
|
10
|
+
src/pyholoscope/focus_stack.py
|
|
11
|
+
src/pyholoscope/focusing.py
|
|
12
|
+
src/pyholoscope/focusing_numba.py
|
|
13
|
+
src/pyholoscope/general.py
|
|
14
|
+
src/pyholoscope/holo_class.py
|
|
15
|
+
src/pyholoscope/off_axis.py
|
|
16
|
+
src/pyholoscope/phase_proc.py
|
|
17
|
+
src/pyholoscope/prop_lut.py
|
|
18
|
+
src/pyholoscope/propagator.py
|
|
19
|
+
src/pyholoscope/roi.py
|
|
20
|
+
src/pyholoscope/sim.py
|
|
21
|
+
src/pyholoscope/utils.py
|
|
22
|
+
src/pyholoscope/windows.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pyholoscope
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""
|
|
2
|
+
PyHoloscope - Fast Holographic Microscopy for Python
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
INLINE = 1
|
|
6
|
+
OFF_AXIS = 2
|
|
7
|
+
|
|
8
|
+
INLINE_MODE = 1 # deprecated, kept for backwards compatibility
|
|
9
|
+
OFFAXIS_MODE = 2 # deprecated, kept for backwards compatibility
|
|
10
|
+
|
|
11
|
+
from pyholoscope.general import *
|
|
12
|
+
from pyholoscope.off_axis import *
|
|
13
|
+
from pyholoscope.utils import *
|
|
14
|
+
from pyholoscope.prop_lut import *
|
|
15
|
+
from pyholoscope.focus_stack import *
|
|
16
|
+
from pyholoscope.roi import *
|
|
17
|
+
from pyholoscope.holo_class import *
|
|
18
|
+
from pyholoscope.focusing import *
|
|
19
|
+
from pyholoscope.phase_proc import *
|
|
20
|
+
from pyholoscope.windows import *
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
try:
|
|
24
|
+
from pyholoscope.focusing_numba import *
|
|
25
|
+
except:
|
|
26
|
+
pass
|
|
27
|
+
from pyholoscope.focus_shift import *
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
PyHoloscope - Fast Holographic Microscopy for Python
|
|
4
|
+
|
|
5
|
+
This file contains functions related to estimating depth from shifted images.
|
|
6
|
+
|
|
7
|
+
This is experimental and does not form part of the documented API.
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import math
|
|
12
|
+
import numpy as np
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
import cupy as cp
|
|
16
|
+
|
|
17
|
+
cudaAvailable = True
|
|
18
|
+
except:
|
|
19
|
+
cudaAvailable = False
|
|
20
|
+
from PIL import Image
|
|
21
|
+
import cv2 as cv
|
|
22
|
+
import scipy
|
|
23
|
+
import time
|
|
24
|
+
|
|
25
|
+
import cv2 as cv
|
|
26
|
+
|
|
27
|
+
from pyholoscope.focus_stack import FocusStack
|
|
28
|
+
from pyholoscope.focusing_numba import propagator_numba
|
|
29
|
+
from pyholoscope.roi import Roi
|
|
30
|
+
from pyholoscope.utils import extract_central
|
|
31
|
+
import pyholoscope.general
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def determine_shift(img1, img2, **kwargs):
|
|
35
|
+
"""Determines shift between two images by Normalised Cross Correlation (NCC). A sqaure template extracted
|
|
36
|
+
from the centre of img2 is compared with a sqaure region extracted from the reference image img1. The size
|
|
37
|
+
of the template (templateSize) must be less than the size of the reference (refSize). The maximum
|
|
38
|
+
detectable shift is the (refSize - templateSize) / 2.
|
|
39
|
+
|
|
40
|
+
Arguments:
|
|
41
|
+
img1 : numpy.ndarray
|
|
42
|
+
reference image
|
|
43
|
+
img2 : numpy.ndarray
|
|
44
|
+
image to be compared with reference
|
|
45
|
+
|
|
46
|
+
Keyword Arguments:
|
|
47
|
+
upsample : int
|
|
48
|
+
factor to scale images by prior to template matching to
|
|
49
|
+
allow for sub-pixel registration.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
returnMax = kwargs.get("returnMax", False)
|
|
53
|
+
upsample = kwargs.get("upsample", 1)
|
|
54
|
+
|
|
55
|
+
refSize = np.shape(img1)[0] / 2
|
|
56
|
+
templateSize = np.shape(img1)[0] / 4
|
|
57
|
+
|
|
58
|
+
if (
|
|
59
|
+
refSize < templateSize
|
|
60
|
+
or min(np.shape(img1)) < refSize
|
|
61
|
+
or min(np.shape(img2)) < refSize
|
|
62
|
+
):
|
|
63
|
+
return -1
|
|
64
|
+
else:
|
|
65
|
+
template = extract_central(img2, templateSize).astype("float32")
|
|
66
|
+
refIm = extract_central(img1, refSize).astype("float32")
|
|
67
|
+
|
|
68
|
+
if upsample != 1:
|
|
69
|
+
template = cv.resize(
|
|
70
|
+
template,
|
|
71
|
+
(np.shape(template)[0] * upsample, np.shape(template)[1] * upsample),
|
|
72
|
+
)
|
|
73
|
+
refIm = cv.resize(
|
|
74
|
+
refIm, (np.shape(refIm)[0] * upsample, np.shape(refIm)[0] * upsample)
|
|
75
|
+
)
|
|
76
|
+
res = cv.matchTemplate(template, refIm, cv.TM_CCORR_NORMED)
|
|
77
|
+
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)
|
|
78
|
+
shift = [
|
|
79
|
+
(max_loc[0] - (refSize - templateSize) * upsample) / upsample,
|
|
80
|
+
(max_loc[1] - (refSize - templateSize) * upsample) / upsample,
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
if returnMax:
|
|
84
|
+
return shift, max_val
|
|
85
|
+
else:
|
|
86
|
+
return shift
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def calibrate_depth_from_shift(img1, img2, depth):
|
|
90
|
+
pass
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
PyHoloscope - Fast Holographic Microscopy for Python
|
|
4
|
+
|
|
5
|
+
Class to store stack of images numerically refocused to different depths.
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import math
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
from PIL import Image
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
################### Class for stack of images focused at different depths ####
|
|
16
|
+
class FocusStack:
|
|
17
|
+
def __init__(self, img, depth_range, num_depths):
|
|
18
|
+
"""Initialise instance of FocusStack class.
|
|
19
|
+
|
|
20
|
+
Arguments:
|
|
21
|
+
img : numpy.ndarray
|
|
22
|
+
example image of the correct size and type, 2D numpy array
|
|
23
|
+
num_depths : (float, float)
|
|
24
|
+
tuple of min depth and max depth in stack
|
|
25
|
+
num_depths : int
|
|
26
|
+
number of images to be stored in stack
|
|
27
|
+
"""
|
|
28
|
+
self.stack = np.zeros(
|
|
29
|
+
(num_depths, np.shape(img)[0], np.shape(img)[1]), dtype=img.dtype
|
|
30
|
+
)
|
|
31
|
+
self.depths = np.linspace(depth_range[0], depth_range[1], num_depths)
|
|
32
|
+
self.min_depth = depth_range[0]
|
|
33
|
+
self.max_depth = depth_range[1]
|
|
34
|
+
self.num_depths = num_depths
|
|
35
|
+
self.depth_range = depth_range
|
|
36
|
+
|
|
37
|
+
def __str__(self):
|
|
38
|
+
return (
|
|
39
|
+
"Refocus stack. Min: "
|
|
40
|
+
+ str(self.min_depth)
|
|
41
|
+
+ ", Max: "
|
|
42
|
+
+ str(self.max_depth)
|
|
43
|
+
+ ", Num: "
|
|
44
|
+
+ str(self.num_depths)
|
|
45
|
+
+ ", Step: "
|
|
46
|
+
+ str((self.max_depth - self.min_depth) / self.num_depths)
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
def add_idx(self, img, idx):
|
|
50
|
+
"""Adds an image to a specific index position.
|
|
51
|
+
|
|
52
|
+
Arguments:
|
|
53
|
+
img : ndarray
|
|
54
|
+
image as a 2D numpy array
|
|
55
|
+
idx : int
|
|
56
|
+
index position
|
|
57
|
+
"""
|
|
58
|
+
self.stack[idx, :, :] = img
|
|
59
|
+
|
|
60
|
+
def add_depth(self, img, depth):
|
|
61
|
+
"""Adds an image to index position closest to the the specifed depth.
|
|
62
|
+
|
|
63
|
+
Arguments:
|
|
64
|
+
img : ndarray
|
|
65
|
+
image as a 2D numpy array
|
|
66
|
+
depth : float
|
|
67
|
+
refocus depth of image
|
|
68
|
+
"""
|
|
69
|
+
self.stack[self.depth_to_index(depth), :, :] = img
|
|
70
|
+
|
|
71
|
+
def get_index(self, idx):
|
|
72
|
+
"""Returns the refocused image stored at the specified index.
|
|
73
|
+
|
|
74
|
+
Arguments:
|
|
75
|
+
idx : int
|
|
76
|
+
index position to return image from
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
numpy.ndarray : image
|
|
80
|
+
|
|
81
|
+
"""
|
|
82
|
+
return self.stack[idx, :, :]
|
|
83
|
+
|
|
84
|
+
def get_depth(self, depth):
|
|
85
|
+
"""Returns the closest refocused image to the specifed depth.
|
|
86
|
+
|
|
87
|
+
Arguments:
|
|
88
|
+
depth : float
|
|
89
|
+
depth to return image from
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
numpy.ndarray : image
|
|
93
|
+
|
|
94
|
+
"""
|
|
95
|
+
return self.get_index(self.depth_to_index(depth))
|
|
96
|
+
|
|
97
|
+
def get_depth_intensity(self, depth):
|
|
98
|
+
"""Returns the amplitude of the refocused image closest to the specified depth.
|
|
99
|
+
|
|
100
|
+
Arguments:
|
|
101
|
+
depth : float
|
|
102
|
+
depth to return image from
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
numpy.ndarray : image
|
|
106
|
+
|
|
107
|
+
"""
|
|
108
|
+
return np.abs(self.get_depth(depth))
|
|
109
|
+
|
|
110
|
+
def get_index_intensity(self, idx):
|
|
111
|
+
"""Return the amplitude of the refocused image at the specified index.
|
|
112
|
+
|
|
113
|
+
Arguments:
|
|
114
|
+
idx : int
|
|
115
|
+
index position to return image from
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
numpy.ndarray : image
|
|
119
|
+
|
|
120
|
+
"""
|
|
121
|
+
return np.abs(self.get_index(idx))
|
|
122
|
+
|
|
123
|
+
def depth_to_index(self, depth):
|
|
124
|
+
"""Returns the index closest to the specified depth.
|
|
125
|
+
|
|
126
|
+
Arguments:
|
|
127
|
+
depth : float
|
|
128
|
+
depth to obtain closest index to
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
int : index
|
|
132
|
+
|
|
133
|
+
"""
|
|
134
|
+
idx = round(
|
|
135
|
+
(depth - self.min_depth)
|
|
136
|
+
/ (self.max_depth - self.min_depth)
|
|
137
|
+
* (self.num_depths - 1)
|
|
138
|
+
)
|
|
139
|
+
if idx < 0:
|
|
140
|
+
idx = 0
|
|
141
|
+
if idx > self.num_depths - 1:
|
|
142
|
+
idx = self.num_depths - 1
|
|
143
|
+
return idx
|
|
144
|
+
|
|
145
|
+
def index_to_depth(self, idx):
|
|
146
|
+
"""Returns depth corresponding to the specified index.
|
|
147
|
+
|
|
148
|
+
Arguments:
|
|
149
|
+
idx : int
|
|
150
|
+
index position
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
float : depth
|
|
154
|
+
|
|
155
|
+
"""
|
|
156
|
+
return self.depths[idx]
|
|
157
|
+
|
|
158
|
+
def write_intensity_to_tif(self, filename, autoContrast=True):
|
|
159
|
+
"""Writes the amplitudes of the stack of refocused images to a 16 bit tif stack
|
|
160
|
+
If autoContrast == True, all images will be autoscaled (across the whole
|
|
161
|
+
stack, not individually) to use the full bit depth.
|
|
162
|
+
|
|
163
|
+
Arguments:
|
|
164
|
+
filename : str
|
|
165
|
+
path/file to save to, should have .tif extension.
|
|
166
|
+
|
|
167
|
+
Keyword Arguments:
|
|
168
|
+
autoContrast : boolean
|
|
169
|
+
if True (default) images are autoscaled
|
|
170
|
+
"""
|
|
171
|
+
|
|
172
|
+
if autoContrast:
|
|
173
|
+
maxVal = np.max(np.abs(self.stack))
|
|
174
|
+
minVal = np.min(np.abs(self.stack))
|
|
175
|
+
|
|
176
|
+
imlist = []
|
|
177
|
+
for m in self.stack:
|
|
178
|
+
if autoContrast:
|
|
179
|
+
im = np.abs(m).astype("float64") - minVal
|
|
180
|
+
im = im / (maxVal - minVal) * 2**16
|
|
181
|
+
imlist.append(Image.fromarray(im.astype("uint16")))
|
|
182
|
+
|
|
183
|
+
else:
|
|
184
|
+
imlist.append(Image.fromarray((255 * np.abs(m)).astype("uint16")))
|
|
185
|
+
|
|
186
|
+
imlist[0].save(
|
|
187
|
+
filename,
|
|
188
|
+
compression="tiff_deflate",
|
|
189
|
+
save_all=True,
|
|
190
|
+
append_images=imlist[1:],
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
def write_phase_to_tif(self, filename):
|
|
194
|
+
"""Writes the phases of the stack of refocused images to a 16 bit tif stack.
|
|
195
|
+
-pi is mapped to 0, pi is mapped to 255.
|
|
196
|
+
|
|
197
|
+
Arguments:
|
|
198
|
+
filename : str
|
|
199
|
+
path/file to save to, should have .tif extension.
|
|
200
|
+
"""
|
|
201
|
+
|
|
202
|
+
imlist = []
|
|
203
|
+
for m in self.stack:
|
|
204
|
+
im = (np.angle(m) + math.pi) * 255
|
|
205
|
+
imlist.append(Image.fromarray(im.astype("uint16")))
|
|
206
|
+
|
|
207
|
+
imlist[0].save(
|
|
208
|
+
filename,
|
|
209
|
+
compression="tiff_deflate",
|
|
210
|
+
save_all=True,
|
|
211
|
+
append_images=imlist[1:],
|
|
212
|
+
)
|