Browse Source

Make edge detector classes abstract

Former-commit-id: 556855c2478d6f0e2fa55116bda4324d0f6ea25c
Former-commit-id: b44d0b9b2608563be8d958f692261928d5d4bf71
Former-commit-id: 4d554bf692a04b0107326530f8c5d57002d31220
pull/1/head
James Jackson-South 10 years ago
parent
commit
59d75438d3
  1. 4
      src/ImageProcessorCore/Image/IImageProcessor.cs
  2. 2
      src/ImageProcessorCore/Image/ImageProcessingExtensions.cs
  3. 17
      src/ImageProcessorCore/ImageProcessor.cs
  4. 22
      src/ImageProcessorCore/Samplers/DetectEdges.cs
  5. 22
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/EdgeDetector2DFilter.cs
  6. 119
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/EdgeDetectorCompassFilter.cs
  7. 23
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/EdgeDetectorFilter.cs
  8. 5
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/IEdgeDetectorFilter.cs
  9. 21
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/KayyaliProcessor.cs
  10. 98
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/KirschProcessor.cs
  11. 15
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/Laplacian3X3Processor.cs
  12. 15
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/Laplacian5X5Processor.cs
  13. 15
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/LaplacianOfGaussianProcessor.cs
  14. 21
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/PrewittProcessor.cs
  15. 21
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/RobertsCrossProcessor.cs
  16. 21
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/ScharrProcessor.cs
  17. 25
      src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/SobelProcessor.cs
  18. 40
      src/ImageProcessorCore/Samplers/Processors/EntropyCropProcessor.cs
  19. 1
      src/ImageProcessorCore/Samplers/Processors/ImageSampler.cs

4
src/ImageProcessorCore/Image/IImageProcessor.cs

