// ============================================================================
// 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 Serilog;
using XP.ImageProcessing.Core;
namespace XP.ImageProcessing.Processors;
///
/// Sobel边缘检测算?
///
public class SobelEdgeProcessor : ImageProcessorBase
{
private static readonly ILogger _logger = Log.ForContext();
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" }));
Parameters.Add("KernelSize", new ProcessorParameter(
"KernelSize",
LocalizationHelper.GetString("SobelEdgeProcessor_KernelSize"),
typeof(int),
3,
1,
7,
LocalizationHelper.GetString("SobelEdgeProcessor_KernelSize_Desc")));
Parameters.Add("Scale", new ProcessorParameter(
"Scale",
LocalizationHelper.GetString("SobelEdgeProcessor_Scale"),
typeof(double),
1.0,
0.1,
5.0,
LocalizationHelper.GetString("SobelEdgeProcessor_Scale_Desc")));
_logger.Debug("InitializeParameters");
}
public override Image Process(Image inputImage)
{
string direction = GetParameter("Direction");
int kernelSize = GetParameter("KernelSize");
double scale = GetParameter("Scale");
// 确保核大小为奇数
if (kernelSize % 2 == 0) kernelSize++;
if (kernelSize > 7) kernelSize = 7;
if (kernelSize < 1) kernelSize = 1;
Image sobelX = new Image(inputImage.Size);
Image sobelY = new Image(inputImage.Size);
Image result = new Image(inputImage.Size);
if (direction == "Horizontal" || direction == "Both")
{
// X方向(水平边缘)
CvInvoke.Sobel(inputImage, sobelX, DepthType.Cv32F, 1, 0, kernelSize);
}
if (direction == "Vertical" || direction == "Both")
{
// Y方向(垂直边缘)
CvInvoke.Sobel(inputImage, sobelY, DepthType.Cv32F, 0, 1, kernelSize);
}
if (direction == "Both")
{
// 计算梯度幅值:sqrt(Gx^2 + Gy^2)
Image magnitude = new Image(inputImage.Size);
// 手动计算幅?
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);
}
}
// 应用缩放并转换为字节类型
var scaled = magnitude * scale;
result = scaled.Convert();
magnitude.Dispose();
scaled.Dispose();
}
else if (direction == "Horizontal")
{
// 只使用X方向
CvInvoke.ConvertScaleAbs(sobelX, result, scale, 0);
}
else // Vertical
{
// 只使用Y方向
CvInvoke.ConvertScaleAbs(sobelY, result, scale, 0);
}
sobelX.Dispose();
sobelY.Dispose();
_logger.Debug("Process: Direction = {Direction}, KernelSize = {KernelSize}, Scale = {Scale}",
direction, kernelSize, scale);
return result;
}
}