// ============================================================================ // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 文件? HierarchicalEnhancementProcessor.cs // 描述: 层次增强算子,基于多尺度高斯分解对不同尺度细节独立增? // 功能: // - 将图像分解为多层细节?+ 基础? // - 对每层细节独立控制增? // - 支持基础层亮度调整和对比度限? // 算法: 多尺度高斯差分分解与重建 // 作? 李伟 wei.lw.li@hexagon.com // ============================================================================ using Emgu.CV; using Emgu.CV.Structure; using Serilog; using XP.ImageProcessing.Core; namespace XP.ImageProcessing.Processors; /// /// 层次增强算子,基于多尺度高斯差分对不同尺度的图像细节进行独立增强 /// public class HierarchicalEnhancementProcessor : ImageProcessorBase { private static readonly ILogger _logger = Log.ForContext(); public HierarchicalEnhancementProcessor() { Name = LocalizationHelper.GetString("HierarchicalEnhancementProcessor_Name"); Description = LocalizationHelper.GetString("HierarchicalEnhancementProcessor_Description"); } protected override void InitializeParameters() { Parameters.Add("Levels", new ProcessorParameter( "Levels", LocalizationHelper.GetString("HierarchicalEnhancementProcessor_Levels"), typeof(int), 4, 2, 8, LocalizationHelper.GetString("HierarchicalEnhancementProcessor_Levels_Desc"))); Parameters.Add("FineGain", new ProcessorParameter( "FineGain", LocalizationHelper.GetString("HierarchicalEnhancementProcessor_FineGain"), typeof(double), 2.0, 0.0, 10.0, LocalizationHelper.GetString("HierarchicalEnhancementProcessor_FineGain_Desc"))); Parameters.Add("MediumGain", new ProcessorParameter( "MediumGain", LocalizationHelper.GetString("HierarchicalEnhancementProcessor_MediumGain"), typeof(double), 1.5, 0.0, 10.0, LocalizationHelper.GetString("HierarchicalEnhancementProcessor_MediumGain_Desc"))); Parameters.Add("CoarseGain", new ProcessorParameter( "CoarseGain", LocalizationHelper.GetString("HierarchicalEnhancementProcessor_CoarseGain"), typeof(double), 1.0, 0.0, 10.0, LocalizationHelper.GetString("HierarchicalEnhancementProcessor_CoarseGain_Desc"))); Parameters.Add("BaseGain", new ProcessorParameter( "BaseGain", LocalizationHelper.GetString("HierarchicalEnhancementProcessor_BaseGain"), typeof(double), 1.0, 0.0, 3.0, LocalizationHelper.GetString("HierarchicalEnhancementProcessor_BaseGain_Desc"))); Parameters.Add("ClipLimit", new ProcessorParameter( "ClipLimit", LocalizationHelper.GetString("HierarchicalEnhancementProcessor_ClipLimit"), typeof(double), 0.0, 0.0, 50.0, LocalizationHelper.GetString("HierarchicalEnhancementProcessor_ClipLimit_Desc"))); _logger.Debug("InitializeParameters"); } public override Image Process(Image inputImage) { int levels = GetParameter("Levels"); double fineGain = GetParameter("FineGain"); double mediumGain = GetParameter("MediumGain"); double coarseGain = GetParameter("CoarseGain"); double baseGain = GetParameter("BaseGain"); double clipLimit = GetParameter("ClipLimit"); _logger.Debug("Process: Levels={Levels}, Fine={Fine}, Medium={Medium}, Coarse={Coarse}, Base={Base}, Clip={Clip}", levels, fineGain, mediumGain, coarseGain, baseGain, clipLimit); int h = inputImage.Height; int w = inputImage.Width; // === 多尺度高斯差分分解(全部在原始分辨率上操作,无需金字塔上下采样) === // 用递增 sigma 的高斯模糊生成平滑层序列:G0(原图), G1, G2, ..., G_n(基础? // 细节?D_i = G_i - G_{i+1} // 重建:output = sum(D_i * gain_i) + G_n * baseGain // 计算每层的高?sigma(指数递增? var sigmas = new double[levels]; for (int i = 0; i < levels; i++) sigmas[i] = Math.Pow(2, i + 1); // 2, 4, 8, 16, ... // 生成平滑层序列(float 数组,避?Emgu float Image 的问题) var smoothLayers = new float[levels + 1][]; // [0]=原图, [1..n]=高斯模糊 smoothLayers[0] = new float[h * w]; var srcData = inputImage.Data; Parallel.For(0, h, y => { int row = y * w; for (int x = 0; x < w; x++) smoothLayers[0][row + x] = srcData[y, x, 0]; }); for (int i = 0; i < levels; i++) { int ksize = ((int)(sigmas[i] * 3)) | 1; // 确保奇数 if (ksize < 3) ksize = 3; using var src = new Image(w, h); // 从上一?float ?byte 做高斯模? var prevLayer = smoothLayers[i]; var sd = src.Data; Parallel.For(0, h, y => { int row = y * w; for (int x = 0; x < w; x++) sd[y, x, 0] = (byte)Math.Clamp((int)Math.Round(prevLayer[row + x]), 0, 255); }); using var dst = new Image(w, h); CvInvoke.GaussianBlur(src, dst, new System.Drawing.Size(ksize, ksize), sigmas[i]); smoothLayers[i + 1] = new float[h * w]; var dd = dst.Data; var nextLayer = smoothLayers[i + 1]; Parallel.For(0, h, y => { int row = y * w; for (int x = 0; x < w; x++) nextLayer[row + x] = dd[y, x, 0]; }); } // === 计算增益插值并直接重建 === var gains = new double[levels]; for (int i = 0; i < levels; i++) { double t = levels <= 1 ? 0.0 : (double)i / (levels - 1); if (t <= 0.5) { double t2 = t * 2.0; gains[i] = fineGain * (1.0 - t2) + mediumGain * t2; } else { double t2 = (t - 0.5) * 2.0; gains[i] = mediumGain * (1.0 - t2) + coarseGain * t2; } } // 重建:output = baseGain * G_n + sum(gain_i * (G_i - G_{i+1})) float fBaseGain = (float)baseGain; float fClip = (float)clipLimit; var baseLayerData = smoothLayers[levels]; var result = new Image(w, h); var resultData = result.Data; // 预转?gains ?float var fGains = new float[levels]; for (int i = 0; i < levels; i++) fGains[i] = (float)gains[i]; Parallel.For(0, h, y => { int row = y * w; for (int x = 0; x < w; x++) { int idx = row + x; float val = baseLayerData[idx] * fBaseGain; for (int i = 0; i < levels; i++) { float detail = smoothLayers[i][idx] - smoothLayers[i + 1][idx]; detail *= fGains[i]; if (fClip > 0) detail = Math.Clamp(detail, -fClip, fClip); val += detail; } resultData[y, x, 0] = (byte)Math.Clamp((int)Math.Round(val), 0, 255); } }); _logger.Debug("Process completed: {Levels} levels, output={W}x{H}", levels, w, h); return result; } }