Tutorial on linear filters¶
from timagetk.algorithms.linearfilter import linearfilter
from timagetk.third_party.vt_parser import FILTERING_METHODS
from timagetk.io import imread
from timagetk.io.util import shared_data
from timagetk.visu.mplt import grayscale_imshow
/builds/J-gEBwyb/0/mosaic/timagetk/src/timagetk/components/labelled_image.py:31: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
from tqdm.autonotebook import tqdm
Linear filters are applied on intensity images (grayscale).
image_path = shared_data('sphere_membrane_0.0.inr.gz', 'sphere')
img = imread(image_path)
middle_z_slice = img.get_shape('z') // 2
List of filtering methods¶
print(FILTERING_METHODS)
['smoothing', 'gradient', 'hessian', 'laplacian', 'zero-crossings-hessian', 'zero-crossings-laplacian', 'gradient-hessian', 'gradient-laplacian', 'gradient-extrema']
Gaussian smoothing¶
Gaussian smoothing is often used to reduce noise and sharp local variations in intensity images.
fimg = linearfilter(img, method='smoothing', sigma=1.0, real=True)
We advise to use real=True
to avoid applying anisotropic filtering on anisotropic images.
The ‘intensity’ of the smoothing is controlled by the parameter sigma
.
fimg2 = linearfilter(img, method='smoothing', sigma=2.0, real=True)
fimg4 = linearfilter(img, method='smoothing', sigma=4.0, real=True)
img_titles = ['Original', f'Sigma=1.0', f'Sigma=2.0', f'Sigma=4.0']
fig, axes = grayscale_imshow([img, fimg, fimg2, fimg4], slice_id=middle_z_slice, title=img_titles, max_per_line=2, figsize=(8, 8), dpi=96)
0%| | 0/4 [00:00<?, ?image/s]
25%|██▌ | 1/4 [00:00<00:01, 2.14image/s]
50%|█████ | 2/4 [00:00<00:00, 2.01image/s]
75%|███████▌ | 3/4 [00:01<00:00, 2.08image/s]
100%|██████████| 4/4 [00:01<00:00, 2.08image/s]
100%|██████████| 4/4 [00:01<00:00, 2.07image/s]
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[6], line 2
1 img_titles = ['Original', f'Sigma=1.0', f'Sigma=2.0', f'Sigma=4.0']
----> 2 fig, axes = grayscale_imshow([img, fimg, fimg2, fimg4], slice_id=middle_z_slice, title=img_titles, max_per_line=2, figsize=(8, 8), dpi=96)
File /builds/J-gEBwyb/0/mosaic/timagetk/src/timagetk/visu/mplt.py:447, in grayscale_imshow(image, slice_id, axis, val_range, cmap, **kwargs)
445 # Update kwargs to pass them to ``_multiple_plots``
446 kwargs.update({'val_range': val_range, 'cmap': cmap, 'title': titles})
--> 447 return _multiple_plots(grayscale_imshow, image, **kwargs)
448 else:
449 image, title_suffix = _to_2d(image, slice_id)
File /builds/J-gEBwyb/0/mosaic/timagetk/src/timagetk/visu/mplt.py:1732, in _multiple_plots(plotting_func, image, **kwargs)
1729 else:
1730 thumb_height = thumb_size
-> 1732 fig, axes = plt.subplots(n_rows, n_columns, gridspec_kw={'width_ratios': width_ratios})
1733 if n_rows == 1 or n_columns == 1:
1734 axes = axes.reshape(n_rows, n_columns)
File /opt/conda/envs/timagetk/lib/python3.9/site-packages/matplotlib/pyplot.py:1614, in subplots(nrows, ncols, sharex, sharey, squeeze, width_ratios, height_ratios, subplot_kw, gridspec_kw, **fig_kw)
1470 """
1471 Create a figure and a set of subplots.
1472
(...)
1611
1612 """
1613 fig = figure(**fig_kw)
-> 1614 axs = fig.subplots(nrows=nrows, ncols=ncols, sharex=sharex, sharey=sharey,
1615 squeeze=squeeze, subplot_kw=subplot_kw,
1616 gridspec_kw=gridspec_kw, height_ratios=height_ratios,
1617 width_ratios=width_ratios)
1618 return fig, axs
File /opt/conda/envs/timagetk/lib/python3.9/site-packages/matplotlib/figure.py:930, in FigureBase.subplots(self, nrows, ncols, sharex, sharey, squeeze, width_ratios, height_ratios, subplot_kw, gridspec_kw)
926 raise ValueError("'width_ratios' must not be defined both as "
927 "parameter and as key in 'gridspec_kw'")
928 gridspec_kw['width_ratios'] = width_ratios
--> 930 gs = self.add_gridspec(nrows, ncols, figure=self, **gridspec_kw)
931 axs = gs.subplots(sharex=sharex, sharey=sharey, squeeze=squeeze,
932 subplot_kw=subplot_kw)
933 return axs
File /opt/conda/envs/timagetk/lib/python3.9/site-packages/matplotlib/figure.py:1542, in FigureBase.add_gridspec(self, nrows, ncols, **kwargs)
1503 """
1504 Return a `.GridSpec` that has this figure as a parent. This allows
1505 complex layout of Axes in the figure.
(...)
1538
1539 """
1541 _ = kwargs.pop('figure', None) # pop in case user has added this...
-> 1542 gs = GridSpec(nrows=nrows, ncols=ncols, figure=self, **kwargs)
1543 return gs
File /opt/conda/envs/timagetk/lib/python3.9/site-packages/matplotlib/gridspec.py:378, in GridSpec.__init__(self, nrows, ncols, figure, left, bottom, right, top, wspace, hspace, width_ratios, height_ratios)
375 self.hspace = hspace
376 self.figure = figure
--> 378 super().__init__(nrows, ncols,
379 width_ratios=width_ratios,
380 height_ratios=height_ratios)
File /opt/conda/envs/timagetk/lib/python3.9/site-packages/matplotlib/gridspec.py:55, in GridSpecBase.__init__(self, nrows, ncols, height_ratios, width_ratios)
53 self._nrows, self._ncols = nrows, ncols
54 self.set_height_ratios(height_ratios)
---> 55 self.set_width_ratios(width_ratios)
File /opt/conda/envs/timagetk/lib/python3.9/site-packages/matplotlib/gridspec.py:110, in GridSpecBase.set_width_ratios(self, width_ratios)
108 width_ratios = [1] * self._ncols
109 elif len(width_ratios) != self._ncols:
--> 110 raise ValueError('Expected the given number of width ratios to '
111 'match the number of columns of the grid')
112 self._col_width_ratios = width_ratios
ValueError: Expected the given number of width ratios to match the number of columns of the grid
<Figure size 640x480 with 0 Axes>
Note that it can decrease the contrast!
Gradient filtering¶
An image gradient is a directional change in the intensity or color in an image. https://en.wikipedia.org/wiki/Image_gradient
fimg = linearfilter(img, method='gradient')
img_titles = ['Original', f'Gradient']
fig, axes = grayscale_imshow([img, fimg], slice_id=middle_z_slice, title=img_titles, figsize=(8, 8), dpi=96)
Hessian filtering¶
In mathematics, the Hessian matrix or Hessian is a square matrix of second-order partial derivatives of a scalar-valued function, or scalar field. https://en.wikipedia.org/wiki/Hessian_matrix
fimg = linearfilter(img, method='hessian')
img_titles = ['Original', f'Hessian']
fig, axes = grayscale_imshow([img, fimg], slice_id=middle_z_slice, title=img_titles, figsize=(8, 8), dpi=96)
Laplacian filtering¶
Discrete Laplace operator is often used in image processing e.g. in edge detection and motion estimation applications. https://en.wikipedia.org/wiki/Discrete_Laplace_operator#Image_Processing
fimg = linearfilter(img, method='laplacian')
img_titles = ['Original', f'Laplacian']
fig, axes = grayscale_imshow([img, fimg], slice_id=middle_z_slice, title=img_titles, figsize=(8, 8), dpi=96)
Other gradient filters¶
gfilters = ['gradient-hessian', 'gradient-laplacian', 'gradient-extrema']
fimg = [linearfilter(img, method=fmeth) for fmeth in gfilters]
img_titles = ['Original'] + gfilters
fig, axes = grayscale_imshow([img]+fimg, slice_id=middle_z_slice, title=img_titles, max_per_line=2, figsize=(8, 8), dpi=96)
Zero-crossing filters¶
zfilters = ['zero-crossings-hessian', 'zero-crossings-laplacian']
fimg = [linearfilter(img, method=fmeth) for fmeth in zfilters]
img_titles = ['Original'] + zfilters
fig, axes = grayscale_imshow([img]+fimg, slice_id=middle_z_slice, title=img_titles, max_per_line=3, figsize=(8, 8), dpi=96)