// ============================================================================ // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 文件名: HistogramEqualizationProcessor.cs // 描述: 直方图均衡化算子,用于增强图像对比度 // 功能: // - 全局直方图均衡化 // - 自适应直方图均衡化(CLAHE) // - 限制对比度增强 // - 改善图像的整体对比度 // 算法: 直方图均衡化、CLAHE // 作者: 李伟 wei.lw.li@hexagon.com // ============================================================================ using Emgu.CV; using Emgu.CV.Structure; using XP.ImageProcessing.Core; using Serilog; namespace XP.ImageProcessing.Processors; /// /// 直方图均衡化算子 /// public class HistogramEqualizationProcessor : ImageProcessorBase { private static readonly ILogger _logger = Log.ForContext(); public HistogramEqualizationProcessor() { Name = LocalizationHelper.GetString("HistogramEqualizationProcessor_Name"); Description = LocalizationHelper.GetString("HistogramEqualizationProcessor_Description"); } protected override void InitializeParameters() { Parameters.Add("Method", new ProcessorParameter( "Method", LocalizationHelper.GetString("HistogramEqualizationProcessor_Method"), typeof(string), "Global", null, null, LocalizationHelper.GetString("HistogramEqualizationProcessor_Method_Desc"), new string[] { "Global", "CLAHE" })); Parameters.Add("ClipLimit", new ProcessorParameter( "ClipLimit", LocalizationHelper.GetString("HistogramEqualizationProcessor_ClipLimit"), typeof(double), 2.0, 1.0, 10.0, LocalizationHelper.GetString("HistogramEqualizationProcessor_ClipLimit_Desc"))); Parameters.Add("TileSize", new ProcessorParameter( "TileSize", LocalizationHelper.GetString("HistogramEqualizationProcessor_TileSize"), typeof(int), 8, 4, 32, LocalizationHelper.GetString("HistogramEqualizationProcessor_TileSize_Desc"))); _logger.Debug("InitializeParameters"); } public override Image Process(Image inputImage) { string method = GetParameter("Method"); double clipLimit = GetParameter("ClipLimit"); int tileSize = GetParameter("TileSize"); Image result; if (method == "CLAHE") { result = ApplyCLAHE(inputImage, clipLimit, tileSize); } else // Global { result = new Image(inputImage.Size); CvInvoke.EqualizeHist(inputImage, result); } _logger.Debug("Process: Method = {Method}, ClipLimit = {ClipLimit}, TileSize = {TileSize}", method, clipLimit, tileSize); return result; } private Image ApplyCLAHE(Image inputImage, double clipLimit, int tileSize) { int width = inputImage.Width; int height = inputImage.Height; int tilesX = (width + tileSize - 1) / tileSize; int tilesY = (height + tileSize - 1) / tileSize; var result = new Image(width, height); // 对每个tile进行直方图均衡化 for (int ty = 0; ty < tilesY; ty++) { for (int tx = 0; tx < tilesX; tx++) { int x = tx * tileSize; int y = ty * tileSize; int w = Math.Min(tileSize, width - x); int h = Math.Min(tileSize, height - y); var roi = new System.Drawing.Rectangle(x, y, w, h); inputImage.ROI = roi; var tile = inputImage.Copy(); inputImage.ROI = System.Drawing.Rectangle.Empty; // 应用直方图均衡化 var equalizedTile = new Image(tile.Size); CvInvoke.EqualizeHist(tile, equalizedTile); // 应用限制(简化版本) var floatTile = tile.Convert(); var floatEqualized = equalizedTile.Convert(); var diff = floatEqualized - floatTile; var limited = floatTile + diff * Math.Min(clipLimit / 10.0, 1.0); var limitedByte = limited.Convert(); // 复制到结果图像 result.ROI = roi; limitedByte.CopyTo(result); result.ROI = System.Drawing.Rectangle.Empty; tile.Dispose(); equalizedTile.Dispose(); floatTile.Dispose(); floatEqualized.Dispose(); diff.Dispose(); limited.Dispose(); limitedByte.Dispose(); } } return result; } }