mirror of https://github.com/SixLabors/ImageSharp
22 changed files with 497 additions and 220 deletions
@ -1,61 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
namespace SixLabors.ImageSharp.Processing |
|||
{ |
|||
/// <summary>
|
|||
/// Enumerates the various types of defined edge detection filters.
|
|||
/// </summary>
|
|||
public enum EdgeDetectionOperators |
|||
{ |
|||
/// <summary>
|
|||
/// The Kayyali operator filter.
|
|||
/// </summary>
|
|||
Kayyali, |
|||
|
|||
/// <summary>
|
|||
/// The Kirsch operator filter.
|
|||
/// </summary>
|
|||
Kirsch, |
|||
|
|||
/// <summary>
|
|||
/// The Laplacian3X3 operator filter.
|
|||
/// </summary>
|
|||
Laplacian3x3, |
|||
|
|||
/// <summary>
|
|||
/// The Laplacian5X5 operator filter.
|
|||
/// </summary>
|
|||
Laplacian5x5, |
|||
|
|||
/// <summary>
|
|||
/// The LaplacianOfGaussian operator filter.
|
|||
/// </summary>
|
|||
LaplacianOfGaussian, |
|||
|
|||
/// <summary>
|
|||
/// The Prewitt operator filter.
|
|||
/// </summary>
|
|||
Prewitt, |
|||
|
|||
/// <summary>
|
|||
/// The RobertsCross operator filter.
|
|||
/// </summary>
|
|||
RobertsCross, |
|||
|
|||
/// <summary>
|
|||
/// The Robinson operator filter.
|
|||
/// </summary>
|
|||
Robinson, |
|||
|
|||
/// <summary>
|
|||
/// The Scharr operator filter.
|
|||
/// </summary>
|
|||
Scharr, |
|||
|
|||
/// <summary>
|
|||
/// The Sobel operator filter.
|
|||
/// </summary>
|
|||
Sobel |
|||
} |
|||
} |
|||
@ -0,0 +1,63 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using SixLabors.ImageSharp.Processing.Processors.Convolution; |
|||
|
|||
namespace SixLabors.ImageSharp.Processing |
|||
{ |
|||
/// <summary>
|
|||
/// Contains reusable static instances of known edge detection kernels.
|
|||
/// </summary>
|
|||
public static class KnownEdgeDetectionOperators |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the Kayyali edge detector kernel.
|
|||
/// </summary>
|
|||
public static EdgeDetector2DKernel Kayyali { get; } = EdgeDetector2DKernel.KayyaliKernel; |
|||
|
|||
/// <summary>
|
|||
/// Gets the Kirsch edge detector kernel.
|
|||
/// </summary>
|
|||
public static EdgeDetectorCompassKernel Kirsch { get; } = EdgeDetectorCompassKernel.Kirsch; |
|||
|
|||
/// <summary>
|
|||
/// Gets the Laplacian 3x3 edge detector kernel.
|
|||
/// </summary>
|
|||
public static EdgeDetectorKernel Laplacian3x3 { get; } = EdgeDetectorKernel.Laplacian3x3; |
|||
|
|||
/// <summary>
|
|||
/// Gets the Laplacian 5x5 edge detector kernel.
|
|||
/// </summary>
|
|||
public static EdgeDetectorKernel Laplacian5x5 { get; } = EdgeDetectorKernel.Laplacian5x5; |
|||
|
|||
/// <summary>
|
|||
/// Gets the Laplacian of Gaussian edge detector kernel.
|
|||
/// </summary>
|
|||
public static EdgeDetectorKernel LaplacianOfGaussian { get; } = EdgeDetectorKernel.LaplacianOfGaussian; |
|||
|
|||
/// <summary>
|
|||
/// Gets the Prewitt edge detector kernel.
|
|||
/// </summary>
|
|||
public static EdgeDetector2DKernel Prewitt { get; } = EdgeDetector2DKernel.PrewittKernel; |
|||
|
|||
/// <summary>
|
|||
/// Gets the Roberts-Cross edge detector kernel.
|
|||
/// </summary>
|
|||
public static EdgeDetector2DKernel RobertsCross { get; } = EdgeDetector2DKernel.RobertsCrossKernel; |
|||
|
|||
/// <summary>
|
|||
/// Gets the Robinson edge detector kernel.
|
|||
/// </summary>
|
|||
public static EdgeDetectorCompassKernel Robinson { get; } = EdgeDetectorCompassKernel.Robinson; |
|||
|
|||
/// <summary>
|
|||
/// Gets the Scharr edge detector kernel.
|
|||
/// </summary>
|
|||
public static EdgeDetector2DKernel Scharr { get; } = EdgeDetector2DKernel.ScharrKernel; |
|||
|
|||
/// <summary>
|
|||
/// Gets the Sobel edge detector kernel.
|
|||
/// </summary>
|
|||
public static EdgeDetector2DKernel Sobel { get; } = EdgeDetector2DKernel.SobelKernel; |
|||
} |
|||
} |
|||
@ -1,55 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
namespace SixLabors.ImageSharp.Processing.Processors.Convolution |
|||
{ |
|||
internal abstract class CompassKernels |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the North gradient operator.
|
|||
/// </summary>
|
|||
public abstract DenseMatrix<float> North { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the NorthWest gradient operator.
|
|||
/// </summary>
|
|||
public abstract DenseMatrix<float> NorthWest { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the West gradient operator.
|
|||
/// </summary>
|
|||
public abstract DenseMatrix<float> West { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the SouthWest gradient operator.
|
|||
/// </summary>
|
|||
public abstract DenseMatrix<float> SouthWest { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the South gradient operator.
|
|||
/// </summary>
|
|||
public abstract DenseMatrix<float> South { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the SouthEast gradient operator.
|
|||
/// </summary>
|
|||
public abstract DenseMatrix<float> SouthEast { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the East gradient operator.
|
|||
/// </summary>
|
|||
public abstract DenseMatrix<float> East { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the NorthEast gradient operator.
|
|||
/// </summary>
|
|||
public abstract DenseMatrix<float> NorthEast { get; } |
|||
|
|||
public DenseMatrix<float>[] Flatten() => |
|||
new[] |
|||
{ |
|||
this.North, this.NorthWest, this.West, this.SouthWest, |
|||
this.South, this.SouthEast, this.East, this.NorthEast |
|||
}; |
|||
} |
|||
} |
|||
@ -0,0 +1,103 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
|
|||
namespace SixLabors.ImageSharp.Processing.Processors.Convolution |
|||
{ |
|||
/// <summary>
|
|||
/// Represents an edge detection convolution kernel consisting of two 1D gradient operators.
|
|||
/// </summary>
|
|||
public readonly struct EdgeDetector2DKernel : IEquatable<EdgeDetector2DKernel> |
|||
{ |
|||
/// <summary>
|
|||
/// An edge detection kernel containing two Kayyali operators.
|
|||
/// </summary>
|
|||
public static EdgeDetector2DKernel KayyaliKernel = new EdgeDetector2DKernel(KayyaliKernels.KayyaliX, KayyaliKernels.KayyaliY); |
|||
|
|||
/// <summary>
|
|||
/// An edge detection kernel containing two Prewitt operators.
|
|||
/// <see href="https://en.wikipedia.org/wiki/Prewitt_operator"/>.
|
|||
/// </summary>
|
|||
public static EdgeDetector2DKernel PrewittKernel = new EdgeDetector2DKernel(PrewittKernels.PrewittX, PrewittKernels.PrewittY); |
|||
|
|||
/// <summary>
|
|||
/// An edge detection kernel containing two Roberts-Cross operators.
|
|||
/// <see href="https://en.wikipedia.org/wiki/Roberts_cross"/>.
|
|||
/// </summary>
|
|||
public static EdgeDetector2DKernel RobertsCrossKernel = new EdgeDetector2DKernel(RobertsCrossKernels.RobertsCrossX, RobertsCrossKernels.RobertsCrossY); |
|||
|
|||
/// <summary>
|
|||
/// An edge detection kernel containing two Scharr operators.
|
|||
/// </summary>
|
|||
public static EdgeDetector2DKernel ScharrKernel = new EdgeDetector2DKernel(ScharrKernels.ScharrX, ScharrKernels.ScharrY); |
|||
|
|||
/// <summary>
|
|||
/// An edge detection kernel containing two Sobel operators.
|
|||
/// <see href="https://en.wikipedia.org/wiki/Sobel_operator"/>.
|
|||
/// </summary>
|
|||
public static EdgeDetector2DKernel SobelKernel = new EdgeDetector2DKernel(SobelKernels.SobelX, SobelKernels.SobelY); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="EdgeDetector2DKernel"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="kernelX">The horizontal gradient operator.</param>
|
|||
/// <param name="kernelY">The vertical gradient operator.</param>
|
|||
public EdgeDetector2DKernel(DenseMatrix<float> kernelX, DenseMatrix<float> kernelY) |
|||
{ |
|||
Guard.IsTrue( |
|||
kernelX.Size.Equals(kernelY.Size), |
|||
$"{nameof(kernelX)} {nameof(kernelY)}", |
|||
"Kernel sizes must be the same."); |
|||
|
|||
this.KernelX = kernelX; |
|||
this.KernelY = kernelY; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the horizontal gradient operator.
|
|||
/// </summary>
|
|||
public DenseMatrix<float> KernelX { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the vertical gradient operator.
|
|||
/// </summary>
|
|||
public DenseMatrix<float> KernelY { get; } |
|||
|
|||
/// <summary>
|
|||
/// Checks whether two <see cref="EdgeDetector2DKernel"/> structures are equal.
|
|||
/// </summary>
|
|||
/// <param name="left">The left hand <see cref="EdgeDetector2DKernel"/> operand.</param>
|
|||
/// <param name="right">The right hand <see cref="EdgeDetector2DKernel"/> operand.</param>
|
|||
/// <returns>
|
|||
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter;
|
|||
/// otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator ==(EdgeDetector2DKernel left, EdgeDetector2DKernel right) |
|||
=> left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Checks whether two <see cref="EdgeDetector2DKernel"/> structures are equal.
|
|||
/// </summary>
|
|||
/// <param name="left">The left hand <see cref="EdgeDetector2DKernel"/> operand.</param>
|
|||
/// <param name="right">The right hand <see cref="EdgeDetector2DKernel"/> operand.</param>
|
|||
/// <returns>
|
|||
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter;
|
|||
/// otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator !=(EdgeDetector2DKernel left, EdgeDetector2DKernel right) |
|||
=> !(left == right); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) |
|||
=> obj is EdgeDetector2DKernel kernel && this.Equals(kernel); |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(EdgeDetector2DKernel other) |
|||
=> this.KernelX.Equals(other.KernelX) |
|||
&& this.KernelY.Equals(other.KernelY); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() => HashCode.Combine(this.KernelX, this.KernelY); |
|||
} |
|||
} |
|||
@ -0,0 +1,161 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
|
|||
namespace SixLabors.ImageSharp.Processing.Processors.Convolution |
|||
{ |
|||
/// <summary>
|
|||
/// Represents an edge detection convolution kernel consisting of eight gradient operators.
|
|||
/// </summary>
|
|||
public readonly struct EdgeDetectorCompassKernel : IEquatable<EdgeDetectorCompassKernel> |
|||
{ |
|||
/// <summary>
|
|||
/// An edge detection kenel comprised of Kirsch gradient operators.
|
|||
/// </summary>
|
|||
public static EdgeDetectorCompassKernel Kirsch = |
|||
new EdgeDetectorCompassKernel( |
|||
KirschKernels.North, |
|||
KirschKernels.NorthWest, |
|||
KirschKernels.West, |
|||
KirschKernels.SouthWest, |
|||
KirschKernels.South, |
|||
KirschKernels.SouthEast, |
|||
KirschKernels.East, |
|||
KirschKernels.NorthEast); |
|||
|
|||
/// <summary>
|
|||
/// An edge detection kenel comprised of Robinson gradient operators.
|
|||
/// </summary>
|
|||
public static EdgeDetectorCompassKernel Robinson = |
|||
new EdgeDetectorCompassKernel( |
|||
RobinsonKernels.North, |
|||
RobinsonKernels.NorthWest, |
|||
RobinsonKernels.West, |
|||
RobinsonKernels.SouthWest, |
|||
RobinsonKernels.South, |
|||
RobinsonKernels.SouthEast, |
|||
RobinsonKernels.East, |
|||
RobinsonKernels.NorthEast); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="EdgeDetectorCompassKernel"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="north">The north gradient operator.</param>
|
|||
/// <param name="northWest">The north-west gradient operator.</param>
|
|||
/// <param name="west">The west gradient operator.</param>
|
|||
/// <param name="southWest">The south-west gradient operator.</param>
|
|||
/// <param name="south">The south gradient operator.</param>
|
|||
/// <param name="southEast">The south-east gradient operator.</param>
|
|||
/// <param name="east">The east gradient operator.</param>
|
|||
/// <param name="northEast">The north-east gradient operator.</param>
|
|||
public EdgeDetectorCompassKernel( |
|||
DenseMatrix<float> north, |
|||
DenseMatrix<float> northWest, |
|||
DenseMatrix<float> west, |
|||
DenseMatrix<float> southWest, |
|||
DenseMatrix<float> south, |
|||
DenseMatrix<float> southEast, |
|||
DenseMatrix<float> east, |
|||
DenseMatrix<float> northEast) |
|||
{ |
|||
this.North = north; |
|||
this.NorthWest = northWest; |
|||
this.West = west; |
|||
this.SouthWest = southWest; |
|||
this.South = south; |
|||
this.SouthEast = southEast; |
|||
this.East = east; |
|||
this.NorthEast = northEast; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the North gradient operator.
|
|||
/// </summary>
|
|||
public DenseMatrix<float> North { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the NorthWest gradient operator.
|
|||
/// </summary>
|
|||
public DenseMatrix<float> NorthWest { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the West gradient operator.
|
|||
/// </summary>
|
|||
public DenseMatrix<float> West { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the SouthWest gradient operator.
|
|||
/// </summary>
|
|||
public DenseMatrix<float> SouthWest { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the South gradient operator.
|
|||
/// </summary>
|
|||
public DenseMatrix<float> South { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the SouthEast gradient operator.
|
|||
/// </summary>
|
|||
public DenseMatrix<float> SouthEast { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the East gradient operator.
|
|||
/// </summary>
|
|||
public DenseMatrix<float> East { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the NorthEast gradient operator.
|
|||
/// </summary>
|
|||
public DenseMatrix<float> NorthEast { get; } |
|||
|
|||
/// <summary>
|
|||
/// Checks whether two <see cref="EdgeDetectorCompassKernel"/> structures are equal.
|
|||
/// </summary>
|
|||
/// <param name="left">The left hand <see cref="EdgeDetectorCompassKernel"/> operand.</param>
|
|||
/// <param name="right">The right hand <see cref="EdgeDetectorCompassKernel"/> operand.</param>
|
|||
/// <returns>
|
|||
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter;
|
|||
/// otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator ==(EdgeDetectorCompassKernel left, EdgeDetectorCompassKernel right) |
|||
=> left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Checks whether two <see cref="EdgeDetectorCompassKernel"/> structures are equal.
|
|||
/// </summary>
|
|||
/// <param name="left">The left hand <see cref="EdgeDetectorCompassKernel"/> operand.</param>
|
|||
/// <param name="right">The right hand <see cref="EdgeDetectorCompassKernel"/> operand.</param>
|
|||
/// <returns>
|
|||
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter;
|
|||
/// otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator !=(EdgeDetectorCompassKernel left, EdgeDetectorCompassKernel right) |
|||
=> !(left == right); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) => obj is EdgeDetectorCompassKernel kernel && this.Equals(kernel); |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(EdgeDetectorCompassKernel other) => this.North.Equals(other.North) && this.NorthWest.Equals(other.NorthWest) && this.West.Equals(other.West) && this.SouthWest.Equals(other.SouthWest) && this.South.Equals(other.South) && this.SouthEast.Equals(other.SouthEast) && this.East.Equals(other.East) && this.NorthEast.Equals(other.NorthEast); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
=> HashCode.Combine( |
|||
this.North, |
|||
this.NorthWest, |
|||
this.West, |
|||
this.SouthWest, |
|||
this.South, |
|||
this.SouthEast, |
|||
this.East, |
|||
this.NorthEast); |
|||
|
|||
internal DenseMatrix<float>[] Flatten() => |
|||
new[] |
|||
{ |
|||
this.North, this.NorthWest, this.West, this.SouthWest, |
|||
this.South, this.SouthEast, this.East, this.NorthEast |
|||
}; |
|||
} |
|||
} |
|||
@ -0,0 +1,75 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
|
|||
namespace SixLabors.ImageSharp.Processing.Processors.Convolution |
|||
{ |
|||
/// <summary>
|
|||
/// Represents an edge detection convolution kernel consisting of a single 2D gradient operator.
|
|||
/// </summary>
|
|||
public readonly struct EdgeDetectorKernel : IEquatable<EdgeDetectorKernel> |
|||
{ |
|||
/// <summary>
|
|||
/// An edge detection kernel containing a 3x3 Laplacian operator.
|
|||
/// </summary>
|
|||
public static EdgeDetectorKernel Laplacian3x3 = new EdgeDetectorKernel(LaplacianKernels.Laplacian3x3); |
|||
|
|||
/// <summary>
|
|||
/// An edge detection kernel containing a 5x5 Laplacian operator.
|
|||
/// </summary>
|
|||
public static EdgeDetectorKernel Laplacian5x5 = new EdgeDetectorKernel(LaplacianKernels.Laplacian5x5); |
|||
|
|||
/// <summary>
|
|||
/// An edge detection kernel containing a Laplacian of Gaussian operator.
|
|||
/// </summary>
|
|||
public static EdgeDetectorKernel LaplacianOfGaussian = new EdgeDetectorKernel(LaplacianKernels.LaplacianOfGaussianXY); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="EdgeDetectorKernel"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="kernelXY">The 2D gradient operator.</param>
|
|||
public EdgeDetectorKernel(DenseMatrix<float> kernelXY) |
|||
=> this.KernelXY = kernelXY; |
|||
|
|||
/// <summary>
|
|||
/// Gets the 2D gradient operator.
|
|||
/// </summary>
|
|||
public DenseMatrix<float> KernelXY { get; } |
|||
|
|||
/// <summary>
|
|||
/// Checks whether two <see cref="EdgeDetectorKernel"/> structures are equal.
|
|||
/// </summary>
|
|||
/// <param name="left">The left hand <see cref="EdgeDetectorKernel"/> operand.</param>
|
|||
/// <param name="right">The right hand <see cref="EdgeDetectorKernel"/> operand.</param>
|
|||
/// <returns>
|
|||
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter;
|
|||
/// otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator ==(EdgeDetectorKernel left, EdgeDetectorKernel right) |
|||
=> left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Checks whether two <see cref="EdgeDetectorKernel"/> structures are equal.
|
|||
/// </summary>
|
|||
/// <param name="left">The left hand <see cref="EdgeDetectorKernel"/> operand.</param>
|
|||
/// <param name="right">The right hand <see cref="EdgeDetectorKernel"/> operand.</param>
|
|||
/// <returns>
|
|||
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter;
|
|||
/// otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator !=(EdgeDetectorKernel left, EdgeDetectorKernel right) |
|||
=> !(left == right); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) |
|||
=> obj is EdgeDetectorKernel kernel && this.Equals(kernel); |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(EdgeDetectorKernel other) |
|||
=> this.KernelXY.Equals(other.KernelXY); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() => this.KernelXY.GetHashCode(); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue