规范类名及命名空间名称
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
// ============================================================================
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
// ============================================================================
|
||||
// Copyright 穢 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// ��辣�? KirschEdgeProcessor.cs
|
||||
// �讛膩: Kirsch颲寧�璉�瘚讠�摮琜��其�璉�瘚见㦛�讛器蝻?
|
||||
// �蠘�:
|
||||
// - Kirsch蝞堒�颲寧�璉�瘚?
|
||||
// - 8銝芣䲮�𤑳�颲寧�璉�瘚?
|
||||
// - 颲枏枂��憭批�摨娍䲮�𤑳�颲寧�
|
||||
// - 撖孵臁憯唳��笔漲雿?
|
||||
// 蝞埈�: Kirsch蝞堒�嚗?�孵�璅⊥踎嚗?
|
||||
// 雿𡏭�? �𦒘� wei.lw.li@hexagon.com
|
||||
// ============================================================================
|
||||
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.Structure;
|
||||
using Serilog;
|
||||
using XP.ImageProcessing.Core;
|
||||
|
||||
namespace XP.ImageProcessing.Processors;
|
||||
|
||||
/// <summary>
|
||||
/// Kirsch颲寧�璉�瘚讠�摮?
|
||||
/// </summary>
|
||||
public class KirschEdgeProcessor : ImageProcessorBase
|
||||
{
|
||||
private static readonly ILogger _logger = Log.ForContext<KirschEdgeProcessor>();
|
||||
|
||||
// Kirsch蝞堒��?銝芣䲮�烐芋�?
|
||||
private static readonly int[][,] KirschKernels = new int[8][,]
|
||||
{
|
||||
// N
|
||||
new int[,] { { 5, 5, 5 }, { -3, 0, -3 }, { -3, -3, -3 } },
|
||||
// NW
|
||||
new int[,] { { 5, 5, -3 }, { 5, 0, -3 }, { -3, -3, -3 } },
|
||||
// W
|
||||
new int[,] { { 5, -3, -3 }, { 5, 0, -3 }, { 5, -3, -3 } },
|
||||
// SW
|
||||
new int[,] { { -3, -3, -3 }, { 5, 0, -3 }, { 5, 5, -3 } },
|
||||
// S
|
||||
new int[,] { { -3, -3, -3 }, { -3, 0, -3 }, { 5, 5, 5 } },
|
||||
// SE
|
||||
new int[,] { { -3, -3, -3 }, { -3, 0, 5 }, { -3, 5, 5 } },
|
||||
// E
|
||||
new int[,] { { -3, -3, 5 }, { -3, 0, 5 }, { -3, -3, 5 } },
|
||||
// NE
|
||||
new int[,] { { -3, 5, 5 }, { -3, 0, 5 }, { -3, -3, -3 } }
|
||||
};
|
||||
|
||||
public KirschEdgeProcessor()
|
||||
{
|
||||
Name = LocalizationHelper.GetString("KirschEdgeProcessor_Name");
|
||||
Description = LocalizationHelper.GetString("KirschEdgeProcessor_Description");
|
||||
}
|
||||
|
||||
protected override void InitializeParameters()
|
||||
{
|
||||
Parameters.Add("Threshold", new ProcessorParameter(
|
||||
"Threshold",
|
||||
LocalizationHelper.GetString("KirschEdgeProcessor_Threshold"),
|
||||
typeof(int),
|
||||
100,
|
||||
0,
|
||||
1000,
|
||||
LocalizationHelper.GetString("KirschEdgeProcessor_Threshold_Desc")));
|
||||
|
||||
Parameters.Add("Scale", new ProcessorParameter(
|
||||
"Scale",
|
||||
LocalizationHelper.GetString("KirschEdgeProcessor_Scale"),
|
||||
typeof(double),
|
||||
1.0,
|
||||
0.1,
|
||||
5.0,
|
||||
LocalizationHelper.GetString("KirschEdgeProcessor_Scale_Desc")));
|
||||
_logger.Debug("InitializeParameters");
|
||||
}
|
||||
|
||||
public override Image<Gray, byte> Process(Image<Gray, byte> inputImage)
|
||||
{
|
||||
int threshold = GetParameter<int>("Threshold");
|
||||
double scale = GetParameter<double>("Scale");
|
||||
|
||||
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;
|
||||
|
||||
// 撖寞�銝芸�蝝惩��?銝枝irsch璅⊥踎嚗����憭批�摨?
|
||||
for (int y = 1; y < height - 1; y++)
|
||||
{
|
||||
for (int x = 1; x < width - 1; x++)
|
||||
{
|
||||
int maxResponse = 0;
|
||||
|
||||
// 撖?銝芣䲮�穃��怨恣蝞?
|
||||
for (int k = 0; k < 8; k++)
|
||||
{
|
||||
int sum = 0;
|
||||
for (int ky = 0; ky < 3; ky++)
|
||||
{
|
||||
for (int kx = 0; kx < 3; kx++)
|
||||
{
|
||||
int pixelValue = inputData[y + ky - 1, x + kx - 1, 0];
|
||||
sum += pixelValue * KirschKernels[k][ky, kx];
|
||||
}
|
||||
}
|
||||
|
||||
// �𣇉�撖孵�?
|
||||
sum = Math.Abs(sum);
|
||||
if (sum > maxResponse)
|
||||
{
|
||||
maxResponse = sum;
|
||||
}
|
||||
}
|
||||
|
||||
// 摨𠉛鍂���澆�蝻拇𦆮
|
||||
if (maxResponse > threshold)
|
||||
{
|
||||
int value = (int)(maxResponse * scale);
|
||||
outputData[y, x, 0] = (byte)Math.Min(255, Math.Max(0, value));
|
||||
}
|
||||
else
|
||||
{
|
||||
outputData[y, x, 0] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Debug("Process: Threshold = {Threshold}, Scale = {Scale}", threshold, scale);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
// ============================================================================
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user