Browse Source

Refactor edge detection to streamline API

Former-commit-id: 9e5b8edfb049780f3f8a553f02b2fee20b29f91d
Former-commit-id: 66241f9dd5f8be909f03d8b6435e86f69b3f95d4
Former-commit-id: b34b5df5f557b528d9dcea49e92d93532b984cb6
pull/17/head
James Jackson-South 10 years ago
parent
commit
04b05fb00e
  1. 2
      ImageProcessor.sln.DotSettings
  2. 2
      src/ImageProcessor/Filters/ColorMatrix/IColorMatrixFilter.cs
  3. 2
      src/ImageProcessor/Filters/ColorMatrix/Saturation.cs
  4. 2
      src/ImageProcessor/Filters/Convolution/Convolution2DFilter.cs
  5. 2
      src/ImageProcessor/Filters/Convolution/Convolution2PassFilter.cs
  6. 8
      src/ImageProcessor/Filters/Convolution/ConvolutionFilter.cs
  7. 26
      src/ImageProcessor/Filters/Convolution/EdgeDetection/EdgeDetector2DFilter.cs
  8. 26
      src/ImageProcessor/Filters/Convolution/EdgeDetection/EdgeDetectorFilter.cs
  9. 19
      src/ImageProcessor/Filters/Convolution/EdgeDetection/IEdgeDetectorFilter.cs
  10. 10
      src/ImageProcessor/Filters/Convolution/EdgeDetection/Kayyali.cs
  11. 10
      src/ImageProcessor/Filters/Convolution/EdgeDetection/Kirsch.cs
  12. 8
      src/ImageProcessor/Filters/Convolution/EdgeDetection/Laplacian3X3.cs
  13. 8
      src/ImageProcessor/Filters/Convolution/EdgeDetection/Laplacian5X5.cs
  14. 10
      src/ImageProcessor/Filters/Convolution/EdgeDetection/LaplacianOfGaussian.cs
  15. 13
      src/ImageProcessor/Filters/Convolution/EdgeDetection/Prewitt.cs
  16. 10
      src/ImageProcessor/Filters/Convolution/EdgeDetection/RobertsCross.cs
  17. 10
      src/ImageProcessor/Filters/Convolution/EdgeDetection/Scharr.cs
  18. 10
      src/ImageProcessor/Filters/Convolution/EdgeDetection/Sobel.cs
  19. 2
      src/ImageProcessor/Filters/Convolution/GuassianBlur.cs
  20. 2
      src/ImageProcessor/Filters/Convolution/GuassianSharpen.cs
  21. 36
      src/ImageProcessor/Filters/ImageFilterExtensions.cs
  22. 2
      src/ImageProcessor/Formats/Gif/Quantizer/OctreeQuantizer.cs
  23. 3
      src/ImageProcessor/ImageProcessor.csproj
  24. 7
      src/ImageProcessor/ParallelImageProcessor.cs
  25. 2
      src/ImageProcessor/Samplers/Resize.cs
  26. 2
      tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs

2
ImageProcessor.sln.DotSettings

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=XY/@EntryIndexedValue">XY</s:String></wpf:ResourceDictionary>

2
src/ImageProcessor/Filters/ColorMatrix/IColorMatrixFilter.cs

