178 lines
6.9 KiB
Python
178 lines
6.9 KiB
Python
import numpy as np
|
|
from scipy import ndimage as ndi
|
|
from .._shared.utils import check_nD
|
|
|
|
|
|
__all__ = ['gabor_kernel', 'gabor']
|
|
|
|
|
|
def _sigma_prefactor(bandwidth):
|
|
b = bandwidth
|
|
# See http://www.cs.rug.nl/~imaging/simplecell.html
|
|
return 1.0 / np.pi * np.sqrt(np.log(2) / 2.0) * \
|
|
(2.0 ** b + 1) / (2.0 ** b - 1)
|
|
|
|
|
|
def gabor_kernel(frequency, theta=0, bandwidth=1, sigma_x=None, sigma_y=None,
|
|
n_stds=3, offset=0):
|
|
"""Return complex 2D Gabor filter kernel.
|
|
|
|
Gabor kernel is a Gaussian kernel modulated by a complex harmonic function.
|
|
Harmonic function consists of an imaginary sine function and a real
|
|
cosine function. Spatial frequency is inversely proportional to the
|
|
wavelength of the harmonic and to the standard deviation of a Gaussian
|
|
kernel. The bandwidth is also inversely proportional to the standard
|
|
deviation.
|
|
|
|
Parameters
|
|
----------
|
|
frequency : float
|
|
Spatial frequency of the harmonic function. Specified in pixels.
|
|
theta : float, optional
|
|
Orientation in radians. If 0, the harmonic is in the x-direction.
|
|
bandwidth : float, optional
|
|
The bandwidth captured by the filter. For fixed bandwidth, ``sigma_x``
|
|
and ``sigma_y`` will decrease with increasing frequency. This value is
|
|
ignored if ``sigma_x`` and ``sigma_y`` are set by the user.
|
|
sigma_x, sigma_y : float, optional
|
|
Standard deviation in x- and y-directions. These directions apply to
|
|
the kernel *before* rotation. If `theta = pi/2`, then the kernel is
|
|
rotated 90 degrees so that ``sigma_x`` controls the *vertical*
|
|
direction.
|
|
n_stds : scalar, optional
|
|
The linear size of the kernel is n_stds (3 by default) standard
|
|
deviations
|
|
offset : float, optional
|
|
Phase offset of harmonic function in radians.
|
|
|
|
Returns
|
|
-------
|
|
g : complex array
|
|
Complex filter kernel.
|
|
|
|
References
|
|
----------
|
|
.. [1] https://en.wikipedia.org/wiki/Gabor_filter
|
|
.. [2] https://web.archive.org/web/20180127125930/http://mplab.ucsd.edu/tutorials/gabor.pdf
|
|
|
|
Examples
|
|
--------
|
|
>>> from skimage.filters import gabor_kernel
|
|
>>> from skimage import io
|
|
>>> from matplotlib import pyplot as plt # doctest: +SKIP
|
|
|
|
>>> gk = gabor_kernel(frequency=0.2)
|
|
>>> plt.figure() # doctest: +SKIP
|
|
>>> io.imshow(gk.real) # doctest: +SKIP
|
|
>>> io.show() # doctest: +SKIP
|
|
|
|
>>> # more ripples (equivalent to increasing the size of the
|
|
>>> # Gaussian spread)
|
|
>>> gk = gabor_kernel(frequency=0.2, bandwidth=0.1)
|
|
>>> plt.figure() # doctest: +SKIP
|
|
>>> io.imshow(gk.real) # doctest: +SKIP
|
|
>>> io.show() # doctest: +SKIP
|
|
"""
|
|
if sigma_x is None:
|
|
sigma_x = _sigma_prefactor(bandwidth) / frequency
|
|
if sigma_y is None:
|
|
sigma_y = _sigma_prefactor(bandwidth) / frequency
|
|
|
|
x0 = np.ceil(max(np.abs(n_stds * sigma_x * np.cos(theta)),
|
|
np.abs(n_stds * sigma_y * np.sin(theta)), 1))
|
|
y0 = np.ceil(max(np.abs(n_stds * sigma_y * np.cos(theta)),
|
|
np.abs(n_stds * sigma_x * np.sin(theta)), 1))
|
|
y, x = np.mgrid[-y0:y0 + 1, -x0:x0 + 1]
|
|
|
|
rotx = x * np.cos(theta) + y * np.sin(theta)
|
|
roty = -x * np.sin(theta) + y * np.cos(theta)
|
|
|
|
g = np.zeros(y.shape, dtype=np.complex)
|
|
g[:] = np.exp(-0.5 * (rotx ** 2 / sigma_x ** 2 + roty ** 2 / sigma_y ** 2))
|
|
g /= 2 * np.pi * sigma_x * sigma_y
|
|
g *= np.exp(1j * (2 * np.pi * frequency * rotx + offset))
|
|
|
|
return g
|
|
|
|
|
|
def gabor(image, frequency, theta=0, bandwidth=1, sigma_x=None,
|
|
sigma_y=None, n_stds=3, offset=0, mode='reflect', cval=0):
|
|
"""Return real and imaginary responses to Gabor filter.
|
|
|
|
The real and imaginary parts of the Gabor filter kernel are applied to the
|
|
image and the response is returned as a pair of arrays.
|
|
|
|
Gabor filter is a linear filter with a Gaussian kernel which is modulated
|
|
by a sinusoidal plane wave. Frequency and orientation representations of
|
|
the Gabor filter are similar to those of the human visual system.
|
|
Gabor filter banks are commonly used in computer vision and image
|
|
processing. They are especially suitable for edge detection and texture
|
|
classification.
|
|
|
|
Parameters
|
|
----------
|
|
image : 2-D array
|
|
Input image.
|
|
frequency : float
|
|
Spatial frequency of the harmonic function. Specified in pixels.
|
|
theta : float, optional
|
|
Orientation in radians. If 0, the harmonic is in the x-direction.
|
|
bandwidth : float, optional
|
|
The bandwidth captured by the filter. For fixed bandwidth, ``sigma_x``
|
|
and ``sigma_y`` will decrease with increasing frequency. This value is
|
|
ignored if ``sigma_x`` and ``sigma_y`` are set by the user.
|
|
sigma_x, sigma_y : float, optional
|
|
Standard deviation in x- and y-directions. These directions apply to
|
|
the kernel *before* rotation. If `theta = pi/2`, then the kernel is
|
|
rotated 90 degrees so that ``sigma_x`` controls the *vertical*
|
|
direction.
|
|
n_stds : scalar, optional
|
|
The linear size of the kernel is n_stds (3 by default) standard
|
|
deviations.
|
|
offset : float, optional
|
|
Phase offset of harmonic function in radians.
|
|
mode : {'constant', 'nearest', 'reflect', 'mirror', 'wrap'}, optional
|
|
Mode used to convolve image with a kernel, passed to `ndi.convolve`
|
|
cval : scalar, optional
|
|
Value to fill past edges of input if ``mode`` of convolution is
|
|
'constant'. The parameter is passed to `ndi.convolve`.
|
|
|
|
Returns
|
|
-------
|
|
real, imag : arrays
|
|
Filtered images using the real and imaginary parts of the Gabor filter
|
|
kernel. Images are of the same dimensions as the input one.
|
|
|
|
References
|
|
----------
|
|
.. [1] https://en.wikipedia.org/wiki/Gabor_filter
|
|
.. [2] https://web.archive.org/web/20180127125930/http://mplab.ucsd.edu/tutorials/gabor.pdf
|
|
|
|
Examples
|
|
--------
|
|
>>> from skimage.filters import gabor
|
|
>>> from skimage import data, io
|
|
>>> from matplotlib import pyplot as plt # doctest: +SKIP
|
|
|
|
>>> image = data.coins()
|
|
>>> # detecting edges in a coin image
|
|
>>> filt_real, filt_imag = gabor(image, frequency=0.6)
|
|
>>> plt.figure() # doctest: +SKIP
|
|
>>> io.imshow(filt_real) # doctest: +SKIP
|
|
>>> io.show() # doctest: +SKIP
|
|
|
|
>>> # less sensitivity to finer details with the lower frequency kernel
|
|
>>> filt_real, filt_imag = gabor(image, frequency=0.1)
|
|
>>> plt.figure() # doctest: +SKIP
|
|
>>> io.imshow(filt_real) # doctest: +SKIP
|
|
>>> io.show() # doctest: +SKIP
|
|
"""
|
|
check_nD(image, 2)
|
|
g = gabor_kernel(frequency, theta, bandwidth, sigma_x, sigma_y, n_stds,
|
|
offset)
|
|
|
|
filtered_real = ndi.convolve(image, np.real(g), mode=mode, cval=cval)
|
|
filtered_imag = ndi.convolve(image, np.imag(g), mode=mode, cval=cval)
|
|
|
|
return filtered_real, filtered_imag
|