// ============================================================================ // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 文件名: GammaProcessor.cs // 描述: Gamma校正算子,用于调整图像亮度和对比度 // 功能: // - Gamma非线性校正 // - 增益调整 // - 使用查找表(LUT)加速处理 // - 适用于图像显示和亮度调整 // 算法: Gamma校正公式 output = (input^(1/gamma)) * gain // 作者: 李伟 wei.lw.li@hexagon.com // ============================================================================ using Emgu.CV; using Emgu.CV.Structure; using XP.ImageProcessing.Core; using Serilog; namespace XP.ImageProcessing.Processors; /// /// Gamma校正算子(支持 8 位和 16 位灰度图像) /// 16 位模式下 LUT 为 ushort[65536] /// public class GammaProcessor : ImageProcessorBase where TDepth : struct, IComparable { private static readonly ILogger _logger = Log.ForContext>(); public GammaProcessor() { Name = LocalizationHelper.GetString("GammaProcessor_Name"); Description = LocalizationHelper.GetString("GammaProcessor_Description"); } protected override void InitializeParameters() { Parameters.Add("Gamma", new ProcessorParameter( "Gamma", LocalizationHelper.GetString("GammaProcessor_Gamma"), typeof(double), 1.0, 0.1, 5.0, LocalizationHelper.GetString("GammaProcessor_Gamma_Desc"))); Parameters.Add("Gain", new ProcessorParameter( "Gain", LocalizationHelper.GetString("GammaProcessor_Gain"), typeof(double), 1.0, 0.1, 3.0, LocalizationHelper.GetString("GammaProcessor_Gain_Desc")) { IsAdvanced = true }); _logger.Debug("InitializeParameters"); } public override Image Process(Image inputImage) { double gamma = GetParameter("Gamma"); double gain = GetParameter("Gain"); if (typeof(TDepth) == typeof(ushort)) { var lut16 = BuildLUT16(gamma, gain); var img16 = inputImage as Image; var result = new Image(inputImage.Width, inputImage.Height); Parallel.For(0, inputImage.Height, y => { for (int x = 0; x < inputImage.Width; x++) result.Data[y, x, 0] = lut16[img16!.Data[y, x, 0]]; }); _logger.Debug("Process(16bit): Gamma={G}, Gain={Gain}", gamma, gain); return (result as Image)!; } else { var lut8 = BuildLUT8(gamma, gain); var result = (inputImage as Image)!.Clone(); int h = inputImage.Height, w = inputImage.Width; for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) result.Data[y, x, 0] = lut8[result.Data[y, x, 0]]; _logger.Debug("Process(8bit): Gamma={G}, Gain={Gain}", gamma, gain); return (result as Image)!; } } private static byte[] BuildLUT8(double gamma, double gain) { var lut = new byte[256]; double invGamma = 1.0 / gamma; for (int i = 0; i < 256; i++) { double normalized = i / 255.0; double corrected = Math.Pow(normalized, invGamma) * gain; lut[i] = (byte)Math.Clamp((int)(corrected * 255.0), 0, 255); } return lut; } private static ushort[] BuildLUT16(double gamma, double gain) { var lut = new ushort[65536]; double invGamma = 1.0 / gamma; for (int i = 0; i < 65536; i++) { double normalized = i / 65535.0; double corrected = Math.Pow(normalized, invGamma) * gain; lut[i] = (ushort)Math.Clamp((int)(corrected * 65535.0), 0, 65535); } return lut; } }