@ -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 - star tY ;
int offsetY = y - shif tY ;
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 ) ;
}
}
}
}