133 lines
4.4 KiB
C#
133 lines
4.4 KiB
C#
// ============================================================================
|
|
// 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;
|
|
}
|
|
} |