Browse Source

Clean upedge detection

Former-commit-id: 3f5ad14a2724c33a3723986e5e5890d7339302dc
Former-commit-id: f371e93de1c3ae0c144bc20c26cc49d0b34b5178
Former-commit-id: 9f3aea38493f3236544703c08560fa9dcdc47990
pull/1/head
James Jackson-South 10 years ago
parent
commit
08de2e30bd
  1. 67
      src/ImageProcessorCore/Filters/DetectEdges.cs
  2. 1
      src/ImageProcessorCore/Filters/Processors/Convolution/Convolution2DFilter.cs
  3. 25
      tests/ImageProcessorCore.Tests/Processors/Filters/DetectEdgesTest.cs

67
src/ImageProcessorCore/Filters/DetectEdges.cs

@ -13,7 +13,7 @@ namespace ImageProcessorCore
public static partial class ImageExtensions public static partial class ImageExtensions
{ {
/// <summary> /// <summary>
/// Detects any edges within the image. Uses the <see cref="SobelProcessor"/> filter /// Detects any edges within the image. Uses the <see cref="SobelProcessor{T,TP}"/> filter
/// operating in Grayscale mode. /// operating in Grayscale mode.
/// </summary> /// </summary>
/// <typeparam name="T">The pixel format.</typeparam> /// <typeparam name="T">The pixel format.</typeparam>
@ -28,6 +28,25 @@ namespace ImageProcessorCore
return DetectEdges(source, source.Bounds, new SobelProcessor<T, TP> { Grayscale = true }, progressHandler); return DetectEdges(source, source.Bounds, new SobelProcessor<T, TP> { Grayscale = true }, progressHandler);
} }
/// <summary>
/// Detects any edges within the image. Uses the <see cref="SobelProcessor{T,TP}"/> filter
/// operating in Grayscale mode.
/// </summary>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <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="progressHandler">A delegate which is called as progress is made processing the image.</param>
/// <returns>The <see cref="Image{T,TP}"/>.</returns>
public static Image<T, TP> DetectEdges<T, TP>(this Image<T, TP> source, Rectangle rectangle, ProgressEventHandler progressHandler = null)
where T : IPackedVector<TP>
where TP : struct
{
return DetectEdges(source, rectangle, new SobelProcessor<T, TP> { Grayscale = true }, progressHandler);
}
/// <summary> /// <summary>
/// Detects any edges within the image. /// Detects any edges within the image.
/// </summary> /// </summary>
@ -35,10 +54,30 @@ namespace ImageProcessorCore
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam> /// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="filter">The filter for detecting edges.</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="grayscale">Whether to convert the image to Grayscale first. Defaults to true.</param>
/// <param name="progressHandler">A delegate which is called as progress is made processing the image.</param> /// <param name="progressHandler">A delegate which is called as progress is made processing the image.</param>
/// <returns>The <see cref="Image{T,TP}"/>.</returns> /// <returns>The <see cref="Image{T,TP}"/>.</returns>
public static Image<T, TP> DetectEdges<T, TP>(this Image<T, TP> source, EdgeDetection filter, bool Grayscale = true, ProgressEventHandler progressHandler = null) public static Image<T, TP> DetectEdges<T, TP>(this Image<T, TP> source, EdgeDetection filter, bool grayscale = true, ProgressEventHandler progressHandler = null)
where T : IPackedVector<TP>
where TP : struct
{
return DetectEdges(source, filter, source.Bounds, grayscale, progressHandler);
}
/// <summary>
/// Detects any edges within the image.
/// </summary>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="filter">The filter for detecting edges.</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>
/// <param name="progressHandler">A delegate which is called as progress is made processing the image.</param>
/// <returns>The <see cref="Image{T,TP}"/>.</returns>
public static Image<T, TP> DetectEdges<T, TP>(this Image<T, TP> source, EdgeDetection filter, Rectangle rectangle, bool grayscale = true, ProgressEventHandler progressHandler = null)
where T : IPackedVector<TP> where T : IPackedVector<TP>
where TP : struct where TP : struct
{ {
@ -47,43 +86,43 @@ namespace ImageProcessorCore
switch (filter) switch (filter)
{ {
case EdgeDetection.Kayyali: case EdgeDetection.Kayyali:
processor = new KayyaliProcessor<T, TP> { Grayscale = Grayscale }; processor = new KayyaliProcessor<T, TP> { Grayscale = grayscale };
break; break;
case EdgeDetection.Kirsch: case EdgeDetection.Kirsch:
processor = new KirschProcessor<T, TP> { Grayscale = Grayscale }; processor = new KirschProcessor<T, TP> { Grayscale = grayscale };
break; break;
case EdgeDetection.Lapacian3X3: case EdgeDetection.Lapacian3X3:
processor = new Laplacian3X3Processor<T, TP> { Grayscale = Grayscale }; processor = new Laplacian3X3Processor<T, TP> { Grayscale = grayscale };
break; break;
case EdgeDetection.Lapacian5X5: case EdgeDetection.Lapacian5X5:
processor = new Laplacian5X5Processor<T, TP> { Grayscale = Grayscale }; processor = new Laplacian5X5Processor<T, TP> { Grayscale = grayscale };
break; break;
case EdgeDetection.LaplacianOfGaussian: case EdgeDetection.LaplacianOfGaussian:
processor = new LaplacianOfGaussianProcessor<T, TP> { Grayscale = Grayscale }; processor = new LaplacianOfGaussianProcessor<T, TP> { Grayscale = grayscale };
break; break;
case EdgeDetection.Prewitt: case EdgeDetection.Prewitt:
processor = new PrewittProcessor<T, TP> { Grayscale = Grayscale }; processor = new PrewittProcessor<T, TP> { Grayscale = grayscale };
break; break;
case EdgeDetection.RobertsCross: case EdgeDetection.RobertsCross:
processor = new RobertsCrossProcessor<T, TP> { Grayscale = Grayscale }; processor = new RobertsCrossProcessor<T, TP> { Grayscale = grayscale };
break; break;
case EdgeDetection.Scharr: case EdgeDetection.Scharr:
processor = new ScharrProcessor<T, TP> { Grayscale = Grayscale }; processor = new ScharrProcessor<T, TP> { Grayscale = grayscale };
break; break;
default: default:
processor = new ScharrProcessor<T, TP> { Grayscale = Grayscale }; processor = new ScharrProcessor<T, TP> { Grayscale = grayscale };
break; break;
} }
return DetectEdges(source, source.Bounds, processor, progressHandler); return DetectEdges(source, rectangle, processor, progressHandler);
} }
/// <summary> /// <summary>
@ -105,6 +144,8 @@ namespace ImageProcessorCore
/// <summary> /// <summary>
/// Detects any edges within the image. /// Detects any edges within the image.
/// </summary> /// </summary>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="rectangle"> /// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter. /// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.

