Deconvolution Filters

Deconvolution Kernel Filter

         Deconvolution serves as the inverse matrix operation to a convolution filter. If a convolution transformation is applied, such as with the Gaussian blur kernel filter, attempting to reverse this operation cannot fully restore the original image due to the averaging of pixel values and the loss of some details. However, deconvolution is valuable for image restoration and deblurring.

         In the example below we apply the Gaussian blur convolution filter and then restore the original image with Deconvolution filer:

// gaussian 3x3 convolution kernel
{
  {1, 2, 1,},
  {2, 4, 2,},
  {1, 2, 1,},
};
DeconvolutionFilterOptions(ConvolutionFilter.GetGaussian(Size, Sigma))

         The restored image is not identical to the original, but it exhibits more details after the deblurring process.

Original image
Deconvolution filter
Original landscape image
Deconvolution Gaussian blur kernel filter
Deconvolution kernel filter

C# code example

         The full C# code example below shows the usage of the Aspose.Imaging .NET API. You can utilize the `ConvolutionFilter` class with "GetGaussian" blurring method and subsequently deblur using the DeconvolutionFilterOptions. In this example, image templates in PNG and SVG formats are loaded from the "templates" folder, and filters are applied from a predefined list.

using System;
using System.Collections.Generic;
using System.IO;
using Aspose.Imaging.ImageFilters.ComplexUtils;
using Aspose.Imaging.ImageFilters.Convolution;
using Aspose.Imaging.ImageFilters.FilterOptions;
const int Size = 5;
const double Sigma = 1.5, Angle = 45;
double[,] customKernel = GetRandomKernel(Size, 7, new Random());
Complex[,] customComplex = ConvolutionFilter.ToComplex(customKernel);
var kernelFilters = new FilterOptionsBase[]
{
// convolution filters
new ConvolutionFilterOptions(ConvolutionFilter.Emboss3x3),
new ConvolutionFilterOptions(ConvolutionFilter.Emboss5x5),
new ConvolutionFilterOptions(ConvolutionFilter.Sharpen3x3),
new ConvolutionFilterOptions(ConvolutionFilter.Sharpen5x5),
new ConvolutionFilterOptions(ConvolutionFilter.GetBlurBox(Size)),
new ConvolutionFilterOptions(ConvolutionFilter.GetBlurMotion(Size, Angle)),
new ConvolutionFilterOptions(ConvolutionFilter.GetGaussian(Size, Sigma)),
new ConvolutionFilterOptions(customKernel),
new GaussianBlurFilterOptions(Size, Sigma),
new SharpenFilterOptions(Size, Sigma),
new MedianFilterOptions(Size),
// deconvolution filters
new DeconvolutionFilterOptions(ConvolutionFilter.GetGaussian(Size, Sigma)),
new DeconvolutionFilterOptions(customKernel),
new DeconvolutionFilterOptions(customComplex),
new GaussWienerFilterOptions(Size, Sigma),
new MotionWienerFilterOptions(Size, Sigma, Angle),
};
var templatesFolder = @"c:\Users\USER\Downloads\templates\";
var dataDir = templatesFolder;
var inputPaths = new[]
{
Path.Combine(dataDir, "template.png"),
Path.Combine(dataDir, "template.svg"),
};
var outputs = new List<string>();
foreach (var inputPath in inputPaths)
{
for (int i = 0; i < kernelFilters.Length; i++)
{
var options = kernelFilters[i];
using (var image = Image.Load(inputPath))
{
var outputPath = $"{inputPath}-{i}.png";
if (image is RasterImage raster)
{
Filter(raster, options, outputPath);
}
else if (image is VectorImage vector)
{
var vectorAsPng = inputPath + ".png";
if (!File.Exists(vectorAsPng))
{
vector.Save(vectorAsPng);
outputs.Add(vectorAsPng);
}
using (var png = Image.Load(vectorAsPng))
{
Filter(png as RasterImage, options, outputPath);
}
}
}
}
}
outputs.ForEach(p => File.Delete(p));
static void Filter(RasterImage raster, FilterOptionsBase options, string outputPath)
{
raster.Filter(raster.Bounds, options);
raster.Save(outputPath);
}
static double[,] GetRandomKernel(int cols, int rows, Random random)
{
double[,] customKernel = new double[cols, rows];
for (int y = 0; y < customKernel.GetLength(0); y++)
{
for (int x = 0; x < customKernel.GetLength(1); x++)
{
customKernel[y, x] = random.NextDouble();
}
}
return customKernel;
}