@ -11,7 +11,7 @@ namespace ImageProcessor.Filters
/// Encapsulates properties and methods for creating processors that utilize a matrix to
/// alter the image pixels.
/// </summary>
public interface IColorMatrixFilter
public interface IColorMatrixFilter : IImageProcessor
{
/// <summary>
/// Gets the <see cref="Matrix4x4"/> used to alter the image.

2
src/ImageProcessor/Filters/ColorMatrix/Saturation.cs

@ -40,7 +40,7 @@ namespace ImageProcessor.Filters
public override Matrix4x4 Matrix => this.matrix;
/// <inheritdoc/>
protected override void OnApply(Rectangle targetRectangle, Rectangle sourceRectangle)
protected override void OnApply(ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle)
{
float saturationFactor = this.saturation / 100f;

2
src/ImageProcessor/Filters/Convolution/Convolution2DFilter.cs

@ -9,7 +9,7 @@ namespace ImageProcessor.Filters
using System.Threading.Tasks;
/// <summary>
/// Defines a filter that uses a matrix to perform convolution across two dimensions against an image.
/// Defines a filter that uses two one-dimensional matrices to perform convolution against an image.
/// </summary>
public abstract class Convolution2DFilter : ParallelImageProcessor
{

2
src/ImageProcessor/Filters/Convolution/Convolution2PassFilter.cs

@ -8,7 +8,7 @@ namespace ImageProcessor.Filters
using System.Threading.Tasks;
/// <summary>
/// Defines a filter that uses a matrix to perform convolution across two dimensions against an image.
/// Defines a filter that uses two one-dimensional matrices to perform two-pass convolution against an image.
/// </summary>
public abstract class Convolution2PassFilter : ParallelImageProcessor
{

8
src/ImageProcessor/Filters/Convolution/ConvolutionFilter.cs

@ -8,19 +8,19 @@ namespace ImageProcessor.Filters
using System.Threading.Tasks;
/// <summary>
/// Defines a filter that uses a matrix to perform convolution across a single dimension against an image.
/// Defines a filter that uses a 2 dimensional matrix to perform convolution against an image.
/// </summary>
public abstract class ConvolutionFilter : ParallelImageProcessor
{
/// <summary>
/// Gets the horizontal gradient operator.
/// Gets the 2d gradient operator.
/// </summary>
public abstract float[,] KernelX { get; }
public abstract float[,] KernelXY { get; }
/// <inheritdoc/>
protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
{
float[,] kernelX = this.KernelX;
float[,] kernelX = this.KernelXY;
int kernelLength = kernelX.GetLength(0);
int radius = kernelLength >> 1;

26
src/ImageProcessor/Filters/Convolution/EdgeDetection/EdgeDetector2DFilter.cs

@ -0,0 +1,26 @@
// <copyright file="EdgeDetector2DFilter.cs" company="James South">
// Copyright (c) James South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageProcessor.Filters
{
/// <summary>
/// Defines a filter that detects edges within an image using two
/// one-dimensional matrices.
/// </summary>
public abstract class EdgeDetector2DFilter : Convolution2DFilter, IEdgeDetectorFilter
{
/// <inheritdoc/>
public bool Greyscale { get; set; }
/// <inheritdoc/>
protected override void OnApply(ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle)
{
if (this.Greyscale)
{
new GreyscaleBt709().Apply(source, source, sourceRectangle);
}
}
}
}

26
src/ImageProcessor/Filters/Convolution/EdgeDetection/EdgeDetectorFilter.cs

@ -0,0 +1,26 @@
// <copyright file="EdgeDetectorFilter.cs" company="James South">
// Copyright (c) James South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageProcessor.Filters
{
/// <summary>
/// Defines a filter that detects edges within an image using a single
/// two dimensional matrix.
/// </summary>
public abstract class EdgeDetectorFilter : ConvolutionFilter, IEdgeDetectorFilter
{
/// <inheritdoc/>
public bool Greyscale { get; set; }
/// <inheritdoc/>
protected override void OnApply(ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle)
{
if (this.Greyscale)
{
new GreyscaleBt709().Apply(source, source, sourceRectangle);
}
}
}
}

19
src/ImageProcessor/Filters/Convolution/EdgeDetection/IEdgeDetectorFilter.cs

@ -0,0 +1,19 @@
// <copyright file="IEdgeDetectorFilter.cs" company="James South">
// Copyright (c) James South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageProcessor.Filters
{
/// <summary>
/// Provides properties and methods allowing the detection of edges within an image.
/// </summary>
public interface IEdgeDetectorFilter : IImageProcessor
{
/// <summary>
/// Gets or sets a value indicating whether to convert the
/// image to greyscale before performing edge detection.
/// </summary>
bool Greyscale { get; set; }
}
}

10
src/ImageProcessor/Filters/Convolution/EdgeDetection/Kayyali.cs

@ -9,11 +9,9 @@ namespace ImageProcessor.Filters
/// The Kayyali operator filter.
/// <see href="http://edgedetection.webs.com/"/>
/// </summary>
public class Kayyali : Convolution2DFilter
public class Kayyali : EdgeDetector2DFilter
{
/// <summary>
/// Gets the horizontal gradient operator.
/// </summary>
/// <inheritdoc/>
public override float[,] KernelX => new float[,]
{
{ 6, 0, -6 },
@ -21,9 +19,7 @@ namespace ImageProcessor.Filters
{ -6, 0, 6 }
};
/// <summary>
/// Gets the vertical gradient operator.
/// </summary>
/// <inheritdoc/>
public override float[,] KernelY => new float[,]
{
{ -6, 0, 6 },

10
src/ImageProcessor/Filters/Convolution/EdgeDetection/Kirsch.cs

@ -9,11 +9,9 @@ namespace ImageProcessor.Filters
/// The Kirsch operator filter.
/// <see href="http://en.wikipedia.org/wiki/Kirsch_operator"/>
/// </summary>
public class Kirsch : Convolution2DFilter
public class Kirsch : EdgeDetector2DFilter
{
/// <summary>
/// Gets the horizontal gradient operator.
/// </summary>
/// <inheritdoc/>
public override float[,] KernelX => new float[,]
{
{ 5, 5, 5 },
@ -21,9 +19,7 @@ namespace ImageProcessor.Filters
{ -3, -3, -3 }
};
/// <summary>
/// Gets the vertical gradient operator.
/// </summary>
/// <inheritdoc/>
public override float[,] KernelY => new float[,]
{
{ 5, -3, -3 },

8
src/ImageProcessor/Filters/Convolution/EdgeDetection/Laplacian3X3.cs

@ -9,12 +9,10 @@ namespace ImageProcessor.Filters
/// The Laplacian 3 x 3 operator filter.
/// <see href="http://en.wikipedia.org/wiki/Discrete_Laplace_operator"/>
/// </summary>
public class Laplacian3X3 : ConvolutionFilter
public class Laplacian3X3 : EdgeDetectorFilter
{
/// <summary>
/// Gets the horizontal gradient operator.
/// </summary>
public override float[,] KernelX => new float[,]
/// <inheritdoc/>
public override float[,] KernelXY => new float[,]
{
{ -1, -1, -1 },
{ -1, 8, -1 },

8
src/ImageProcessor/Filters/Convolution/EdgeDetection/Laplacian5X5.cs

@ -9,12 +9,10 @@ namespace ImageProcessor.Filters
/// The Laplacian 5 x 5 operator filter.
/// <see href="http://en.wikipedia.org/wiki/Discrete_Laplace_operator"/>
/// </summary>
public class Laplacian5X5 : ConvolutionFilter
public class Laplacian5X5 : EdgeDetectorFilter
{
/// <summary>
/// Gets the horizontal gradient operator.
/// </summary>
public override float[,] KernelX => new float[,]
/// <inheritdoc/>
public override float[,] KernelXY => new float[,]
{
{ -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1 },

10
src/ImageProcessor/Filters/Convolution/EdgeDetection/LaplacianOfGaussian.cs

@ -7,14 +7,12 @@ namespace ImageProcessor.Filters
{
/// <summary>
/// The Laplacian of Gaussian operator filter.
/// <see href="http://fourier.eng.hmc.edu/e161/lectures/gradient/node9.html"/>
/// <see href="http://fourier.eng.hmc.edu/e161/lectures/gradient/node8.html"/>
/// </summary>
public class LaplacianOfGaussian : ConvolutionFilter
public class LaplacianOfGaussian : EdgeDetectorFilter
{
/// <summary>
/// Gets the horizontal gradient operator.
/// </summary>
public override float[,] KernelX => new float[,]
/// <inheritdoc/>
public override float[,] KernelXY => new float[,]
{
{ 0, 0, -1, 0, 0 },
{ 0, -1, -2, -1, 0 },

13
src/ImageProcessor/Filters/Convolution/EdgeDetection/Prewitt.cs

@ -9,11 +9,9 @@ namespace ImageProcessor.Filters
/// The Prewitt operator filter.
/// <see href="http://en.wikipedia.org/wiki/Prewitt_operator"/>
/// </summary>
public class Prewitt : Convolution2DFilter
public class Prewitt : EdgeDetector2DFilter
{
/// <summary>
/// Gets the horizontal gradient operator.
/// </summary>
/// <inheritdoc/>
public override float[,] KernelX => new float[,]
{
{ -1, 0, 1 },
@ -21,14 +19,15 @@ namespace ImageProcessor.Filters
{ -1, 0, 1 }
};
/// <summary>
/// Gets the vertical gradient operator.
/// </summary>
/// <inheritdoc/>
public override float[,] KernelY => new float[,]
{
{ 1, 1, 1 },
{ 0, 0, 0 },
{ -1, -1, -1 }
};
/// <inheritdoc/>
public bool Greyscale { get; set; }
}
}

10
src/ImageProcessor/Filters/Convolution/EdgeDetection/RobertsCross.cs

@ -9,20 +9,16 @@ namespace ImageProcessor.Filters
/// The Roberts Cross operator filter.
/// <see href="http://en.wikipedia.org/wiki/Roberts_cross"/>
/// </summary>
public class RobertsCross : Convolution2DFilter
public class RobertsCross : EdgeDetector2DFilter
{
/// <summary>
/// Gets the horizontal gradient operator.
/// </summary>
/// <inheritdoc/>
public override float[,] KernelX => new float[,]
{
{ 1, 0 },
{ 0, -1 }
};
/// <summary>
/// Gets the vertical gradient operator.
/// </summary>
/// <inheritdoc/>
public override float[,] KernelY => new float[,]
{
{ 0, 1 },

10
src/ImageProcessor/Filters/Convolution/EdgeDetection/Scharr.cs

@ -9,11 +9,9 @@ namespace ImageProcessor.Filters
/// The Scharr operator filter.
/// <see href="http://en.wikipedia.org/wiki/Sobel_operator#Alternative_operators"/>
/// </summary>
public class Scharr : Convolution2DFilter
public class Scharr : EdgeDetector2DFilter
{
/// <summary>
/// Gets the horizontal gradient operator.
/// </summary>
/// <inheritdoc/>
public override float[,] KernelX => new float[,]
{
{ -3, 0, 3 },
@ -21,9 +19,7 @@ namespace ImageProcessor.Filters
{ -3, 0, 3 }
};
/// <summary>
/// Gets the vertical gradient operator.
/// </summary>
/// <inheritdoc/>
public override float[,] KernelY => new float[,]
{
{ 3, 10, 3 },

10
src/ImageProcessor/Filters/Convolution/EdgeDetection/Sobel.cs

@ -9,11 +9,9 @@ namespace ImageProcessor.Filters
/// The Sobel operator filter.
/// <see href="http://en.wikipedia.org/wiki/Sobel_operator"/>
/// </summary>
public class Sobel : Convolution2DFilter
public class Sobel : EdgeDetector2DFilter
{
/// <summary>
/// Gets the horizontal gradient operator.
/// </summary>
/// <inheritdoc/>
public override float[,] KernelX => new float[,]
{
{ -1, 0, 1 },
@ -21,9 +19,7 @@ namespace ImageProcessor.Filters
{ -1, 0, 1 }
};
/// <summary>
/// Gets the vertical gradient operator.
/// </summary>
/// <inheritdoc/>
public override float[,] KernelY => new float[,]
{
{ 1, 2, 1 },

2
src/ImageProcessor/Filters/Convolution/GuassianBlur.cs

@ -82,7 +82,7 @@ namespace ImageProcessor.Filters
public override int Parallelism => 1;
/// <inheritdoc/>
protected override void OnApply(Rectangle targetRectangle, Rectangle sourceRectangle)
protected override void OnApply(ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle)
{
if (this.kernelY == null)
{

2
src/ImageProcessor/Filters/Convolution/GuassianSharpen.cs

@ -82,7 +82,7 @@ namespace ImageProcessor.Filters
public override int Parallelism => 1;
/// <inheritdoc/>
protected override void OnApply(Rectangle targetRectangle, Rectangle sourceRectangle)
protected override void OnApply(ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle)
{
if (this.kernelY == null)
{

36
src/ImageProcessor/Filters/ImageFilterExtensions.cs

@ -135,6 +135,42 @@ namespace ImageProcessor.Filters
return source.Process(rectangle, new Contrast(amount));
}
/// <summary>
/// Detects any edges within the image. Uses the <see cref="Sobel"/> filter
/// operating in greyscale mode.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <returns>The <see cref="Image"/>.</returns>
public static Image DetectEdges(this Image source)
{
return DetectEdges(source, source.Bounds, new Sobel { Greyscale = true });
}
/// <summary>
/// Detects any edges within the image.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="filter">The filter for detecting edges.</param>
/// <returns>The <see cref="Image"/>.</returns>
public static Image DetectEdges(this Image source, IEdgeDetectorFilter filter)
{
return DetectEdges(source, source.Bounds, filter);
}
/// <summary>
/// Detects any edges within the image.
/// </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>
/// <param name="filter">The filter for detecting edges.</param>
/// <returns>The <see cref="Image"/>.</returns>
public static Image DetectEdges(this Image source, Rectangle rectangle, IEdgeDetectorFilter filter)
{
return source.Process(rectangle, filter);
}
/// <summary>
/// Applies greyscale toning to the image.
/// </summary>

2
src/ImageProcessor/Formats/Gif/Quantizer/OctreeQuantizer.cs

@ -8,8 +8,6 @@ namespace ImageProcessor.Formats
using System;
using System.Collections.Generic;
using ImageProcessor.Common.Extensions;
/// <summary>
/// Encapsulates methods to calculate the colour palette if an image using an Octree pattern.
/// <see href="http://msdn.microsoft.com/en-us/library/aa479306.aspx"/>

3
src/ImageProcessor/ImageProcessor.csproj

@ -57,6 +57,9 @@
<Compile Include="Filters\ColorMatrix\Saturation.cs" />
<Compile Include="Filters\ColorMatrix\GreyscaleMode.cs" />
<Compile Include="Filters\Brightness.cs" />
<Compile Include="Filters\Convolution\EdgeDetection\EdgeDetector2DFilter.cs" />
<Compile Include="Filters\Convolution\EdgeDetection\EdgeDetectorFilter.cs" />
<Compile Include="Filters\Convolution\EdgeDetection\IEdgeDetectorFilter.cs" />
<Compile Include="Filters\Convolution\EdgeDetection\Scharr.cs" />
<Compile Include="Filters\Convolution\EdgeDetection\RobertsCross.cs" />
<Compile Include="Filters\Convolution\EdgeDetection\Prewitt.cs" />

7
src/ImageProcessor/ParallelImageProcessor.cs

@ -21,7 +21,7 @@ namespace ImageProcessor
/// <inheritdoc/>
public void Apply(ImageBase target, ImageBase source, Rectangle sourceRectangle)
{
this.OnApply(target.Bounds, sourceRectangle);
this.OnApply(source, target.Bounds, sourceRectangle);
if (this.Parallelism > 1)
{
@ -66,7 +66,7 @@ namespace ImageProcessor
sourceRectangle = source.Bounds;
}
this.OnApply(target.Bounds, sourceRectangle);
this.OnApply(source, target.Bounds, sourceRectangle);
if (this.Parallelism > 1)
{
@ -98,6 +98,7 @@ namespace ImageProcessor
/// <summary>
/// This method is called before the process is applied to prepare the processor.
/// </summary>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="targetRectangle">
/// The <see cref="Rectangle"/> structure that specifies the location and size of the drawn image.
/// The image is scaled to fit the rectangle.
@ -105,7 +106,7 @@ namespace ImageProcessor
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
protected virtual void OnApply(Rectangle targetRectangle, Rectangle sourceRectangle)
protected virtual void OnApply(ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle)
{
}

2
src/ImageProcessor/Samplers/Resize.cs

@ -48,7 +48,7 @@ namespace ImageProcessor.Samplers
public IResampler Sampler { get; }
/// <inheritdoc/>
protected override void OnApply(Rectangle targetRectangle, Rectangle sourceRectangle)
protected override void OnApply(ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle)
{
this.horizontalWeights = this.PrecomputeWeights(targetRectangle.Width, sourceRectangle.Width);
this.verticalWeights = this.PrecomputeWeights(targetRectangle.Height, sourceRectangle.Height);

2
tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs

@ -37,7 +37,7 @@ namespace ImageProcessor.Tests
{ "Prewitt", new Prewitt() },
{ "RobertsCross", new RobertsCross() },
{ "Scharr", new Scharr() },
{ "Sobel", new Sobel() },
{ "Sobel", new Sobel {Greyscale = true} },
{ "GuassianBlur", new GuassianBlur(10) },
{ "GuassianSharpen", new GuassianSharpen(10) }
};

Loading…
Cancel
Save