diff --git a/src/ImageSharp/Processing/EdgeDetectionOperators.cs b/src/ImageSharp/Processing/EdgeDetectionOperators.cs
deleted file mode 100644
index 3e986f802..000000000
--- a/src/ImageSharp/Processing/EdgeDetectionOperators.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-namespace SixLabors.ImageSharp.Processing
-{
- ///
- /// Enumerates the various types of defined edge detection filters.
- ///
- public enum EdgeDetectionOperators
- {
- ///
- /// The Kayyali operator filter.
- ///
- Kayyali,
-
- ///
- /// The Kirsch operator filter.
- ///
- Kirsch,
-
- ///
- /// The Laplacian3X3 operator filter.
- ///
- Laplacian3x3,
-
- ///
- /// The Laplacian5X5 operator filter.
- ///
- Laplacian5x5,
-
- ///
- /// The LaplacianOfGaussian operator filter.
- ///
- LaplacianOfGaussian,
-
- ///
- /// The Prewitt operator filter.
- ///
- Prewitt,
-
- ///
- /// The RobertsCross operator filter.
- ///
- RobertsCross,
-
- ///
- /// The Robinson operator filter.
- ///
- Robinson,
-
- ///
- /// The Scharr operator filter.
- ///
- Scharr,
-
- ///
- /// The Sobel operator filter.
- ///
- Sobel
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Processing/Extensions/Convolution/DetectEdgesExtensions.cs b/src/ImageSharp/Processing/Extensions/Convolution/DetectEdgesExtensions.cs
index 61b900848..2377151bb 100644
--- a/src/ImageSharp/Processing/Extensions/Convolution/DetectEdgesExtensions.cs
+++ b/src/ImageSharp/Processing/Extensions/Convolution/DetectEdgesExtensions.cs
@@ -1,7 +1,6 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
-using SixLabors.ImageSharp.Processing.Processors;
using SixLabors.ImageSharp.Processing.Processors.Convolution;
namespace SixLabors.ImageSharp.Processing
@@ -12,144 +11,230 @@ namespace SixLabors.ImageSharp.Processing
public static class DetectEdgesExtensions
{
///
- /// Detects any edges within the image. Uses the filter
- /// operating in grayscale mode.
+ /// Detects any edges within the image.
+ /// Uses the kernel operating in grayscale mode.
///
/// The image this method extends.
/// The to allow chaining of operations.
public static IImageProcessingContext DetectEdges(this IImageProcessingContext source) =>
- DetectEdges(source, new SobelProcessor(true));
+ DetectEdges(source, KnownEdgeDetectorKernels.Sobel);
///
- /// Detects any edges within the image. Uses the filter
- /// operating in grayscale mode.
+ /// Detects any edges within the image.
+ /// Uses the kernel operating in grayscale mode.
///
/// The image this method extends.
///
/// The structure that specifies the portion of the image object to alter.
///
/// The to allow chaining of operations.
- public static IImageProcessingContext DetectEdges(this IImageProcessingContext source, Rectangle rectangle) =>
- DetectEdges(source, rectangle, new SobelProcessor(true));
+ public static IImageProcessingContext DetectEdges(
+ this IImageProcessingContext source,
+ Rectangle rectangle) =>
+ DetectEdges(source, KnownEdgeDetectorKernels.Sobel, rectangle);
///
- /// Detects any edges within the image.
+ /// Detects any edges within the image operating in grayscale mode.
///
/// The image this method extends.
- /// The filter for detecting edges.
+ /// The 2D edge detector kernel.
/// The to allow chaining of operations.
public static IImageProcessingContext DetectEdges(
this IImageProcessingContext source,
- EdgeDetectionOperators filter) =>
- DetectEdges(source, GetProcessor(filter, true));
+ EdgeDetector2DKernel kernel) =>
+ DetectEdges(source, kernel, true);
///
- /// Detects any edges within the image.
+ /// Detects any edges within the image using a .
///
/// The image this method extends.
- /// The filter for detecting edges.
- /// Whether to convert the image to grayscale first. Defaults to true.
+ /// The 2D edge detector kernel.
+ ///
+ /// Whether to convert the image to grayscale before performing edge detection.
+ ///
/// The to allow chaining of operations.
public static IImageProcessingContext DetectEdges(
this IImageProcessingContext source,
- EdgeDetectionOperators filter,
- bool grayscale) =>
- DetectEdges(source, GetProcessor(filter, grayscale));
+ EdgeDetector2DKernel kernel,
+ bool grayscale)
+ {
+ var processor = new EdgeDetector2DProcessor(kernel, grayscale);
+ source.ApplyProcessor(processor);
+ return source;
+ }
///
- /// Detects any edges within the image.
+ /// Detects any edges within the image operating in grayscale mode.
///
/// The image this method extends.
- /// The filter for detecting edges.
+ /// The 2D edge detector kernel.
///
/// The structure that specifies the portion of the image object to alter.
///
- /// Whether to convert the image to grayscale first. Defaults to true.
/// The to allow chaining of operations.
public static IImageProcessingContext DetectEdges(
this IImageProcessingContext source,
- EdgeDetectionOperators filter,
- Rectangle rectangle,
- bool grayscale = true) =>
- DetectEdges(source, rectangle, GetProcessor(filter, grayscale));
+ EdgeDetector2DKernel kernel,
+ Rectangle rectangle) =>
+ DetectEdges(source, kernel, true, rectangle);
///
- /// Detects any edges within the image.
+ /// Detects any edges within the image using a .
///
/// The image this method extends.
- /// The filter for detecting edges.
+ /// The 2D edge detector kernel.
+ ///
+ /// Whether to convert the image to grayscale before performing edge detection.
+ ///
+ ///
+ /// The structure that specifies the portion of the image object to alter.
+ ///
/// The to allow chaining of operations.
- private static IImageProcessingContext DetectEdges(this IImageProcessingContext source, IImageProcessor filter)
+ public static IImageProcessingContext DetectEdges(
+ this IImageProcessingContext source,
+ EdgeDetector2DKernel kernel,
+ bool grayscale,
+ Rectangle rectangle)
{
- return source.ApplyProcessor(filter);
+ var processor = new EdgeDetector2DProcessor(kernel, grayscale);
+ source.ApplyProcessor(processor, rectangle);
+ return source;
}
///
- /// Detects any edges within the image.
+ /// Detects any edges within the image operating in grayscale mode.
///
/// The image this method extends.
- ///
- /// The structure that specifies the portion of the image object to alter.
+ /// The edge detector kernel.
+ /// The to allow chaining of operations.
+ public static IImageProcessingContext DetectEdges(
+ this IImageProcessingContext source,
+ EdgeDetectorKernel kernel) =>
+ DetectEdges(source, kernel, true);
+
+ ///
+ /// Detects any edges within the image using a .
+ ///
+ /// The image this method extends.
+ /// The edge detector kernel.
+ ///
+ /// Whether to convert the image to grayscale before performing edge detection.
///
- /// The filter for detecting edges.
/// The to allow chaining of operations.
- private static IImageProcessingContext DetectEdges(
+ public static IImageProcessingContext DetectEdges(
this IImageProcessingContext source,
- Rectangle rectangle,
- IImageProcessor filter)
+ EdgeDetectorKernel kernel,
+ bool grayscale)
{
- source.ApplyProcessor(filter, rectangle);
+ var processor = new EdgeDetectorProcessor(kernel, grayscale);
+ source.ApplyProcessor(processor);
return source;
}
- private static IImageProcessor GetProcessor(EdgeDetectionOperators filter, bool grayscale)
- {
- IImageProcessor processor;
-
- switch (filter)
- {
- case EdgeDetectionOperators.Kayyali:
- processor = new KayyaliProcessor(grayscale);
- break;
-
- case EdgeDetectionOperators.Kirsch:
- processor = new KirschProcessor(grayscale);
- break;
-
- case EdgeDetectionOperators.Laplacian3x3:
- processor = new Laplacian3x3Processor(grayscale);
- break;
-
- case EdgeDetectionOperators.Laplacian5x5:
- processor = new Laplacian5x5Processor(grayscale);
- break;
-
- case EdgeDetectionOperators.LaplacianOfGaussian:
- processor = new LaplacianOfGaussianProcessor(grayscale);
- break;
-
- case EdgeDetectionOperators.Prewitt:
- processor = new PrewittProcessor(grayscale);
- break;
+ ///
+ /// Detects any edges within the image operating in grayscale mode.
+ ///
+ /// The image this method extends.
+ /// The edge detector kernel.
+ ///
+ /// The structure that specifies the portion of the image object to alter.
+ ///
+ /// The to allow chaining of operations.
+ public static IImageProcessingContext DetectEdges(
+ this IImageProcessingContext source,
+ EdgeDetectorKernel kernel,
+ Rectangle rectangle) =>
+ DetectEdges(source, kernel, true, rectangle);
- case EdgeDetectionOperators.RobertsCross:
- processor = new RobertsCrossProcessor(grayscale);
- break;
+ ///
+ /// Detects any edges within the image using a .
+ ///
+ /// The image this method extends.
+ /// The edge detector kernel.
+ ///
+ /// Whether to convert the image to grayscale before performing edge detection.
+ ///
+ ///
+ /// The structure that specifies the portion of the image object to alter.
+ ///
+ /// The to allow chaining of operations.
+ public static IImageProcessingContext DetectEdges(
+ this IImageProcessingContext source,
+ EdgeDetectorKernel kernel,
+ bool grayscale,
+ Rectangle rectangle)
+ {
+ var processor = new EdgeDetectorProcessor(kernel, grayscale);
+ source.ApplyProcessor(processor, rectangle);
+ return source;
+ }
- case EdgeDetectionOperators.Robinson:
- processor = new RobinsonProcessor(grayscale);
- break;
+ ///
+ /// Detects any edges within the image operating in grayscale mode.
+ ///
+ /// The image this method extends.
+ /// Thecompass edge detector kernel.
+ /// The to allow chaining of operations.
+ public static IImageProcessingContext DetectEdges(
+ this IImageProcessingContext source,
+ EdgeDetectorCompassKernel kernel) =>
+ DetectEdges(source, kernel, true);
- case EdgeDetectionOperators.Scharr:
- processor = new ScharrProcessor(grayscale);
- break;
+ ///
+ /// Detects any edges within the image using a .
+ ///
+ /// The image this method extends.
+ /// Thecompass edge detector kernel.
+ ///
+ /// Whether to convert the image to grayscale before performing edge detection.
+ ///
+ /// The to allow chaining of operations.
+ public static IImageProcessingContext DetectEdges(
+ this IImageProcessingContext source,
+ EdgeDetectorCompassKernel kernel,
+ bool grayscale)
+ {
+ var processor = new EdgeDetectorCompassProcessor(kernel, grayscale);
+ source.ApplyProcessor(processor);
+ return source;
+ }
- default:
- processor = new SobelProcessor(grayscale);
- break;
- }
+ ///
+ /// Detects any edges within the image operating in grayscale mode.
+ ///
+ /// The image this method extends.
+ /// Thecompass edge detector kernel.
+ ///
+ /// The structure that specifies the portion of the image object to alter.
+ ///
+ /// The to allow chaining of operations.
+ public static IImageProcessingContext DetectEdges(
+ this IImageProcessingContext source,
+ EdgeDetectorCompassKernel kernel,
+ Rectangle rectangle) =>
+ DetectEdges(source, kernel, true, rectangle);
- return processor;
+ ///
+ /// Detects any edges within the image using a .
+ ///
+ /// The image this method extends.
+ /// Thecompass edge detector kernel.
+ ///
+ /// Whether to convert the image to grayscale before performing edge detection.
+ ///
+ ///
+ /// The structure that specifies the portion of the image object to alter.
+ ///
+ /// The to allow chaining of operations.
+ public static IImageProcessingContext DetectEdges(
+ this IImageProcessingContext source,
+ EdgeDetectorCompassKernel kernel,
+ bool grayscale,
+ Rectangle rectangle)
+ {
+ var processor = new EdgeDetectorCompassProcessor(kernel, grayscale);
+ source.ApplyProcessor(processor, rectangle);
+ return source;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/KnownEdgeDetectorKernels.cs b/src/ImageSharp/Processing/KnownEdgeDetectorKernels.cs
new file mode 100644
index 000000000..2e279d340
--- /dev/null
+++ b/src/ImageSharp/Processing/KnownEdgeDetectorKernels.cs
@@ -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
+{
+ ///
+ /// Contains reusable static instances of known edge detection kernels.
+ ///
+ public static class KnownEdgeDetectorKernels
+ {
+ ///
+ /// Gets the Kayyali edge detector kernel.
+ ///
+ public static EdgeDetector2DKernel Kayyali { get; } = EdgeDetector2DKernel.KayyaliKernel;
+
+ ///
+ /// Gets the Kirsch edge detector kernel.
+ ///
+ public static EdgeDetectorCompassKernel Kirsch { get; } = EdgeDetectorCompassKernel.Kirsch;
+
+ ///
+ /// Gets the Laplacian 3x3 edge detector kernel.
+ ///
+ public static EdgeDetectorKernel Laplacian3x3 { get; } = EdgeDetectorKernel.Laplacian3x3;
+
+ ///
+ /// Gets the Laplacian 5x5 edge detector kernel.
+ ///
+ public static EdgeDetectorKernel Laplacian5x5 { get; } = EdgeDetectorKernel.Laplacian5x5;
+
+ ///
+ /// Gets the Laplacian of Gaussian edge detector kernel.
+ ///
+ public static EdgeDetectorKernel LaplacianOfGaussian { get; } = EdgeDetectorKernel.LaplacianOfGaussian;
+
+ ///
+ /// Gets the Prewitt edge detector kernel.
+ ///
+ public static EdgeDetector2DKernel Prewitt { get; } = EdgeDetector2DKernel.PrewittKernel;
+
+ ///
+ /// Gets the Roberts-Cross edge detector kernel.
+ ///
+ public static EdgeDetector2DKernel RobertsCross { get; } = EdgeDetector2DKernel.RobertsCrossKernel;
+
+ ///
+ /// Gets the Robinson edge detector kernel.
+ ///
+ public static EdgeDetectorCompassKernel Robinson { get; } = EdgeDetectorCompassKernel.Robinson;
+
+ ///
+ /// Gets the Scharr edge detector kernel.
+ ///
+ public static EdgeDetector2DKernel Scharr { get; } = EdgeDetector2DKernel.ScharrKernel;
+
+ ///
+ /// Gets the Sobel edge detector kernel.
+ ///
+ public static EdgeDetector2DKernel Sobel { get; } = EdgeDetector2DKernel.SobelKernel;
+ }
+}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs
new file mode 100644
index 000000000..1d0a29a35
--- /dev/null
+++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs
@@ -0,0 +1,42 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+using SixLabors.ImageSharp.PixelFormats;
+
+namespace SixLabors.ImageSharp.Processing.Processors.Convolution
+{
+ ///
+ /// Defines edge detection using the two 1D gradient operators.
+ ///
+ public sealed class EdgeDetector2DProcessor : IImageProcessor
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The 2D edge detector kernel.
+ ///
+ /// Whether to convert the image to grayscale before performing edge detection.
+ ///
+ public EdgeDetector2DProcessor(EdgeDetector2DKernel kernel, bool grayscale)
+ {
+ this.Kernel = kernel;
+ this.Grayscale = grayscale;
+ }
+
+ ///
+ /// Gets the 2D edge detector kernel.
+ ///
+ public EdgeDetector2DKernel Kernel { get; }
+
+ ///
+ /// Gets a value indicating whether to convert the image to grayscale before performing
+ /// edge detection.
+ ///
+ public bool Grayscale { get; }
+
+ ///
+ public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle)
+ where TPixel : unmanaged, IPixel
+ => new EdgeDetector2DProcessor(configuration, this, source, sourceRectangle);
+ }
+}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs
index 6c831e727..80f8a7706 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs
@@ -13,42 +13,29 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
internal class EdgeDetector2DProcessor : ImageProcessor
where TPixel : unmanaged, IPixel
{
+ private readonly DenseMatrix kernelX;
+ private readonly DenseMatrix kernelY;
+ private readonly bool grayscale;
+
///
/// Initializes a new instance of the class.
///
/// The configuration which allows altering default behaviour or extending the library.
- /// The horizontal gradient operator.
- /// The vertical gradient operator.
- /// Whether to convert the image to grayscale before performing edge detection.
+ /// The defining the processor parameters.
/// The source for the current processor instance.
/// The source area to process for the current processor instance.
- internal EdgeDetector2DProcessor(
+ public EdgeDetector2DProcessor(
Configuration configuration,
- in DenseMatrix kernelX,
- in DenseMatrix kernelY,
- bool grayscale,
+ EdgeDetector2DProcessor definition,
Image source,
Rectangle sourceRectangle)
: base(configuration, source, sourceRectangle)
{
- Guard.IsTrue(kernelX.Size.Equals(kernelY.Size), $"{nameof(kernelX)} {nameof(kernelY)}", "Kernel sizes must be the same.");
- this.KernelX = kernelX;
- this.KernelY = kernelY;
- this.Grayscale = grayscale;
+ this.kernelX = definition.Kernel.KernelX;
+ this.kernelY = definition.Kernel.KernelY;
+ this.grayscale = definition.Grayscale;
}
- ///
- /// Gets the horizontal gradient operator.
- ///
- public DenseMatrix KernelX { get; }
-
- ///
- /// Gets the vertical gradient operator.
- ///
- public DenseMatrix KernelY { get; }
-
- public bool Grayscale { get; }
-
///
protected override void BeforeImageApply()
{
@@ -57,7 +44,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
opaque.Execute();
}
- if (this.Grayscale)
+ if (this.grayscale)
{
new GrayscaleBt709Processor(1F).Execute(this.Configuration, this.Source, this.SourceRectangle);
}
@@ -68,7 +55,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
protected override void OnFrameApply(ImageFrame source)
{
- using var processor = new Convolution2DProcessor(this.Configuration, this.KernelX, this.KernelY, true, this.Source, this.SourceRectangle);
+ using var processor = new Convolution2DProcessor(
+ this.Configuration,
+ in this.kernelX,
+ in this.kernelY,
+ true,
+ this.Source,
+ this.SourceRectangle);
processor.Apply(source);
}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs
new file mode 100644
index 000000000..083a69bd2
--- /dev/null
+++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs
@@ -0,0 +1,42 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+using SixLabors.ImageSharp.PixelFormats;
+
+namespace SixLabors.ImageSharp.Processing.Processors.Convolution
+{
+ ///
+ /// Defines edge detection using eight gradient operators.
+ ///
+ public sealed class EdgeDetectorCompassProcessor : IImageProcessor
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The edge detector kernel.
+ ///
+ /// Whether to convert the image to grayscale before performing edge detection.
+ ///
+ public EdgeDetectorCompassProcessor(EdgeDetectorCompassKernel kernel, bool grayscale)
+ {
+ this.Kernel = kernel;
+ this.Grayscale = grayscale;
+ }
+
+ ///
+ /// Gets the edge detector kernel.
+ ///
+ public EdgeDetectorCompassKernel Kernel { get; }
+
+ ///
+ /// Gets a value indicating whether to convert the image to grayscale before performing
+ /// edge detection.
+ ///
+ public bool Grayscale { get; }
+
+ ///
+ public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle)
+ where TPixel : unmanaged, IPixel
+ => new EdgeDetectorCompassProcessor(configuration, this, source, sourceRectangle);
+ }
+}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs
index 164488155..27963613e 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs
@@ -18,25 +18,27 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
internal class EdgeDetectorCompassProcessor : ImageProcessor
where TPixel : unmanaged, IPixel
{
+ private readonly DenseMatrix[] kernels;
+ private readonly bool grayscale;
+
///
/// Initializes a new instance of the class.
///
/// The configuration which allows altering default behaviour or extending the library.
- /// Gets the kernels to use.
- /// Whether to convert the image to grayscale before performing edge detection.
+ /// The defining the processor parameters.
/// The source for the current processor instance.
/// The source area to process for the current processor instance.
- internal EdgeDetectorCompassProcessor(Configuration configuration, CompassKernels kernels, bool grayscale, Image source, Rectangle sourceRectangle)
+ internal EdgeDetectorCompassProcessor(
+ Configuration configuration,
+ EdgeDetectorCompassProcessor definition,
+ Image source,
+ Rectangle sourceRectangle)
: base(configuration, source, sourceRectangle)
{
- this.Grayscale = grayscale;
- this.Kernels = kernels;
+ this.grayscale = definition.Grayscale;
+ this.kernels = definition.Kernel.Flatten();
}
- private CompassKernels Kernels { get; }
-
- private bool Grayscale { get; }
-
///
protected override void BeforeImageApply()
{
@@ -45,7 +47,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
opaque.Execute();
}
- if (this.Grayscale)
+ if (this.grayscale)
{
new GrayscaleBt709Processor(1F).Execute(this.Configuration, this.Source, this.SourceRectangle);
}
@@ -56,29 +58,27 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
protected override void OnFrameApply(ImageFrame source)
{
- DenseMatrix[] kernels = this.Kernels.Flatten();
-
var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
// We need a clean copy for each pass to start from
using ImageFrame cleanCopy = source.Clone();
- using (var processor = new ConvolutionProcessor(this.Configuration, kernels[0], true, this.Source, interest))
+ using (var processor = new ConvolutionProcessor(this.Configuration, in this.kernels[0], true, this.Source, interest))
{
processor.Apply(source);
}
- if (kernels.Length == 1)
+ if (this.kernels.Length == 1)
{
return;
}
// Additional runs
- for (int i = 1; i < kernels.Length; i++)
+ for (int i = 1; i < this.kernels.Length; i++)
{
using ImageFrame pass = cleanCopy.Clone();
- using (var processor = new ConvolutionProcessor(this.Configuration, kernels[i], true, this.Source, interest))
+ using (var processor = new ConvolutionProcessor(this.Configuration, in this.kernels[i], true, this.Source, interest))
{
processor.Apply(pass);
}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs
index a9d20b547..6fcfca662 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs
@@ -6,26 +6,37 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Processing.Processors.Convolution
{
///
- /// Defines a processor that detects edges within an image using a single two dimensional matrix.
+ /// Defines edge detection using a single 2D gradient operator.
///
- public abstract class EdgeDetectorProcessor : IImageProcessor
+ public sealed class EdgeDetectorProcessor : IImageProcessor
{
///
/// Initializes a new instance of the class.
///
- /// A value indicating whether to convert the image to grayscale before performing edge detection.
- protected EdgeDetectorProcessor(bool grayscale)
+ /// The edge detector kernel.
+ ///
+ /// Whether to convert the image to grayscale before performing edge detection.
+ ///
+ public EdgeDetectorProcessor(EdgeDetectorKernel kernel, bool grayscale)
{
+ this.Kernel = kernel;
this.Grayscale = grayscale;
}
///
- /// Gets a value indicating whether to convert the image to grayscale before performing edge detection.
+ /// Gets the edge detector kernel.
+ ///
+ public EdgeDetectorKernel Kernel { get; }
+
+ ///
+ /// Gets a value indicating whether to convert the image to grayscale before performing
+ /// edge detection.
///
public bool Grayscale { get; }
///
- public abstract IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle)
- where TPixel : unmanaged, IPixel;
+ public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle)
+ where TPixel : unmanaged, IPixel
+ => new EdgeDetectorProcessor(configuration, this, source, sourceRectangle);
}
}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs
index 45639d93a..62dd54919 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs
@@ -13,33 +13,27 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
internal class EdgeDetectorProcessor : ImageProcessor
where TPixel : unmanaged, IPixel
{
+ private readonly bool grayscale;
+ private readonly DenseMatrix kernelXY;
+
///
/// Initializes a new instance of the class.
///
/// The configuration which allows altering default behaviour or extending the library.
- /// The 2d gradient operator.
- /// Whether to convert the image to grayscale before performing edge detection.
+ /// The defining the processor parameters.
/// The source for the current processor instance.
/// The target area to process for the current processor instance.
public EdgeDetectorProcessor(
Configuration configuration,
- in DenseMatrix kernelXY,
- bool grayscale,
+ EdgeDetectorProcessor definition,
Image source,
Rectangle sourceRectangle)
: base(configuration, source, sourceRectangle)
{
- this.KernelXY = kernelXY;
- this.Grayscale = grayscale;
+ this.kernelXY = definition.Kernel.KernelXY;
+ this.grayscale = definition.Grayscale;
}
- public bool Grayscale { get; }
-
- ///
- /// Gets the 2d gradient operator.
- ///
- public DenseMatrix KernelXY { get; }
-
///
protected override void BeforeImageApply()
{
@@ -48,7 +42,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
opaque.Execute();
}
- if (this.Grayscale)
+ if (this.grayscale)
{
new GrayscaleBt709Processor(1F).Execute(this.Configuration, this.Source, this.SourceRectangle);
}
@@ -59,10 +53,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
protected override void OnFrameApply(ImageFrame source)
{
- using (var processor = new ConvolutionProcessor(this.Configuration, this.KernelXY, true, this.Source, this.SourceRectangle))
- {
- processor.Apply(source);
- }
+ using var processor = new ConvolutionProcessor(this.Configuration, in this.kernelXY, true, this.Source, this.SourceRectangle);
+ processor.Apply(source);
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/KayyaliProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/KayyaliProcessor.cs
deleted file mode 100644
index c13e8b543..000000000
--- a/src/ImageSharp/Processing/Processors/Convolution/KayyaliProcessor.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-namespace SixLabors.ImageSharp.Processing.Processors.Convolution
-{
- ///
- /// Defines edge detection processing using the Kayyali operator filter.
- /// See .
- ///
- public sealed class KayyaliProcessor : EdgeDetectorProcessor
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// Whether to convert the image to grayscale before performing edge detection.
- public KayyaliProcessor(bool grayscale)
- : base(grayscale)
- {
- }
-
- ///
- public override IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle)
- => new EdgeDetector2DProcessor(
- configuration,
- KayyaliKernels.KayyaliX,
- KayyaliKernels.KayyaliY,
- this.Grayscale,
- source,
- sourceRectangle);
- }
-}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/CompassKernels.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/CompassKernels.cs
deleted file mode 100644
index 24caa40f8..000000000
--- a/src/ImageSharp/Processing/Processors/Convolution/Kernels/CompassKernels.cs
+++ /dev/null
@@ -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
- {
- ///
- /// Gets the North gradient operator.
- ///
- public abstract DenseMatrix North { get; }
-
- ///
- /// Gets the NorthWest gradient operator.
- ///
- public abstract DenseMatrix NorthWest { get; }
-
- ///
- /// Gets the West gradient operator.
- ///
- public abstract DenseMatrix West { get; }
-
- ///
- /// Gets the SouthWest gradient operator.
- ///
- public abstract DenseMatrix SouthWest { get; }
-
- ///
- /// Gets the South gradient operator.
- ///
- public abstract DenseMatrix South { get; }
-
- ///
- /// Gets the SouthEast gradient operator.
- ///
- public abstract DenseMatrix SouthEast { get; }
-
- ///
- /// Gets the East gradient operator.
- ///
- public abstract DenseMatrix East { get; }
-
- ///
- /// Gets the NorthEast gradient operator.
- ///
- public abstract DenseMatrix NorthEast { get; }
-
- public DenseMatrix[] Flatten() =>
- new[]
- {
- this.North, this.NorthWest, this.West, this.SouthWest,
- this.South, this.SouthEast, this.East, this.NorthEast
- };
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetector2DKernel.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetector2DKernel.cs
new file mode 100644
index 000000000..ed363595d
--- /dev/null
+++ b/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetector2DKernel.cs
@@ -0,0 +1,103 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+
+namespace SixLabors.ImageSharp.Processing.Processors.Convolution
+{
+ ///
+ /// Represents an edge detection convolution kernel consisting of two 1D gradient operators.
+ ///
+ public readonly struct EdgeDetector2DKernel : IEquatable
+ {
+ ///
+ /// An edge detection kernel containing two Kayyali operators.
+ ///
+ public static EdgeDetector2DKernel KayyaliKernel = new EdgeDetector2DKernel(KayyaliKernels.KayyaliX, KayyaliKernels.KayyaliY);
+
+ ///
+ /// An edge detection kernel containing two Prewitt operators.
+ /// .
+ ///
+ public static EdgeDetector2DKernel PrewittKernel = new EdgeDetector2DKernel(PrewittKernels.PrewittX, PrewittKernels.PrewittY);
+
+ ///
+ /// An edge detection kernel containing two Roberts-Cross operators.
+ /// .
+ ///
+ public static EdgeDetector2DKernel RobertsCrossKernel = new EdgeDetector2DKernel(RobertsCrossKernels.RobertsCrossX, RobertsCrossKernels.RobertsCrossY);
+
+ ///
+ /// An edge detection kernel containing two Scharr operators.
+ ///
+ public static EdgeDetector2DKernel ScharrKernel = new EdgeDetector2DKernel(ScharrKernels.ScharrX, ScharrKernels.ScharrY);
+
+ ///
+ /// An edge detection kernel containing two Sobel operators.
+ /// .
+ ///
+ public static EdgeDetector2DKernel SobelKernel = new EdgeDetector2DKernel(SobelKernels.SobelX, SobelKernels.SobelY);
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The horizontal gradient operator.
+ /// The vertical gradient operator.
+ public EdgeDetector2DKernel(DenseMatrix kernelX, DenseMatrix kernelY)
+ {
+ Guard.IsTrue(
+ kernelX.Size.Equals(kernelY.Size),
+ $"{nameof(kernelX)} {nameof(kernelY)}",
+ "Kernel sizes must be the same.");
+
+ this.KernelX = kernelX;
+ this.KernelY = kernelY;
+ }
+
+ ///
+ /// Gets the horizontal gradient operator.
+ ///
+ public DenseMatrix KernelX { get; }
+
+ ///
+ /// Gets the vertical gradient operator.
+ ///
+ public DenseMatrix KernelY { get; }
+
+ ///
+ /// Checks whether two structures are equal.
+ ///
+ /// The left hand operand.
+ /// The right hand operand.
+ ///
+ /// True if the parameter is equal to the parameter;
+ /// otherwise, false.
+ ///
+ public static bool operator ==(EdgeDetector2DKernel left, EdgeDetector2DKernel right)
+ => left.Equals(right);
+
+ ///
+ /// Checks whether two structures are equal.
+ ///
+ /// The left hand operand.
+ /// The right hand operand.
+ ///
+ /// True if the parameter is not equal to the parameter;
+ /// otherwise, false.
+ ///
+ public static bool operator !=(EdgeDetector2DKernel left, EdgeDetector2DKernel right)
+ => !(left == right);
+
+ ///
+ public override bool Equals(object obj)
+ => obj is EdgeDetector2DKernel kernel && this.Equals(kernel);
+
+ ///
+ public bool Equals(EdgeDetector2DKernel other)
+ => this.KernelX.Equals(other.KernelX)
+ && this.KernelY.Equals(other.KernelY);
+
+ ///
+ public override int GetHashCode() => HashCode.Combine(this.KernelX, this.KernelY);
+ }
+}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorCompassKernel.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorCompassKernel.cs
new file mode 100644
index 000000000..bda861799
--- /dev/null
+++ b/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorCompassKernel.cs
@@ -0,0 +1,163 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+
+namespace SixLabors.ImageSharp.Processing.Processors.Convolution
+{
+ ///
+ /// Represents an edge detection convolution kernel consisting of eight gradient operators.
+ ///
+ public readonly struct EdgeDetectorCompassKernel : IEquatable
+ {
+ ///
+ /// An edge detection kenel comprised of Kirsch gradient operators.
+ /// .
+ ///
+ public static EdgeDetectorCompassKernel Kirsch =
+ new EdgeDetectorCompassKernel(
+ KirschKernels.North,
+ KirschKernels.NorthWest,
+ KirschKernels.West,
+ KirschKernels.SouthWest,
+ KirschKernels.South,
+ KirschKernels.SouthEast,
+ KirschKernels.East,
+ KirschKernels.NorthEast);
+
+ ///
+ /// An edge detection kenel comprised of Robinson gradient operators.
+ ///
+ ///
+ public static EdgeDetectorCompassKernel Robinson =
+ new EdgeDetectorCompassKernel(
+ RobinsonKernels.North,
+ RobinsonKernels.NorthWest,
+ RobinsonKernels.West,
+ RobinsonKernels.SouthWest,
+ RobinsonKernels.South,
+ RobinsonKernels.SouthEast,
+ RobinsonKernels.East,
+ RobinsonKernels.NorthEast);
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The north gradient operator.
+ /// The north-west gradient operator.
+ /// The west gradient operator.
+ /// The south-west gradient operator.
+ /// The south gradient operator.
+ /// The south-east gradient operator.
+ /// The east gradient operator.
+ /// The north-east gradient operator.
+ public EdgeDetectorCompassKernel(
+ DenseMatrix north,
+ DenseMatrix northWest,
+ DenseMatrix west,
+ DenseMatrix southWest,
+ DenseMatrix south,
+ DenseMatrix southEast,
+ DenseMatrix east,
+ DenseMatrix 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;
+ }
+
+ ///
+ /// Gets the North gradient operator.
+ ///
+ public DenseMatrix North { get; }
+
+ ///
+ /// Gets the NorthWest gradient operator.
+ ///
+ public DenseMatrix NorthWest { get; }
+
+ ///
+ /// Gets the West gradient operator.
+ ///
+ public DenseMatrix West { get; }
+
+ ///
+ /// Gets the SouthWest gradient operator.
+ ///
+ public DenseMatrix SouthWest { get; }
+
+ ///
+ /// Gets the South gradient operator.
+ ///
+ public DenseMatrix South { get; }
+
+ ///
+ /// Gets the SouthEast gradient operator.
+ ///
+ public DenseMatrix SouthEast { get; }
+
+ ///
+ /// Gets the East gradient operator.
+ ///
+ public DenseMatrix East { get; }
+
+ ///
+ /// Gets the NorthEast gradient operator.
+ ///
+ public DenseMatrix NorthEast { get; }
+
+ ///
+ /// Checks whether two structures are equal.
+ ///
+ /// The left hand operand.
+ /// The right hand operand.
+ ///
+ /// True if the parameter is equal to the parameter;
+ /// otherwise, false.
+ ///
+ public static bool operator ==(EdgeDetectorCompassKernel left, EdgeDetectorCompassKernel right)
+ => left.Equals(right);
+
+ ///
+ /// Checks whether two structures are equal.
+ ///
+ /// The left hand operand.
+ /// The right hand operand.
+ ///
+ /// True if the parameter is not equal to the parameter;
+ /// otherwise, false.
+ ///
+ public static bool operator !=(EdgeDetectorCompassKernel left, EdgeDetectorCompassKernel right)
+ => !(left == right);
+
+ ///
+ public override bool Equals(object obj) => obj is EdgeDetectorCompassKernel kernel && this.Equals(kernel);
+
+ ///
+ 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);
+
+ ///
+ public override int GetHashCode()
+ => HashCode.Combine(
+ this.North,
+ this.NorthWest,
+ this.West,
+ this.SouthWest,
+ this.South,
+ this.SouthEast,
+ this.East,
+ this.NorthEast);
+
+ internal DenseMatrix[] Flatten() =>
+ new[]
+ {
+ this.North, this.NorthWest, this.West, this.SouthWest,
+ this.South, this.SouthEast, this.East, this.NorthEast
+ };
+ }
+}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorKernel.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorKernel.cs
new file mode 100644
index 000000000..86b8a24d9
--- /dev/null
+++ b/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorKernel.cs
@@ -0,0 +1,78 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+
+namespace SixLabors.ImageSharp.Processing.Processors.Convolution
+{
+ ///
+ /// Represents an edge detection convolution kernel consisting of a single 2D gradient operator.
+ ///
+ public readonly struct EdgeDetectorKernel : IEquatable
+ {
+ ///
+ /// An edge detection kernel containing a 3x3 Laplacian operator.
+ ///
+ ///
+ public static EdgeDetectorKernel Laplacian3x3 = new EdgeDetectorKernel(LaplacianKernels.Laplacian3x3);
+
+ ///
+ /// An edge detection kernel containing a 5x5 Laplacian operator.
+ ///
+ ///
+ public static EdgeDetectorKernel Laplacian5x5 = new EdgeDetectorKernel(LaplacianKernels.Laplacian5x5);
+
+ ///
+ /// An edge detection kernel containing a Laplacian of Gaussian operator.
+ /// .
+ ///
+ public static EdgeDetectorKernel LaplacianOfGaussian = new EdgeDetectorKernel(LaplacianKernels.LaplacianOfGaussianXY);
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The 2D gradient operator.
+ public EdgeDetectorKernel(DenseMatrix kernelXY)
+ => this.KernelXY = kernelXY;
+
+ ///
+ /// Gets the 2D gradient operator.
+ ///
+ public DenseMatrix KernelXY { get; }
+
+ ///
+ /// Checks whether two structures are equal.
+ ///
+ /// The left hand operand.
+ /// The right hand operand.
+ ///
+ /// True if the parameter is equal to the parameter;
+ /// otherwise, false.
+ ///
+ public static bool operator ==(EdgeDetectorKernel left, EdgeDetectorKernel right)
+ => left.Equals(right);
+
+ ///
+ /// Checks whether two structures are equal.
+ ///
+ /// The left hand operand.
+ /// The right hand operand.
+ ///
+ /// True if the parameter is not equal to the parameter;
+ /// otherwise, false.
+ ///
+ public static bool operator !=(EdgeDetectorKernel left, EdgeDetectorKernel right)
+ => !(left == right);
+
+ ///
+ public override bool Equals(object obj)
+ => obj is EdgeDetectorKernel kernel && this.Equals(kernel);
+
+ ///
+ public bool Equals(EdgeDetectorKernel other)
+ => this.KernelXY.Equals(other.KernelXY);
+
+ ///
+ public override int GetHashCode() => this.KernelXY.GetHashCode();
+ }
+}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/KayyaliKernels.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/KayyaliKernels.cs
similarity index 100%
rename from src/ImageSharp/Processing/Processors/Convolution/Kernels/KayyaliKernels.cs
rename to src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/KayyaliKernels.cs
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/KirschKernels.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/KirschKernels.cs
similarity index 79%
rename from src/ImageSharp/Processing/Processors/Convolution/Kernels/KirschKernels.cs
rename to src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/KirschKernels.cs
index 28c5590ef..87ccb174d 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/Kernels/KirschKernels.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/KirschKernels.cs
@@ -1,17 +1,18 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Processing.Processors.Convolution
{
///
- /// Contains the eight matrices used for Kirsch edge detection
+ /// Contains the eight matrices used for Kirsch edge detection.
+ /// .
///
- internal class KirschKernels : CompassKernels
+ internal static class KirschKernels
{
///
/// Gets the North gradient operator
///
- public override DenseMatrix North =>
+ public static DenseMatrix North =>
new float[,]
{
{ 5, 5, 5 },
@@ -22,7 +23,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// Gets the NorthWest gradient operator
///
- public override DenseMatrix NorthWest =>
+ public static DenseMatrix NorthWest =>
new float[,]
{
{ 5, 5, -3 },
@@ -33,7 +34,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// Gets the West gradient operator
///
- public override DenseMatrix West =>
+ public static DenseMatrix West =>
new float[,]
{
{ 5, -3, -3 },
@@ -44,7 +45,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// Gets the SouthWest gradient operator
///
- public override DenseMatrix SouthWest =>
+ public static DenseMatrix SouthWest =>
new float[,]
{
{ -3, -3, -3 },
@@ -55,7 +56,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// Gets the South gradient operator
///
- public override DenseMatrix South =>
+ public static DenseMatrix South =>
new float[,]
{
{ -3, -3, -3 },
@@ -66,7 +67,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// Gets the SouthEast gradient operator
///
- public override DenseMatrix SouthEast =>
+ public static DenseMatrix SouthEast =>
new float[,]
{
{ -3, -3, -3 },
@@ -77,7 +78,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// Gets the East gradient operator
///
- public override DenseMatrix East =>
+ public static DenseMatrix East =>
new float[,]
{
{ -3, -3, 5 },
@@ -88,7 +89,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// Gets the NorthEast gradient operator
///
- public override DenseMatrix NorthEast =>
+ public static DenseMatrix NorthEast =>
new float[,]
{
{ -3, 5, 5 },
@@ -96,4 +97,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
{ -3, -3, -3 }
};
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/LaplacianKernelFactory.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/LaplacianKernelFactory.cs
similarity index 100%
rename from src/ImageSharp/Processing/Processors/Convolution/Kernels/LaplacianKernelFactory.cs
rename to src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/LaplacianKernelFactory.cs
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/LaplacianKernels.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/LaplacianKernels.cs
similarity index 80%
rename from src/ImageSharp/Processing/Processors/Convolution/Kernels/LaplacianKernels.cs
rename to src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/LaplacianKernels.cs
index ce574341f..7036300c7 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/Kernels/LaplacianKernels.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/LaplacianKernels.cs
@@ -1,10 +1,12 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Processing.Processors.Convolution
{
///
- /// Contains Laplacian kernels of different sizes
+ /// Contains Laplacian kernels of different sizes.
+ ///
+ /// .
///
internal static class LaplacianKernels
{
@@ -31,4 +33,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
{ 0, 0, -1, 0, 0 }
};
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/PrewittKernels.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/PrewittKernels.cs
similarity index 100%
rename from src/ImageSharp/Processing/Processors/Convolution/Kernels/PrewittKernels.cs
rename to src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/PrewittKernels.cs
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/RobertsCrossKernels.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/RobertsCrossKernels.cs
similarity index 100%
rename from src/ImageSharp/Processing/Processors/Convolution/Kernels/RobertsCrossKernels.cs
rename to src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/RobertsCrossKernels.cs
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/RobinsonKernels.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/RobinsonKernels.cs
similarity index 78%
rename from src/ImageSharp/Processing/Processors/Convolution/Kernels/RobinsonKernels.cs
rename to src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/RobinsonKernels.cs
index 857c772b0..7d0478aa5 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/Kernels/RobinsonKernels.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/RobinsonKernels.cs
@@ -1,17 +1,18 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Processing.Processors.Convolution
{
///
/// Contains the kernels used for Robinson edge detection.
+ ///
///
- internal class RobinsonKernels : CompassKernels
+ internal static class RobinsonKernels
{
///
/// Gets the North gradient operator
///
- public override DenseMatrix North =>
+ public static DenseMatrix North =>
new float[,]
{
{ 1, 2, 1 },
@@ -22,7 +23,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// Gets the NorthWest gradient operator
///
- public override DenseMatrix NorthWest =>
+ public static DenseMatrix NorthWest =>
new float[,]
{
{ 2, 1, 0 },
@@ -33,7 +34,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// Gets the West gradient operator
///
- public override DenseMatrix West =>
+ public static DenseMatrix West =>
new float[,]
{
{ 1, 0, -1 },
@@ -44,7 +45,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// Gets the SouthWest gradient operator
///
- public override DenseMatrix SouthWest =>
+ public static DenseMatrix SouthWest =>
new float[,]
{
{ 0, -1, -2 },
@@ -55,7 +56,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// Gets the South gradient operator
///
- public override DenseMatrix South =>
+ public static DenseMatrix South =>
new float[,]
{
{ -1, -2, -1 },
@@ -66,7 +67,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// Gets the SouthEast gradient operator
///
- public override DenseMatrix SouthEast =>
+ public static DenseMatrix SouthEast =>
new float[,]
{
{ -2, -1, 0 },
@@ -77,7 +78,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// Gets the East gradient operator
///
- public override DenseMatrix East =>
+ public static DenseMatrix East =>
new float[,]
{
{ -1, 0, 1 },
@@ -88,7 +89,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// Gets the NorthEast gradient operator
///
- public override DenseMatrix NorthEast =>
+ public static DenseMatrix NorthEast =>
new float[,]
{
{ 0, 1, 2 },
@@ -96,4 +97,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
{ -2, -1, 0 }
};
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/ScharrKernels.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/ScharrKernels.cs
similarity index 100%
rename from src/ImageSharp/Processing/Processors/Convolution/Kernels/ScharrKernels.cs
rename to src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/ScharrKernels.cs
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/SobelKernels.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/SobelKernels.cs
similarity index 100%
rename from src/ImageSharp/Processing/Processors/Convolution/Kernels/SobelKernels.cs
rename to src/ImageSharp/Processing/Processors/Convolution/Kernels/Implementation/SobelKernels.cs
diff --git a/src/ImageSharp/Processing/Processors/Convolution/KirschProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/KirschProcessor.cs
deleted file mode 100644
index 62bd17016..000000000
--- a/src/ImageSharp/Processing/Processors/Convolution/KirschProcessor.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-namespace SixLabors.ImageSharp.Processing.Processors.Convolution
-{
- ///
- /// Defines edge detection using the Kirsch operator filter.
- /// See .
- ///
- public sealed class KirschProcessor : EdgeDetectorProcessor
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// Whether to convert the image to grayscale before performing edge detection.
- public KirschProcessor(bool grayscale)
- : base(grayscale)
- {
- }
-
- ///
- public override IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle)
- => new EdgeDetectorCompassProcessor(configuration, new KirschKernels(), this.Grayscale, source, sourceRectangle);
- }
-}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Laplacian3x3Processor.cs b/src/ImageSharp/Processing/Processors/Convolution/Laplacian3x3Processor.cs
deleted file mode 100644
index 957c61b07..000000000
--- a/src/ImageSharp/Processing/Processors/Convolution/Laplacian3x3Processor.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-namespace SixLabors.ImageSharp.Processing.Processors.Convolution
-{
- ///
- /// Applies edge detection processing to the image using the Laplacian 3x3 operator filter.
- ///
- ///
- public sealed class Laplacian3x3Processor : EdgeDetectorProcessor
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// Whether to convert the image to grayscale before performing edge detection.
- public Laplacian3x3Processor(bool grayscale)
- : base(grayscale)
- {
- }
-
- ///
- public override IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle)
- => new EdgeDetectorProcessor(configuration, LaplacianKernels.Laplacian3x3, this.Grayscale, source, sourceRectangle);
- }
-}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Laplacian5x5Processor.cs b/src/ImageSharp/Processing/Processors/Convolution/Laplacian5x5Processor.cs
deleted file mode 100644
index 8b28662ae..000000000
--- a/src/ImageSharp/Processing/Processors/Convolution/Laplacian5x5Processor.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-namespace SixLabors.ImageSharp.Processing.Processors.Convolution
-{
- ///
- /// Defines edge detection processing using the Laplacian 5x5 operator filter.
- /// .
- ///
- public sealed class Laplacian5x5Processor : EdgeDetectorProcessor
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// Whether to convert the image to grayscale before performing edge detection.
- public Laplacian5x5Processor(bool grayscale)
- : base(grayscale)
- {
- }
-
- ///
- public override IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle)
- => new EdgeDetectorProcessor(configuration, LaplacianKernels.Laplacian5x5, this.Grayscale, source, sourceRectangle);
- }
-}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/LaplacianOfGaussianProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/LaplacianOfGaussianProcessor.cs
deleted file mode 100644
index 5c8f7c40d..000000000
--- a/src/ImageSharp/Processing/Processors/Convolution/LaplacianOfGaussianProcessor.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-namespace SixLabors.ImageSharp.Processing.Processors.Convolution
-{
- ///
- /// Applies edge detection processing to the image using the Laplacian of Gaussian operator filter.
- /// See .
- ///
- public sealed class LaplacianOfGaussianProcessor : EdgeDetectorProcessor
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// Whether to convert the image to grayscale before performing edge detection.
- public LaplacianOfGaussianProcessor(bool grayscale)
- : base(grayscale)
- {
- }
-
- ///
- public override IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle)
- => new EdgeDetectorProcessor(configuration, LaplacianKernels.LaplacianOfGaussianXY, this.Grayscale, source, sourceRectangle);
- }
-}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/PrewittProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/PrewittProcessor.cs
deleted file mode 100644
index c5ae14935..000000000
--- a/src/ImageSharp/Processing/Processors/Convolution/PrewittProcessor.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-namespace SixLabors.ImageSharp.Processing.Processors.Convolution
-{
- ///
- /// Defines edge detection using the Prewitt operator filter.
- /// See .
- ///
- public sealed class PrewittProcessor : EdgeDetectorProcessor
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// Whether to convert the image to grayscale before performing edge detection.
- public PrewittProcessor(bool grayscale)
- : base(grayscale)
- {
- }
-
- ///
- public override IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle)
- => new EdgeDetector2DProcessor(
- configuration,
- PrewittKernels.PrewittX,
- PrewittKernels.PrewittY,
- this.Grayscale,
- source,
- sourceRectangle);
- }
-}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/RobertsCrossProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/RobertsCrossProcessor.cs
deleted file mode 100644
index 57df83a14..000000000
--- a/src/ImageSharp/Processing/Processors/Convolution/RobertsCrossProcessor.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-namespace SixLabors.ImageSharp.Processing.Processors.Convolution
-{
- ///
- /// Defines edge detection processing using the Roberts Cross operator filter.
- /// See .
- ///
- public sealed class RobertsCrossProcessor : EdgeDetectorProcessor
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// Whether to convert the image to grayscale before performing edge detection.
- public RobertsCrossProcessor(bool grayscale)
- : base(grayscale)
- {
- }
-
- ///
- public override IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle)
- => new EdgeDetector2DProcessor(
- configuration,
- RobertsCrossKernels.RobertsCrossX,
- RobertsCrossKernels.RobertsCrossY,
- this.Grayscale,
- source,
- sourceRectangle);
- }
-}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/RobinsonProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/RobinsonProcessor.cs
deleted file mode 100644
index 22c8562e2..000000000
--- a/src/ImageSharp/Processing/Processors/Convolution/RobinsonProcessor.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-namespace SixLabors.ImageSharp.Processing.Processors.Convolution
-{
- ///
- /// Defines edge detection using the Robinson operator filter.
- /// See .
- ///
- public sealed class RobinsonProcessor : EdgeDetectorProcessor
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// Whether to convert the image to grayscale before performing edge detection.
- public RobinsonProcessor(bool grayscale)
- : base(grayscale)
- {
- }
-
- ///
- public override IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle)
- => new EdgeDetectorCompassProcessor(configuration, new RobinsonKernels(), this.Grayscale, source, sourceRectangle);
- }
-}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/ScharrProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/ScharrProcessor.cs
deleted file mode 100644
index d9a0745e2..000000000
--- a/src/ImageSharp/Processing/Processors/Convolution/ScharrProcessor.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-namespace SixLabors.ImageSharp.Processing.Processors.Convolution
-{
- ///
- /// Defines edge detection processing using the Scharr operator filter.
- ///
- ///
- public sealed class ScharrProcessor : EdgeDetectorProcessor
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// Whether to convert the image to grayscale before performing edge detection.
- public ScharrProcessor(bool grayscale)
- : base(grayscale)
- {
- }
-
- ///
- public override IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle)
- => new EdgeDetector2DProcessor(
- configuration,
- ScharrKernels.ScharrX,
- ScharrKernels.ScharrY,
- this.Grayscale,
- source,
- sourceRectangle);
- }
-}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/SobelProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/SobelProcessor.cs
deleted file mode 100644
index 73632392e..000000000
--- a/src/ImageSharp/Processing/Processors/Convolution/SobelProcessor.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-namespace SixLabors.ImageSharp.Processing.Processors.Convolution
-{
- ///
- /// Defines edge detection using the Sobel operator filter.
- /// See .
- ///
- public sealed class SobelProcessor : EdgeDetectorProcessor
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// Whether to convert the image to grayscale before performing edge detection.
- public SobelProcessor(bool grayscale)
- : base(grayscale)
- {
- }
-
- ///
- public override IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle)
- => new EdgeDetector2DProcessor(
- configuration,
- SobelKernels.SobelX,
- SobelKernels.SobelY,
- this.Grayscale,
- source,
- sourceRectangle);
- }
-}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs
index ebc8f0e4f..dd9c06938 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs
@@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
Configuration configuration = this.Source.GetConfiguration();
// Detect the edges.
- new SobelProcessor(false).Execute(this.Configuration, temp, this.SourceRectangle);
+ new EdgeDetector2DProcessor(KnownEdgeDetectorKernels.Sobel, false).Execute(this.Configuration, temp, this.SourceRectangle);
// Apply threshold binarization filter.
new BinaryThresholdProcessor(this.definition.Threshold).Execute(this.Configuration, temp, this.SourceRectangle);
diff --git a/tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs b/tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs
index d40201bd8..ce2fa988c 100644
--- a/tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs
+++ b/tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs
@@ -37,17 +37,17 @@ namespace SixLabors.ImageSharp.Benchmarks
[Benchmark(Description = "ImageSharp DetectEdges")]
public void ImageProcessorCoreDetectEdges()
{
- this.image.Mutate(x => x.DetectEdges(EdgeDetectionOperators.Kayyali));
- this.image.Mutate(x => x.DetectEdges(EdgeDetectionOperators.Kayyali));
- this.image.Mutate(x => x.DetectEdges(EdgeDetectionOperators.Kirsch));
- this.image.Mutate(x => x.DetectEdges(EdgeDetectionOperators.Laplacian3x3));
- this.image.Mutate(x => x.DetectEdges(EdgeDetectionOperators.Laplacian5x5));
- this.image.Mutate(x => x.DetectEdges(EdgeDetectionOperators.LaplacianOfGaussian));
- this.image.Mutate(x => x.DetectEdges(EdgeDetectionOperators.Prewitt));
- this.image.Mutate(x => x.DetectEdges(EdgeDetectionOperators.RobertsCross));
- this.image.Mutate(x => x.DetectEdges(EdgeDetectionOperators.Robinson));
- this.image.Mutate(x => x.DetectEdges(EdgeDetectionOperators.Scharr));
- this.image.Mutate(x => x.DetectEdges(EdgeDetectionOperators.Sobel));
+ this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectorKernels.Kayyali));
+ this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectorKernels.Kayyali));
+ this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectorKernels.Kirsch));
+ this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectorKernels.Laplacian3x3));
+ this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectorKernels.Laplacian5x5));
+ this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectorKernels.LaplacianOfGaussian));
+ this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectorKernels.Prewitt));
+ this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectorKernels.RobertsCross));
+ this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectorKernels.Robinson));
+ this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectorKernels.Scharr));
+ this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectorKernels.Sobel));
}
}
}
diff --git a/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs
index a0e9be110..3ffb8f4e3 100644
--- a/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs
+++ b/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs
@@ -1,75 +1,201 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
-using System.Collections.Generic;
-
+using System.Diagnostics.CodeAnalysis;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Processing.Processors.Convolution;
-using SixLabors.ImageSharp.Tests.TestUtilities;
-
using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Convolution
{
+ [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1313:Parameter names should begin with lower-case letter", Justification = "OK. Used for TheoryData compatibility.")]
public class DetectEdgesTest : BaseImageOperationsExtensionTest
{
[Fact]
- public void DetectEdges_SobelProcessorDefaultsSet()
+ public void DetectEdges_EdgeDetector2DProcessorDefaultsSet()
{
this.operations.DetectEdges();
+ EdgeDetector2DProcessor processor = this.Verify();
- // TODO: Enable once we have updated the images
- SobelProcessor processor = this.Verify();
Assert.True(processor.Grayscale);
+ Assert.Equal(KnownEdgeDetectorKernels.Sobel, processor.Kernel);
}
[Fact]
- public void DetectEdges_Rect_SobelProcessorDefaultsSet()
+ public void DetectEdges_Rect_EdgeDetector2DProcessorDefaultsSet()
{
this.operations.DetectEdges(this.rect);
+ EdgeDetector2DProcessor processor = this.Verify(this.rect);
+
+ Assert.True(processor.Grayscale);
+ Assert.Equal(KnownEdgeDetectorKernels.Sobel, processor.Kernel);
+ }
+
+ public static TheoryData EdgeDetector2DKernelData =
+ new TheoryData
+ {
+ { KnownEdgeDetectorKernels.Kayyali, true },
+ { KnownEdgeDetectorKernels.Kayyali, false },
+ { KnownEdgeDetectorKernels.Prewitt, true },
+ { KnownEdgeDetectorKernels.Prewitt, false },
+ { KnownEdgeDetectorKernels.RobertsCross, true },
+ { KnownEdgeDetectorKernels.RobertsCross, false },
+ { KnownEdgeDetectorKernels.Scharr, true },
+ { KnownEdgeDetectorKernels.Scharr, false },
+ { KnownEdgeDetectorKernels.Sobel, true },
+ { KnownEdgeDetectorKernels.Sobel, false },
+ };
+
+ [Theory]
+ [MemberData(nameof(EdgeDetector2DKernelData))]
+ public void DetectEdges_EdgeDetector2DProcessor_DefaultGrayScale_Set(EdgeDetector2DKernel kernel, bool _)
+ {
+ this.operations.DetectEdges(kernel);
+ EdgeDetector2DProcessor processor = this.Verify();
+
+ Assert.True(processor.Grayscale);
+ Assert.Equal(kernel, processor.Kernel);
+ }
+
+ [Theory]
+ [MemberData(nameof(EdgeDetector2DKernelData))]
+ public void DetectEdges_Rect_EdgeDetector2DProcessor_DefaultGrayScale_Set(EdgeDetector2DKernel kernel, bool _)
+ {
+ this.operations.DetectEdges(kernel, this.rect);
+ EdgeDetector2DProcessor processor = this.Verify(this.rect);
+
+ Assert.True(processor.Grayscale);
+ Assert.Equal(kernel, processor.Kernel);
+ }
+
+ [Theory]
+ [MemberData(nameof(EdgeDetector2DKernelData))]
+ public void DetectEdges_EdgeDetector2DProcessorSet(EdgeDetector2DKernel kernel, bool grayscale)
+ {
+ this.operations.DetectEdges(kernel, grayscale);
+ EdgeDetector2DProcessor processor = this.Verify();
+
+ Assert.Equal(grayscale, processor.Grayscale);
+ Assert.Equal(kernel, processor.Kernel);
+ }
+
+ [Theory]
+ [MemberData(nameof(EdgeDetector2DKernelData))]
+ public void DetectEdges_Rect_EdgeDetector2DProcessorSet(EdgeDetector2DKernel kernel, bool grayscale)
+ {
+ this.operations.DetectEdges(kernel, grayscale, this.rect);
+ EdgeDetector2DProcessor processor = this.Verify(this.rect);
+
+ Assert.Equal(grayscale, processor.Grayscale);
+ Assert.Equal(kernel, processor.Kernel);
+ }
+
+ public static TheoryData EdgeDetectorKernelData =
+ new TheoryData
+ {
+ { KnownEdgeDetectorKernels.Laplacian3x3, true },
+ { KnownEdgeDetectorKernels.Laplacian3x3, false },
+ { KnownEdgeDetectorKernels.Laplacian5x5, true },
+ { KnownEdgeDetectorKernels.Laplacian5x5, false },
+ { KnownEdgeDetectorKernels.LaplacianOfGaussian, true },
+ { KnownEdgeDetectorKernels.LaplacianOfGaussian, false },
+ };
+
+ [Theory]
+ [MemberData(nameof(EdgeDetectorKernelData))]
+ public void DetectEdges_EdgeDetectorProcessor_DefaultGrayScale_Set(EdgeDetectorKernel kernel, bool _)
+ {
+ this.operations.DetectEdges(kernel);
+ EdgeDetectorProcessor processor = this.Verify();
- // TODO: Enable once we have updated the images
- SobelProcessor processor = this.Verify(this.rect);
Assert.True(processor.Grayscale);
+ Assert.Equal(kernel, processor.Kernel);
}
- public static IEnumerable