ImageDev

Denoising

This example shows how to denoise a grayscale image with three different algorithms available in ImageDev.
The first denoising algorithm applied in this example is BoxFilter2d. This linear filter computes a moving average on a square window with a user-defined size. It is fast to apply but softens the objects edges and adds blur to the input image.

The second denoising algorithm is MedianFilter2d. This non-linear filter replaces each pixel by the median value of its neighborhood. It is slower to compute than a box filter but preserves the edges better. It is especially efficient for removing impulse noise.

At last, a NonLocalMeansFilter2d algorithm is applied. This adaptive filter performs a weighted averaging of each pixel with similar pixels of its neighborhood. It is very slow to compute but preserves edges very efficiently.

<b>(a)</b>
(a)
<b>(b)</b>
(b)
<b>(c)</b>
(c)
<b>(d)</b>
(d)
Figure 1. Denoising filters (a) the initial image, (b) the box filter result,
(c) the median filter result, and (d) the non-local means filter result

Each filter result is saved in the project directory. As expected, the box filter generates blur, the median filter preserves edges better, and the non-local means filter preserves also the internal structure of nuclei.

#include <ImageDev/ImageDev.h>
#include <ioformat/IOFormat.h>
#include <string.h>

using namespace imagedev;

int
main( int argc, char* argv[] )
{
    int status = 0;

    try
    {
        // ImageDev library initialization
        if ( imagedev::isInitialized() == false )
            imagedev::init();

        // Open a tif file to denoise
        auto imageInput = ioformat::readImage( std::string( IMAGEDEVDATA_IMAGES_FOLDER ) + "mnu.tif" );

        // Apply an average filter
        std::cout << "Applying a box filter... " << std::endl;
        auto imageOutput = boxFilter2d( imageInput, 7, 7, BoxFilter2d::AutoScale::YES );
        ioformat::writeView( imageOutput, "T03_01_box.png" );

        // Apply a median filter processing
        std::cout << "Applying a median filter... " << std::endl;
        imageOutput =
            medianFilter2d( imageInput, 3, MedianFilter2d::KernelMode::SQUARE, MedianFilter2d::SearchMode::AUTOMATIC );
        ioformat::writeView( imageOutput, "T03_01_median.png" );

        // Apply a non-local means filter processing
        std::cout << "Applying a non-local means filter... " << std::endl;
        imageOutput = nonLocalMeansFilter2d( imageInput, 3, 3, 0.6, NonLocalMeansFilter2d::SQUARE );
        ioformat::writeView( imageOutput, "T03_01_nlm.png" );

        std::cout << "This example ran successfully." << std::endl;
    }
    catch ( const imagedev::Exception& error )
    {
        // Print potential exception in the standard output
        std::cerr << "ImageDev exception: " << error.what() << std::endl;
        status = -1;
    }

    // ImageDev library finalization
    imagedev::finish();

    // Check if we must ask for an enter key to close the program
    if ( !( ( argc == 2 ) && strcmp( argv[1], "--no-stop-at-end" ) == 0 ) )
        std::cout << "Press Enter key to close this window." << std::endl, getchar();

    return status;
}
using System;
using ImageDev;
using IOLink;
using IOFormat;

namespace T03_01_Denoising
{
    class Program
    {
        static void Main(string[] args)
        {
            int status = 0;

            try
            {
                // Initialize the ImageDev library if not done
                if (Initialization.IsInitialized() == false)
                    Initialization.Init();

                // Open a tif file to denoise
                ImageView imageInput = ViewIO.ReadImage("Data/images/mnu.tif") as ImageView;

                // Apply an average filter
                Console.WriteLine("Applying a box filter...");
                ImageView imageOutput = Processing.BoxFilter2d(imageInput, 7, 7) as ImageView;
                IOFormat.ViewIO.WriteView(imageOutput, "T03_01_box.png");

                // Apply a median filter processing
                Console.WriteLine("Applying a median filter... ");
                imageOutput = Processing.MedianFilter2d(imageInput, 3, MedianFilter2d.KernelMode.SQUARE);
                IOFormat.ViewIO.WriteView(imageOutput, "T03_01_median.png");

                // Apply a non-local means filter processing
                Console.WriteLine("Applying a non-local means filter... ");
                imageOutput = Processing.NonLocalMeansFilter2d(imageInput, 3, 3);
                IOFormat.ViewIO.WriteView(imageOutput, "T03_01_nlm.png");

            }
            catch (Exception error)
            {
                // Print potential exception in the standard output
                System.Console.WriteLine("HelloImageDev exception: " + error.ToString());
                status = -1;
            }

            // ImageDev library finalization
            Initialization.Finish();

            // Check if we must ask for an enter key to close the program
            if (!((args.Length >= 1) && (args[0] == "--no-stop-at-end")))
            {
                System.Console.WriteLine("Press Enter key to close this window.");
                System.Console.ReadKey();
            }

            System.Environment.Exit(status);
        }
    }
}
import imagedev
import imagedev_data
import ioformat

# Open a tif file to denoise
image_input = ioformat.read_image(imagedev_data.get_image_path("mnu.tif"))

# Apply an average filter
print("Applying a box filter...")
image_output = imagedev.box_filter_2d(image_input, 7, 7)
ioformat.write_view(image_output, "T03_01_box.png")

# Apply a median filter processing
print("Applying a median filter...")
image_output = imagedev.median_filter_2d(image_input, 3, imagedev.MedianFilter2d.SQUARE)
ioformat.write_view(image_output, "T03_01_median.png")

# Apply a non-local means filter processing
print("Applying a non-local means filter...")
image_output = imagedev.non_local_means_filter_2d(image_input, 3, 3)
ioformat.write_view(image_output, "T03_01_nlm.png")


See also