合并图像处理库,删除图像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,197 @@
// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: BandPassFilterProcessor.cs
// 描述: 带通滤波器算子,用于频域图像处理
// 功能:
// - 在频域中保留特定频率范围的信号
// - 支持理想、巴特沃斯、高斯三种滤波器类型
// - 可调节低频和高频截止频率
// - 通过FFT实现频域滤波
// 算法: 基于离散傅里叶变换(DFT)的频域滤波
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog;
using System.Drawing;
namespace ImageProcessing.Processors;
/// <summary>
/// 带通滤波器算子
/// </summary>
public class BandPassFilterProcessor : ImageProcessorBase
{
private static readonly ILogger _logger = Log.ForContext<BandPassFilterProcessor>();
public BandPassFilterProcessor()
{
Name = LocalizationHelper.GetString("BandPassFilterProcessor_Name");
Description = LocalizationHelper.GetString("BandPassFilterProcessor_Description");
}
protected override void InitializeParameters()
{
Parameters.Add("LowCutoff", new ProcessorParameter(
"LowCutoff",
LocalizationHelper.GetString("BandPassFilterProcessor_LowCutoff"),
typeof(int),
10,
1,
200,
LocalizationHelper.GetString("BandPassFilterProcessor_LowCutoff_Desc")));
Parameters.Add("HighCutoff", new ProcessorParameter(
"HighCutoff",
LocalizationHelper.GetString("BandPassFilterProcessor_HighCutoff"),
typeof(int),
50,
2,
500,
LocalizationHelper.GetString("BandPassFilterProcessor_HighCutoff_Desc")));
Parameters.Add("FilterType", new ProcessorParameter(
"FilterType",
LocalizationHelper.GetString("BandPassFilterProcessor_FilterType"),
typeof(string),
"Ideal",
null,
null,
LocalizationHelper.GetString("BandPassFilterProcessor_FilterType_Desc"),
new string[] { "Ideal", "Butterworth", "Gaussian" }));
Parameters.Add("Order", new ProcessorParameter(
"Order",
LocalizationHelper.GetString("BandPassFilterProcessor_Order"),
typeof(int),
2,
1,
10,
LocalizationHelper.GetString("BandPassFilterProcessor_Order_Desc")));
_logger.Debug("InitializeParameters");
}
public override Image<Gray, byte> Process(Image<Gray, byte> inputImage)
{
int lowCutoff = GetParameter<int>("LowCutoff");
int highCutoff = GetParameter<int>("HighCutoff");
string filterType = GetParameter<string>("FilterType");
int order = GetParameter<int>("Order");
if (highCutoff <= lowCutoff)
{
highCutoff = lowCutoff + 10;
}
var floatImage = inputImage.Convert<Gray, float>();
var imaginaryImage = new Image<Gray, float>(floatImage.Size);
imaginaryImage.SetZero();
using (var planes = new Emgu.CV.Util.VectorOfMat())
{
planes.Push(floatImage.Mat);
planes.Push(imaginaryImage.Mat);
Mat complexMat = new Mat();
CvInvoke.Merge(planes, complexMat);
Mat dftMat = new Mat();
CvInvoke.Dft(complexMat, dftMat, DxtType.Forward, 0);
var mask = CreateBandPassMask(floatImage.Size, lowCutoff, highCutoff, filterType, order);
using (var dftPlanes = new Emgu.CV.Util.VectorOfMat())
{
CvInvoke.Split(dftMat, dftPlanes);
Mat real = dftPlanes[0];
Mat imag = dftPlanes[1];
CvInvoke.Multiply(real, mask.Mat, real);
CvInvoke.Multiply(imag, mask.Mat, imag);
using (var filteredPlanes = new Emgu.CV.Util.VectorOfMat())
{
filteredPlanes.Push(real);
filteredPlanes.Push(imag);
Mat filteredDft = new Mat();
CvInvoke.Merge(filteredPlanes, filteredDft);
Mat idftMat = new Mat();
CvInvoke.Dft(filteredDft, idftMat, DxtType.Inverse | DxtType.Scale, 0);
using (var idftPlanes = new Emgu.CV.Util.VectorOfMat())
{
CvInvoke.Split(idftMat, idftPlanes);
var result = new Image<Gray, float>(floatImage.Size);
idftPlanes[0].CopyTo(result);
double minVal = 0, maxVal = 0;
Point minLoc = new Point();
Point maxLoc = new Point();
CvInvoke.MinMaxLoc(result, ref minVal, ref maxVal, ref minLoc, ref maxLoc);
if (maxVal > minVal)
{
result = (result - minVal) * (255.0 / (maxVal - minVal));
}
complexMat.Dispose();
dftMat.Dispose();
filteredDft.Dispose();
idftMat.Dispose();
_logger.Debug("Process: LowCutoff = {0}, HighCutoff = {1}, FilterType = {2}, Order = {3}", lowCutoff, highCutoff, filterType, order);
return result.Convert<Gray, byte>();
}
}
}
}
}
private Image<Gray, float> CreateBandPassMask(Size size, int lowCutoff, int highCutoff, string filterType, int order)
{
var mask = new Image<Gray, float>(size);
int cx = size.Width / 2;
int cy = size.Height / 2;
for (int y = 0; y < size.Height; y++)
{
for (int x = 0; x < size.Width; x++)
{
double dx = x - cx;
double dy = y - cy;
double distance = Math.Sqrt(dx * dx + dy * dy);
float value = 0;
switch (filterType)
{
case "理想":
value = (distance >= lowCutoff && distance <= highCutoff) ? 1.0f : 0.0f;
break;
case "巴特沃斯":
double highPass = 1.0 / (1.0 + Math.Pow(lowCutoff / (distance + 0.001), 2 * order));
double lowPass = 1.0 / (1.0 + Math.Pow(distance / (highCutoff + 0.001), 2 * order));
value = (float)(highPass * lowPass);
break;
case "高斯":
double highPassGaussian = 1.0 - Math.Exp(-distance * distance / (2.0 * lowCutoff * lowCutoff));
double lowPassGaussian = Math.Exp(-distance * distance / (2.0 * highCutoff * highCutoff));
value = (float)(highPassGaussian * lowPassGaussian);
break;
}
mask.Data[y, x, 0] = value;
}
}
return mask;
}
}
@@ -0,0 +1,78 @@
// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: BilateralFilterProcessor.cs
// 描述: 双边滤波算子,用于保边降噪
// 功能:
// - 双边滤波
// - 保持边缘清晰的同时平滑图像
// - 可调节核大小和标准差
// 算法: 双边滤波
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog;
namespace ImageProcessing.Processors;
/// <summary>
/// 双边滤波算子
/// </summary>
public class BilateralFilterProcessor : ImageProcessorBase
{
private static readonly ILogger _logger = Log.ForContext<BilateralFilterProcessor>();
public BilateralFilterProcessor()
{
Name = LocalizationHelper.GetString("BilateralFilterProcessor_Name");
Description = LocalizationHelper.GetString("BilateralFilterProcessor_Description");
}
protected override void InitializeParameters()
{
Parameters.Add("Diameter", new ProcessorParameter(
"Diameter",
LocalizationHelper.GetString("BilateralFilterProcessor_Diameter"),
typeof(int),
9,
1,
31,
LocalizationHelper.GetString("BilateralFilterProcessor_Diameter_Desc")));
Parameters.Add("SigmaColor", new ProcessorParameter(
"SigmaColor",
LocalizationHelper.GetString("BilateralFilterProcessor_SigmaColor"),
typeof(double),
75.0,
1.0,
200.0,
LocalizationHelper.GetString("BilateralFilterProcessor_SigmaColor_Desc")));
Parameters.Add("SigmaSpace", new ProcessorParameter(
"SigmaSpace",
LocalizationHelper.GetString("BilateralFilterProcessor_SigmaSpace"),
typeof(double),
75.0,
1.0,
200.0,
LocalizationHelper.GetString("BilateralFilterProcessor_SigmaSpace_Desc")));
_logger.Debug("InitializeParameters");
}
public override Image<Gray, byte> Process(Image<Gray, byte> inputImage)
{
int diameter = GetParameter<int>("Diameter");
double sigmaColor = GetParameter<double>("SigmaColor");
double sigmaSpace = GetParameter<double>("SigmaSpace");
var result = inputImage.Clone();
CvInvoke.BilateralFilter(inputImage, result, diameter, sigmaColor, sigmaSpace);
_logger.Debug("Process: Diameter = {Diameter}, SigmaColor = {SigmaColor}, SigmaSpace = {SigmaSpace}",
diameter, sigmaColor, sigmaSpace);
return result;
}
}
@@ -0,0 +1,69 @@
// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: GaussianBlurProcessor.cs
// 描述: 高斯模糊算子,用于图像平滑和降噪
// 功能:
// - 高斯核卷积平滑
// - 可调节核大小和标准差
// - 有效去除高斯噪声
// - 保持边缘相对清晰
// 算法: 高斯滤波器卷积
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog;
namespace ImageProcessing.Processors;
/// <summary>
/// 高斯模糊算子
/// </summary>
public class GaussianBlurProcessor : ImageProcessorBase
{
private static readonly ILogger _logger = Log.ForContext<GammaProcessor>();
public GaussianBlurProcessor()
{
Name = LocalizationHelper.GetString("GaussianBlurProcessor_Name");
Description = LocalizationHelper.GetString("GaussianBlurProcessor_Description");
}
protected override void InitializeParameters()
{
Parameters.Add("KernelSize", new ProcessorParameter(
"KernelSize",
LocalizationHelper.GetString("GaussianBlurProcessor_KernelSize"),
typeof(int),
5,
1,
31,
LocalizationHelper.GetString("GaussianBlurProcessor_KernelSize_Desc")));
Parameters.Add("Sigma", new ProcessorParameter(
"Sigma",
LocalizationHelper.GetString("GaussianBlurProcessor_Sigma"),
typeof(double),
1.5,
0.1,
10.0,
LocalizationHelper.GetString("GaussianBlurProcessor_Sigma_Desc")));
_logger.Debug("InitializeParameters");
}
public override Image<Gray, byte> Process(Image<Gray, byte> inputImage)
{
int kernelSize = GetParameter<int>("KernelSize");
double sigma = GetParameter<double>("Sigma");
if (kernelSize % 2 == 0) kernelSize++;
var result = inputImage.Clone();
CvInvoke.GaussianBlur(inputImage, result,
new System.Drawing.Size(kernelSize, kernelSize), sigma);
_logger.Debug("Process: KernelSize = {KernelSize}, Sigma = {Sigma}", kernelSize, sigma);
return result;
}
}
@@ -0,0 +1,148 @@
// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: HighPassFilterProcessor.cs
// 描述: 高通滤波算子,用于边缘增强
// 功能:
// - 高通滤波(频域)
// - 边缘增强
// - 去除低频信息
// - 可调节截止频率
// 算法: 高斯高通滤波器(频域)
// 作者: 李伟 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 HighPassFilterProcessor : ImageProcessorBase
{
private static readonly ILogger _logger = Log.ForContext<HighPassFilterProcessor>();
public HighPassFilterProcessor()
{
Name = LocalizationHelper.GetString("HighPassFilterProcessor_Name");
Description = LocalizationHelper.GetString("HighPassFilterProcessor_Description");
}
protected override void InitializeParameters()
{
Parameters.Add("CutoffFrequency", new ProcessorParameter(
"CutoffFrequency",
LocalizationHelper.GetString("HighPassFilterProcessor_CutoffFrequency"),
typeof(double),
30.0,
1.0,
200.0,
LocalizationHelper.GetString("HighPassFilterProcessor_CutoffFrequency_Desc")));
_logger.Debug("InitializeParameters");
}
public override Image<Gray, byte> Process(Image<Gray, byte> inputImage)
{
double cutoffFrequency = GetParameter<double>("CutoffFrequency");
int rows = inputImage.Rows;
int cols = inputImage.Cols;
// 转换为浮点型
Image<Gray, float> floatImage = inputImage.Convert<Gray, float>();
// 创建复数图像用于FFT
Mat complexImage = new Mat();
using (var planes = new Emgu.CV.Util.VectorOfMat())
{
planes.Push(floatImage.Mat);
planes.Push(Mat.Zeros(rows, cols, DepthType.Cv32F, 1));
CvInvoke.Merge(planes, complexImage);
}
// 执行DFT
Mat dftImage = new Mat();
CvInvoke.Dft(complexImage, dftImage, DxtType.Forward);
// 分离实部和虚部
using (var dftPlanes = new Emgu.CV.Util.VectorOfMat())
{
CvInvoke.Split(dftImage, dftPlanes);
Mat real = dftPlanes[0];
Mat imag = dftPlanes[1];
// 创建高通滤波器
Mat filter = CreateHighPassFilter(rows, cols, cutoffFrequency);
// 应用滤波器
CvInvoke.Multiply(real, filter, real);
CvInvoke.Multiply(imag, filter, imag);
// 合并并执行逆DFT
using (var filteredPlanes = new Emgu.CV.Util.VectorOfMat())
{
filteredPlanes.Push(real);
filteredPlanes.Push(imag);
Mat filteredDft = new Mat();
CvInvoke.Merge(filteredPlanes, filteredDft);
Mat ifftImage = new Mat();
CvInvoke.Dft(filteredDft, ifftImage, DxtType.Inverse | DxtType.Scale);
// 分离实部
using (var ifftPlanes = new Emgu.CV.Util.VectorOfMat())
{
CvInvoke.Split(ifftImage, ifftPlanes);
// 转换回byte类型
Mat resultMat = new Mat();
ifftPlanes[0].ConvertTo(resultMat, DepthType.Cv8U);
Image<Gray, byte> result = resultMat.ToImage<Gray, byte>();
// 释放资源
floatImage.Dispose();
complexImage.Dispose();
dftImage.Dispose();
filter.Dispose();
filteredDft.Dispose();
ifftImage.Dispose();
resultMat.Dispose();
_logger.Debug("Process: CutoffFrequency = {CutoffFrequency}", cutoffFrequency);
return result;
}
}
}
}
/// <summary>
/// 创建高斯高通滤波器
/// </summary>
private Mat CreateHighPassFilter(int rows, int cols, double d0)
{
var filter = new Image<Gray, float>(cols, rows);
int centerX = cols / 2;
int centerY = rows / 2;
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
double distance = Math.Sqrt(Math.Pow(i - centerY, 2) + Math.Pow(j - centerX, 2));
float value = (float)(1 - Math.Exp(-(distance * distance) / (2 * d0 * d0)));
filter.Data[i, j, 0] = value;
}
}
return filter.Mat;
}
}
@@ -0,0 +1,148 @@
// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: LowPassFilterProcessor.cs
// 描述: 低通滤波算子,用于去除高频噪声
// 功能:
// - 低通滤波(频域)
// - 去除高频噪声
// - 平滑图像
// - 可调节截止频率
// 算法: 高斯低通滤波器(频域)
// 作者: 李伟 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 LowPassFilterProcessor : ImageProcessorBase
{
private static readonly ILogger _logger = Log.ForContext<LowPassFilterProcessor>();
public LowPassFilterProcessor()
{
Name = LocalizationHelper.GetString("LowPassFilterProcessor_Name");
Description = LocalizationHelper.GetString("LowPassFilterProcessor_Description");
}
protected override void InitializeParameters()
{
Parameters.Add("CutoffFrequency", new ProcessorParameter(
"CutoffFrequency",
LocalizationHelper.GetString("LowPassFilterProcessor_CutoffFrequency"),
typeof(double),
30.0,
1.0,
200.0,
LocalizationHelper.GetString("LowPassFilterProcessor_CutoffFrequency_Desc")));
_logger.Debug("InitializeParameters");
}
public override Image<Gray, byte> Process(Image<Gray, byte> inputImage)
{
double cutoffFrequency = GetParameter<double>("CutoffFrequency");
int rows = inputImage.Rows;
int cols = inputImage.Cols;
// 转换为浮点型
Image<Gray, float> floatImage = inputImage.Convert<Gray, float>();
// 创建复数图像用于FFT
Mat complexImage = new Mat();
using (var planes = new Emgu.CV.Util.VectorOfMat())
{
planes.Push(floatImage.Mat);
planes.Push(Mat.Zeros(rows, cols, DepthType.Cv32F, 1));
CvInvoke.Merge(planes, complexImage);
}
// 执行DFT
Mat dftImage = new Mat();
CvInvoke.Dft(complexImage, dftImage, DxtType.Forward);
// 分离实部和虚部
using (var dftPlanes = new Emgu.CV.Util.VectorOfMat())
{
CvInvoke.Split(dftImage, dftPlanes);
Mat real = dftPlanes[0];
Mat imag = dftPlanes[1];
// 创建低通滤波器
Mat filter = CreateLowPassFilter(rows, cols, cutoffFrequency);
// 应用滤波器
CvInvoke.Multiply(real, filter, real);
CvInvoke.Multiply(imag, filter, imag);
// 合并并执行逆DFT
using (var filteredPlanes = new Emgu.CV.Util.VectorOfMat())
{
filteredPlanes.Push(real);
filteredPlanes.Push(imag);
Mat filteredDft = new Mat();
CvInvoke.Merge(filteredPlanes, filteredDft);
Mat ifftImage = new Mat();
CvInvoke.Dft(filteredDft, ifftImage, DxtType.Inverse | DxtType.Scale);
// 分离实部
using (var ifftPlanes = new Emgu.CV.Util.VectorOfMat())
{
CvInvoke.Split(ifftImage, ifftPlanes);
// 转换回byte类型
Mat resultMat = new Mat();
ifftPlanes[0].ConvertTo(resultMat, DepthType.Cv8U);
Image<Gray, byte> result = resultMat.ToImage<Gray, byte>();
// 释放资源
floatImage.Dispose();
complexImage.Dispose();
dftImage.Dispose();
filter.Dispose();
filteredDft.Dispose();
ifftImage.Dispose();
resultMat.Dispose();
_logger.Debug("Process: CutoffFrequency = {CutoffFrequency}", cutoffFrequency);
return result;
}
}
}
}
/// <summary>
/// 创建高斯低通滤波器
/// </summary>
private Mat CreateLowPassFilter(int rows, int cols, double d0)
{
var filter = new Image<Gray, float>(cols, rows);
int centerX = cols / 2;
int centerY = rows / 2;
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
double distance = Math.Sqrt(Math.Pow(i - centerY, 2) + Math.Pow(j - centerX, 2));
float value = (float)Math.Exp(-(distance * distance) / (2 * d0 * d0));
filter.Data[i, j, 0] = value;
}
}
return filter.Mat;
}
}
@@ -0,0 +1,61 @@
// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: MeanFilterProcessor.cs
// 描述: 均值滤波算子,用于图像平滑
// 功能:
// - 均值滤波
// - 简单快速的平滑方法
// - 可调节核大小
// 算法: 均值滤波
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog;
using System.Drawing;
namespace ImageProcessing.Processors;
/// <summary>
/// 均值滤波算子
/// </summary>
public class MeanFilterProcessor : ImageProcessorBase
{
private static readonly ILogger _logger = Log.ForContext<MeanFilterProcessor>();
public MeanFilterProcessor()
{
Name = LocalizationHelper.GetString("MeanFilterProcessor_Name");
Description = LocalizationHelper.GetString("MeanFilterProcessor_Description");
}
protected override void InitializeParameters()
{
Parameters.Add("KernelSize", new ProcessorParameter(
"KernelSize",
LocalizationHelper.GetString("MeanFilterProcessor_KernelSize"),
typeof(int),
5,
1,
31,
LocalizationHelper.GetString("MeanFilterProcessor_KernelSize_Desc")));
_logger.Debug("InitializeParameters");
}
public override Image<Gray, byte> Process(Image<Gray, byte> inputImage)
{
int kernelSize = GetParameter<int>("KernelSize");
// 确保核大小为奇数
if (kernelSize % 2 == 0) kernelSize++;
var result = inputImage.Clone();
CvInvoke.Blur(inputImage, result, new Size(kernelSize, kernelSize), new Point(-1, -1));
_logger.Debug("Process: KernelSize = {KernelSize}", kernelSize);
return result;
}
}
@@ -0,0 +1,61 @@
// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: MedianFilterProcessor.cs
// 描述: 中值滤波算子,用于去除椒盐噪声
// 功能:
// - 中值滤波
// - 有效去除椒盐噪声
// - 保持边缘清晰
// - 可调节核大小
// 算法: 中值滤波
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog;
namespace ImageProcessing.Processors;
/// <summary>
/// 中值滤波算子
/// </summary>
public class MedianFilterProcessor : ImageProcessorBase
{
private static readonly ILogger _logger = Log.ForContext<MedianFilterProcessor>();
public MedianFilterProcessor()
{
Name = LocalizationHelper.GetString("MedianFilterProcessor_Name");
Description = LocalizationHelper.GetString("MedianFilterProcessor_Description");
}
protected override void InitializeParameters()
{
Parameters.Add("KernelSize", new ProcessorParameter(
"KernelSize",
LocalizationHelper.GetString("MedianFilterProcessor_KernelSize"),
typeof(int),
5,
1,
31,
LocalizationHelper.GetString("MedianFilterProcessor_KernelSize_Desc")));
_logger.Debug("InitializeParameters");
}
public override Image<Gray, byte> Process(Image<Gray, byte> inputImage)
{
int kernelSize = GetParameter<int>("KernelSize");
// 确保核大小为奇数
if (kernelSize % 2 == 0) kernelSize++;
var result = inputImage.Clone();
CvInvoke.MedianBlur(inputImage, result, kernelSize);
_logger.Debug("Process: KernelSize = {KernelSize}", kernelSize);
return result;
}
}
@@ -0,0 +1,123 @@
// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: ShockFilterProcessor.cs
// 描述: 冲击滤波算子,用于图像锐化和边缘增强
// 功能:
// - 基于PDE的图像锐化
// - 增强边缘同时保持平滑区域
// - 可调节迭代次数和滤波强度
// - 适用于模糊图像的恢复
// 算法: 冲击滤波器(Shock Filter)基于偏微分方程
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog;
namespace ImageProcessing.Processors;
/// <summary>
/// 冲击滤波算子
/// </summary>
public class ShockFilterProcessor : ImageProcessorBase
{
private static readonly ILogger _logger = Log.ForContext<ShockFilterProcessor>();
public ShockFilterProcessor()
{
Name = LocalizationHelper.GetString("ShockFilterProcessor_Name");
Description = LocalizationHelper.GetString("ShockFilterProcessor_Description");
}
protected override void InitializeParameters()
{
Parameters.Add("Iterations", new ProcessorParameter(
"Iterations",
LocalizationHelper.GetString("ShockFilterProcessor_Iterations"),
typeof(int),
5,
1,
20,
LocalizationHelper.GetString("ShockFilterProcessor_Iterations_Desc")));
Parameters.Add("Theta", new ProcessorParameter(
"Theta",
LocalizationHelper.GetString("ShockFilterProcessor_Theta"),
typeof(double),
0.5,
0.0,
2.0,
LocalizationHelper.GetString("ShockFilterProcessor_Theta_Desc")));
Parameters.Add("Dt", new ProcessorParameter(
"Dt",
LocalizationHelper.GetString("ShockFilterProcessor_Dt"),
typeof(double),
0.25,
0.1,
1.0,
LocalizationHelper.GetString("ShockFilterProcessor_Dt_Desc")));
_logger.Debug("InitializeParameters");
}
public override Image<Gray, byte> Process(Image<Gray, byte> inputImage)
{
int iterations = GetParameter<int>("Iterations");
double theta = GetParameter<double>("Theta");
double dt = GetParameter<double>("Dt");
var result = inputImage.Convert<Gray, float>();
for (int iter = 0; iter < iterations; iter++)
{
result = ShockFilterIteration(result, theta, dt);
}
_logger.Debug("Process: Iterations = {Iterations}, Theta = {Theta}, Dt = {Dt}", iterations, theta, dt);
return result.Convert<Gray, byte>();
}
private Image<Gray, float> ShockFilterIteration(Image<Gray, float> input, double theta, double dt)
{
int width = input.Width;
int height = input.Height;
var output = new Image<Gray, float>(width, height);
for (int y = 1; y < height - 1; y++)
{
for (int x = 1; x < width - 1; x++)
{
float dx = (input.Data[y, x + 1, 0] - input.Data[y, x - 1, 0]) / 2.0f;
float dy = (input.Data[y + 1, x, 0] - input.Data[y - 1, x, 0]) / 2.0f;
float gradMag = (float)Math.Sqrt(dx * dx + dy * dy);
float dxx = input.Data[y, x + 1, 0] - 2 * input.Data[y, x, 0] + input.Data[y, x - 1, 0];
float dyy = input.Data[y + 1, x, 0] - 2 * input.Data[y, x, 0] + input.Data[y - 1, x, 0];
float laplacian = dxx + dyy;
float sign = laplacian > 0 ? 1.0f : -1.0f;
if (gradMag > theta)
{
output.Data[y, x, 0] = input.Data[y, x, 0] - (float)(dt * sign * gradMag);
}
else
{
output.Data[y, x, 0] = input.Data[y, x, 0];
}
}
}
for (int x = 0; x < width; x++)
{
output.Data[0, x, 0] = input.Data[0, x, 0];
output.Data[height - 1, x, 0] = input.Data[height - 1, x, 0];
}
for (int y = 0; y < height; y++)
{
output.Data[y, 0, 0] = input.Data[y, 0, 0];
output.Data[y, width - 1, 0] = input.Data[y, width - 1, 0];
}
return output;
}
}