ConvolutionKernel Class

An immutable convolution matrix for ImageProcessingExtensions.Convolve.

public sealed class ConvolutionKernel

Remarks

The matrix is applied as written, without being flipped: the weight at column x and row y multiplies the pixel x - Width / 2 columns to the right of and y - Height / 2 rows below the pixel being computed, so the top-left weight applies to the top-left neighbor. Both dimensions are odd, which makes the middle weight the one of the pixel itself.

The weights are used as given: they are not normalized. A matrix whose weights add up to 1 keeps the overall brightness; divide the weights by their sum to obtain one.

A separable matrix, whose every weight is the product of a weight of a column and a weight of a row (ConvolutionKernel.CreateSeparable, or a matrix the constructor recognizes as one, see ConvolutionKernel.IsSeparable), is applied in two passes: every row is filtered by the row weights, then the filtered rows are combined by the column weights, in double precision without rounding in between. The time then grows with the sum of the dimensions of the matrix instead of their product.

Constructors

NameDescription
ConvolutionKernel(int, int, ReadOnlySpan<double>)Initializes a new instance of the ConvolutionKernel class.

ConvolutionKernel(int, int, ReadOnlySpan<double>)

ConvolutionKernel.cs

Initializes a new instance of the ConvolutionKernel class.

public ConvolutionKernel(int width, int height, ReadOnlySpan<double> values)

Parameters

width int
The number of columns. Must be positive and odd.
height int
The number of rows. Must be positive and odd.
values ReadOnlySpan<double>
The weights, row by row from the top-left one (width times height finite values). They are copied.

Exceptions

ArgumentOutOfRangeException
width or height is not positive or is even.
ArgumentException
values does not hold exactly width times height values, or a value is not finite.

Properties

NameDescription
EmbossGets the emboss matrix [-2, -1, 0; -1, 1, 1; 0, 1, 2], which lights the image from the bottom right. Its weights add up to 1, so flat areas keep their color.
HeightGets the number of rows.
IsSeparableGets a value indicating whether the matrix is applied in two passes, a row then a column. It is the case of a matrix created by ConvolutionKernel.CreateSeparable, and of a matrix given weight by weight whose every weight is exactly, in double precision, the product of a weight of its largest weight's column, divided by that weight, and a weight of its row (a box, a binomial or a Sobel matrix): finding the factors costs one pass over the weights.
Laplacian3x3Gets the Laplacian of the four nearest neighbors, the sum of the second derivatives [1, -2, 1] of both directions: [0, 1, 0; 1, -4, 1; 0, 1, 0], as cv2.Laplacian with ksize = 1. Its weights add up to zero, and it is negative on the bright side of an edge.
Laplacian5x5Gets the 5x5 Laplacian, the sum of the second derivatives [1, 0, -2, 0, 1] of each direction smoothed by [1, 4, 6, 4, 1] across it (the second derivatives of the 5x5 Sobel operator), as cv2.Laplacian with ksize = 5: [2, 4, 4, 4, 2; 4, 0, -8, 0, 4; 4, -8, -24, -8, 4; 4, 0, -8, 0, 4; 2, 4, 4, 4, 2]. Its weights add up to zero.
LaplacianOfGaussianGets the 5x5 Laplacian of Gaussian, the Laplacian of a slightly blurred image, which responds less to noise: [0, 0, 1, 0, 0; 0, 1, 2, 1, 0; 1, 2, -16, 2, 1; 0, 1, 2, 1, 0; 0, 0, 1, 0, 0]. Its weights add up to zero. It is the classic 5x5 approximation with the sign of the Laplacian (negative in the middle, like ConvolutionKernel.Laplacian3x3); the "Mexican hat" form of that approximation is its negation.
PrewittXGets the horizontal Prewitt operator, the derivative [-1, 0, 1] of the rows averaged across them: [-1, 0, 1; -1, 0, 1; -1, 0, 1].
PrewittYGets the vertical Prewitt operator, ConvolutionKernel.PrewittX transposed: [-1, -1, -1; 0, 0, 0; 1, 1, 1].
ScharrXGets the horizontal Scharr operator, a Sobel operator whose smoothing [3, 10, 3] makes the response closer to the same for every direction of the edge: [-3, 0, 3; -10, 0, 10; -3, 0, 3], as cv2.Scharr with dx = 1 and dy = 0.
ScharrYGets the vertical Scharr operator, ConvolutionKernel.ScharrX transposed: [-3, -10, -3; 0, 0, 0; 3, 10, 3].
Sharpen3x3Gets the sharpen matrix [0, -1, 0; -1, 5, -1; 0, -1, 0]: the pixel minus the Laplacian of its four nearest neighbors. Its weights add up to 1, so flat areas keep their color.
SobelXGets the horizontal Sobel operator, the derivative [-1, 0, 1] of the rows smoothed by [1, 2, 1] across them: [-1, 0, 1; -2, 0, 2; -1, 0, 1]. It responds to vertical edges, positively where the right side is brighter, as cv2.Sobel with dx = 1 and dy = 0.
SobelYGets the vertical Sobel operator, ConvolutionKernel.SobelX transposed: [-1, -2, -1; 0, 0, 0; 1, 2, 1]. It responds to horizontal edges, positively where the bottom side is brighter.
WidthGets the number of columns.

