ImageDev

NonLocalMeansFilter2d

Adaptive filter denoising a two-dimensional image.

Access to parameter description

For an introduction to image filters: see Images Filtering.

This algorithm computes a weighted mean of a large set of pixels (search windows) around the pixel to be denoised (target pixel). The pixel weight in the search window is a function of the similarity between this pixel and the target pixel. A pixel very similar to the target pixel is assigned to a weight close to 1.0. A pixel very different from the target pixel is assigned to a weight close to 0 and has a small influence on the resulting denoised value.

The similarity between a pixel and the target pixel is based on the squared intensity differences between two patches of user-defined size, centered on the current pixel and the target pixel.

Images are often corrupted by noise because of the acquisition process. For an image $y$ defined on $\Omega$, which is the image domain, the noise added by acquisition is assimilated to an additive white gaussian noise: $$ y[k] = x[k] + e[k], \forall k \in \Omega $$ where $$ e[k] \sim \mathcal{N}(0, \sigma), \forall k \in \Omega $$
The denoised image $z$ is an estimation of $x$ as follows: $$ z[k] = \frac{\sum_{n\in\mathbb{Z}^3} w[k,n]\cdot y[k+n]}{\sum_{n\in\mathbb{Z}^3} w[k,n]} $$ with $$ w[k,n] = f(n)\exp\left(-\frac{ssd(k,n)}{\lambda}\right) $$ where: The algorithm looks for matchings within the search window area around each pixel.

The basic implementation of the previous equation has a complexity of $\mathcal{O}(P^2S^2NM)$ that can be reduced to $\mathcal{O}(S^2NM)$ where $N$ and $M$ are respectively the X and Y dimensions of the input image, $P$ is the patch size, and $S$ is the search window size.

Reference:
A.Buades, B. Coll, J.M.Morel. "A Non-Local Algorithm for Image Denoising". Proceedings of the 2005 IEEE Computer Society Conference on Computer Vision and Pattern Recognition (CVPR), vol. 2, pp. 60-65, 2005.

See also
See related example

Function Syntax

This function returns the outputImage output parameter.
// Function prototype.
std::shared_ptr< iolink::ImageView >
nonLocalMeansFilter2d( std::shared_ptr< iolink::ImageView > inputImage,
                       uint32_t patchRadius,
                       uint32_t kernelRadius,
                       double similarity,
                       NonLocalMeansFilter2d::KernelShape kernelShape,
                       std::shared_ptr< iolink::ImageView > outputImage = NULL );
This function returns the outputImage output parameter.
// Function prototype.
non_local_means_filter_2d( input_image,
                           patch_radius = 3,
                           kernel_radius = 6,
                           similarity = 0.6,
                           kernel_shape = NonLocalMeansFilter2d.KernelShape.SQUARE,
                           output_image = None )
This function returns the outputImage output parameter.
// Function prototype.
public static IOLink.ImageView
NonLocalMeansFilter2d( IOLink.ImageView inputImage,
                       UInt32 patchRadius = 3,
                       UInt32 kernelRadius = 6,
                       double similarity = 0.6,
                       NonLocalMeansFilter2d.KernelShape kernelShape = ImageDev.NonLocalMeansFilter2d.KernelShape.SQUARE,
                       IOLink.ImageView outputImage = null );

Class Syntax

Parameters

Class Name NonLocalMeansFilter2d

