Files
XplorePlane/XP.ImageProcessing.Processors/边缘检测/SobelEdgeProcessor.cs
T
wei.lw.li d5d964d115 feat: 滤波/边缘检测算子标记高级参数
滤波类:GaussianBlur(Sigma)、Bilateral(SigmaSpace)、
BandPass(FilterType,Order)、ShockFilter(Dt)
边缘检测:Sobel(Direction,KernelSize,Scale)、
HorizontalEdge(Method,Sensitivity)、Kirsch(Scale)
2026-08-12 09:25:08 +08:00

121 lines
4.6 KiB
C#

// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: SobelEdgeProcessor.cs
// 描述: Sobel边缘检测算子,用于检测图像边缘
// 功能:
// - Sobel算子边缘检测
// - 支持X方向、Y方向和组合检测
// - 可调节核大小
// - 输出边缘强度图
// 算法: Sobel算子
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using XP.ImageProcessing.Core;
using Serilog;
namespace XP.ImageProcessing.Processors;
/// <summary>
/// Sobel边缘检测算子(支持 8 位和 16 位灰度图像)
/// </summary>
public class SobelEdgeProcessor<TDepth> : ImageProcessorBase<TDepth>
where TDepth : struct, IComparable
{
private static readonly ILogger _logger = Log.ForContext<SobelEdgeProcessor<TDepth>>();
public SobelEdgeProcessor()
{
Name = LocalizationHelper.GetString("SobelEdgeProcessor_Name");
Description = LocalizationHelper.GetString("SobelEdgeProcessor_Description");
}
protected override void InitializeParameters()
{
Parameters.Add("Direction", new ProcessorParameter(
"Direction",
LocalizationHelper.GetString("SobelEdgeProcessor_Direction"),
typeof(string),
"Both",
null,
null,
LocalizationHelper.GetString("SobelEdgeProcessor_Direction_Desc"),
new string[] { "Both", "Horizontal", "Vertical" }) { IsAdvanced = true });
Parameters.Add("KernelSize", new ProcessorParameter(
"KernelSize",
LocalizationHelper.GetString("SobelEdgeProcessor_KernelSize"),
typeof(int),
3,
1,
7,
LocalizationHelper.GetString("SobelEdgeProcessor_KernelSize_Desc")) { IsAdvanced = true });
Parameters.Add("Scale", new ProcessorParameter(
"Scale",
LocalizationHelper.GetString("SobelEdgeProcessor_Scale"),
typeof(double),
1.0,
0.1,
5.0,
LocalizationHelper.GetString("SobelEdgeProcessor_Scale_Desc")) { IsAdvanced = true });
_logger.Debug("InitializeParameters");
}
public override Image<Gray, TDepth> Process(Image<Gray, TDepth> inputImage)
{
string direction = GetParameter<string>("Direction");
int kernelSize = GetParameter<int>("KernelSize");
double scale = GetParameter<double>("Scale");
if (kernelSize % 2 == 0) kernelSize++;
if (kernelSize > 7) kernelSize = 7;
if (kernelSize < 1) kernelSize = 1;
Image<Gray, float> sobelX = new Image<Gray, float>(inputImage.Size);
Image<Gray, float> sobelY = new Image<Gray, float>(inputImage.Size);
if (direction == "Horizontal" || direction == "Both")
CvInvoke.Sobel(inputImage, sobelX, DepthType.Cv32F, 1, 0, kernelSize);
if (direction == "Vertical" || direction == "Both")
CvInvoke.Sobel(inputImage, sobelY, DepthType.Cv32F, 0, 1, kernelSize);
Image<Gray, float> magnitude = new Image<Gray, float>(inputImage.Size);
if (direction == "Both")
{
for (int y = 0; y < inputImage.Height; y++)
for (int x = 0; x < inputImage.Width; x++)
{
float gx = sobelX.Data[y, x, 0];
float gy = sobelY.Data[y, x, 0];
magnitude.Data[y, x, 0] = (float)Math.Sqrt(gx * gx + gy * gy) * (float)scale;
}
}
else if (direction == "Horizontal")
{
for (int y = 0; y < inputImage.Height; y++)
for (int x = 0; x < inputImage.Width; x++)
magnitude.Data[y, x, 0] = Math.Abs(sobelX.Data[y, x, 0]) * (float)scale;
}
else
{
for (int y = 0; y < inputImage.Height; y++)
for (int x = 0; x < inputImage.Width; x++)
magnitude.Data[y, x, 0] = Math.Abs(sobelY.Data[y, x, 0]) * (float)scale;
}
sobelX.Dispose();
sobelY.Dispose();
var result = PixelDepthHelper.FromFloatImage<TDepth>(magnitude);
magnitude.Dispose();
_logger.Debug("Process: Direction = {Direction}, KernelSize = {KernelSize}, Scale = {Scale}", direction, kernelSize, scale);
return result;
}
}