Gets the emboss matrix [-2, -1, 0; -1, 1, 1; 0, 1, 2], which lights the image from the bottom right. Its weights add up to 1, so flat areas keep their color.

public static ConvolutionKernel Emboss { get; }

Property value

ConvolutionKernel

Gets the number of rows.

public int Height { get; }

Property value

int

Gets a value indicating whether the matrix is applied in two passes, a row then a column. It is the case of a matrix created by ConvolutionKernel.CreateSeparable, and of a matrix given weight by weight whose every weight is exactly, in double precision, the product of a weight of its largest weight's column, divided by that weight, and a weight of its row (a box, a binomial or a Sobel matrix): finding the factors costs one pass over the weights.

public bool IsSeparable { get; }

Property value

bool

Gets the Laplacian of the four nearest neighbors, the sum of the second derivatives [1, -2, 1] of both directions: [0, 1, 0; 1, -4, 1; 0, 1, 0], as cv2.Laplacian with ksize = 1. Its weights add up to zero, and it is negative on the bright side of an edge.

public static ConvolutionKernel Laplacian3x3 { get; }

Property value

ConvolutionKernel

Gets the 5x5 Laplacian, the sum of the second derivatives [1, 0, -2, 0, 1] of each direction smoothed by [1, 4, 6, 4, 1] across it (the second derivatives of the 5x5 Sobel operator), as cv2.Laplacian with ksize = 5: [2, 4, 4, 4, 2; 4, 0, -8, 0, 4; 4, -8, -24, -8, 4; 4, 0, -8, 0, 4; 2, 4, 4, 4, 2]. Its weights add up to zero.

public static ConvolutionKernel Laplacian5x5 { get; }

Property value

ConvolutionKernel

LaplacianOfGaussian

ConvolutionKernel.cs

Gets the 5x5 Laplacian of Gaussian, the Laplacian of a slightly blurred image, which responds less to noise: [0, 0, 1, 0, 0; 0, 1, 2, 1, 0; 1, 2, -16, 2, 1; 0, 1, 2, 1, 0; 0, 0, 1, 0, 0]. Its weights add up to zero. It is the classic 5x5 approximation with the sign of the Laplacian (negative in the middle, like ConvolutionKernel.Laplacian3x3); the "Mexican hat" form of that approximation is its negation.

public static ConvolutionKernel LaplacianOfGaussian { get; }

Property value

ConvolutionKernel

Gets the horizontal Prewitt operator, the derivative [-1, 0, 1] of the rows averaged across them: [-1, 0, 1; -1, 0, 1; -1, 0, 1].

public static ConvolutionKernel PrewittX { get; }

Property value

ConvolutionKernel

Gets the vertical Prewitt operator, ConvolutionKernel.PrewittX transposed: [-1, -1, -1; 0, 0, 0; 1, 1, 1].

public static ConvolutionKernel PrewittY { get; }

Property value

ConvolutionKernel

Gets the horizontal Scharr operator, a Sobel operator whose smoothing [3, 10, 3] makes the response closer to the same for every direction of the edge: [-3, 0, 3; -10, 0, 10; -3, 0, 3], as cv2.Scharr with dx = 1 and dy = 0.

public static ConvolutionKernel ScharrX { get; }

Property value

ConvolutionKernel

Gets the vertical Scharr operator, ConvolutionKernel.ScharrX transposed: [-3, -10, -3; 0, 0, 0; 3, 10, 3].

public static ConvolutionKernel ScharrY { get; }

Property value

