diff --git a/src/ImageProcessor/Filters/Convolution/GuassianBlur.cs b/src/ImageProcessor/Filters/Convolution/GuassianBlur.cs new file mode 100644 index 000000000..37fa90173 --- /dev/null +++ b/src/ImageProcessor/Filters/Convolution/GuassianBlur.cs @@ -0,0 +1,116 @@ +namespace ImageProcessor.Filters.Convolution +{ + using System; + using System.Runtime.CompilerServices; + + public class GuassianBlur : ConvolutionFilter + { + private int kernelSize; + + private float standardDeviation; + + /// + /// Initializes a new instance of the class. + /// + /// + /// The size. + /// + /// + /// The standard deviation 'sigma' value for calculating Gaussian curves. + /// + public GuassianBlur(int size, float standardDeviation) + { + this.kernelSize = size; + this.standardDeviation = standardDeviation; + } + + public override float[,] KernelX { get; } + + /// + /// Create a 2 dimensional Gaussian kernel using the Gaussian G(x y) function for + /// blurring images. + /// + /// Kernel Size + /// A Gaussian Kernel with the given size. + private float[,] CreateGuassianBlurFilter() + { + // Create kernel + int size = this.kernelSize; + float[,] kernel = this.CreateGaussianKernel2D(size); + float min = kernel[0, 0]; + + // Convert to integer blurring kernel. First of all the integer kernel is calculated from Kernel2D + // by dividing all elements by the element with the smallest value. + float[,] intKernel = new float[size, size]; + int divider = 0; + + for (int i = 0; i < size; i++) + { + for (int j = 0; j < size; j++) + { + float v = kernel[i, j] / min; + + if (v > ushort.MaxValue) + { + v = ushort.MaxValue; + } + + intKernel[i, j] = (int)v; + + // Collect the divider + divider += (int)intKernel[i, j]; + } + } + + // Update filter + //this.Divider = divider; + return intKernel; + } + + /// + /// Create a 2 dimensional Gaussian kernel using the Gaussian G(x y) function + /// + /// Kernel Size + /// A Gaussian Kernel with the given size and deviation. + public float[,] CreateGaussianKernel2D(int kernelSize) + { + float[,] kernel = new float[kernelSize, kernelSize]; + + int midpoint = kernelSize / 2; + + for (int i = 0; i < kernelSize; i++) + { + int x = i - midpoint; + + for (int j = 0; j < kernelSize; j++) + { + int y = j - midpoint; + float gxy = this.Gaussian2D(x, y); + kernel[i, j] = gxy; + } + } + + return kernel; + } + + /// + /// Implementation of 2D Gaussian G(x) function + /// + /// The x provided to G(x y) + /// The y provided to G(x y) + /// The Gaussian G(x y) + private float Gaussian2D(float x, float y) + { + const float Numerator = 1.0f; + float denominator = (float)((2 * Math.PI) * Math.Pow(this.standardDeviation, 2)); + + float exponentNumerator = (-x * x) + (-y * y); + float exponentDenominator = (float)(2 * Math.Pow(this.standardDeviation, 2)); + + float left = Numerator / denominator; + float right = (float)Math.Exp(exponentNumerator / exponentDenominator); + + return left * right; + } + } +} diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj index a21765142..c56f3b26e 100644 --- a/src/ImageProcessor/ImageProcessor.csproj +++ b/src/ImageProcessor/ImageProcessor.csproj @@ -49,6 +49,7 @@ + @@ -64,6 +65,7 @@ +