@ -3,10 +3,10 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
using System.Threading.Tasks;
namespace ImageProcessorCore.Processors
{
using System.Threading.Tasks;
/// <summary>
/// A delegate which is called as progress is made processing an image.
/// </summary>

2
src/ImageProcessorCore/Image/ImageProcessingExtensions.cs

@ -171,7 +171,9 @@ namespace ImageProcessorCore
// Several properties still require copying
if (!clone)
{
transformedImage.CopyProperties(source);
}
action(source, transformedImage);

17
src/ImageProcessorCore/ImageProcessor.cs

@ -5,6 +5,7 @@
namespace ImageProcessorCore.Processors
{
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@ -17,18 +18,13 @@ namespace ImageProcessorCore.Processors
where TColor : IPackedVector<TPacked>
where TPacked : struct
{
/// <inheritdoc/>
public event ProgressEventHandler OnProgress;
/// <summary>
/// The number of rows processed by a derived class.
/// Gets or sets the number of rows processed by a derived class.
/// </summary>
protected int NumRowsProcessed;
/// <summary>
/// The total number of rows that will be processed by a derived class.
/// </summary>
protected int TotalRows;
/// <inheritdoc/>
public event ProgressEventHandler OnProgress;
/// <inheritdoc/>
public virtual ParallelOptions ParallelOptions { get; set; } = Bootstrapper.Instance.ParallelOptions;
@ -36,6 +32,11 @@ namespace ImageProcessorCore.Processors
/// <inheritdoc/>
public virtual bool Compand { get; set; } = false;
/// <summary>
/// Gets or sets the total number of rows that will be processed by a derived class.
/// </summary>
protected int TotalRows { get; set; }
/// <summary>
/// Must be called by derived classes after processing a single row.
/// </summary>

22
src/ImageProcessorCore/Samplers/DetectEdges.cs

@ -25,7 +25,7 @@ namespace ImageProcessorCore
where TColor : IPackedVector<TPacked>
where TPacked : struct
{
return DetectEdges(source, source.Bounds, new SobelProcessor<TColor, TPacked>(true), progressHandler);
return DetectEdges(source, source.Bounds, new SobelProcessor<TColor, TPacked> { Grayscale = true }, progressHandler);
}
/// <summary>
@ -44,7 +44,7 @@ namespace ImageProcessorCore
where TColor : IPackedVector<TPacked>
where TPacked : struct
{
return DetectEdges(source, rectangle, new SobelProcessor<TColor, TPacked>(true), progressHandler);
return DetectEdges(source, rectangle, new SobelProcessor<TColor, TPacked> { Grayscale = true }, progressHandler);
}
/// <summary>
@ -86,39 +86,39 @@ namespace ImageProcessorCore
switch (filter)
{
case EdgeDetection.Kayyali:
processor = new KayyaliProcessor<TColor, TPacked>(grayscale);
processor = new KayyaliProcessor<TColor, TPacked> { Grayscale = grayscale };
break;
case EdgeDetection.Kirsch:
processor = new KirschProcessor<TColor, TPacked>(grayscale);
processor = new KirschProcessor<TColor, TPacked> { Grayscale = grayscale };
break;
case EdgeDetection.Lapacian3X3:
processor = new Laplacian3X3Processor<TColor, TPacked>(grayscale);
processor = new Laplacian3X3Processor<TColor, TPacked> { Grayscale = grayscale };
break;
case EdgeDetection.Lapacian5X5:
processor = new Laplacian5X5Processor<TColor, TPacked>(grayscale);
processor = new Laplacian5X5Processor<TColor, TPacked> { Grayscale = grayscale };
break;
case EdgeDetection.LaplacianOfGaussian:
processor = new LaplacianOfGaussianProcessor<TColor, TPacked>(grayscale);
processor = new LaplacianOfGaussianProcessor<TColor, TPacked> { Grayscale = grayscale };
break;
case EdgeDetection.Prewitt:
processor = new PrewittProcessor<TColor, TPacked>(grayscale);
processor = new PrewittProcessor<TColor, TPacked> { Grayscale = grayscale };
break;
case EdgeDetection.RobertsCross:
processor = new RobertsCrossProcessor<TColor, TPacked>(grayscale);
processor = new RobertsCrossProcessor<TColor, TPacked> { Grayscale = grayscale };
break;
case EdgeDetection.Scharr:
processor = new ScharrProcessor<TColor, TPacked>(grayscale);
processor = new ScharrProcessor<TColor, TPacked> { Grayscale = grayscale };
break;
default:
processor = new SobelProcessor<TColor, TPacked>(grayscale);
processor = new SobelProcessor<TColor, TPacked> { Grayscale = grayscale };
break;
}

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

@ -11,39 +11,27 @@ namespace ImageProcessorCore.Processors
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public class EdgeDetector2DFilter<TColor, TPacked> : ImageSampler<TColor, TPacked>, IEdgeDetectorFilter<TColor, TPacked>
public abstract class EdgeDetector2DFilter<TColor, TPacked> : ImageSampler<TColor, TPacked>, IEdgeDetectorFilter<TColor, TPacked>
where TColor : IPackedVector<TPacked>
where TPacked : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="EdgeDetector2DFilter{TColor,TPacked}"/> class.
/// </summary>
/// <param name="kernelX">The horizontal gradient operator.</param>
/// <param name="kernelY">The vertical gradient operator.</param>
/// <param name="grayscale">Whether to convert the image to grayscale before performing edge detection..</param>
public EdgeDetector2DFilter(float[,] kernelX, float[,] kernelY, bool grayscale)
{
this.KernelX = kernelX;
this.KernelY = kernelY;
this.Grayscale = grayscale;
}
/// <summary>
/// Gets the horizontal gradient operator.
/// </summary>
public float[,] KernelX { get; }
public abstract float[,] KernelX { get; }
/// <summary>
/// Gets the vertical gradient operator.
/// </summary>
public float[,] KernelY { get; }
public abstract float[,] KernelY { get; }
/// <inheritdoc/>
public bool Grayscale { get; }
public bool Grayscale { get; set; }
/// <inheritdoc />
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
{
// TODO: Figure out a way to pass event handlers to child classes.
new Convolution2DFilter<TColor, TPacked>(this.KernelX, this.KernelY).Apply(target, source, targetRectangle, sourceRectangle, startY, endY);
}

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

@ -9,34 +9,63 @@ namespace ImageProcessorCore.Processors
using System.Numerics;
using System.Threading.Tasks;
public class EdgeDetectorCompassFilter<TColor, TPacked> : ImageSampler<TColor, TPacked>, IEdgeDetectorFilter<TColor, TPacked>
/// <summary>
/// Defines a filter that detects edges within an image using a eight two dimensional matrices.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public abstract class EdgeDetectorCompassFilter<TColor, TPacked> : ImageSampler<TColor, TPacked>, IEdgeDetectorFilter<TColor, TPacked>
where TColor : IPackedVector<TPacked>
where TPacked : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="EdgeDetectorCompassFilter{TColor,TPacked}"/> class.
/// Gets the North gradient operator
/// </summary>
/// <param name="kernels">
/// The collection of 2d gradient operator.
/// </param>
/// <param name="grayscale">Whether to convert the image to grayscale before performing edge detection..</param>
public EdgeDetectorCompassFilter(float[][,] kernels, bool grayscale)
{
this.Kernels = kernels;
this.Grayscale = grayscale;
}
public abstract float[,] North { get; }
/// <summary>
/// Gets the collection of 2d gradient operators.
/// Gets the NorthWest gradient operator
/// </summary>
public float[][,] Kernels { get; }
public abstract float[,] NorthWest { get; }
/// <inheritdoc />
public bool Grayscale { get; }
/// <summary>
/// Gets the West gradient operator
/// </summary>
public abstract float[,] West { get; }
/// <summary>
/// Gets the SouthWest gradient operator
/// </summary>
public abstract float[,] SouthWest { get; }
/// <summary>
/// Gets the South gradient operator
/// </summary>
public abstract float[,] South { get; }
/// <summary>
/// Gets the SouthEast gradient operator
/// </summary>
public abstract float[,] SouthEast { get; }
/// <summary>
/// Gets the East gradient operator
/// </summary>
public abstract float[,] East { get; }
/// <summary>
/// Gets the NorthEast gradient operator
/// </summary>
public abstract float[,] NorthEast { get; }
/// <inheritdoc/>
public bool Grayscale { get; set; }
/// <inheritdoc />
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 };
int startX = sourceRectangle.X;
int endX = sourceRectangle.Right;
@ -46,34 +75,33 @@ namespace ImageProcessorCore.Processors
int minY = Math.Max(0, startY);
int maxY = Math.Min(source.Height, endY);
// Reset offset if necessary.
if (minX > 0)
{
startX = 0;
}
// First run.
new ConvolutionFilter<TColor, TPacked>(kernels[0]).Apply(target, source, targetRectangle, sourceRectangle, startY, endY);
if (minY > 0)
if (kernels.Length == 1)
{
startY = 0;
return;
}
int shiftY = startY;
int shiftX = startX;
new EdgeDetectorFilter<TColor, TPacked>(this.Kernels[0], this.Grayscale).Apply(target, source, sourceRectangle, targetRectangle, startY, endY);
//this.ApplyConvolution(target, source, sourceRectangle, this.Grayscale, this.Kernels[0]);
// Reset offset if necessary.
if (minX > 0)
{
shiftX = 0;
}
if (this.Kernels.Length == 1)
if (minY > 0)
{
return;
shiftY = 0;
}
for (int i = 1; i < this.Kernels.Length; i++)
// Additional runs.
for (int i = 1; i < kernels.Length; i++)
{
ImageBase<TColor, TPacked> pass = new Image<TColor, TPacked>(source.Width, source.Height);
new EdgeDetectorFilter<TColor, TPacked>(this.Kernels[0], false).Apply(pass, source, sourceRectangle, targetRectangle, startY, endY);
// this.ApplyConvolution(pass, source, sourceRectangle, false, this.Kernels[0]);
new ConvolutionFilter<TColor, TPacked>(kernels[i]).Apply(pass, source, sourceRectangle, targetRectangle, startY, endY);
using (PixelAccessor<TColor, TPacked> passPixels = pass.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock())
@ -84,15 +112,14 @@ namespace ImageProcessorCore.Processors
this.ParallelOptions,
y =>
{
int offsetY = y - startY;
int offsetY = y - shiftY;
for (int x = minX; x < maxX; x++)
{
int offsetX = x - startX;
Vector4 passColor = passPixels[offsetX, offsetY].ToVector4();
Vector4 targetColor = targetPixels[offsetX, offsetY].ToVector4();
int offsetX = x - shiftX;
// Grab the max components of the two pixels
TColor packed = default(TColor);
packed.PackFromVector4(Vector4.Max(passColor, targetColor));
packed.PackFromVector4(Vector4.Max(passPixels[offsetX, offsetY].ToVector4(), targetPixels[offsetX, offsetY].ToVector4()));
targetPixels[offsetX, offsetY] = packed;
}
});
@ -108,21 +135,5 @@ namespace ImageProcessorCore.Processors
new GrayscaleBt709Processor<TColor, TPacked>().Apply(source, sourceRectangle);
}
}
/// <summary>
/// Applies the convolution process to the specified portion of the specified <see cref="ImageBase{TColor, TPacked}"/> at the specified location
/// and with the specified size.
/// </summary>
/// <param name="target">Target image to apply the process to.</param>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
/// <param name="grayScale">Whether to convert the image to grayscale before performing edge detection.</param>
/// <param name="kernel">The kernel operator.</param>
private void ApplyConvolution(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, bool grayScale, float[,] kernel)
{
new EdgeDetectorFilter<TColor, TPacked>(kernel, grayScale).Apply(target, source, sourceRectangle);
}
}
}
}

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

