2021-01-14 08:07:24 +01:00
|
|
|
"""
|
|
|
|
Ridge filters.
|
|
|
|
|
|
|
|
Ridge filters can be used to detect continuous edges, such as vessels,
|
|
|
|
neurites, wrinkles, rivers, and other tube-like structures. The present
|
|
|
|
class of ridge filters relies on the eigenvalues of the Hessian matrix of
|
|
|
|
image intensities to detect tube-like structures where the intensity changes
|
|
|
|
perpendicular but not along the structure.
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
from warnings import warn
|
|
|
|
|
|
|
|
import numpy as np
|
|
|
|
|
|
|
|
from ..util import img_as_float, invert
|
|
|
|
from .._shared.utils import check_nD
|
|
|
|
from ..feature.corner import hessian_matrix, hessian_matrix_eigvals
|
|
|
|
|
|
|
|
|
|
|
|
def _divide_nonzero(array1, array2, cval=1e-10):
|
|
|
|
"""
|
|
|
|
Divides two arrays.
|
|
|
|
|
|
|
|
Denominator is set to small value where zero to avoid ZeroDivisionError and
|
|
|
|
return finite float array.
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
----------
|
|
|
|
array1 : (N, ..., M) ndarray
|
|
|
|
Array 1 in the enumerator.
|
|
|
|
array2 : (N, ..., M) ndarray
|
|
|
|
Array 2 in the denominator.
|
|
|
|
cval : float, optional
|
|
|
|
Value used to replace zero entries in the denominator.
|
|
|
|
|
|
|
|
Returns
|
|
|
|
-------
|
|
|
|
array : (N, ..., M) ndarray
|
|
|
|
Quotient of the array division.
|
|
|
|
"""
|
|
|
|
|
|
|
|
# Copy denominator
|
|
|
|
denominator = np.copy(array2)
|
|
|
|
|
|
|
|
# Set zero entries of denominator to small value
|
|
|
|
denominator[denominator == 0] = cval
|
|
|
|
|
|
|
|
# Return quotient
|
|
|
|
return np.divide(array1, denominator)
|
|
|
|
|
|
|
|
|
|
|
|
def _sortbyabs(array, axis=0):
|
|
|
|
"""
|
|
|
|
Sort array along a given axis by absolute values.
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
----------
|
|
|
|
array : (N, ..., M) ndarray
|
|
|
|
Array with input image data.
|
|
|
|
axis : int
|
|
|
|
Axis along which to sort.
|
|
|
|
|
|
|
|
Returns
|
|
|
|
-------
|
|
|
|
array : (N, ..., M) ndarray
|
|
|
|
Array sorted along a given axis by absolute values.
|
|
|
|
|
|
|
|
Notes
|
|
|
|
-----
|
|
|
|
Modified from: http://stackoverflow.com/a/11253931/4067734
|
|
|
|
"""
|
|
|
|
|
|
|
|
# Create auxiliary array for indexing
|
|
|
|
index = list(np.ix_(*[np.arange(i) for i in array.shape]))
|
|
|
|
|
|
|
|
# Get indices of abs sorted array
|
|
|
|
index[axis] = np.abs(array).argsort(axis)
|
|
|
|
|
|
|
|
# Return abs sorted array
|
|
|
|
return array[tuple(index)]
|
|
|
|
|
|
|
|
|
|
|
|
def _check_sigmas(sigmas):
|
|
|
|
"""Check sigma values for ridges filters.
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
----------
|
|
|
|
sigmas : iterable of floats
|
|
|
|
Sigmas argument to be checked
|
|
|
|
|
|
|
|
Returns
|
|
|
|
-------
|
|
|
|
sigmas : ndarray
|
|
|
|
input iterable converted to ndarray
|
|
|
|
|
|
|
|
Raises
|
|
|
|
------
|
|
|
|
ValueError if any input value is negative
|
|
|
|
|
|
|
|
"""
|
|
|
|
sigmas = np.asarray(sigmas).ravel()
|
|
|
|
if np.any(sigmas < 0.0):
|
|
|
|
raise ValueError('Sigma values should be equal to or greater '
|
|
|
|
'than zero.')
|
|
|
|
return sigmas
|
|
|
|
|
|
|
|
|
|
|
|
def compute_hessian_eigenvalues(image, sigma, sorting='none',
|
|
|
|
mode='constant', cval=0):
|
|
|
|
"""
|
|
|
|
Compute Hessian eigenvalues of nD images.
|
|
|
|
|
|
|
|
For 2D images, the computation uses a more efficient, skimage-based
|
|
|
|
algorithm.
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
----------
|
|
|
|
image : (N, ..., M) ndarray
|
|
|
|
Array with input image data.
|
|
|
|
sigma : float
|
|
|
|
Smoothing factor of image for detection of structures at different
|
|
|
|
(sigma) scales.
|
|
|
|
sorting : {'val', 'abs', 'none'}, optional
|
|
|
|
Sorting of eigenvalues by values ('val') or absolute values ('abs'),
|
|
|
|
or without sorting ('none'). Default is 'none'.
|
|
|
|
mode : {'constant', 'reflect', 'wrap', 'nearest', 'mirror'}, optional
|
|
|
|
How to handle values outside the image borders.
|
|
|
|
cval : float, optional
|
|
|
|
Used in conjunction with mode 'constant', the value outside
|
|
|
|
the image boundaries.
|
|
|
|
|
|
|
|
Returns
|
|
|
|
-------
|
|
|
|
eigenvalues : (D, N, ..., M) ndarray
|
|
|
|
Array with (sorted) eigenvalues of Hessian eigenvalues for each pixel
|
|
|
|
of the input image.
|
|
|
|
"""
|
|
|
|
|
|
|
|
# Convert image to float
|
|
|
|
image = img_as_float(image)
|
|
|
|
|
|
|
|
# Make nD hessian
|
|
|
|
hessian_elements = hessian_matrix(image, sigma=sigma, order='rc',
|
|
|
|
mode=mode, cval=cval)
|
|
|
|
|
|
|
|
# Correct for scale
|
|
|
|
hessian_elements = [(sigma ** 2) * e for e in hessian_elements]
|
|
|
|
|
|
|
|
# Compute Hessian eigenvalues
|
|
|
|
hessian_eigenvalues = hessian_matrix_eigvals(hessian_elements)
|
|
|
|
|
|
|
|
if sorting == 'abs':
|
|
|
|
|
|
|
|
# Sort eigenvalues by absolute values in ascending order
|
|
|
|
hessian_eigenvalues = _sortbyabs(hessian_eigenvalues, axis=0)
|
|
|
|
|
|
|
|
elif sorting == 'val':
|
|
|
|
|
|
|
|
# Sort eigenvalues by values in ascending order
|
|
|
|
hessian_eigenvalues = np.sort(hessian_eigenvalues, axis=0)
|
|
|
|
|
|
|
|
# Return Hessian eigenvalues
|
|
|
|
return hessian_eigenvalues
|
|
|
|
|
|
|
|
|
|
|
|
def meijering(image, sigmas=range(1, 10, 2), alpha=None,
|
|
|
|
black_ridges=True, mode='reflect', cval=0):
|
|
|
|
"""
|
|
|
|
Filter an image with the Meijering neuriteness filter.
|
|
|
|
|
|
|
|
This filter can be used to detect continuous ridges, e.g. neurites,
|
|
|
|
wrinkles, rivers. It can be used to calculate the fraction of the
|
|
|
|
whole image containing such objects.
|
|
|
|
|
|
|
|
Calculates the eigenvectors of the Hessian to compute the similarity of
|
|
|
|
an image region to neurites, according to the method described in [1]_.
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
----------
|
|
|
|
image : (N, M[, ..., P]) ndarray
|
|
|
|
Array with input image data.
|
|
|
|
sigmas : iterable of floats, optional
|
|
|
|
Sigmas used as scales of filter
|
|
|
|
alpha : float, optional
|
|
|
|
Frangi correction constant that adjusts the filter's
|
|
|
|
sensitivity to deviation from a plate-like structure.
|
|
|
|
black_ridges : boolean, optional
|
|
|
|
When True (the default), the filter detects black ridges; when
|
|
|
|
False, it detects white ridges.
|
|
|
|
mode : {'constant', 'reflect', 'wrap', 'nearest', 'mirror'}, optional
|
|
|
|
How to handle values outside the image borders.
|
|
|
|
cval : float, optional
|
|
|
|
Used in conjunction with mode 'constant', the value outside
|
|
|
|
the image boundaries.
|
|
|
|
|
|
|
|
Returns
|
|
|
|
-------
|
|
|
|
out : (N, M[, ..., P]) ndarray
|
|
|
|
Filtered image (maximum of pixels across all scales).
|
|
|
|
|
|
|
|
See also
|
|
|
|
--------
|
|
|
|
sato
|
|
|
|
frangi
|
|
|
|
hessian
|
|
|
|
|
|
|
|
References
|
|
|
|
----------
|
|
|
|
.. [1] Meijering, E., Jacob, M., Sarria, J. C., Steiner, P., Hirling, H.,
|
|
|
|
Unser, M. (2004). Design and validation of a tool for neurite tracing
|
|
|
|
and analysis in fluorescence microscopy images. Cytometry Part A,
|
|
|
|
58(2), 167-176.
|
|
|
|
:DOI:`10.1002/cyto.a.20022`
|
|
|
|
"""
|
|
|
|
|
|
|
|
# Check (sigma) scales
|
|
|
|
sigmas = _check_sigmas(sigmas)
|
|
|
|
|
|
|
|
# Get image dimensions
|
|
|
|
ndim = image.ndim
|
|
|
|
|
|
|
|
# Set parameters
|
|
|
|
if alpha is None:
|
|
|
|
alpha = 1.0 / ndim
|
|
|
|
|
|
|
|
# Invert image to detect dark ridges on bright background
|
|
|
|
if black_ridges:
|
|
|
|
image = invert(image)
|
|
|
|
|
|
|
|
# Generate empty (n+1)D arrays for storing auxiliary images filtered at
|
|
|
|
# different (sigma) scales
|
|
|
|
filtered_array = np.zeros(sigmas.shape + image.shape)
|
|
|
|
|
|
|
|
# Filtering for all (sigma) scales
|
|
|
|
for i, sigma in enumerate(sigmas):
|
|
|
|
|
|
|
|
# Calculate (sorted) eigenvalues
|
|
|
|
eigenvalues = compute_hessian_eigenvalues(image, sigma, sorting='abs',
|
|
|
|
mode=mode, cval=cval)
|
|
|
|
|
|
|
|
if ndim > 1:
|
|
|
|
|
|
|
|
# Set coefficients for scaling eigenvalues
|
|
|
|
coefficients = [alpha] * ndim
|
|
|
|
coefficients[0] = 1
|
|
|
|
|
|
|
|
# Compute normalized eigenvalues l_i = e_i + sum_{j!=i} alpha * e_j
|
|
|
|
auxiliary = [np.sum([eigenvalues[i] * np.roll(coefficients, j)[i]
|
|
|
|
for j in range(ndim)], axis=0) for i in range(ndim)]
|
|
|
|
|
|
|
|
# Get maximum eigenvalues by magnitude
|
|
|
|
auxiliary = auxiliary[-1]
|
|
|
|
|
|
|
|
# Rescale image intensity and avoid ZeroDivisionError
|
|
|
|
filtered = _divide_nonzero(auxiliary, np.min(auxiliary))
|
|
|
|
|
|
|
|
# Remove background
|
|
|
|
filtered = np.where(auxiliary < 0, filtered, 0)
|
|
|
|
|
|
|
|
# Store results in (n+1)D matrices
|
|
|
|
filtered_array[i] = filtered
|
|
|
|
|
|
|
|
# Return for every pixel the maximum value over all (sigma) scales
|
|
|
|
return np.max(filtered_array, axis=0)
|
|
|
|
|
|
|
|
|
|
|
|
def sato(image, sigmas=range(1, 10, 2), black_ridges=True,
|
|
|
|
mode=None, cval=0):
|
|
|
|
"""
|
|
|
|
Filter an image with the Sato tubeness filter.
|
|
|
|
|
|
|
|
This filter can be used to detect continuous ridges, e.g. tubes,
|
|
|
|
wrinkles, rivers. It can be used to calculate the fraction of the
|
|
|
|
whole image containing such objects.
|
|
|
|
|
|
|
|
Defined only for 2-D and 3-D images. Calculates the eigenvectors of the
|
|
|
|
Hessian to compute the similarity of an image region to tubes, according to
|
|
|
|
the method described in [1]_.
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
----------
|
|
|
|
image : (N, M[, P]) ndarray
|
|
|
|
Array with input image data.
|
|
|
|
sigmas : iterable of floats, optional
|
|
|
|
Sigmas used as scales of filter.
|
|
|
|
black_ridges : boolean, optional
|
|
|
|
When True (the default), the filter detects black ridges; when
|
|
|
|
False, it detects white ridges.
|
|
|
|
mode : {'constant', 'reflect', 'wrap', 'nearest', 'mirror'}, optional
|
|
|
|
How to handle values outside the image borders.
|
|
|
|
cval : float, optional
|
|
|
|
Used in conjunction with mode 'constant', the value outside
|
|
|
|
the image boundaries.
|
|
|
|
|
|
|
|
Returns
|
|
|
|
-------
|
|
|
|
out : (N, M[, P]) ndarray
|
|
|
|
Filtered image (maximum of pixels across all scales).
|
|
|
|
|
|
|
|
See also
|
|
|
|
--------
|
|
|
|
meijering
|
|
|
|
frangi
|
|
|
|
hessian
|
|
|
|
|
|
|
|
References
|
|
|
|
----------
|
|
|
|
.. [1] Sato, Y., Nakajima, S., Shiraga, N., Atsumi, H., Yoshida, S.,
|
|
|
|
Koller, T., ..., Kikinis, R. (1998). Three-dimensional multi-scale line
|
|
|
|
filter for segmentation and visualization of curvilinear structures in
|
|
|
|
medical images. Medical image analysis, 2(2), 143-168.
|
|
|
|
:DOI:`10.1016/S1361-8415(98)80009-1`
|
|
|
|
"""
|
|
|
|
|
|
|
|
# Check image dimensions
|
|
|
|
check_nD(image, [2, 3])
|
|
|
|
|
|
|
|
# Check (sigma) scales
|
|
|
|
sigmas = _check_sigmas(sigmas)
|
|
|
|
|
|
|
|
if mode is None:
|
|
|
|
warn("Previously, sato implicitly used 'constant' as the "
|
|
|
|
"border mode when dealing with the edge of the array. The new "
|
|
|
|
"behavior is 'reflect'. To recover the old behavior, use "
|
|
|
|
"mode='constant'. To avoid this warning, please explicitly "
|
|
|
|
"set the mode.", category=FutureWarning, stacklevel=2)
|
|
|
|
mode = 'reflect'
|
|
|
|
|
|
|
|
# Invert image to detect bright ridges on dark background
|
|
|
|
if not black_ridges:
|
|
|
|
image = invert(image)
|
|
|
|
|
|
|
|
# Generate empty (n+1)D arrays for storing auxiliary images filtered
|
|
|
|
# at different (sigma) scales
|
|
|
|
filtered_array = np.zeros(sigmas.shape + image.shape)
|
|
|
|
|
|
|
|
# Filtering for all (sigma) scales
|
|
|
|
for i, sigma in enumerate(sigmas):
|
|
|
|
|
|
|
|
# Calculate (sorted) eigenvalues
|
|
|
|
lamba1, *lambdas = compute_hessian_eigenvalues(image, sigma,
|
|
|
|
sorting='val',
|
|
|
|
mode=mode, cval=cval)
|
|
|
|
|
|
|
|
# Compute tubeness, see equation (9) in reference [1]_.
|
|
|
|
# np.abs(lambda2) in 2D, np.sqrt(np.abs(lambda2 * lambda3)) in 3D
|
|
|
|
filtered = np.abs(np.multiply.reduce(lambdas)) ** (1/len(lambdas))
|
|
|
|
|
|
|
|
# Remove background and store results in (n+1)D matrices
|
|
|
|
filtered_array[i] = np.where(lambdas[-1] > 0, filtered, 0)
|
|
|
|
|
|
|
|
# Return for every pixel the maximum value over all (sigma) scales
|
|
|
|
return np.max(filtered_array, axis=0)
|
|
|
|
|
|
|
|
|
|
|
|
def frangi(image, sigmas=range(1, 10, 2), scale_range=None,
|
|
|
|
scale_step=None, alpha=0.5, beta=0.5, gamma=15,
|
|
|
|
black_ridges=True, mode='reflect', cval=0):
|
|
|
|
"""
|
|
|
|
Filter an image with the Frangi vesselness filter.
|
|
|
|
|
|
|
|
This filter can be used to detect continuous ridges, e.g. vessels,
|
|
|
|
wrinkles, rivers. It can be used to calculate the fraction of the
|
|
|
|
whole image containing such objects.
|
|
|
|
|
|
|
|
Defined only for 2-D and 3-D images. Calculates the eigenvectors of the
|
|
|
|
Hessian to compute the similarity of an image region to vessels, according
|
|
|
|
to the method described in [1]_.
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
----------
|
|
|
|
image : (N, M[, P]) ndarray
|
|
|
|
Array with input image data.
|
|
|
|
sigmas : iterable of floats, optional
|
|
|
|
Sigmas used as scales of filter, i.e.,
|
|
|
|
np.arange(scale_range[0], scale_range[1], scale_step)
|
|
|
|
scale_range : 2-tuple of floats, optional
|
|
|
|
The range of sigmas used.
|
|
|
|
scale_step : float, optional
|
|
|
|
Step size between sigmas.
|
|
|
|
alpha : float, optional
|
|
|
|
Frangi correction constant that adjusts the filter's
|
|
|
|
sensitivity to deviation from a plate-like structure.
|
|
|
|
beta : float, optional
|
|
|
|
Frangi correction constant that adjusts the filter's
|
|
|
|
sensitivity to deviation from a blob-like structure.
|
|
|
|
gamma : float, optional
|
|
|
|
Frangi correction constant that adjusts the filter's
|
|
|
|
sensitivity to areas of high variance/texture/structure.
|
|
|
|
black_ridges : boolean, optional
|
|
|
|
When True (the default), the filter detects black ridges; when
|
|
|
|
False, it detects white ridges.
|
|
|
|
mode : {'constant', 'reflect', 'wrap', 'nearest', 'mirror'}, optional
|
|
|
|
How to handle values outside the image borders.
|
|
|
|
cval : float, optional
|
|
|
|
Used in conjunction with mode 'constant', the value outside
|
|
|
|
the image boundaries.
|
|
|
|
|
|
|
|
Returns
|
|
|
|
-------
|
|
|
|
out : (N, M[, P]) ndarray
|
|
|
|
Filtered image (maximum of pixels across all scales).
|
|
|
|
|
|
|
|
Notes
|
|
|
|
-----
|
|
|
|
Written by Marc Schrijver, November 2001
|
|
|
|
Re-Written by D. J. Kroon, University of Twente, May 2009, [2]_
|
|
|
|
Adoption of 3D version from D. G. Ellis, Januar 20017, [3]_
|
|
|
|
|
|
|
|
See also
|
|
|
|
--------
|
|
|
|
meijering
|
|
|
|
sato
|
|
|
|
hessian
|
|
|
|
|
|
|
|
References
|
|
|
|
----------
|
|
|
|
.. [1] Frangi, A. F., Niessen, W. J., Vincken, K. L., & Viergever, M. A.
|
|
|
|
(1998,). Multiscale vessel enhancement filtering. In International
|
|
|
|
Conference on Medical Image Computing and Computer-Assisted
|
|
|
|
Intervention (pp. 130-137). Springer Berlin Heidelberg.
|
|
|
|
:DOI:`10.1007/BFb0056195`
|
|
|
|
.. [2] Kroon, D. J.: Hessian based Frangi vesselness filter.
|
|
|
|
.. [3] Ellis, D. G.: https://github.com/ellisdg/frangi3d/tree/master/frangi
|
|
|
|
"""
|
|
|
|
if scale_range is not None and scale_step is not None:
|
|
|
|
warn('Use keyword parameter `sigmas` instead of `scale_range` and '
|
|
|
|
'`scale_range` which will be removed in version 0.17.',
|
|
|
|
stacklevel=2)
|
|
|
|
sigmas = np.arange(scale_range[0], scale_range[1], scale_step)
|
|
|
|
|
|
|
|
# Check image dimensions
|
|
|
|
check_nD(image, [2, 3])
|
|
|
|
|
|
|
|
# Check (sigma) scales
|
|
|
|
sigmas = _check_sigmas(sigmas)
|
|
|
|
|
|
|
|
# Rescale filter parameters
|
|
|
|
alpha_sq = 2 * alpha ** 2
|
|
|
|
beta_sq = 2 * beta ** 2
|
|
|
|
gamma_sq = 2 * gamma ** 2
|
|
|
|
|
|
|
|
# Get image dimensions
|
|
|
|
ndim = image.ndim
|
|
|
|
|
|
|
|
# Invert image to detect dark ridges on light background
|
|
|
|
if black_ridges:
|
|
|
|
image = invert(image)
|
|
|
|
|
|
|
|
# Generate empty (n+1)D arrays for storing auxiliary images filtered
|
|
|
|
# at different (sigma) scales
|
|
|
|
filtered_array = np.zeros(sigmas.shape + image.shape)
|
|
|
|
lambdas_array = np.zeros_like(filtered_array)
|
|
|
|
|
|
|
|
# Filtering for all (sigma) scales
|
|
|
|
for i, sigma in enumerate(sigmas):
|
|
|
|
|
|
|
|
# Calculate (abs sorted) eigenvalues
|
|
|
|
lambda1, *lambdas = compute_hessian_eigenvalues(image, sigma,
|
|
|
|
sorting='abs',
|
|
|
|
mode=mode, cval=cval)
|
|
|
|
|
|
|
|
# Compute sensitivity to deviation from a plate-like
|
|
|
|
# structure see equations (11) and (15) in reference [1]_
|
|
|
|
r_a = np.inf if ndim == 2 else _divide_nonzero(*lambdas) ** 2
|
|
|
|
|
|
|
|
# Compute sensitivity to deviation from a blob-like structure,
|
|
|
|
# see equations (10) and (15) in reference [1]_,
|
|
|
|
# np.abs(lambda2) in 2D, np.sqrt(np.abs(lambda2 * lambda3)) in 3D
|
|
|
|
filtered_raw = np.abs(np.multiply.reduce(lambdas)) ** (1/len(lambdas))
|
|
|
|
r_b = _divide_nonzero(lambda1, filtered_raw) ** 2
|
|
|
|
|
|
|
|
# Compute sensitivity to areas of high variance/texture/structure,
|
|
|
|
# see equation (12)in reference [1]_
|
|
|
|
r_g = sum([lambda1 ** 2] + [lambdai ** 2 for lambdai in lambdas])
|
|
|
|
|
|
|
|
# Compute output image for given (sigma) scale and store results in
|
|
|
|
# (n+1)D matrices, see equations (13) and (15) in reference [1]_
|
|
|
|
filtered_array[i] = ((1 - np.exp(-r_a / alpha_sq))
|
|
|
|
* np.exp(-r_b / beta_sq)
|
|
|
|
* (1 - np.exp(-r_g / gamma_sq)))
|
|
|
|
|
|
|
|
lambdas_array[i] = np.max(lambdas, axis=0)
|
|
|
|
|
|
|
|
# Remove background
|
|
|
|
filtered_array[lambdas_array > 0] = 0
|
|
|
|
|
|
|
|
# Return for every pixel the maximum value over all (sigma) scales
|
|
|
|
return np.max(filtered_array, axis=0)
|
|
|
|
|
|
|
|
|
|
|
|
def hessian(image, sigmas=range(1, 10, 2), scale_range=None, scale_step=None,
|
|
|
|
alpha=0.5, beta=0.5, gamma=15, black_ridges=True, mode=None,
|
|
|
|
cval=0):
|
|
|
|
"""Filter an image with the Hybrid Hessian filter.
|
|
|
|
|
|
|
|
This filter can be used to detect continuous edges, e.g. vessels,
|
|
|
|
wrinkles, rivers. It can be used to calculate the fraction of the whole
|
|
|
|
image containing such objects.
|
|
|
|
|
|
|
|
Defined only for 2-D and 3-D images. Almost equal to Frangi filter, but
|
|
|
|
uses alternative method of smoothing. Refer to [1]_ to find the differences
|
|
|
|
between Frangi and Hessian filters.
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
----------
|
|
|
|
image : (N, M[, P]) ndarray
|
|
|
|
Array with input image data.
|
|
|
|
sigmas : iterable of floats, optional
|
|
|
|
Sigmas used as scales of filter, i.e.,
|
|
|
|
np.arange(scale_range[0], scale_range[1], scale_step)
|
|
|
|
scale_range : 2-tuple of floats, optional
|
|
|
|
The range of sigmas used.
|
|
|
|
scale_step : float, optional
|
|
|
|
Step size between sigmas.
|
|
|
|
beta : float, optional
|
|
|
|
Frangi correction constant that adjusts the filter's
|
|
|
|
sensitivity to deviation from a blob-like structure.
|
|
|
|
gamma : float, optional
|
|
|
|
Frangi correction constant that adjusts the filter's
|
|
|
|
sensitivity to areas of high variance/texture/structure.
|
|
|
|
black_ridges : boolean, optional
|
|
|
|
When True (the default), the filter detects black ridges; when
|
|
|
|
False, it detects white ridges.
|
|
|
|
mode : {'constant', 'reflect', 'wrap', 'nearest', 'mirror'}, optional
|
|
|
|
How to handle values outside the image borders.
|
|
|
|
cval : float, optional
|
|
|
|
Used in conjunction with mode 'constant', the value outside
|
|
|
|
the image boundaries.
|
|
|
|
|
|
|
|
Returns
|
|
|
|
-------
|
|
|
|
out : (N, M[, P]) ndarray
|
|
|
|
Filtered image (maximum of pixels across all scales).
|
|
|
|
|
|
|
|
Notes
|
|
|
|
-----
|
|
|
|
Written by Marc Schrijver (November 2001)
|
|
|
|
Re-Written by D. J. Kroon University of Twente (May 2009) [2]_
|
|
|
|
|
|
|
|
See also
|
|
|
|
--------
|
|
|
|
meijering
|
|
|
|
sato
|
|
|
|
frangi
|
|
|
|
|
|
|
|
References
|
|
|
|
----------
|
|
|
|
.. [1] Ng, C. C., Yap, M. H., Costen, N., & Li, B. (2014,). Automatic
|
|
|
|
wrinkle detection using hybrid Hessian filter. In Asian Conference on
|
|
|
|
Computer Vision (pp. 609-622). Springer International Publishing.
|
|
|
|
:DOI:`10.1007/978-3-319-16811-1_40`
|
|
|
|
.. [2] Kroon, D. J.: Hessian based Frangi vesselness filter.
|
|
|
|
"""
|
|
|
|
|
|
|
|
if mode is None:
|
|
|
|
warn("Previously, hessian implicitly used 'constant' as the "
|
|
|
|
"border mode when dealing with the edge of the array. The new "
|
|
|
|
"behavior is 'reflect'. To recover the old behavior, use "
|
|
|
|
"mode='constant'. To avoid this warning, please explicitly "
|
|
|
|
"set the mode.", category=FutureWarning, stacklevel=2)
|
|
|
|
mode = 'reflect'
|
|
|
|
|
|
|
|
filtered = frangi(image, sigmas=sigmas, scale_range=scale_range,
|
|
|
|
scale_step=scale_step, alpha=alpha, beta=beta,
|
|
|
|
gamma=gamma, black_ridges=black_ridges, mode=mode,
|
|
|
|
cval=cval)
|
|
|
|
|
|
|
|
filtered[filtered <= 0] = 1
|
|
|
|
return filtered
|