Hello ImageDev
This first example, also presented in the Getting Started section of the Reference Guide, briefly introduces how to open an image from a file and apply two consecutive image processing algorithms on it.
The initial image is a grayscale image that appears almost totally gray when opened with a basic image viewer.
Figure 1. Default display of the initial image
The reason of this aspect is the poor contrast of the image. Almost all pixel intensities are 128 or 129 which are basically displayed in a same neutral gray. A few sparse pixels have the value 0 (black) or 255 (white).
The first step of this example applies the RescaleIntensity algorithm in Percentile mode. This algorithm consists of expanding the image dynamics from two input values to the output range [0, 255].
You can notice that the syntax to invoke this first algorithm is the function mode. The algorithm is executed in a single instruction.
Figure 2. Result of the image normalization
The magic happens and we can now read the text. The image still contains some salt noise which corresponds to the 255 values from the initial image.
To remove the white spots, the example applies a median filter which is an efficient filter for removing impulse noise.
The syntax used to apply this second algorithm is the class mode. The syntax change here serves the purpose of demonstrating the options of both class and function programming using ImageDev. This step also could be launched with a single instruction like in the previous step.
Figure 3. Final image after median filter denoising
Notes:
See also
Figure 1. Default display of the initial image
The reason of this aspect is the poor contrast of the image. Almost all pixel intensities are 128 or 129 which are basically displayed in a same neutral gray. A few sparse pixels have the value 0 (black) or 255 (white).
The first step of this example applies the RescaleIntensity algorithm in Percentile mode. This algorithm consists of expanding the image dynamics from two input values to the output range [0, 255].
- The first input value is taken from the first intensity of the cumulated histogram representing at least 2% of all data. It falls on 128.
- The second input value is taken from the first intensity of the cumulated histogram representing at least 98% of all data. It falls on 129.
You can notice that the syntax to invoke this first algorithm is the function mode. The algorithm is executed in a single instruction.
Figure 2. Result of the image normalization
The magic happens and we can now read the text. The image still contains some salt noise which corresponds to the 255 values from the initial image.
To remove the white spots, the example applies a median filter which is an efficient filter for removing impulse noise.
The syntax used to apply this second algorithm is the class mode. The syntax change here serves the purpose of demonstrating the options of both class and function programming using ImageDev. This step also could be launched with a single instruction like in the previous step.
Figure 3. Final image after median filter denoising
Notes:
- In Python, the imshow method displays ImageDev images in a window. You can remove the comment symbol in front of each 'imagedev.imshow' instruction to visualize the result images.
- This example also shows how to properly catch exceptions. The catch section is run when an
error occurs in the try section. In this case the program ends properly with an error message instead of
causing a crash. To force the program to pass inside the catch function you can:
- Rename or move the password.dat file to cause an exception when invoking the Init function.
- Change the intensityOutputRange of the rescaleIntensity methode to [10, 65535] to cause an inconstancy between the output range and the output type (8-bit).
#include <ImageDev/ImageDev.h> #include <ioformat/IOFormat.h> #include <iolink/view/ImageViewProvider.h> using namespace imagedev; using namespace ioformat; using namespace iolink; int main() { try { // ImageDev library initialization if ( imagedev::isInitialized() == false ) imagedev::init(); // Open a tif file auto imageInput = readImage( std::string( IMAGEDEVDATA_IMAGES_FOLDER ) + "hello_imagedev.tif" ); // Apply a normalization of its graylevels using function coding style auto imageNorm = rescaleIntensity( imageInput, RescaleIntensity::OutputType::SAME_AS_INPUT, RescaleIntensity::RangeMode::PERCENTILE, { 2, 98 }, { 0, 255 }, { 0, 255 } ); // Save the normalized image as a png file writeView( imageNorm, R"(T01_01_norm.png)" ); // Apply a median filter processing using class coding style MedianFilter2d processMedian; processMedian.setInputImage( imageNorm ); processMedian.setKernelMode( MedianFilter2d::KernelMode::DISK ); processMedian.setKernelRadius( 1 ); processMedian.execute(); auto imageMedian = processMedian.outputImage(); // Save the resulting image as a png file writeView( processMedian.outputImage(), R"(T01_01_output.png)" ); // ImageDev library finalization imagedev::finish(); } catch ( imagedev::Exception& error ) { // Print potential exception in the standard output std::cerr << "HelloImageDev exception: " << error.what() << std::endl; return -1; } return 0; }
using System; using ImageDev; using IOLink; using IOFormat; namespace T01_01_HelloImageDev { class Program { static void Main( string[] args ) { try { // Initialize the ImageDev library if not done if ( Initialization.IsInitialized() == false ) Initialization.Init(); // Open a tif file ImageView imageInput = ViewIO.ReadImage( @"Data/images/hello_imagedev.tif" ); // Apply a normalization of its graylevels using function coding style ImageView imageNorm = Processing.RescaleIntensity( imageInput, RescaleIntensity.OutputType.SAME_AS_INPUT, RescaleIntensity.RangeMode.PERCENTILE, new double[] { 2, 98 }, new double[] { 0, 255 }, new double[] { 10, 255 } ); ViewIO.WriteView( imageNorm, @"T01_01_norm.png" ); // Apply a median filter processing using class coding style MedianFilter2d processMedian = new MedianFilter2d { inputImage = imageNorm, kernelMode = MedianFilter2d.KernelMode.DISK, kernelRadius = 1, }; processMedian.Execute(); var imageMedian = processMedian.outputImage; // Notify the garbage collector that the intermediate image can be freed imageNorm.Dispose(); // Save the resulting image as a png file ViewIO.WriteView( imageMedian, @"T01_01_output.png" ); // ImageDev library finalization Initialization.Finish(); } catch ( Exception error ) { // Print potential exception in the standard output System.Console.WriteLine("HelloImageDev exception: " + error.ToString() ); System.Environment.Exit( -1 ); } } } }
import imagedev import imagedev_data import ioformat try: # Initialize the ImageDev library if not done if (imagedev.is_initialized() == False): imagedev.init() # Open and display a tif file image_input = ioformat.read_image(imagedev_data.get_image_path("hello_imagedev.tif")) #imagedev.imshow(image_input, False) # Apply a normalization of its graylevels using function coding style image_norm = imagedev.rescale_intensity(image_input, range_mode=imagedev.RescaleIntensity.RangeMode.PERCENTILE) # Display and save the normalized image as a png file #imagedev.imshow(image_norm, False) ioformat.write_view(image_norm, "T01_01_norm.png") # Apply a median filter processing using class coding style process_median = imagedev.MedianFilter2d() process_median.input_image = image_norm process_median.kernel_mode = imagedev.MedianFilter2d.KernelMode.DISK process_median.kernel_radius = 1 process_median.execute() im_median = process_median.output_image # Display and save the resulting image as a png file #imagedev.imshow(im_median) ioformat.write_view(im_median, "T01_01_output.png") # ImageDev library finalization imagedev.finish() except Exception as error: # Print potential exception in the standard output print("HelloImageDev exception: " + str(error))
See also