1
src/ImageProcessorCore/Filters/Processors/Convolution/Convolution2DFilter.cs

@ -112,6 +112,7 @@ namespace ImageProcessorCore.Processors
packed.PackFromVector4(new Vector4(red, green, blue, targetColor.Z)); packed.PackFromVector4(new Vector4(red, green, blue, targetColor.Z));
targetPixels[x, y] = packed; targetPixels[x, y] = packed;
} }
this.OnRowProcessed(); this.OnRowProcessed();
} }
}); });

25
tests/ImageProcessorCore.Tests/Processors/Filters/DetectEdgesTest.cs

@ -49,5 +49,30 @@ namespace ImageProcessorCore.Tests
} }
} }
} }
[Theory]
[MemberData("DetectEdgesFilters")]
public void ImageShouldApplyDetectEdgesFilterInBox(EdgeDetection detector)
{
const string path = "TestOutput/DetectEdges";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
foreach (string file in Files)
{
using (FileStream stream = File.OpenRead(file))
{
string filename = Path.GetFileNameWithoutExtension(file) + "-" + detector + "-InBox" + Path.GetExtension(file);
Image image = new Image(stream);
using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{
image.DetectEdges(detector, new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2))
.Save(output);
}
}
}
}
} }
} }
Loading…
Cancel
Save