// ============================================================================ // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 文件名: DifferenceProcessor.cs // 描述: 差分运算算子,用于边缘检测和变化检测 // 功能: // - 对图像进行差分运算 // - 支持水平、垂直和对角线差分 // - 可用于边缘检测 // - 可选归一化输出 // 算法: 像素级差分运算 // 作者: 李伟 wei.lw.li@hexagon.com // ============================================================================ using Emgu.CV; using Emgu.CV.Structure; using XP.ImageProcessing.Core; using Serilog; using System.Drawing; namespace XP.ImageProcessing.Processors; /// /// 差分运算算子 /// public class DifferenceProcessor : ImageProcessorBase { private static readonly ILogger _logger = Log.ForContext(); public DifferenceProcessor() { Name = LocalizationHelper.GetString("DifferenceProcessor_Name"); Description = LocalizationHelper.GetString("DifferenceProcessor_Description"); } protected override void InitializeParameters() { Parameters.Add("Direction", new ProcessorParameter( "Direction", LocalizationHelper.GetString("DifferenceProcessor_Direction"), typeof(string), "Horizontal", null, null, LocalizationHelper.GetString("DifferenceProcessor_Direction_Desc"), new string[] { "Horizontal", "Vertical", "Both" })); Parameters.Add("Normalize", new ProcessorParameter( "Normalize", LocalizationHelper.GetString("DifferenceProcessor_Normalize"), typeof(bool), true, null, null, LocalizationHelper.GetString("DifferenceProcessor_Normalize_Desc"))); _logger.Debug("InitializeParameters"); } public override Image Process(Image inputImage) { string direction = GetParameter("Direction"); bool normalize = GetParameter("Normalize"); int width = inputImage.Width; int height = inputImage.Height; var floatImage = inputImage.Convert(); var result = new Image(width, height); if (direction == "Horizontal") { // 水平差分: I(x+1,y) - I(x,y) for (int y = 0; y < height; y++) { for (int x = 0; x < width - 1; x++) { result.Data[y, x, 0] = floatImage.Data[y, x + 1, 0] - floatImage.Data[y, x, 0]; } result.Data[y, width - 1, 0] = 0; } } else if (direction == "Vertical") { // 垂直差分: I(x,y+1) - I(x,y) for (int y = 0; y < height - 1; y++) { for (int x = 0; x < width; x++) { result.Data[y, x, 0] = floatImage.Data[y + 1, x, 0] - floatImage.Data[y, x, 0]; } } for (int x = 0; x < width; x++) { result.Data[height - 1, x, 0] = 0; } } else // Both { // 梯度幅值: sqrt((dx)^2 + (dy)^2) for (int y = 0; y < height - 1; y++) { for (int x = 0; x < width - 1; x++) { float dx = floatImage.Data[y, x + 1, 0] - floatImage.Data[y, x, 0]; float dy = floatImage.Data[y + 1, x, 0] - floatImage.Data[y, x, 0]; result.Data[y, x, 0] = (float)Math.Sqrt(dx * dx + dy * dy); } } } if (normalize) { 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)); } } floatImage.Dispose(); _logger.Debug("Process: Direction = {Direction}, Normalize = {Normalize}", direction, normalize); return result.Convert(); } }