Parameter Name Description Type Supported Values Default Value
input
inputImage
The input image. Image Grayscale or Multispectral nullptr
input
kernelShape
The shape of the search window.
SQUARE The search window is a square.
DISK The search window is a disk.
Enumeration SQUARE
input
kernelRadius
The search window half size side length or radius, in pixels.
In case of a square, a value N produces a square of 2N+1 pixels side length. In case of a disk, a value N produces a disk with a 2N+1 pixels diameter. The larger the search window, the better the results usually are. But the size of the search window also affects the run time significantly. This value has to be set to a large enough value so that similar structures can be found within the search window area. Too small values result in simple blurring of the image because there is not enough structural data within the search window area.
UInt32 >=1 6
input
patchRadius
The patch box half size side length, in pixels.
The weight of a pixel in the search windows is computed by comparing the neighborhood of this pixel with the neighborhood of the target pixel. This value represents the edge size of the neighborhood volume, in number of pixels (patch neighborhood is a square), and affects the quality of the result. If this value is either much smaller or much larger than the finest structures of the image, the algorithm shows few or no effect at all. This parameter has almost no effect on the computation time.
UInt32 Any value 3
input
similarity
The similarity is used to compute weight w(k,n) assigned to each pixel in the search window.
The squared similarity is proportional to the standard deviation of the assumed gaussian noise of the input image. The larger this value, the more the resulting image is smoothed. The similarity has no effect on the computation time.
Float64 >=0.001 0.6
output
outputImage
The output image. Its dimensions, type, and calibration are forced to the same values as the input. Image nullptr

Object Examples

std::shared_ptr< iolink::ImageView > polystyrene = ioformat::readImage( std::string( IMAGEDEVDATA_IMAGES_FOLDER ) + "polystyrene.tif" );

NonLocalMeansFilter2d nonLocalMeansFilter2dAlgo;
nonLocalMeansFilter2dAlgo.setInputImage( polystyrene );
nonLocalMeansFilter2dAlgo.setPatchRadius( 3 );
nonLocalMeansFilter2dAlgo.setKernelRadius( 3 );
nonLocalMeansFilter2dAlgo.setSimilarity( 0.6 );
nonLocalMeansFilter2dAlgo.setKernelShape( NonLocalMeansFilter2d::KernelShape::SQUARE );
nonLocalMeansFilter2dAlgo.execute();

std::cout << "outputImage:" << nonLocalMeansFilter2dAlgo.outputImage()->toString();
polystyrene = ioformat.read_image(imagedev_data.get_image_path("polystyrene.tif"))

non_local_means_filter_2d_algo = imagedev.NonLocalMeansFilter2d()
non_local_means_filter_2d_algo.input_image = polystyrene
non_local_means_filter_2d_algo.patch_radius = 3
non_local_means_filter_2d_algo.kernel_radius = 3
non_local_means_filter_2d_algo.similarity = 0.6
non_local_means_filter_2d_algo.kernel_shape = imagedev.NonLocalMeansFilter2d.SQUARE
non_local_means_filter_2d_algo.execute()

print( "output_image:", str( non_local_means_filter_2d_algo.output_image ) );
ImageView polystyrene = ViewIO.ReadImage( @"Data/images/polystyrene.tif" );

NonLocalMeansFilter2d nonLocalMeansFilter2dAlgo = new NonLocalMeansFilter2d
{
    inputImage = polystyrene,
    patchRadius = 3,
    kernelRadius = 3,
    similarity = 0.6,
    kernelShape = NonLocalMeansFilter2d.KernelShape.SQUARE
};
nonLocalMeansFilter2dAlgo.Execute();

Console.WriteLine( "outputImage:" + nonLocalMeansFilter2dAlgo.outputImage.ToString() );

Function Examples

std::shared_ptr< iolink::ImageView > polystyrene = ioformat::readImage( std::string( IMAGEDEVDATA_IMAGES_FOLDER ) + "polystyrene.tif" );

auto result = nonLocalMeansFilter2d( polystyrene, 3, 3, 0.6, NonLocalMeansFilter2d::KernelShape::SQUARE );

std::cout << "outputImage:" << result->toString();
polystyrene = ioformat.read_image(imagedev_data.get_image_path("polystyrene.tif"))

result = imagedev.non_local_means_filter_2d( polystyrene, 3, 3, 0.6, imagedev.NonLocalMeansFilter2d.SQUARE )

print( "output_image:", str( result ) );
ImageView polystyrene = ViewIO.ReadImage( @"Data/images/polystyrene.tif" );

IOLink.ImageView result = Processing.NonLocalMeansFilter2d( polystyrene, 3, 3, 0.6, NonLocalMeansFilter2d.KernelShape.SQUARE );

Console.WriteLine( "outputImage:" + result.ToString() );