Files
XplorePlane/XP.ImageProcessing.Processors/边缘检测/HorizontalEdgeProcessor.cs
T
2026-04-13 14:36:18 +08:00

199 lines
6.3 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 Serilog;
using XP.ImageProcessing.Core;
namespace XP.ImageProcessing.Processors;
/// <summary>
/// 水平边缘检测算�
/// </summary>
public class HorizontalEdgeProcessor : ImageProcessorBase
{
private static readonly ILogger _logger = Log.ForContext<HorizontalEdgeProcessor>();
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" }));
Parameters.Add("Sensitivity", new ProcessorParameter(
"Sensitivity",
LocalizationHelper.GetString("HorizontalEdgeProcessor_Sensitivity"),
typeof(double),
1.0,
0.1,
5.0,
LocalizationHelper.GetString("HorizontalEdgeProcessor_Sensitivity_Desc")));
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, byte> Process(Image<Gray, byte> inputImage)
{
string method = GetParameter<string>("Method");
double sensitivity = GetParameter<double>("Sensitivity");
int threshold = GetParameter<int>("Threshold");
Image<Gray, byte> result;
if (method == "Sobel")
{
result = ApplySobel(inputImage, sensitivity, threshold);
}
else if (method == "Prewitt")
{
result = ApplyPrewitt(inputImage, sensitivity, threshold);
}
else // Simple
{
result = ApplySimple(inputImage, sensitivity, threshold);
}
_logger.Debug("Process: Method = {Method}, Sensitivity = {Sensitivity}, Threshold = {Threshold}",
method, sensitivity, threshold);
return result;
}
private Image<Gray, byte> ApplySobel(Image<Gray, byte> inputImage, double sensitivity, int threshold)
{
// 使用Sobelç®—å­æ£€æµ‹æ°´å¹³è¾¹ç¼˜ï¼ˆYæ–¹å‘导数ï¼?
Image<Gray, float> sobelY = new Image<Gray, float>(inputImage.Size);
CvInvoke.Sobel(inputImage, sobelY, DepthType.Cv32F, 0, 1, 3);
// 转æ¢ä¸ºç»å¯¹å€¼å¹¶åº”ç”¨çµæ•åº?
Image<Gray, byte> result = new Image<Gray, byte>(inputImage.Size);
CvInvoke.ConvertScaleAbs(sobelY, result, sensitivity, 0);
// 应用阈�
if (threshold > 0)
{
CvInvoke.Threshold(result, result, threshold, 255, ThresholdType.Binary);
CvInvoke.Threshold(result, result, 0, 255, ThresholdType.ToZero);
}
sobelY.Dispose();
return result;
}
private Image<Gray, byte> ApplyPrewitt(Image<Gray, byte> inputImage, double sensitivity, int threshold)
{
// Prewitt水平算å­
// [ 1 1 1]
// [ 0 0 0]
// [-1 -1 -1]
int width = inputImage.Width;
int height = inputImage.Height;
byte[,,] inputData = inputImage.Data;
Image<Gray, byte> result = new Image<Gray, byte>(width, height);
byte[,,] outputData = result.Data;
for (int y = 1; y < height - 1; y++)
{
for (int x = 1; x < width - 1; x++)
{
int sum = 0;
// 上行
sum += inputData[y - 1, x - 1, 0];
sum += inputData[y - 1, x, 0];
sum += inputData[y - 1, x + 1, 0];
// 下行
sum -= inputData[y + 1, x - 1, 0];
sum -= inputData[y + 1, x, 0];
sum -= inputData[y + 1, x + 1, 0];
// å–ç»å¯¹å€¼å¹¶åº”ç”¨çµæ•åº?
int value = (int)(Math.Abs(sum) * sensitivity);
// 应用阈�
if (value > threshold)
{
outputData[y, x, 0] = (byte)Math.Min(255, value);
}
else
{
outputData[y, x, 0] = 0;
}
}
}
return result;
}
private Image<Gray, byte> ApplySimple(Image<Gray, byte> inputImage, double sensitivity, int threshold)
{
// 简å•差分算å­?
// [ 1 1 1]
// [ 0 0 0]
// [-1 -1 -1]
// 但æƒé‡æ›´ç®€å?
int width = inputImage.Width;
int height = inputImage.Height;
byte[,,] inputData = inputImage.Data;
Image<Gray, byte> result = new Image<Gray, byte>(width, height);
byte[,,] outputData = result.Data;
for (int y = 1; y < height - 1; y++)
{
for (int x = 0; x < width; x++)
{
// 简å•的上下差分
int diff = inputData[y - 1, x, 0] - inputData[y + 1, x, 0];
int value = (int)(Math.Abs(diff) * sensitivity);
// 应用阈�
if (value > threshold)
{
outputData[y, x, 0] = (byte)Math.Min(255, value);
}
else
{
outputData[y, x, 0] = 0;
}
}
}
return result;
}
}