135 lines
4.5 KiB
C#
135 lines
4.5 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 Serilog;
|
||
using XP.ImageProcessing.Core;
|
||
|
||
namespace XP.ImageProcessing.Processors;
|
||
|
||
/// <summary>
|
||
/// Sobel边缘检测算å?
|
||
/// </summary>
|
||
public class SobelEdgeProcessor : ImageProcessorBase
|
||
{
|
||
private static readonly ILogger _logger = Log.ForContext<SobelEdgeProcessor>();
|
||
|
||
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<Gray, byte> Process(Image<Gray, byte> 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);
|
||
Image<Gray, byte> result = new Image<Gray, byte>(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<Gray, float> magnitude = new Image<Gray, float>(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<Gray, byte>();
|
||
|
||
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;
|
||
}
|
||
} |