Browse Source

Update tests

pull/1574/head
James Jackson-South 6 years ago
parent
commit
a9aa3e5ef6
  1. 245
      src/ImageSharp/Processing/Extensions/Convolution/DetectEdgesExtensions.cs
  2. 2
      src/ImageSharp/Processing/KnownEdgeDetectorKernels.cs
  3. 2
      src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs
  4. 22
      tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs
  5. 196
      tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs
  6. 92
      tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs

245
src/ImageSharp/Processing/Extensions/Convolution/DetectEdgesExtensions.cs

@ -1,7 +1,6 @@
// 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
{
/// <summary>
/// Detects any edges within the image. Uses the <see cref="SobelProcessor"/> filter
/// operating in grayscale mode.
/// Detects any edges within the image.
/// Uses the <see cref="KnownEdgeDetectorKernels.Sobel"/> kernel operating in grayscale mode.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext DetectEdges(this IImageProcessingContext source) =>
DetectEdges(source, new SobelProcessor(true));
DetectEdges(source, KnownEdgeDetectorKernels.Sobel);
/// <summary>
/// Detects any edges within the image. Uses the <see cref="SobelProcessor"/> filter
/// operating in grayscale mode.
/// Detects any edges within the image.
/// Uses the <see cref="KnownEdgeDetectorKernels.Sobel"/> kernel operating in grayscale mode.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
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);
/// <summary>
/// Detects any edges within the image.
/// Detects any edges within the image operating in grayscale mode.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="filter">The filter for detecting edges.</param>
/// <param name="kernel">The 2D edge detector kernel.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext DetectEdges(
this IImageProcessingContext source,
KnownEdgeDetectionOperators filter) =>
DetectEdges(source, GetProcessor(filter, true));
EdgeDetector2DKernel kernel) =>
DetectEdges(source, kernel, true);
/// <summary>
/// Detects any edges within the image.
/// Detects any edges within the image using a <see cref="EdgeDetector2DKernel"/>.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="filter">The filter for detecting edges.</param>
/// <param name="grayscale">Whether to convert the image to grayscale first. Defaults to true.</param>
/// <param name="kernel">The 2D edge detector kernel.</param>
/// <param name="grayscale">
/// Whether to convert the image to grayscale before performing edge detection.
/// </param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext DetectEdges(
this IImageProcessingContext source,
KnownEdgeDetectionOperators filter,
bool grayscale) =>
DetectEdges(source, GetProcessor(filter, grayscale));
EdgeDetector2DKernel kernel,
bool grayscale)
{
var processor = new EdgeDetector2DProcessor(kernel, grayscale);
source.ApplyProcessor(processor);
return source;
}
/// <summary>
/// Detects any edges within the image.
/// Detects any edges within the image operating in grayscale mode.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="filter">The filter for detecting edges.</param>
/// <param name="kernel">The 2D edge detector kernel.</param>
/// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param>
/// <param name="grayscale">Whether to convert the image to grayscale first. Defaults to true.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext DetectEdges(
this IImageProcessingContext source,
KnownEdgeDetectionOperators filter,
Rectangle rectangle,
bool grayscale = true) =>
DetectEdges(source, rectangle, GetProcessor(filter, grayscale));
EdgeDetector2DKernel kernel,
Rectangle rectangle) =>
DetectEdges(source, kernel, true, rectangle);
/// <summary>
/// Detects any edges within the image.
/// Detects any edges within the image using a <see cref="EdgeDetector2DKernel"/>.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="filter">The filter for detecting edges.</param>
/// <param name="kernel">The 2D edge detector kernel.</param>
/// <param name="grayscale">
/// Whether to convert the image to grayscale before performing edge detection.
/// </param>
/// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
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;
}
/// <summary>
/// Detects any edges within the image.
/// Detects any edges within the image operating in grayscale mode.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// <param name="kernel">The edge detector kernel.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext DetectEdges(
this IImageProcessingContext source,
EdgeDetectorKernel kernel) =>
DetectEdges(source, kernel, true);
/// <summary>
/// Detects any edges within the image using a <see cref="EdgeDetectorKernel"/>.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="kernel">The edge detector kernel.</param>
/// <param name="grayscale">
/// Whether to convert the image to grayscale before performing edge detection.
/// </param>
/// <param name="filter">The filter for detecting edges.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
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(KnownEdgeDetectionOperators filter, bool grayscale)
{
IImageProcessor processor;
switch (filter)
{
case KnownEdgeDetectionOperators.Kayyali:
processor = new KayyaliProcessor(grayscale);
break;
case KnownEdgeDetectionOperators.Kirsch:
processor = new KirschProcessor(grayscale);
break;
case KnownEdgeDetectionOperators.Laplacian3x3:
processor = new Laplacian3x3Processor(grayscale);
break;
case KnownEdgeDetectionOperators.Laplacian5x5:
processor = new Laplacian5x5Processor(grayscale);
break;
case KnownEdgeDetectionOperators.LaplacianOfGaussian:
processor = new LaplacianOfGaussianProcessor(grayscale);
break;
case KnownEdgeDetectionOperators.Prewitt:
processor = new PrewittProcessor(grayscale);
break;
/// <summary>
/// Detects any edges within the image operating in grayscale mode.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="kernel">The edge detector kernel.</param>
/// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext DetectEdges(
this IImageProcessingContext source,
EdgeDetectorKernel kernel,
Rectangle rectangle) =>
DetectEdges(source, kernel, true, rectangle);
case KnownEdgeDetectionOperators.RobertsCross:
processor = new RobertsCrossProcessor(grayscale);
break;
/// <summary>
/// Detects any edges within the image using a <see cref="EdgeDetectorKernel"/>.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="kernel">The edge detector kernel.</param>
/// <param name="grayscale">
/// Whether to convert the image to grayscale before performing edge detection.
/// </param>
/// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
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 KnownEdgeDetectionOperators.Robinson:
processor = new RobinsonProcessor(grayscale);
break;
/// <summary>
/// Detects any edges within the image operating in grayscale mode.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="kernel">Thecompass edge detector kernel.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext DetectEdges(
this IImageProcessingContext source,
EdgeDetectorCompassKernel kernel) =>
DetectEdges(source, kernel, true);
case KnownEdgeDetectionOperators.Scharr:
processor = new ScharrProcessor(grayscale);
break;
/// <summary>
/// Detects any edges within the image using a <see cref="EdgeDetectorCompassKernel"/>.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="kernel">Thecompass edge detector kernel.</param>
/// <param name="grayscale">
/// Whether to convert the image to grayscale before performing edge detection.
/// </param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
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;
}
/// <summary>
/// Detects any edges within the image operating in grayscale mode.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="kernel">Thecompass edge detector kernel.</param>
/// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext DetectEdges(
this IImageProcessingContext source,
EdgeDetectorCompassKernel kernel,
Rectangle rectangle) =>
DetectEdges(source, kernel, true, rectangle);
return processor;
/// <summary>
/// Detects any edges within the image using a <see cref="EdgeDetectorCompassKernel"/>.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="kernel">Thecompass edge detector kernel.</param>
/// <param name="grayscale">
/// Whether to convert the image to grayscale before performing edge detection.
/// </param>
/// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
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;
}
}
}

