# 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);

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)


## 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);


## 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);


## 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);


## 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);


## 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);