nl_means_layered#

Applies the non-local means filter to each 2D layer of a 3D image (stack of 2D images) in parallel. This function is applicable in removing noise from SEM images.

[1]:
import matplotlib.pyplot as plt
import numpy as np
import porespy as ps
from edt import edt
import inspect
ps.visualization.set_mpl_style()
inspect.signature(ps.filters.nl_means_layered)
[1]:
<Signature (im, cores=None, axis=0, patch_size=5, patch_distance=15, h=4)>

im#

The input image is a greyscale image with noise to be removed. Let’s create a test image:

[2]:
np.random.seed(10)
im = ps.generators.blobs(shape=[50, 50, 50])
dt = edt(im)
fig, ax = plt.subplots(1, 1, figsize=[6, 6])
ax.imshow(dt[:,:,15])
ax.axis(False);
../../../_images/examples_filters_reference_nl_means_layered_4_0.svg
[3]:
filtered_im = ps.filters.nl_means_layered(dt)
fig, ax = plt.subplots(1, 1, figsize=[6, 6])
ax.imshow(filtered_im[:,:,15])
ax.axis(False);
/home/runner/work/porespy/porespy/porespy/filters/_nlmeans.py:63: FutureWarning: `multichannel` is a deprecated argument name for `match_histograms`. It will be removed in version 1.0. Please use `channel_axis` instead.
  temp[:, :, i] = match_histograms(temp[:, :, i], temp[:, :, 0],
/home/runner/work/porespy/porespy/porespy/filters/_nlmeans.py:68: FutureWarning: `multichannel` is a deprecated argument name for `estimate_sigma`. It will be removed in version 1.0. Please use `channel_axis` instead.
  sigma_est = np.mean(estimate_sigma(temp[:, :, 0], multichannel=False))
/home/runner/work/porespy/porespy/porespy/filters/_nlmeans.py:59: FutureWarning: `multichannel` is a deprecated argument name for `denoise_nl_means`. It will be removed in version 1.0. Please use `channel_axis` instead.
  return func(**kwargs)
../../../_images/examples_filters_reference_nl_means_layered_5_1.svg

cores#

The number of cores to use for the processing. The default is all cores. Let’s change it to a smaller number (this will slow down the processing time):

[4]:
filtered_im = ps.filters.nl_means_layered(dt, cores=1)
fig, ax = plt.subplots(1, 1, figsize=[6, 6])
ax.imshow(filtered_im[:,:,15])
ax.axis(False);
../../../_images/examples_filters_reference_nl_means_layered_8_0.svg

axis#

The axis along which 2D slices for the filtering process should be taken. This can be 0,1, or 2 corresponding to x, y, and z axis. By default the slices are taken along x axis. When using tomography images, this should correspond to the axis of rotation of the tomography stage.

[5]:
im_x = ps.filters.nl_means_layered(dt, axis=0)
im_y = ps.filters.nl_means_layered(dt, axis=1)
im_z = ps.filters.nl_means_layered(dt, axis=2)
fig, ax = plt.subplots(1, 4, figsize=[15, 5])
ax[0].imshow(dt[:,:,15])
ax[0].axis(False);
ax[1].imshow(im_x[:,:,15])
ax[1].axis(False);
ax[2].imshow(im_y[:,:,15])
ax[2].axis(False);
ax[3].imshow(im_z[:,:,15])
ax[3].axis(False);
../../../_images/examples_filters_reference_nl_means_layered_11_0.svg

patch_size#

The size of patches used for denoising filter. The default is 5.

[6]:
im_1 = ps.filters.nl_means_layered(dt, patch_size=1)
im_2 = ps.filters.nl_means_layered(dt, patch_size=3)
im_3 = ps.filters.nl_means_layered(dt, patch_size=8)
fig, ax = plt.subplots(1, 4, figsize=[15, 5])
ax[0].imshow(dt[:,:,15])
ax[0].axis(False);
ax[1].imshow(im_1[:,:,15])
ax[1].axis(False);
ax[2].imshow(im_2[:,:,15])
ax[2].axis(False);
ax[3].imshow(im_3[:,:,15])
ax[3].axis(False);
../../../_images/examples_filters_reference_nl_means_layered_14_0.svg

patch_distance#

Maximal distance in pixels where to search patches used for denoising. The default is 15.

[7]:
im_1 = ps.filters.nl_means_layered(dt, patch_distance=10)
im_2 = ps.filters.nl_means_layered(dt)
im_3 = ps.filters.nl_means_layered(dt, patch_distance=20)
fig, ax = plt.subplots(1, 4, figsize=[15, 5])
ax[0].imshow(dt[:,:,15])
ax[0].axis(False);
ax[1].imshow(im_1[:,:,15])
ax[1].axis(False);
ax[2].imshow(im_2[:,:,15])
ax[2].axis(False);
ax[3].imshow(im_3[:,:,15])
ax[3].axis(False);
../../../_images/examples_filters_reference_nl_means_layered_17_0.svg

h#

Cut-off distance (in gray levels). The higher h, the more permissive one is in accepting patches. A higher h results in a smoother image, at the expense of blurring features. For a Gaussian noise of standard deviation sigma, a rule of thumb is to choose the value of h to be sigma of slightly less. The default is 4.

[8]:
im_1 = ps.filters.nl_means_layered(dt, h=2)
im_2 = ps.filters.nl_means_layered(dt)
im_3 = ps.filters.nl_means_layered(dt, h=6)
fig, ax = plt.subplots(1, 4, figsize=[15, 5])
ax[0].imshow(dt[:,:,15])
ax[0].axis(False);
ax[1].imshow(im_1[:,:,15])
ax[1].axis(False);
ax[2].imshow(im_2[:,:,15])
ax[2].axis(False);
ax[3].imshow(im_3[:,:,15])
ax[3].axis(False);
../../../_images/examples_filters_reference_nl_means_layered_20_0.svg