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.

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)
<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:

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/380508fa6dd47234049d148b2aa382f83ef787a834e2ef7ae67d9eba64676ee3.svg
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/amin/Code/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/amin/Code/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/amin/Code/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/ac76bc7f522e6f65c802be93a307802a20ad57fbcaf86860d6a8133d50a64012.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):

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/0657b3fe61571a659d85c196923332cd9001f0854de0d3bdaaf473adb3460a4e.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.

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/db87fe2389c7dd8745e0f47a295048c0f87492a679d4b8d967f05044c8b1a220.svg

patch_size#

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

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/927fa6bd2bd0cce389a659b981f349c9eda48aaaece3fb5823b46b3545c3da0c.svg

patch_distance#

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

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/c10acb6d969cb25b2037e469b440e458a6c720933dbcf4cac7960a42673131cc.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.

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/9b6b846030da688f08dd576fca0242c6ee9778035776b1d779fab09c7a83206f.svg