Source code for spinningdiskanalyzer.imaging.filters
"""In-memory filtering of images"""
from skimage import restoration
from pythreshold.local_th.bernsen import bernsen_threshold
from numpy import ndarray
from numpy import where
from numpy import median
from logging import getLogger
log = getLogger(__name__)
[docs]
def rolling_ball(image: ndarray, radius: int = 50) -> ndarray:
"""
Removes the background from the `image` using the rolling-ball method.
Returns the image foreground obtained by subtracting the background
from the input image.
"""
log.info('Started background correction using rolling-ball method.')
background = restoration.rolling_ball(image, radius=radius)
foreground = where(image > background, image - background, 0)
log.info('Finished background correction using rolling-ball method.')
return foreground
[docs]
def thresholding_bernsen(
image: ndarray,
radius: int = 15,
contrast: int = 15,
) -> ndarray:
"""
Returns the local segmentation thresholds using the Bernsen method.
The parameters window `radius` and `contrast` threshold correspond
to the [ImageJ definitions], though the [Python implementation]
actually uses a square window with a side length corresponding to
the diameter.
[ImageJ definitions]: https://imagej.net/plugins/auto-local-threshold
[Python implementation]: https://github.com/manuelaguadomtz/pythreshold
"""
log.info('Started local thresholding using Bernsen method.')
window = 2*radius + 1
thresholds = bernsen_threshold(image, w_size=window, c_thr=contrast)
thresholded = where(image >= thresholds, 0, 255).astype('uint8')
log.info('Finished local thresholding using Bernsen method.')
return thresholded
[docs]
def invert(image: ndarray) -> ndarray:
"""Returns the given `image` with all color values inverted."""
if image.dtype == 'uint16':
max_int = 2**16 - 1
elif image.dtype == 'uint8':
max_int = 2**8 - 1
else:
raise ValueError('Image data must be either 8- or 16-bit integer.')
return (max_int - image)
[docs]
def white_on_black(image: ndarray) -> ndarray:
"""
Inverts the `image` if not white-on-black, or returns the input.
By "white-on-black" we mean that the background is mostly dark
with light features on it.
"""
if median(image) > image.max()/2:
return invert(image)
else:
return image
[docs]
def black_on_white(image: ndarray) -> ndarray:
"""
Inverts the `image` if not black-on-white, or returns the input.
By "black-on-white" we mean that the background is mostly light
with dark features on it.
"""
if median(image) <= image.max()/2:
return invert(image)
else:
return image