ConvolutionKernel

Gets the sharpen matrix [0, -1, 0; -1, 5, -1; 0, -1, 0]: the pixel minus the Laplacian of its four nearest neighbors. Its weights add up to 1, so flat areas keep their color.

public static ConvolutionKernel Sharpen3x3 { get; }

Property value

ConvolutionKernel

Gets the horizontal Sobel operator, the derivative [-1, 0, 1] of the rows smoothed by [1, 2, 1] across them: [-1, 0, 1; -2, 0, 2; -1, 0, 1]. It responds to vertical edges, positively where the right side is brighter, as cv2.Sobel with dx = 1 and dy = 0.

public static ConvolutionKernel SobelX { get; }

Property value

ConvolutionKernel

Gets the vertical Sobel operator, ConvolutionKernel.SobelX transposed: [-1, -2, -1; 0, 0, 0; 1, 2, 1]. It responds to horizontal edges, positively where the bottom side is brighter.

public static ConvolutionKernel SobelY { get; }

Property value

ConvolutionKernel

Gets the number of columns.

public int Width { get; }

Property value

int

Indexers

NameDescription
this[int, int]Gets a weight.

this[int, int]

ConvolutionKernel.cs

Gets a weight.

public double this[int x, int y] { get; }

Parameters

x int
The column, from 0 (left) to ConvolutionKernel.Width - 1.
y int
The row, from 0 (top) to ConvolutionKernel.Height - 1.

Property value

double

Exceptions

ArgumentOutOfRangeException
x or y is out of range.

Methods

NameDescription
CreateMotionBlur(double, double)Creates the matrix of a motion blur: a straight segment of length pixels through the center, at degrees from the horizontal, as the trail of a camera or a subject that moved while the shutter was open. Apply it with ImageProcessingExtensions.Convolve.
CreateSeparable(ReadOnlySpan<double>, ReadOnlySpan<double>)Creates a separable matrix: the weight at column x and row y is columnWeights[y] * rowWeights[x]. It is applied in two passes (every row filtered by rowWeights, then the filtered rows combined by columnWeights), so the time grows with the sum of the two lengths instead of their product.

CreateMotionBlur(double, double)

ConvolutionKernel.cs

Creates the matrix of a motion blur: a straight segment of length pixels through the center, at degrees from the horizontal, as the trail of a camera or a subject that moved while the shutter was open. Apply it with ImageProcessingExtensions.Convolve.

public static ConvolutionKernel CreateMotionBlur(double length, double degrees)

Parameters

length double
The length of the segment, in pixels: at least 1 and at most 2000. A length of 1 keeps the image as it is.
degrees double
The angle of the segment, in degrees.

Returns

ConvolutionKernel The matrix.

Exceptions

ArgumentOutOfRangeException
length is not between 1 and 2000.
ArgumentException
degrees is not a finite number.

Remarks

The weight of a pixel is the length of the part of the segment inside its square, divided by the length of the segment, so the weights add up to 1 and the brightness is kept: a horizontal segment of 5 pixels is the row [1, 1, 1, 1, 1] / 5, and a segment of 3 pixels at 45 degrees gives sqrt(2) / 3 to the center and (3 - sqrt(2)) / 6 to each of the two diagonal neighbors. The segment is centered, so the blur does not move the image. The matrix is as small as the segment allows: its width and height are odd.

As for ImageProcessingExtensions.Rotate, a positive angle turns clockwise on the screen (the vertical axis points down); a segment and its opposite are the same, so 0 and 180 give the same matrix.

CreateSeparable(ReadOnlySpan<double>, ReadOnlySpan<double>)

ConvolutionKernel.cs

Creates a separable matrix: the weight at column x and row y is columnWeights[y] * rowWeights[x]. It is applied in two passes (every row filtered by rowWeights, then the filtered rows combined by columnWeights), so the time grows with the sum of the two lengths instead of their product.

public static ConvolutionKernel CreateSeparable(ReadOnlySpan<double> rowWeights, ReadOnlySpan<double> columnWeights)

Parameters

rowWeights ReadOnlySpan<double>
The weights of a row, from left to right: an odd number of finite values. They are copied.
columnWeights ReadOnlySpan<double>
The weights of a column, from top to bottom: an odd number of finite values. They are copied.

Returns

ConvolutionKernel The matrix.

Exceptions

ArgumentException
A span is empty or holds an even number of values, or a value is not finite.