Browse Source

Use Jagged array for other edge detection filters.

Former-commit-id: 01b45cf5bc15f50c9e56d9e9ede8459ddda590cc
Former-commit-id: a8dee96f99b651b0513be43d1812c043818a3148
Former-commit-id: 1c4a5a0430cce0695d87fef840d82f637b72e391
af/merge-core
James Jackson-South 10 years ago
parent
commit
41249090d8
  1. 13
      Settings.StyleCop
  2. 20
      src/ImageProcessorCore/Samplers/Processors/Convolution/Convolution2DFilter.cs
  3. 12
      src/ImageProcessorCore/Samplers/Processors/Convolution/ConvolutionFilter.cs
  4. 18
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/EdgeDetectorCompassFilter.cs
  5. 2
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/EdgeDetectorFilter.cs
  6. 17
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/KayyaliProcessor.cs
  7. 124
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/KirschProcessor.cs
  8. 18
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/Laplacian3X3Processor.cs
  9. 22
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/Laplacian5X5Processor.cs
  10. 22
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/LaplacianOfGaussianProcessor.cs
  11. 17
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/PrewittProcessor.cs
  12. 17
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/RobertsCrossProcessor.cs
  13. 124
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/RobinsonProcessor.cs
  14. 17
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/ScharrProcessor.cs
  15. 17
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/SobelProcessor.cs

13
Settings.StyleCop

@ -1,5 +1,5 @@
<StyleCopSettings Version="105"> <StyleCopSettings Version="105">
<GlobalSettings> <GlobalSettings>
<CollectionProperty Name="RecognizedWords"> <CollectionProperty Name="RecognizedWords">
<Value>enum</Value> <Value>enum</Value>
<Value>exif</Value> <Value>exif</Value>
@ -11,14 +11,21 @@
<Value>unzig</Value> <Value>unzig</Value>
<Value>cb</Value> <Value>cb</Value>
<Value>cr</Value> <Value>cr</Value>
<Value>Laplacian</Value>
<Value>Sobel</Value>
<Value>Scharr</Value>
<Value>rrggbb</Value>
<Value>rrggbbaa</Value>
</CollectionProperty> </CollectionProperty>
</GlobalSettings> </GlobalSettings>
<Analyzers> <Analyzers>
<Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules"> <Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules">
<AnalyzerSettings> <AnalyzerSettings>
<StringProperty Name="CompanyName">James Jackson-South</StringProperty> <StringProperty Name="CompanyName">James Jackson-South</StringProperty>
<StringProperty Name="Copyright">Copyright © James Jackson-South and contributors. <StringProperty Name="Copyright">
Licensed under the Apache License, Version 2.0.</StringProperty> Copyright © James Jackson-South and contributors.
Licensed under the Apache License, Version 2.0.
</StringProperty>
</AnalyzerSettings> </AnalyzerSettings>
</Analyzer> </Analyzer>
</Analyzers> </Analyzers>

20
src/ImageProcessorCore/Samplers/Processors/Convolution/Convolution2DFilter.cs

@ -42,10 +42,10 @@ namespace ImageProcessorCore.Processors
/// <inheritdoc/> /// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
{ {
int kernelYHeight = KernelY.Length; int kernelYHeight = this.KernelY.Length;
int kernelYWidth = KernelY[0].Length; int kernelYWidth = this.KernelY[0].Length;
int kernelXHeight = KernelX.Length; int kernelXHeight = this.KernelX.Length;
int kernelXWidth = KernelX[0].Length; int kernelXWidth = this.KernelX[0].Length;
int radiusY = kernelYHeight >> 1; int radiusY = kernelYHeight >> 1;
int radiusX = kernelXWidth >> 1; int radiusX = kernelXWidth >> 1;
@ -98,16 +98,16 @@ namespace ImageProcessorCore.Processors
if (fy < kernelXHeight) if (fy < kernelXHeight)
{ {
rX += KernelX[fy][fx] * r; rX += this.KernelX[fy][fx] * r;
gX += KernelX[fy][fx] * g; gX += this.KernelX[fy][fx] * g;
bX += KernelX[fy][fx] * b; bX += this.KernelX[fy][fx] * b;
} }
if (fx < kernelYWidth) if (fx < kernelYWidth)
{ {
rY += KernelY[fy][fx] * r; rY += this.KernelY[fy][fx] * r;
gY += KernelY[fy][fx] * g; gY += this.KernelY[fy][fx] * g;
bY += KernelY[fy][fx] * b; bY += this.KernelY[fy][fx] * b;
} }
} }
} }

