Files
XplorePlane/XP.ImageProcessing.Processors/边缘检测/HorizontalEdgeProcessor.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

141 lines
5.8 KiB
C#

// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: HorizontalEdgeProcessor.cs
// 描述: 水平边缘检测算子,专门用于检测水平方向的边缘
// 功能:
// - 检测水平边缘
// - 支持Prewitt和Sobel算子
// - 可调节检测灵敏度
// - 适用于检测水平线条和纹理
// 算法: Prewitt/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>
/// 水平边缘检测算子(支持 8 位和 16 位灰度图像)
/// </summary>
public class HorizontalEdgeProcessor<TDepth> : ImageProcessorBase<TDepth>
where TDepth : struct, IComparable
{
private static readonly ILogger _logger = Log.ForContext<HorizontalEdgeProcessor<TDepth>>();
public HorizontalEdgeProcessor()
{
Name = LocalizationHelper.GetString("HorizontalEdgeProcessor_Name");
Description = LocalizationHelper.GetString("HorizontalEdgeProcessor_Description");
}
protected override void InitializeParameters()
{
Parameters.Add("Method", new ProcessorParameter(
"Method",
LocalizationHelper.GetString("HorizontalEdgeProcessor_Method"),
typeof(string),
"Sobel",
null,
null,
LocalizationHelper.GetString("HorizontalEdgeProcessor_Method_Desc"),
new string[] { "Sobel", "Prewitt", "Simple" }) { IsAdvanced = true });
Parameters.Add("Sensitivity", new ProcessorParameter(
"Sensitivity",
LocalizationHelper.GetString("HorizontalEdgeProcessor_Sensitivity"),
typeof(double),
1.0,
0.1,
5.0,
LocalizationHelper.GetString("HorizontalEdgeProcessor_Sensitivity_Desc")) { IsAdvanced = true });
Parameters.Add("Threshold", new ProcessorParameter(
"Threshold",
LocalizationHelper.GetString("HorizontalEdgeProcessor_Threshold"),
typeof(int),
20,
0,
255,
LocalizationHelper.GetString("HorizontalEdgeProcessor_Threshold_Desc")));
_logger.Debug("InitializeParameters");
}
public override Image<Gray, TDepth> Process(Image<Gray, TDepth> inputImage)
{
string method = GetParameter<string>("Method");
double sensitivity = GetParameter<double>("Sensitivity");
int threshold = GetParameter<int>("Threshold");
if (typeof(TDepth) == typeof(ushort))
threshold = PixelDepthHelper.ScaleThreshold<TDepth>(threshold);
Image<Gray, TDepth> result;
if (method == "Sobel")
result = ApplySobel(inputImage, sensitivity, threshold);
else if (method == "Prewitt")
result = ApplyPrewitt(inputImage, sensitivity, threshold);
else
result = ApplySimple(inputImage, sensitivity, threshold);
_logger.Debug("Process: Method = {Method}, Sensitivity = {Sensitivity}, Threshold = {Threshold}", method, sensitivity, threshold);
return result;
}
private Image<Gray, TDepth> ApplySobel(Image<Gray, TDepth> inputImage, double sensitivity, int threshold)
{
var sobelY = new Image<Gray, float>(inputImage.Size);
CvInvoke.Sobel(inputImage, sobelY, DepthType.Cv32F, 0, 1, 3);
var magnitude = new Image<Gray, float>(inputImage.Size);
for (int y = 0; y < inputImage.Height; y++)
for (int x = 0; x < inputImage.Width; x++)
{
float v = Math.Abs(sobelY.Data[y, x, 0]) * (float)sensitivity;
magnitude.Data[y, x, 0] = v >= threshold ? v : 0;
}
sobelY.Dispose();
var result = PixelDepthHelper.FromFloatImage<TDepth>(magnitude);
magnitude.Dispose();
return result;
}
private Image<Gray, TDepth> ApplyPrewitt(Image<Gray, TDepth> inputImage, double sensitivity, int threshold)
{
int width = inputImage.Width, height = inputImage.Height;
var result = new Image<Gray, TDepth>(width, height);
for (int y = 1; y < height - 1; y++)
for (int x = 1; x < width - 1; x++)
{
int sum = PixelDepthHelper.ReadPixel(inputImage, y - 1, x - 1)
+ PixelDepthHelper.ReadPixel(inputImage, y - 1, x)
+ PixelDepthHelper.ReadPixel(inputImage, y - 1, x + 1)
- PixelDepthHelper.ReadPixel(inputImage, y + 1, x - 1)
- PixelDepthHelper.ReadPixel(inputImage, y + 1, x)
- PixelDepthHelper.ReadPixel(inputImage, y + 1, x + 1);
int value = (int)(Math.Abs(sum) * sensitivity);
PixelDepthHelper.WritePixel(result, y, x, value > threshold ? value : 0);
}
return result;
}
private Image<Gray, TDepth> ApplySimple(Image<Gray, TDepth> inputImage, double sensitivity, int threshold)
{
int width = inputImage.Width, height = inputImage.Height;
var result = new Image<Gray, TDepth>(width, height);
for (int y = 1; y < height - 1; y++)
for (int x = 0; x < width; x++)
{
int diff = PixelDepthHelper.ReadPixel(inputImage, y - 1, x)
- PixelDepthHelper.ReadPixel(inputImage, y + 1, x);
int value = (int)(Math.Abs(diff) * sensitivity);
PixelDepthHelper.WritePixel(result, y, x, value > threshold ? value : 0);
}
return result;
}
}