合并图像处理库,删除图像lib库

This commit is contained in:
李伟
2026-04-13 13:40:37 +08:00
parent 2a762396d5
commit c7ce4ea6a1
105 changed files with 16341 additions and 133 deletions
@@ -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 ImageProcessing.Core;
using Serilog;
namespace 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算子(8方向模板)
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog;
namespace ImageProcessing.Processors;
/// <summary>
/// Kirsch边缘检测算子
/// </summary>
public class KirschEdgeProcessor : ImageProcessorBase
{
private static readonly ILogger _logger = Log.ForContext<KirschEdgeProcessor>();
// Kirsch算子的8个方向模板
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;
// 对每个像素应用8个Kirsch模板,取最大响应
for (int y = 1; y < height - 1; y++)
{
for (int x = 1; x < width - 1; x++)
{
int maxResponse = 0;
// 对8个方向分别计算
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 ImageProcessing.Core;
using Serilog;
namespace 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;
}
}