12
src/ImageProcessorCore/Samplers/Processors/Convolution/ConvolutionFilter.cs

@ -21,7 +21,7 @@ namespace ImageProcessorCore.Processors
/// Initializes a new instance of the <see cref="ConvolutionFilter{TColor,TPacked}"/> class. /// Initializes a new instance of the <see cref="ConvolutionFilter{TColor,TPacked}"/> class.
/// </summary> /// </summary>
/// <param name="kernelXY">The 2d gradient operator.</param> /// <param name="kernelXY">The 2d gradient operator.</param>
public ConvolutionFilter(float[,] kernelXY) public ConvolutionFilter(float[][] kernelXY)
{ {
this.KernelXY = kernelXY; this.KernelXY = kernelXY;
} }
@ -29,12 +29,12 @@ namespace ImageProcessorCore.Processors
/// <summary> /// <summary>
/// Gets the 2d gradient operator. /// Gets the 2d gradient operator.
/// </summary> /// </summary>
public virtual float[,] KernelXY { get; } public virtual float[][] KernelXY { get; }
/// <inheritdoc/> /// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
{ {
float[,] kernelX = this.KernelXY; float[][] kernelX = this.KernelXY;
int kernelLength = kernelX.GetLength(0); int kernelLength = kernelX.GetLength(0);
int radius = kernelLength >> 1; int radius = kernelLength >> 1;
@ -82,9 +82,9 @@ namespace ImageProcessorCore.Processors
float g = currentColor.Y; float g = currentColor.Y;
float b = currentColor.Z; float b = currentColor.Z;
rX += kernelX[fy, fx] * r; rX += kernelX[fy][fx] * r;
gX += kernelX[fy, fx] * g; gX += kernelX[fy][fx] * g;
bX += kernelX[fy, fx] * b; bX += kernelX[fy][fx] * b;
} }
} }

18
src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/EdgeDetectorCompassFilter.cs