@ -6,28 +6,27 @@
namespace ImageProcessorCore.Processors
{
/// <summary>
/// Defines a filter that detects edges within an image using a single
/// two dimensional matrix.
/// Defines a filter that detects edges within an image using a single two dimensional matrix.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public class EdgeDetectorFilter<TColor, TPacked> : ConvolutionFilter<TColor, TPacked>, IEdgeDetectorFilter<TColor, TPacked>
public abstract class EdgeDetectorFilter<TColor, TPacked> : ImageSampler<TColor, TPacked>, IEdgeDetectorFilter<TColor, TPacked>
where TColor : IPackedVector<TPacked>
where TPacked : struct
{
/// <inheritdoc/>
public bool Grayscale { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="EdgeDetectorFilter{TColor,TPacked}"/> class.
/// Gets the 2d gradient operator.
/// </summary>
/// <param name="kernelXY">The 2d gradient operator.</param>
/// <param name="grayscale">Whether to convert the image to grayscale before performing edge detection..</param>
public EdgeDetectorFilter(float[,] kernelXY, bool grayscale)
: base(kernelXY)
{
this.Grayscale = grayscale;
}
public abstract float[,] KernelXY { get; }
/// <inheritdoc/>
public bool Grayscale { get; }
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
{
new ConvolutionFilter<TColor, TPacked>(this.KernelXY).Apply(target, source, targetRectangle, sourceRectangle, startY, endY);
}
/// <inheritdoc/>
protected override void OnApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle)

5
src/ImageProcessorCore/Samplers/Processors/Convolution/EdgeDetection/IEdgeDetectorFilter.cs

@ -22,9 +22,8 @@ namespace ImageProcessorCore.Processors
public interface IEdgeDetectorFilter
{
/// <summary>
/// Gets a value indicating whether to convert the
/// image to grayscale before performing edge detection.
/// Gets or sets a value indicating whether to convert the image to grayscale before performing edge detection.
/// </summary>
bool Grayscale { get; }
bool Grayscale { get; set; }
}
}

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

@ -15,29 +15,16 @@ namespace ImageProcessorCore.Processors
where TColor : IPackedVector<TPacked>
where TPacked : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="KayyaliProcessor{TColor,TPacked}"/> class.
/// </summary>
/// <param name="grayscale">Whether to convert the image to grayscale before performing edge detection..</param>
public KayyaliProcessor(bool grayscale)
: base(KernelA, KernelB, grayscale)
{
}
/// <summary>
/// Gets the horizontal gradient operator.
/// </summary>
public static float[,] KernelA => new float[,]
/// <inheritdoc/>
public override float[,] KernelX => new float[,]
{
{ 6, 0, -6 },
{ 0, 0, 0 },
{ -6, 0, 6 }
};
/// <summary>
/// Gets the vertical gradient operator.
/// </summary>
public static float[,] KernelB => new float[,]
/// <inheritdoc/>
public override float[,] KernelY => new float[,]
{
{ -6, 0, 6 },
{ 0, 0, 0 },

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

@ -15,96 +15,68 @@ namespace ImageProcessorCore.Processors
where TColor : IPackedVector<TPacked>
where TPacked : struct
{
public KirschProcessor(bool grayscale)
: base(new[] { North, Northwest, West, Southwest, South, Southeast, East, Northeast }, grayscale)
/// <inheritdoc/>
public override float[,] North => new float[,]
{
}
/// <summary>
/// Gets the North direction Kirsch kernel mask.
/// </summary>
///
public static float[,] North => new float[,]
{
{ -3, -3, 5 },
{ -3, 0, 5 },
{ -3, -3, 5 }
};
/// <summary>
/// Gets the Northwest direction Kirsch kernel mask.
/// </summary>
///
public static float[,] Northwest => new float[,]
{
{ -3, 5, 5 },
{ -3, 0, 5 },
{ -3, -3, -3 }
};
/// <summary>
/// Gets the West direction Kirsch kernel mask.
/// </summary>
///
public static float[,] West => new float[,]
{
{ 5, 5, 5 },
{ 5, 5, 5 },
{ -3, 0, -3 },
{ -3, -3, -3 }
};
/// <summary>
/// Gets the Southwest direction Kirsch kernel mask.
/// </summary>
///
public static float[,] Southwest => new float[,]
/// <inheritdoc/>
public override float[,] NorthWest => new float[,]
{
{ 5, 5, -3 },
{ 5, 0, -3 },
{ 5, 5, -3 },
{ 5, 0, -3 },
{ -3, -3, -3 }
};
/// <summary>
/// Gets the South direction Kirsch kernel mask.
/// </summary>
///
public static float[,] South => new float[,]
/// <inheritdoc/>
public override float[,] West => new float[,]
{
{ 5, -3, -3 },
{ 5, 0, -3 },
{ 5, -3, -3 }
{ 5, -3, -3 },
{ 5, 0, -3 },
{ 5, -3, -3 }
};
/// <summary>
/// Gets the Southeast direction Kirsch kernel mask.
/// </summary>
public static float[,] Southeast => new float[,]
/// <inheritdoc/>
public override float[,] SouthWest => new float[,]
{
{ -3, -3, -3 },
{ 5, 0, -3 },
{ 5, 5, -3 }
};
/// <summary>
/// Gets the East direction Kirsch kernel mask.
/// </summary>
///
public static float[,] East => new float[,]
/// <inheritdoc/>
public override float[,] South => new float[,]
{
{ -3, -3, -3 },
{ -3, 0, -3 },
{ 5, 5, 5 }
};
/// <summary>
/// Gets the Northeast direction Kirsch kernel mask.
/// </summary>
///
public static float[,] Northeast => new float[,]
/// <inheritdoc/>
public override float[,] SouthEast => new float[,]
{
{ -3, -3, -3 },
{ -3, 0, 5 },
{ -3, 5, 5 }
};
/// <inheritdoc/>
public override float[,] East => new float[,]
{
{ -3, -3, 5 },
{ -3, 0, 5 },
{ -3, -3, 5 }
};
/// <inheritdoc/>
public override float[,] NorthEast => new float[,]
{
{ -3, 5, 5 },
{ -3, 0, 5 },
{ -3, -3, -3 }
};
}
}
}

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

