mirror of https://github.com/SixLabors/ImageSharp
Browse Source
Former-commit-id: 604e3759aba908e0614162aeeb1342fc8bbea41f Former-commit-id: 4ffda848ba0286e0dda46fb65c0c187a99a9481b Former-commit-id: 00ae35f7a65252bccd9a52adce6b26183d4a8a01pull/17/head
15 changed files with 483 additions and 3 deletions
@ -0,0 +1,97 @@ |
|||||
|
// <copyright file="Convolution2DFilter.cs" company="James South">
|
||||
|
// Copyright (c) James South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessor.Filters |
||||
|
{ |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines a filter that uses a matrix to perform convolution across two dimensions against an image.
|
||||
|
/// </summary>
|
||||
|
public abstract class Convolution2DFilter : ParallelImageProcessor |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets the horizontal gradient operator.
|
||||
|
/// </summary>
|
||||
|
public abstract float[,] KernelX { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the vertical gradient operator.
|
||||
|
/// </summary>
|
||||
|
public abstract float[,] KernelY { get; } |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) |
||||
|
{ |
||||
|
float[,] kernelX = this.KernelX; |
||||
|
float[,] kernelY = this.KernelY; |
||||
|
int kernelLength = kernelX.GetLength(0); |
||||
|
int radius = kernelLength >> 1; |
||||
|
|
||||
|
int sourceY = sourceRectangle.Y; |
||||
|
int sourceBottom = sourceRectangle.Bottom; |
||||
|
int startX = sourceRectangle.X; |
||||
|
int endX = sourceRectangle.Right; |
||||
|
int maxY = sourceBottom - 1; |
||||
|
int maxX = endX - 1; |
||||
|
|
||||
|
Parallel.For( |
||||
|
startY, |
||||
|
endY, |
||||
|
y => |
||||
|
{ |
||||
|
if (y >= sourceY && y < sourceBottom) |
||||
|
{ |
||||
|
for (int x = startX; x < endX; x++) |
||||
|
{ |
||||
|
float rX = 0; |
||||
|
float gX = 0; |
||||
|
float bX = 0; |
||||
|
float rY = 0; |
||||
|
float gY = 0; |
||||
|
float bY = 0; |
||||
|
|
||||
|
// Apply each matrix multiplier to the color components for each pixel.
|
||||
|
for (int fy = 0; fy < kernelLength; fy++) |
||||
|
{ |
||||
|
int fyr = fy - radius; |
||||
|
int offsetY = y + fyr; |
||||
|
|
||||
|
offsetY = offsetY.Clamp(0, maxY); |
||||
|
|
||||
|
for (int fx = 0; fx < kernelLength; fx++) |
||||
|
{ |
||||
|
int fxr = fx - radius; |
||||
|
int offsetX = x + fxr; |
||||
|
|
||||
|
offsetX = offsetX.Clamp(0, maxX); |
||||
|
|
||||
|
Color currentColor = source[offsetX, offsetY]; |
||||
|
float r = currentColor.R; |
||||
|
float g = currentColor.G; |
||||
|
float b = currentColor.B; |
||||
|
|
||||
|
rX += kernelX[fy, fx] * r; |
||||
|
gX += kernelX[fy, fx] * g; |
||||
|
bX += kernelX[fy, fx] * b; |
||||
|
|
||||
|
rY += kernelY[fy, fx] * r; |
||||
|
gY += kernelY[fy, fx] * g; |
||||
|
bY += kernelY[fy, fx] * b; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
float red = (float)Math.Sqrt((rX * rX) + (rY * rY)); |
||||
|
float green = (float)Math.Sqrt((gX * gX) + (gY * gY)); |
||||
|
float blue = (float)Math.Sqrt((bX * bX) + (bY * bY)); |
||||
|
|
||||
|
target[x, y] = new Color(red, green, blue); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,83 @@ |
|||||
|
// <copyright file="ConvolutionFilter.cs" company="James South">
|
||||
|
// Copyright (c) James South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
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.
|
||||
|
/// </summary>
|
||||
|
public abstract class ConvolutionFilter : ParallelImageProcessor |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets the horizontal gradient operator.
|
||||
|
/// </summary>
|
||||
|
public abstract float[,] KernelX { get; } |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) |
||||
|
{ |
||||
|
float[,] kernelX = this.KernelX; |
||||
|
int kernelLength = kernelX.GetLength(0); |
||||
|
int radius = kernelLength >> 1; |
||||
|
|
||||
|
int sourceY = sourceRectangle.Y; |
||||
|
int sourceBottom = sourceRectangle.Bottom; |
||||
|
int startX = sourceRectangle.X; |
||||
|
int endX = sourceRectangle.Right; |
||||
|
int maxY = sourceBottom - 1; |
||||
|
int maxX = endX - 1; |
||||
|
|
||||
|
Parallel.For( |
||||
|
startY, |
||||
|
endY, |
||||
|
y => |
||||
|
{ |
||||
|
if (y >= sourceY && y < sourceBottom) |
||||
|
{ |
||||
|
for (int x = startX; x < endX; x++) |
||||
|
{ |
||||
|
float rX = 0; |
||||
|
float gX = 0; |
||||
|
float bX = 0; |
||||
|
|
||||
|
// Apply each matrix multiplier to the color components for each pixel.
|
||||
|
for (int fy = 0; fy < kernelLength; fy++) |
||||
|
{ |
||||
|
int fyr = fy - radius; |
||||
|
int offsetY = y + fyr; |
||||
|
|
||||
|
offsetY = offsetY.Clamp(0, maxY); |
||||
|
|
||||
|
for (int fx = 0; fx < kernelLength; fx++) |
||||
|
{ |
||||
|
int fxr = fx - radius; |
||||
|
int offsetX = x + fxr; |
||||
|
|
||||
|
offsetX = offsetX.Clamp(0, maxX); |
||||
|
|
||||
|
Color currentColor = source[offsetX, offsetY]; |
||||
|
float r = currentColor.R; |
||||
|
float g = currentColor.G; |
||||
|
float b = currentColor.B; |
||||
|
|
||||
|
rX += kernelX[fy, fx] * r; |
||||
|
gX += kernelX[fy, fx] * g; |
||||
|
bX += kernelX[fy, fx] * b; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
float red = rX; |
||||
|
float green = gX; |
||||
|
float blue = bX; |
||||
|
|
||||
|
target[x, y] = new Color(red, green, blue); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
// <copyright file="Kayyali.cs" company="James South">
|
||||
|
// Copyright (c) James South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessor.Filters |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The Kayyali operator filter.
|
||||
|
/// <see href="http://edgedetection.webs.com/"/>
|
||||
|
/// </summary>
|
||||
|
public class Kayyali : Convolution2DFilter |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets the horizontal gradient operator.
|
||||
|
/// </summary>
|
||||
|
public override float[,] KernelX => new float[,] |
||||
|
{ |
||||
|
{ 6, 0, -6 }, |
||||
|
{ 0, 0, 0 }, |
||||
|
{ -6, 0, 6 } |
||||
|
}; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the vertical gradient operator.
|
||||
|
/// </summary>
|
||||
|
public override float[,] KernelY => new float[,] |
||||
|
{ |
||||
|
{ -6, 0, 6 }, |
||||
|
{ 0, 0, 0 }, |
||||
|
{ 6, 0, -6 } |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
// <copyright file="Kirsch.cs" company="James South">
|
||||
|
// Copyright (c) James South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessor.Filters |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The Kirsch operator filter.
|
||||
|
/// <see href="http://en.wikipedia.org/wiki/Kirsch_operator"/>
|
||||
|
/// </summary>
|
||||
|
public class Kirsch : Convolution2DFilter |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets the horizontal gradient operator.
|
||||
|
/// </summary>
|
||||
|
public override float[,] KernelX => new float[,] |
||||
|
{ |
||||
|
{ 5, 5, 5 }, |
||||
|
{ -3, 0, -3 }, |
||||
|
{ -3, -3, -3 } |
||||
|
}; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the vertical gradient operator.
|
||||
|
/// </summary>
|
||||
|
public override float[,] KernelY => new float[,] |
||||
|
{ |
||||
|
{ 5, -3, -3 }, |
||||
|
{ 5, 0, -3 }, |
||||
|
{ 5, -3, -3 } |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
// <copyright file="Laplacian3X3.cs" company="James South">
|
||||
|
// Copyright (c) James South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessor.Filters |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The Laplacian 3 x 3 operator filter.
|
||||
|
/// <see href="http://en.wikipedia.org/wiki/Discrete_Laplace_operator"/>
|
||||
|
/// </summary>
|
||||
|
public class Laplacian3X3 : ConvolutionFilter |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets the horizontal gradient operator.
|
||||
|
/// </summary>
|
||||
|
public override float[,] KernelX => new float[,] |
||||
|
{ |
||||
|
{ -1, -1, -1 }, |
||||
|
{ -1, 8, -1 }, |
||||
|
{ -1, -1, -1 } |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
// <copyright file="Laplacian5X5.cs" company="James South">
|
||||
|
// Copyright (c) James South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessor.Filters |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The Laplacian 5 x 5 operator filter.
|
||||
|
/// <see href="http://en.wikipedia.org/wiki/Discrete_Laplace_operator"/>
|
||||
|
/// </summary>
|
||||
|
public class Laplacian5X5 : ConvolutionFilter |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets the horizontal gradient operator.
|
||||
|
/// </summary>
|
||||
|
public override float[,] KernelX => new float[,] |
||||
|
{ |
||||
|
{ -1, -1, -1, -1, -1 }, |
||||
|
{ -1, -1, -1, -1, -1 }, |
||||
|
{ -1, -1, 24, -1, -1 }, |
||||
|
{ -1, -1, -1, -1, -1 }, |
||||
|
{ -1, -1, -1, -1, -1 } |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
// <copyright file="LaplacianOfGaussian.cs" company="James South">
|
||||
|
// Copyright (c) James South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessor.Filters |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The Laplacian of Gaussian operator filter.
|
||||
|
/// <see href="http://fourier.eng.hmc.edu/e161/lectures/gradient/node9.html"/>
|
||||
|
/// </summary>
|
||||
|
public class LaplacianOfGaussian : ConvolutionFilter |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets the horizontal gradient operator.
|
||||
|
/// </summary>
|
||||
|
public override float[,] KernelX => new float[,] |
||||
|
{ |
||||
|
{ 0, 0, -1, 0, 0 }, |
||||
|
{ 0, -1, -2, -1, 0 }, |
||||
|
{ -1, -2, 16, -2, -1 }, |
||||
|
{ 0, -1, -2, -1, 0 }, |
||||
|
{ 0, 0, -1, 0, 0 } |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
// <copyright file="Prewitt.cs" company="James South">
|
||||
|
// Copyright (c) James South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessor.Filters |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The Prewitt operator filter.
|
||||
|
/// <see href="http://en.wikipedia.org/wiki/Prewitt_operator"/>
|
||||
|
/// </summary>
|
||||
|
public class Prewitt : Convolution2DFilter |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets the horizontal gradient operator.
|
||||
|
/// </summary>
|
||||
|
public override float[,] KernelX => new float[,] |
||||
|
{ |
||||
|
{ -1, 0, 1 }, |
||||
|
{ -1, 0, 1 }, |
||||
|
{ -1, 0, 1 } |
||||
|
}; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the vertical gradient operator.
|
||||
|
/// </summary>
|
||||
|
public override float[,] KernelY => new float[,] |
||||
|
{ |
||||
|
{ 1, 1, 1 }, |
||||
|
{ 0, 0, 0 }, |
||||
|
{ -1, -1, -1 } |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
// <copyright file="RobertsCross.cs" company="James South">
|
||||
|
// Copyright (c) James South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessor.Filters |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The Roberts Cross operator filter.
|
||||
|
/// <see href="http://en.wikipedia.org/wiki/Roberts_cross"/>
|
||||
|
/// </summary>
|
||||
|
public class RobertsCross : Convolution2DFilter |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets the horizontal gradient operator.
|
||||
|
/// </summary>
|
||||
|
public override float[,] KernelX => new float[,] |
||||
|
{ |
||||
|
{ 1, 0 }, |
||||
|
{ 0, -1 } |
||||
|
}; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the vertical gradient operator.
|
||||
|
/// </summary>
|
||||
|
public override float[,] KernelY => new float[,] |
||||
|
{ |
||||
|
{ 0, 1 }, |
||||
|
{ -1, 0 } |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
// <copyright file="Scharr.cs" company="James South">
|
||||
|
// Copyright (c) James South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessor.Filters |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The Scharr operator filter.
|
||||
|
/// <see href="http://en.wikipedia.org/wiki/Sobel_operator#Alternative_operators"/>
|
||||
|
/// </summary>
|
||||
|
public class Scharr : Convolution2DFilter |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets the horizontal gradient operator.
|
||||
|
/// </summary>
|
||||
|
public override float[,] KernelX => new float[,] |
||||
|
{ |
||||
|
{ -3, 0, 3 }, |
||||
|
{ -10, 0, 10 }, |
||||
|
{ -3, 0, 3 } |
||||
|
}; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the vertical gradient operator.
|
||||
|
/// </summary>
|
||||
|
public override float[,] KernelY => new float[,] |
||||
|
{ |
||||
|
{ 3, 10, 3 }, |
||||
|
{ 0, 0, 0 }, |
||||
|
{ -3, -10, -3 } |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
// <copyright file="Sobel.cs" company="James South">
|
||||
|
// Copyright (c) James South and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
|
||||
|
namespace ImageProcessor.Filters |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The Sobel operator filter.
|
||||
|
/// <see href="http://en.wikipedia.org/wiki/Sobel_operator"/>
|
||||
|
/// </summary>
|
||||
|
public class Sobel : Convolution2DFilter |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets the horizontal gradient operator.
|
||||
|
/// </summary>
|
||||
|
public override float[,] KernelX => new float[,] |
||||
|
{ |
||||
|
{ -1, 0, 1 }, |
||||
|
{ -2, 0, 2 }, |
||||
|
{ -1, 0, 1 } |
||||
|
}; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the vertical gradient operator.
|
||||
|
/// </summary>
|
||||
|
public override float[,] KernelY => new float[,] |
||||
|
{ |
||||
|
{ 1, 2, 1 }, |
||||
|
{ 0, 0, 0 }, |
||||
|
{ -1, -2, -1 } |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -1 +1 @@ |
|||||
eb00c54ee74016c2b70f81963e7e8f83cb2dd54b |
3f05708641eb3ed085d4689aae4a960eb067fd16 |
||||
Loading…
Reference in new issue