2
src/ImageSharp/Processing/KnownEdgeDetectionOperators.cs → src/ImageSharp/Processing/KnownEdgeDetectorKernels.cs

@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing
/// <summary>
/// Contains reusable static instances of known edge detection kernels.
/// </summary>
public static class KnownEdgeDetectionOperators
public static class KnownEdgeDetectorKernels
{
/// <summary>
/// Gets the Kayyali edge detector kernel.

2
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);

22
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(KnownEdgeDetectionOperators.Kayyali));
this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectionOperators.Kayyali));
this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectionOperators.Kirsch));
this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectionOperators.Laplacian3x3));
this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectionOperators.Laplacian5x5));
this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectionOperators.LaplacianOfGaussian));
this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectionOperators.Prewitt));
this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectionOperators.RobertsCross));
this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectionOperators.Robinson));
this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectionOperators.Scharr));
this.image.Mutate(x => x.DetectEdges(KnownEdgeDetectionOperators.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));
}
}
}

196
tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs

@ -1,12 +1,8 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.Collections.Generic;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Processing.Processors.Convolution;
using SixLabors.ImageSharp.Tests.TestUtilities;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Convolution
@ -14,62 +10,190 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution
public class DetectEdgesTest : BaseImageOperationsExtensionTest
{
[Fact]
public void DetectEdges_SobelProcessorDefaultsSet()
public void DetectEdges_EdgeDetector2DProcessorDefaultsSet()
{
this.operations.DetectEdges();
EdgeDetector2DProcessor processor = this.Verify<EdgeDetector2DProcessor>();
// TODO: Enable once we have updated the images
SobelProcessor processor = this.Verify<SobelProcessor>();
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<EdgeDetector2DProcessor>(this.rect);
Assert.True(processor.Grayscale);
Assert.Equal(KnownEdgeDetectorKernels.Sobel, processor.Kernel);
}
public static TheoryData<EdgeDetector2DKernel, bool> EdgeDetector2DKernelData =
new TheoryData<EdgeDetector2DKernel, bool>
{
{ 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<EdgeDetector2DProcessor>();
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<EdgeDetector2DProcessor>(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<EdgeDetector2DProcessor>();
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<EdgeDetector2DProcessor>(this.rect);
Assert.Equal(grayscale, processor.Grayscale);
Assert.Equal(kernel, processor.Kernel);
}
public static TheoryData<EdgeDetectorKernel, bool> EdgeDetectorKernelData =
new TheoryData<EdgeDetectorKernel, bool>
{
{ 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<EdgeDetectorProcessor>();
// TODO: Enable once we have updated the images
SobelProcessor processor = this.Verify<SobelProcessor>(this.rect);
Assert.True(processor.Grayscale);
Assert.Equal(kernel, processor.Kernel);
}
public static IEnumerable<object[]> EdgeDetectionTheoryData => new[]
[Theory]
[MemberData(nameof(EdgeDetectorKernelData))]
public void DetectEdges_Rect_EdgeDetectorProcessor_DefaultGrayScale_Set(EdgeDetectorKernel kernel, bool _)
{
new object[] { new TestType<KayyaliProcessor>(), KnownEdgeDetectionOperators.Kayyali },
new object[] { new TestType<KirschProcessor>(), KnownEdgeDetectionOperators.Kirsch },
new object[] { new TestType<Laplacian3x3Processor>(), KnownEdgeDetectionOperators.Laplacian3x3 },
new object[] { new TestType<Laplacian5x5Processor>(), KnownEdgeDetectionOperators.Laplacian5x5 },
new object[] { new TestType<LaplacianOfGaussianProcessor>(), KnownEdgeDetectionOperators.LaplacianOfGaussian },
new object[] { new TestType<PrewittProcessor>(), KnownEdgeDetectionOperators.Prewitt },
new object[] { new TestType<RobertsCrossProcessor>(), KnownEdgeDetectionOperators.RobertsCross },
new object[] { new TestType<RobinsonProcessor>(), KnownEdgeDetectionOperators.Robinson },
new object[] { new TestType<ScharrProcessor>(), KnownEdgeDetectionOperators.Scharr },
new object[] { new TestType<SobelProcessor>(), KnownEdgeDetectionOperators.Sobel },
};
this.operations.DetectEdges(kernel, this.rect);
EdgeDetectorProcessor processor = this.Verify<EdgeDetectorProcessor>(this.rect);
Assert.True(processor.Grayscale);
Assert.Equal(kernel, processor.Kernel);
}
[Theory]
[MemberData(nameof(EdgeDetectionTheoryData))]
public void DetectEdges_filter_SobelProcessorDefaultsSet<TProcessor>(TestType<TProcessor> type, KnownEdgeDetectionOperators filter)
where TProcessor : EdgeDetectorProcessor
[MemberData(nameof(EdgeDetectorKernelData))]
public void DetectEdges_EdgeDetectorProcessorSet(EdgeDetectorKernel kernel, bool grayscale)
{
this.operations.DetectEdges(filter);
this.operations.DetectEdges(kernel, grayscale);
EdgeDetectorProcessor processor = this.Verify<EdgeDetectorProcessor>();
Assert.Equal(grayscale, processor.Grayscale);
Assert.Equal(kernel, processor.Kernel);
}
[Theory]
[MemberData(nameof(EdgeDetectorKernelData))]
public void DetectEdges_Rect_EdgeDetectorProcessorSet(EdgeDetectorKernel kernel, bool grayscale)
{
this.operations.DetectEdges(kernel, grayscale, this.rect);
EdgeDetectorProcessor processor = this.Verify<EdgeDetectorProcessor>(this.rect);
Assert.Equal(grayscale, processor.Grayscale);
Assert.Equal(kernel, processor.Kernel);
}
public static TheoryData<EdgeDetectorCompassKernel, bool> EdgeDetectorCompassKernelData =
new TheoryData<EdgeDetectorCompassKernel, bool>
{
{ KnownEdgeDetectorKernels.Kirsch, true },
{ KnownEdgeDetectorKernels.Kirsch, false },
{ KnownEdgeDetectorKernels.Robinson, true },
{ KnownEdgeDetectorKernels.Robinson, false },
};
[Theory]
[MemberData(nameof(EdgeDetectorCompassKernelData))]
public void DetectEdges_EdgeDetectorCompassProcessor_DefaultGrayScale_Set(EdgeDetectorCompassKernel kernel, bool _)
{
this.operations.DetectEdges(kernel);
EdgeDetectorCompassProcessor processor = this.Verify<EdgeDetectorCompassProcessor>();
Assert.True(processor.Grayscale);
Assert.Equal(kernel, processor.Kernel);
}
[Theory]
[MemberData(nameof(EdgeDetectorCompassKernelData))]
public void DetectEdges_Rect_EdgeDetectorCompassProcessor_DefaultGrayScale_Set(EdgeDetectorCompassKernel kernel, bool _)
{
this.operations.DetectEdges(kernel, this.rect);
EdgeDetectorCompassProcessor processor = this.Verify<EdgeDetectorCompassProcessor>(this.rect);
// TODO: Enable once we have updated the images
var processor = this.Verify<TProcessor>();
Assert.True(processor.Grayscale);
Assert.Equal(kernel, processor.Kernel);
}
[Theory]
[MemberData(nameof(EdgeDetectorCompassKernelData))]
public void DetectEdges_EdgeDetectorCompassProcessorSet(EdgeDetectorCompassKernel kernel, bool grayscale)
{
this.operations.DetectEdges(kernel, grayscale);
EdgeDetectorCompassProcessor processor = this.Verify<EdgeDetectorCompassProcessor>();
Assert.Equal(grayscale, processor.Grayscale);
Assert.Equal(kernel, processor.Kernel);
}
[Theory]
[MemberData(nameof(EdgeDetectionTheoryData))]
public void DetectEdges_filter_grayscale_SobelProcessorDefaultsSet<TProcessor>(TestType<TProcessor> type, KnownEdgeDetectionOperators filter)
where TProcessor : EdgeDetectorProcessor
[MemberData(nameof(EdgeDetectorCompassKernelData))]
public void DetectEdges_Rect_EdgeDetectorCompassProcessorSet(EdgeDetectorCompassKernel kernel, bool grayscale)
{
bool grey = (int)filter % 2 == 0;
this.operations.DetectEdges(filter, grey);
this.operations.DetectEdges(kernel, grayscale, this.rect);
EdgeDetectorCompassProcessor processor = this.Verify<EdgeDetectorCompassProcessor>(this.rect);
// TODO: Enable once we have updated the images
var processor = this.Verify<TProcessor>();
Assert.Equal(grey, processor.Grayscale);
Assert.Equal(grayscale, processor.Grayscale);
Assert.Equal(kernel, processor.Kernel);
}
}
}

92
tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs

@ -3,6 +3,7 @@
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Processing.Processors.Convolution;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using Xunit;
@ -20,18 +21,29 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution
public const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.RgbaVector;
public static readonly TheoryData<KnownEdgeDetectionOperators> DetectEdgesFilters = new TheoryData<KnownEdgeDetectionOperators>
public static readonly TheoryData<EdgeDetectorKernel> DetectEdgesFilters
= new TheoryData<EdgeDetectorKernel>
{
KnownEdgeDetectionOperators.Kayyali,
KnownEdgeDetectionOperators.Kirsch,
KnownEdgeDetectionOperators.Laplacian3x3,
KnownEdgeDetectionOperators.Laplacian5x5,
KnownEdgeDetectionOperators.LaplacianOfGaussian,
KnownEdgeDetectionOperators.Prewitt,
KnownEdgeDetectionOperators.RobertsCross,
KnownEdgeDetectionOperators.Robinson,
KnownEdgeDetectionOperators.Scharr,
KnownEdgeDetectionOperators.Sobel
KnownEdgeDetectorKernels.Laplacian3x3,
KnownEdgeDetectorKernels.Laplacian5x5,
KnownEdgeDetectorKernels.LaplacianOfGaussian,
};
public static readonly TheoryData<EdgeDetector2DKernel> DetectEdges2DFilters
= new TheoryData<EdgeDetector2DKernel>
{
KnownEdgeDetectorKernels.Kayyali,
KnownEdgeDetectorKernels.Prewitt,
KnownEdgeDetectorKernels.RobertsCross,
KnownEdgeDetectorKernels.Scharr,
KnownEdgeDetectorKernels.Sobel
};
public static readonly TheoryData<EdgeDetectorCompassKernel> DetectEdgesCompassFilters
= new TheoryData<EdgeDetectorCompassKernel>
{
KnownEdgeDetectorKernels.Kirsch,
KnownEdgeDetectorKernels.Robinson,
};
[Theory]
@ -53,7 +65,39 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution
[Theory]
[WithTestPatternImages(nameof(DetectEdgesFilters), 100, 100, PixelTypes.Rgba32)]
[WithFileCollection(nameof(TestImages), nameof(DetectEdgesFilters), PixelTypes.Rgba32)]
public void DetectEdges_WorksWithAllFilters<TPixel>(TestImageProvider<TPixel> provider, KnownEdgeDetectionOperators detector)
public void DetectEdges_WorksWithAllFilters<TPixel>(TestImageProvider<TPixel> provider, EdgeDetectorKernel detector)
where TPixel : unmanaged, IPixel<TPixel>
{
bool hasAlpha = provider.SourceFileOrDescription.Contains("TestPattern");
ImageComparer comparer = hasAlpha ? TransparentComparer : OpaqueComparer;
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.DetectEdges(detector));
image.DebugSave(provider, detector.ToString());
image.CompareToReferenceOutput(comparer, provider, detector.ToString());
}
}
[Theory]
[WithTestPatternImages(nameof(DetectEdgesFilters), 100, 100, PixelTypes.Rgba32)]
[WithFileCollection(nameof(TestImages), nameof(DetectEdges2DFilters), PixelTypes.Rgba32)]
public void DetectEdges2D_WorksWithAllFilters<TPixel>(TestImageProvider<TPixel> provider, EdgeDetector2DKernel detector)
where TPixel : unmanaged, IPixel<TPixel>
{
bool hasAlpha = provider.SourceFileOrDescription.Contains("TestPattern");
ImageComparer comparer = hasAlpha ? TransparentComparer : OpaqueComparer;
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.DetectEdges(detector));
image.DebugSave(provider, detector.ToString());
image.CompareToReferenceOutput(comparer, provider, detector.ToString());
}
}
[Theory]
[WithTestPatternImages(nameof(DetectEdgesCompassFilters), 100, 100, PixelTypes.Rgba32)]
[WithFileCollection(nameof(TestImages), nameof(DetectEdgesFilters), PixelTypes.Rgba32)]
public void DetectEdgesCompass_WorksWithAllFilters<TPixel>(TestImageProvider<TPixel> provider, EdgeDetectorCompassKernel detector)
where TPixel : unmanaged, IPixel<TPixel>
{
bool hasAlpha = provider.SourceFileOrDescription.Contains("TestPattern");
@ -115,7 +159,29 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution
[Theory]
[WithFile(Tests.TestImages.Png.Bike, nameof(DetectEdgesFilters), PixelTypes.Rgba32)]
public void WorksWithDiscoBuffers<TPixel>(TestImageProvider<TPixel> provider, KnownEdgeDetectionOperators detector)
public void WorksWithDiscoBuffers<TPixel>(TestImageProvider<TPixel> provider, EdgeDetectorKernel detector)
where TPixel : unmanaged, IPixel<TPixel>
{
provider.RunBufferCapacityLimitProcessorTest(
41,
c => c.DetectEdges(detector),
detector);
}
[Theory]
[WithFile(Tests.TestImages.Png.Bike, nameof(DetectEdges2DFilters), PixelTypes.Rgba32)]
public void WorksWithDiscoBuffers2D<TPixel>(TestImageProvider<TPixel> provider, EdgeDetector2DKernel detector)
where TPixel : unmanaged, IPixel<TPixel>
{
provider.RunBufferCapacityLimitProcessorTest(
41,
c => c.DetectEdges(detector),
detector);
}
[Theory]
[WithFile(Tests.TestImages.Png.Bike, nameof(DetectEdgesCompassFilters), PixelTypes.Rgba32)]
public void WorksWithDiscoBuffersCompass<TPixel>(TestImageProvider<TPixel> provider, EdgeDetectorCompassKernel detector)
where TPixel : unmanaged, IPixel<TPixel>
{
provider.RunBufferCapacityLimitProcessorTest(

Loading…
Cancel
Save