@ -15,19 +15,8 @@ namespace ImageProcessorCore.Processors
where TColor : IPackedVector<TPacked>
where TPacked : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="Laplacian3X3Processor{TColor,TPacked}"/> class.
/// </summary>
/// <param name="grayscale">Whether to convert the image to grayscale before performing edge detection..</param>
public Laplacian3X3Processor(bool grayscale)
: base(Kernel, grayscale)
{
}
/// <summary>
/// Gets the 2d gradient operator.
/// </summary>
public static float[,] Kernel => new float[,]
/// <inheritdoc/>
public override float[,] KernelXY => new float[,]
{
{ -1, -1, -1 },
{ -1, 8, -1 },

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

@ -15,19 +15,8 @@ namespace ImageProcessorCore.Processors
where TColor : IPackedVector<TPacked>
where TPacked : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="Laplacian5X5Processor{TColor,TPacked}"/> class.
/// </summary>
/// <param name="grayscale">Whether to convert the image to grayscale before performing edge detection..</param>
public Laplacian5X5Processor(bool grayscale)
: base(Kernel, grayscale)
{
}
/// <summary>
/// Gets the 2d gradient operator.
/// </summary>
public static float[,] Kernel => new float[,]
/// <inheritdoc/>
public override float[,] KernelXY => new float[,]
{
{ -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1 },

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

@ -15,19 +15,8 @@ namespace ImageProcessorCore.Processors
where TColor : IPackedVector<TPacked>
where TPacked : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="LaplacianOfGaussianProcessor{TColor,TPacked}"/> class.
/// </summary>
/// <param name="grayscale">Whether to convert the image to grayscale before performing edge detection..</param>
public LaplacianOfGaussianProcessor(bool grayscale)
: base(Kernel, grayscale)
{
}
/// <summary>
/// Gets the 2d gradient operator.
/// </summary>
public static float[,] Kernel => new float[,]
/// <inheritdoc/>
public override float[,] KernelXY => new float[,]
{
{ 0, 0, -1, 0, 0 },
{ 0, -1, -2, -1, 0 },

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

@ -15,29 +15,16 @@ namespace ImageProcessorCore.Processors
where TColor : IPackedVector<TPacked>
where TPacked : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="PrewittProcessor{TColor,TPacked}"/> class.
/// </summary>
/// <param name="grayscale">Whether to convert the image to grayscale before performing edge detection..</param>
public PrewittProcessor(bool grayscale)
: base(KernelA, KernelB, grayscale)
{
}
/// <summary>
/// Gets the horizontal gradient operator.
/// </summary>
public static float[,] KernelA => new float[,]
/// <inheritdoc/>
public override float[,] KernelX => new float[,]
{
{ -1, 0, 1 },
{ -1, 0, 1 },
{ -1, 0, 1 }
};
/// <summary>
/// Gets the vertical gradient operator.
/// </summary>
public static float[,] KernelB => new float[,]
/// <inheritdoc/>
public override float[,] KernelY => new float[,]
{
{ 1, 1, 1 },
{ 0, 0, 0 },

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

@ -15,28 +15,15 @@ namespace ImageProcessorCore.Processors
where TColor : IPackedVector<TPacked>
where TPacked : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="RobertsCrossProcessor{TColor,TPacked}"/> class.
/// </summary>
/// <param name="grayscale">Whether to convert the image to grayscale before performing edge detection..</param>
public RobertsCrossProcessor(bool grayscale)
: base(KernelA, KernelB, grayscale)
{
}
/// <summary>
/// Gets the horizontal gradient operator.
/// </summary>
public static float[,] KernelA => new float[,]
/// <inheritdoc/>
public override float[,] KernelX => new float[,]
{
{ 1, 0 },
{ 0, -1 }
};
/// <summary>
/// Gets the vertical gradient operator.
/// </summary>
public static float[,] KernelB => new float[,]
/// <inheritdoc/>
public override float[,] KernelY => new float[,]
{
{ 0, 1 },
{ -1, 0 }

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

@ -15,29 +15,16 @@ namespace ImageProcessorCore.Processors
where TColor : IPackedVector<TPacked>
where TPacked : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="ScharrProcessor{TColor,TPacked}"/> class.
/// </summary>
/// <param name="grayscale">Whether to convert the image to grayscale before performing edge detection..</param>
public ScharrProcessor(bool grayscale)
: base(KernelA, KernelB, grayscale)
{
}
/// <summary>
/// Gets the horizontal gradient operator.
/// </summary>
public static float[,] KernelA => new float[,]
/// <inheritdoc/>
public override float[,] KernelX => new float[,]
{
{ -3, 0, 3 },
{ -10, 0, 10 },
{ -3, 0, 3 }
};
/// <summary>
/// Gets the vertical gradient operator.
/// </summary>
public static float[,] KernelB => new float[,]
/// <inheritdoc/>
public override float[,] KernelY => new float[,]
{
{ 3, 10, 3 },
{ 0, 0, 0 },

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

@ -15,33 +15,20 @@ namespace ImageProcessorCore.Processors
where TColor : IPackedVector<TPacked>
where TPacked : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="SobelProcessor{TColor,TPacked}"/> class.
/// </summary>
/// <param name="grayscale">Whether to convert the image to grayscale before performing edge detection..</param>
public SobelProcessor(bool grayscale)
: base(KernelA, KernelB, grayscale)
{
}
/// <summary>
/// Gets the horizontal gradient operator.
/// </summary>
public static float[,] KernelA => new float[,]
/// <inheritdoc/>
public override float[,] KernelX => new float[,]
{
{ -1, 0, 1 },
{ -2, 0, 2 },
{ -1, 0, 1 }
};
/// <summary>
/// Gets the horizontal gradient operator.
/// </summary>
public static float[,] KernelB => new float[,]
/// <inheritdoc/>
public override float[,] KernelY => new float[,]
{
{ 1, 2, 1 },
{ -1, -2, -1 },
{ 0, 0, 0 },
{ -1, -2, -1 }
{ 1, 2, 1 }
};
}
}

40
src/ImageProcessorCore/Samplers/Processors/EntropyCropProcessor.cs

@ -41,25 +41,6 @@ namespace ImageProcessorCore.Processors
/// </summary>
public float Value { get; }
/// <inheritdoc/>
protected override void OnApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle)
{
ImageBase<TColor, TPacked> temp = new Image<TColor, TPacked>(source.Width, source.Height);
// Detect the edges.
new SobelProcessor<TColor, TPacked>(false).Apply(temp, source, sourceRectangle);
// Apply threshold binarization filter.
new BinaryThresholdProcessor<TColor, TPacked>(.5f).Apply(temp, sourceRectangle);
// Search for the first white pixels
Rectangle rectangle = ImageMaths.GetFilteredBoundingRectangle(temp, 0);
// Reset the target pixel to the correct size.
target.SetPixels(rectangle.Width, rectangle.Height, new TColor[rectangle.Width * rectangle.Height]);
this.cropRectangle = rectangle;
}
/// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
{
@ -96,6 +77,25 @@ namespace ImageProcessorCore.Processors
}
}
/// <inheritdoc/>
protected override void OnApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle)
{
ImageBase<TColor, TPacked> temp = new Image<TColor, TPacked>(source.Width, source.Height);
// Detect the edges.
new SobelProcessor<TColor, TPacked>().Apply(temp, source, sourceRectangle);
// Apply threshold binarization filter.
new BinaryThresholdProcessor<TColor, TPacked>(.5f).Apply(temp, sourceRectangle);
// Search for the first white pixels
Rectangle rectangle = ImageMaths.GetFilteredBoundingRectangle(temp, 0);
// Reset the target pixel to the correct size.
target.SetPixels(rectangle.Width, rectangle.Height, new TColor[rectangle.Width * rectangle.Height]);
this.cropRectangle = rectangle;
}
/// <inheritdoc/>
protected override void AfterApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle)
{
@ -106,4 +106,4 @@ namespace ImageProcessorCore.Processors
}
}
}
}
}

1
src/ImageProcessorCore/Samplers/Processors/ImageSampler.cs

@ -32,7 +32,6 @@ namespace ImageProcessorCore.Processors
}
catch (Exception ex)
{
throw new ImageProcessingException($"An error occured when processing the image using {this.GetType().Name}. See the inner exception for more detail.", ex);
}
}

Loading…
Cancel
Save