@ -21,42 +21,42 @@ namespace ImageProcessorCore.Processors
/// <summary> /// <summary>
/// Gets the North gradient operator /// Gets the North gradient operator
/// </summary> /// </summary>
public abstract float[,] North { get; } public abstract float[][] North { get; }
/// <summary> /// <summary>
/// Gets the NorthWest gradient operator /// Gets the NorthWest gradient operator
/// </summary> /// </summary>
public abstract float[,] NorthWest { get; } public abstract float[][] NorthWest { get; }
/// <summary> /// <summary>
/// Gets the West gradient operator /// Gets the West gradient operator
/// </summary> /// </summary>
public abstract float[,] West { get; } public abstract float[][] West { get; }
/// <summary> /// <summary>
/// Gets the SouthWest gradient operator /// Gets the SouthWest gradient operator
/// </summary> /// </summary>
public abstract float[,] SouthWest { get; } public abstract float[][] SouthWest { get; }
/// <summary> /// <summary>
/// Gets the South gradient operator /// Gets the South gradient operator
/// </summary> /// </summary>
public abstract float[,] South { get; } public abstract float[][] South { get; }
/// <summary> /// <summary>
/// Gets the SouthEast gradient operator /// Gets the SouthEast gradient operator
/// </summary> /// </summary>
public abstract float[,] SouthEast { get; } public abstract float[][] SouthEast { get; }
/// <summary> /// <summary>
/// Gets the East gradient operator /// Gets the East gradient operator
/// </summary> /// </summary>
public abstract float[,] East { get; } public abstract float[][] East { get; }
/// <summary> /// <summary>
/// Gets the NorthEast gradient operator /// Gets the NorthEast gradient operator
/// </summary> /// </summary>
public abstract float[,] NorthEast { get; } public abstract float[][] NorthEast { get; }
/// <inheritdoc/> /// <inheritdoc/>
public bool Grayscale { get; set; } public bool Grayscale { get; set; }
@ -64,7 +64,7 @@ namespace ImageProcessorCore.Processors
/// <inheritdoc /> /// <inheritdoc />
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
{ {
float[][,] kernels = { this.North, this.NorthWest, this.West, this.SouthWest, this.South, this.SouthEast, this.East, this.NorthEast }; float[][][] kernels = { this.North, this.NorthWest, this.West, this.SouthWest, this.South, this.SouthEast, this.East, this.NorthEast };
int startX = sourceRectangle.X; int startX = sourceRectangle.X;
int endX = sourceRectangle.Right; int endX = sourceRectangle.Right;

2
src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/EdgeDetectorFilter.cs

@ -20,7 +20,7 @@ namespace ImageProcessorCore.Processors
/// <summary> /// <summary>
/// Gets the 2d gradient operator. /// Gets the 2d gradient operator.
/// </summary> /// </summary>
public abstract float[,] KernelXY { get; } public abstract float[][] KernelXY { get; }
/// <inheritdoc/> /// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)

17
src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/KayyaliProcessor.cs

@ -5,24 +5,33 @@
namespace ImageProcessorCore.Processors namespace ImageProcessorCore.Processors
{ {
using System.Diagnostics.CodeAnalysis;
/// <summary> /// <summary>
/// The Kayyali operator filter. /// The Kayyali operator filter.
/// <see href="http://edgedetection.webs.com/"/> /// <see href="http://edgedetection.webs.com/"/>
/// </summary> /// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam> /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
[SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")]
public class KayyaliProcessor<TColor, TPacked> : EdgeDetector2DFilter<TColor, TPacked> public class KayyaliProcessor<TColor, TPacked> : EdgeDetector2DFilter<TColor, TPacked>
where TColor : IPackedVector<TPacked> where TColor : IPackedVector<TPacked>
where TPacked : struct where TPacked : struct
{ {
private static readonly float[][] kernelX = new float[3][] /// <summary>
/// The horizontal gradient operator.
/// </summary>
private static readonly float[][] KayyaliX =
{ {
new float[] { 6, 0, -6 }, new float[] { 6, 0, -6 },
new float[] { 0, 0, 0 }, new float[] { 0, 0, 0 },
new float[] { -6, 0, 6 } new float[] { -6, 0, 6 }
}; };
private static readonly float[][] kernelY = new float[3][] /// <summary>
/// The vertical gradient operator.
/// </summary>
private static readonly float[][] KayyaliY =
{ {
new float[] { -6, 0, 6 }, new float[] { -6, 0, 6 },
new float[] { 0, 0, 0 }, new float[] { 0, 0, 0 },
@ -30,9 +39,9 @@ namespace ImageProcessorCore.Processors
}; };
/// <inheritdoc/> /// <inheritdoc/>
public override float[][] KernelX => kernelX; public override float[][] KernelX => KayyaliX;
/// <inheritdoc/> /// <inheritdoc/>
public override float[][] KernelY => kernelY; public override float[][] KernelY => KayyaliY;
} }
} }

124
src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/KirschProcessor.cs

@ -2,81 +2,123 @@
// Copyright (c) James Jackson-South and contributors. // Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
// </copyright> // </copyright>
namespace ImageProcessorCore.Processors namespace ImageProcessorCore.Processors
{ {
using System.Diagnostics.CodeAnalysis;
/// <summary> /// <summary>
/// The Kirsch operator filter. /// The Kirsch operator filter.
/// <see href="http://en.wikipedia.org/wiki/Kirsch_operator"/> /// <see href="http://en.wikipedia.org/wiki/Kirsch_operator"/>
/// </summary> /// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam> /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
[SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")]
public class KirschProcessor<TColor, TPacked> : EdgeDetectorCompassFilter<TColor, TPacked> public class KirschProcessor<TColor, TPacked> : EdgeDetectorCompassFilter<TColor, TPacked>
where TColor : IPackedVector<TPacked> where TColor : IPackedVector<TPacked>
where TPacked : struct where TPacked : struct
{ {
/// <inheritdoc/> /// <summary>
public override float[,] North => new float[,] /// The North gradient operator
/// </summary>
private static readonly float[][] KirschNorth =
{ {
{ 5, 5, 5 }, new float[] { 5, 5, 5 },
{ -3, 0, -3 }, new float[] { -3, 0, -3 },
{ -3, -3, -3 } new float[] { -3, -3, -3 }
}; };
/// <inheritdoc/> /// <summary>
public override float[,] NorthWest => new float[,] /// The NorthWest gradient operator
/// </summary>
private static readonly float[][] KirschNorthWest =
{ {
{ 5, 5, -3 }, new float[] { 5, 5, -3 },
{ 5, 0, -3 }, new float[] { 5, 0, -3 },
{ -3, -3, -3 } new float[] { -3, -3, -3 }
}; };
/// <inheritdoc/> /// <summary>
public override float[,] West => new float[,] /// The West gradient operator
/// </summary>
private static readonly float[][] KirschWest =
{ {
{ 5, -3, -3 }, new float[] { 5, -3, -3 },
{ 5, 0, -3 }, new float[] { 5, 0, -3 },
{ 5, -3, -3 } new float[] { 5, -3, -3 }
}; };
/// <inheritdoc/> /// <summary>
public override float[,] SouthWest => new float[,] /// The SouthWest gradient operator
/// </summary>
private static readonly float[][] KirschSouthWest =
{ {
{ -3, -3, -3 }, new float[] { -3, -3, -3 },
{ 5, 0, -3 }, new float[] { 5, 0, -3 },
{ 5, 5, -3 } new float[] { 5, 5, -3 }
}; };
/// <inheritdoc/> /// <summary>
public override float[,] South => new float[,] /// The South gradient operator
/// </summary>
private static readonly float[][] KirschSouth =
{ {
{ -3, -3, -3 }, new float[] { -3, -3, -3 },
{ -3, 0, -3 }, new float[] { -3, 0, -3 },
{ 5, 5, 5 } new float[] { 5, 5, 5 }
}; };
/// <inheritdoc/> /// <summary>
public override float[,] SouthEast => new float[,] /// The SouthEast gradient operator
/// </summary>
private static readonly float[][] KirschSouthEast =
{ {
{ -3, -3, -3 }, new float[] { -3, -3, -3 },
{ -3, 0, 5 }, new float[] { -3, 0, 5 },
{ -3, 5, 5 } new float[] { -3, 5, 5 }
}; };
/// <inheritdoc/> /// <summary>
public override float[,] East => new float[,] /// The East gradient operator
/// </summary>
private static readonly float[][] KirschEast =
{ {
{ -3, -3, 5 }, new float[] { -3, -3, 5 },
{ -3, 0, 5 }, new float[] { -3, 0, 5 },
{ -3, -3, 5 } new float[] { -3, -3, 5 }
}; };
/// <inheritdoc/> /// <summary>
public override float[,] NorthEast => new float[,] /// The NorthEast gradient operator
/// </summary>
private static readonly float[][] KirschNorthEast =
{ {
{ -3, 5, 5 }, new float[] { -3, 5, 5 },
{ -3, 0, 5 }, new float[] { -3, 0, 5 },
{ -3, -3, -3 } new float[] { -3, -3, -3 }
}; };
/// <inheritdoc/>
public override float[][] North => KirschNorth;
/// <inheritdoc/>
public override float[][] NorthWest => KirschNorthWest;
/// <inheritdoc/>
public override float[][] West => KirschWest;
/// <inheritdoc/>
public override float[][] SouthWest => KirschSouthWest;
/// <inheritdoc/>
public override float[][] South => KirschSouth;
/// <inheritdoc/>
public override float[][] SouthEast => KirschSouthEast;
/// <inheritdoc/>
public override float[][] East => KirschEast;
/// <inheritdoc/>
public override float[][] NorthEast => KirschNorthEast;
} }
} }

18
src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/Laplacian3X3Processor.cs

@ -5,22 +5,30 @@
namespace ImageProcessorCore.Processors namespace ImageProcessorCore.Processors
{ {
using System.Diagnostics.CodeAnalysis;
/// <summary> /// <summary>
/// The Laplacian 3 x 3 operator filter. /// The Laplacian 3 x 3 operator filter.
/// <see href="http://en.wikipedia.org/wiki/Discrete_Laplace_operator"/> /// <see href="http://en.wikipedia.org/wiki/Discrete_Laplace_operator"/>
/// </summary> /// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam> /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
[SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")]
public class Laplacian3X3Processor<TColor, TPacked> : EdgeDetectorFilter<TColor, TPacked> public class Laplacian3X3Processor<TColor, TPacked> : EdgeDetectorFilter<TColor, TPacked>
where TColor : IPackedVector<TPacked> where TColor : IPackedVector<TPacked>
where TPacked : struct where TPacked : struct
{ {
/// <inheritdoc/> /// <summary>
public override float[,] KernelXY => new float[,] /// The 2d gradient operator.
/// </summary>
private static readonly float[][] Laplacian3X3XY = new float[][]
{ {
{ -1, -1, -1 }, new float[] { -1, -1, -1 },
{ -1, 8, -1 }, new float[] { -1, 8, -1 },
{ -1, -1, -1 } new float[] { -1, -1, -1 }
}; };
/// <inheritdoc/>
public override float[][] KernelXY => Laplacian3X3XY;
} }
} }

22
src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/Laplacian5X5Processor.cs

@ -5,24 +5,32 @@
namespace ImageProcessorCore.Processors namespace ImageProcessorCore.Processors
{ {
using System.Diagnostics.CodeAnalysis;
/// <summary> /// <summary>
/// The Laplacian 5 x 5 operator filter. /// The Laplacian 5 x 5 operator filter.
/// <see href="http://en.wikipedia.org/wiki/Discrete_Laplace_operator"/> /// <see href="http://en.wikipedia.org/wiki/Discrete_Laplace_operator"/>
/// </summary> /// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam> /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
[SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")]
public class Laplacian5X5Processor<TColor, TPacked> : EdgeDetectorFilter<TColor, TPacked> public class Laplacian5X5Processor<TColor, TPacked> : EdgeDetectorFilter<TColor, TPacked>
where TColor : IPackedVector<TPacked> where TColor : IPackedVector<TPacked>
where TPacked : struct where TPacked : struct
{ {
/// <inheritdoc/> /// <summary>
public override float[,] KernelXY => new float[,] /// The 2d gradient operator.
/// </summary>
private static readonly float[][] Laplacian5X5XY =
{ {
{ -1, -1, -1, -1, -1 }, new float[] { -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1 }, new float[] { -1, -1, -1, -1, -1 },
{ -1, -1, 24, -1, -1 }, new float[] { -1, -1, 24, -1, -1 },
{ -1, -1, -1, -1, -1 }, new float[] { -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1 } new float[] { -1, -1, -1, -1, -1 }
}; };
/// <inheritdoc/>
public override float[][] KernelXY => Laplacian5X5XY;
} }
} }

22
src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/LaplacianOfGaussianProcessor.cs

@ -5,24 +5,32 @@
namespace ImageProcessorCore.Processors namespace ImageProcessorCore.Processors
{ {
using System.Diagnostics.CodeAnalysis;
/// <summary> /// <summary>
/// The Laplacian of Gaussian operator filter. /// The Laplacian of Gaussian operator filter.
/// <see href="http://fourier.eng.hmc.edu/e161/lectures/gradient/node8.html"/> /// <see href="http://fourier.eng.hmc.edu/e161/lectures/gradient/node8.html"/>
/// </summary> /// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam> /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
[SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")]
public class LaplacianOfGaussianProcessor<TColor, TPacked> : EdgeDetectorFilter<TColor, TPacked> public class LaplacianOfGaussianProcessor<TColor, TPacked> : EdgeDetectorFilter<TColor, TPacked>
where TColor : IPackedVector<TPacked> where TColor : IPackedVector<TPacked>
where TPacked : struct where TPacked : struct
{ {
/// <inheritdoc/> /// <summary>
public override float[,] KernelXY => new float[,] /// The 2d gradient operator.
/// </summary>
private static readonly float[][] LaplacianOfGaussianXY =
{ {
{ 0, 0, -1, 0, 0 }, new float[] { 0, 0, -1, 0, 0 },
{ 0, -1, -2, -1, 0 }, new float[] { 0, -1, -2, -1, 0 },
{ -1, -2, 16, -2, -1 }, new float[] { -1, -2, 16, -2, -1 },
{ 0, -1, -2, -1, 0 }, new float[] { 0, -1, -2, -1, 0 },
{ 0, 0, -1, 0, 0 } new float[] { 0, 0, -1, 0, 0 }
}; };
/// <inheritdoc/>
public override float[][] KernelXY => LaplacianOfGaussianXY;
} }
} }

17
src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/PrewittProcessor.cs

@ -5,24 +5,33 @@
namespace ImageProcessorCore.Processors namespace ImageProcessorCore.Processors
{ {
using System.Diagnostics.CodeAnalysis;
/// <summary> /// <summary>
/// The Prewitt operator filter. /// The Prewitt operator filter.
/// <see href="http://en.wikipedia.org/wiki/Prewitt_operator"/> /// <see href="http://en.wikipedia.org/wiki/Prewitt_operator"/>
/// </summary> /// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam> /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
[SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")]
public class PrewittProcessor<TColor, TPacked> : EdgeDetector2DFilter<TColor, TPacked> public class PrewittProcessor<TColor, TPacked> : EdgeDetector2DFilter<TColor, TPacked>
where TColor : IPackedVector<TPacked> where TColor : IPackedVector<TPacked>
where TPacked : struct where TPacked : struct
{ {
private static readonly float[][] kernelX = new float[3][] /// <summary>
/// The horizontal gradient operator.
/// </summary>
private static readonly float[][] PrewittX =
{ {
new float[] { -1, 0, 1 }, new float[] { -1, 0, 1 },
new float[] { -1, 0, 1 }, new float[] { -1, 0, 1 },
new float[] { -1, 0, 1 } new float[] { -1, 0, 1 }
}; };
private static readonly float[][] kernelY = new float[3][] /// <summary>
/// The vertical gradient operator.
/// </summary>
private static readonly float[][] PrewittY =
{ {
new float[] { 1, 1, 1 }, new float[] { 1, 1, 1 },
new float[] { 0, 0, 0 }, new float[] { 0, 0, 0 },
@ -30,9 +39,9 @@ namespace ImageProcessorCore.Processors
}; };
/// <inheritdoc/> /// <inheritdoc/>
public override float[][] KernelX => kernelX; public override float[][] KernelX => PrewittX;
/// <inheritdoc/> /// <inheritdoc/>
public override float[][] KernelY => kernelY; public override float[][] KernelY => PrewittY;
} }
} }

17
src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/RobertsCrossProcessor.cs

@ -5,32 +5,41 @@
namespace ImageProcessorCore.Processors namespace ImageProcessorCore.Processors
{ {
using System.Diagnostics.CodeAnalysis;
/// <summary> /// <summary>
/// The Roberts Cross operator filter. /// The Roberts Cross operator filter.
/// <see href="http://en.wikipedia.org/wiki/Roberts_cross"/> /// <see href="http://en.wikipedia.org/wiki/Roberts_cross"/>
/// </summary> /// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam> /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
[SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")]
public class RobertsCrossProcessor<TColor, TPacked> : EdgeDetector2DFilter<TColor, TPacked> public class RobertsCrossProcessor<TColor, TPacked> : EdgeDetector2DFilter<TColor, TPacked>
where TColor : IPackedVector<TPacked> where TColor : IPackedVector<TPacked>
where TPacked : struct where TPacked : struct
{ {
private static readonly float[][] kernelX = new float[2][] /// <summary>
/// The horizontal gradient operator.
/// </summary>
private static readonly float[][] RobertsCrossX =
{ {
new float[] { 1, 0 }, new float[] { 1, 0 },
new float[] { 0, -1 } new float[] { 0, -1 }
}; };
private static readonly float[][] kernelY = new float[2][] /// <summary>
/// The vertical gradient operator.
/// </summary>
private static readonly float[][] RobertsCrossY =
{ {
new float[] { 0, 1 }, new float[] { 0, 1 },
new float[] { -1, 0 } new float[] { -1, 0 }
}; };
/// <inheritdoc/> /// <inheritdoc/>
public override float[][] KernelX => kernelX; public override float[][] KernelX => RobertsCrossX;
/// <inheritdoc/> /// <inheritdoc/>
public override float[][] KernelY => kernelY; public override float[][] KernelY => RobertsCrossY;
} }
} }

124
src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/RobinsonProcessor.cs

@ -2,81 +2,123 @@
// Copyright (c) James Jackson-South and contributors. // Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
// </copyright> // </copyright>
namespace ImageProcessorCore.Processors namespace ImageProcessorCore.Processors
{ {
using System.Diagnostics.CodeAnalysis;
/// <summary> /// <summary>
/// The Kirsch operator filter. /// The Kirsch operator filter.
/// <see href="http://www.tutorialspoint.com/dip/Robinson_Compass_Mask.htm"/> /// <see href="http://www.tutorialspoint.com/dip/Robinson_Compass_Mask.htm"/>
/// </summary> /// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam> /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
[SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")]
public class RobinsonProcessor<TColor, TPacked> : EdgeDetectorCompassFilter<TColor, TPacked> public class RobinsonProcessor<TColor, TPacked> : EdgeDetectorCompassFilter<TColor, TPacked>
where TColor : IPackedVector<TPacked> where TColor : IPackedVector<TPacked>
where TPacked : struct where TPacked : struct
{ {
/// <inheritdoc/> /// <summary>
public override float[,] North => new float[,] /// The North gradient operator
/// </summary>
private static readonly float[][] RobinsonNorth =
{ {
{ 1, 2, 1 }, new float[] { 1, 2, 1 },
{ 0, 0, 0 }, new float[] { 0, 0, 0 },
{ -1, -2, -1 } new float[] { -1, -2, -1 }
}; };
/// <inheritdoc/> /// <summary>
public override float[,] NorthWest => new float[,] /// The NorthWest gradient operator
/// </summary>
private static readonly float[][] RobinsonNorthWest =
{ {
{ 2, 1, 0 }, new float[] { 2, 1, 0 },
{ 1, 0, -1 }, new float[] { 1, 0, -1 },
{ 0, -1, -2 } new float[] { 0, -1, -2 }
}; };
/// <inheritdoc/> /// <summary>
public override float[,] West => new float[,] /// The West gradient operator
/// </summary>
private static readonly float[][] RobinsonWest =
{ {
{ 1, 0, -1 }, new float[] { 1, 0, -1 },
{ 2, 0, -2 }, new float[] { 2, 0, -2 },
{ 1, 0, -1 } new float[] { 1, 0, -1 }
}; };
/// <inheritdoc/> /// <summary>
public override float[,] SouthWest => new float[,] /// The SouthWest gradient operator
/// </summary>
private static readonly float[][] RobinsonSouthWest =
{ {
{ 0, -1, -2 }, new float[] { 0, -1, -2 },
{ 1, 0, -1 }, new float[] { 1, 0, -1 },
{ 2, 1, 0 } new float[] { 2, 1, 0 }
}; };
/// <inheritdoc/> /// <summary>
public override float[,] South => new float[,] /// The South gradient operator
/// </summary>
private static readonly float[][] RobinsonSouth =
{ {
{ -1, -2, -1 }, new float[] { -1, -2, -1 },
{ 0, 0, 0 }, new float[] { 0, 0, 0 },
{ 1, 2, 1 } new float[] { 1, 2, 1 }
}; };
/// <inheritdoc/> /// <summary>
public override float[,] SouthEast => new float[,] /// The SouthEast gradient operator
/// </summary>
private static readonly float[][] RobinsonSouthEast =
{ {
{ -2, -1, 0 }, new float[] { -2, -1, 0 },
{ -1, 0, 1 }, new float[] { -1, 0, 1 },
{ 0, 1, 2 } new float[] { 0, 1, 2 }
}; };
/// <inheritdoc/> /// <summary>
public override float[,] East => new float[,] /// The East gradient operator
/// </summary>
private static readonly float[][] RobinsonEast =
{ {
{ -1, 0, 1 }, new float[] { -1, 0, 1 },
{ -2, 0, 2 }, new float[] { -2, 0, 2 },
{ -1, 0, 1 } new float[] { -1, 0, 1 }
}; };
/// <inheritdoc/> /// <summary>
public override float[,] NorthEast => new float[,] /// The NorthEast gradient operator
/// </summary>
private static readonly float[][] RobinsonNorthEast =
{ {
{ 0, 1, 2 }, new float[] { 0, 1, 2 },
{ -1, 0, 1 }, new float[] { -1, 0, 1 },
{ -2, -1, 0 } new float[] { -2, -1, 0 }
}; };
/// <inheritdoc/>
public override float[][] North => RobinsonNorth;
/// <inheritdoc/>
public override float[][] NorthWest => RobinsonNorthWest;
/// <inheritdoc/>
public override float[][] West => RobinsonWest;
/// <inheritdoc/>
public override float[][] SouthWest => RobinsonSouthWest;
/// <inheritdoc/>
public override float[][] South => RobinsonSouth;
/// <inheritdoc/>
public override float[][] SouthEast => RobinsonSouthEast;
/// <inheritdoc/>
public override float[][] East => RobinsonEast;
/// <inheritdoc/>
public override float[][] NorthEast => RobinsonNorthEast;
} }
} }

17
src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/ScharrProcessor.cs

@ -5,24 +5,33 @@
namespace ImageProcessorCore.Processors namespace ImageProcessorCore.Processors
{ {
using System.Diagnostics.CodeAnalysis;
/// <summary> /// <summary>
/// The Scharr operator filter. /// The Scharr operator filter.
/// <see href="http://en.wikipedia.org/wiki/Sobel_operator#Alternative_operators"/> /// <see href="http://en.wikipedia.org/wiki/Sobel_operator#Alternative_operators"/>
/// </summary> /// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam> /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
[SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")]
public class ScharrProcessor<TColor, TPacked> : EdgeDetector2DFilter<TColor, TPacked> public class ScharrProcessor<TColor, TPacked> : EdgeDetector2DFilter<TColor, TPacked>
where TColor : IPackedVector<TPacked> where TColor : IPackedVector<TPacked>
where TPacked : struct where TPacked : struct
{ {
private static readonly float[][] kernelX = new float[3][] /// <summary>
/// The horizontal gradient operator.
/// </summary>
private static readonly float[][] ScharrX = new float[3][]
{ {
new float[] { -3, 0, 3 }, new float[] { -3, 0, 3 },
new float[] { -10, 0, 10 }, new float[] { -10, 0, 10 },
new float[] { -3, 0, 3 } new float[] { -3, 0, 3 }
}; };
private static readonly float[][] kernelY = new float[3][] /// <summary>
/// The vertical gradient operator.
/// </summary>
private static readonly float[][] ScharrY = new float[3][]
{ {
new float[] { 3, 10, 3 }, new float[] { 3, 10, 3 },
new float[] { 0, 0, 0 }, new float[] { 0, 0, 0 },
@ -30,9 +39,9 @@ namespace ImageProcessorCore.Processors
}; };
/// <inheritdoc/> /// <inheritdoc/>
public override float[][] KernelX => kernelX; public override float[][] KernelX => ScharrX;
/// <inheritdoc/> /// <inheritdoc/>
public override float[][] KernelY => kernelY; public override float[][] KernelY => ScharrY;
} }
} }

17
src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/SobelProcessor.cs

@ -5,24 +5,33 @@
namespace ImageProcessorCore.Processors namespace ImageProcessorCore.Processors
{ {
using System.Diagnostics.CodeAnalysis;
/// <summary> /// <summary>
/// The Sobel operator filter. /// The Sobel operator filter.
/// <see href="http://en.wikipedia.org/wiki/Sobel_operator"/> /// <see href="http://en.wikipedia.org/wiki/Sobel_operator"/>
/// </summary> /// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam> /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
[SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")]
public class SobelProcessor<TColor, TPacked> : EdgeDetector2DFilter<TColor, TPacked> public class SobelProcessor<TColor, TPacked> : EdgeDetector2DFilter<TColor, TPacked>
where TColor : IPackedVector<TPacked> where TColor : IPackedVector<TPacked>
where TPacked : struct where TPacked : struct
{ {
private static readonly float[][] kernelX = new float[3][] /// <summary>
/// The horizontal gradient operator.
/// </summary>
private static readonly float[][] SobelX =
{ {
new float[] { -1, 0, 1 }, new float[] { -1, 0, 1 },
new float[] { -2, 0, 2 }, new float[] { -2, 0, 2 },
new float[] { -1, 0, 1 } new float[] { -1, 0, 1 }
}; };
private static readonly float[][] kernelY = new float[3][] /// <summary>
/// The vertical gradient operator.
/// </summary>
private static readonly float[][] SobelY =
{ {
new float[] { -1, -2, -1 }, new float[] { -1, -2, -1 },
new float[] { 0, 0, 0 }, new float[] { 0, 0, 0 },
@ -30,9 +39,9 @@ namespace ImageProcessorCore.Processors
}; };
/// <inheritdoc/> /// <inheritdoc/>
public override float[][] KernelX => kernelX; public override float[][] KernelX => SobelX;
/// <inheritdoc/> /// <inheritdoc/>
public override float[][] KernelY => kernelY; public override float[][] KernelY => SobelY;
} }
} }

Loading…
Cancel
Save