bbb3bf5326
1. 资源泄漏:HighPass/LowPass滤波器Image对象未dispose(改用using+Clone) 2. 线程安全:GammaProcessor LUT从实例字段改为方法局部变量 3. 资源泄漏:BandPassFilter补充floatImage和mask的Dispose 4. 边界情况:ThresholdProcessor Otsu16初始阈值改为中值(防全黑/全白) 5. 异常安全:RemoveOutliers的medianImage用try-finally保证释放 6. 空引用:SuperResolution InputMetadata空检查
114 lines
4.1 KiB
C#
114 lines
4.1 KiB
C#
// ============================================================================
|
|
// 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;
|
|
|
|
/// <summary>
|
|
/// Gamma校正算子(支持 8 位和 16 位灰度图像)
|
|
/// 16 位模式下 LUT 为 ushort[65536]
|
|
/// </summary>
|
|
public class GammaProcessor<TDepth> : ImageProcessorBase<TDepth>
|
|
where TDepth : struct, IComparable
|
|
{
|
|
private static readonly ILogger _logger = Log.ForContext<GammaProcessor<TDepth>>();
|
|
|
|
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<Gray, TDepth> Process(Image<Gray, TDepth> inputImage)
|
|
{
|
|
double gamma = GetParameter<double>("Gamma");
|
|
double gain = GetParameter<double>("Gain");
|
|
|
|
if (typeof(TDepth) == typeof(ushort))
|
|
{
|
|
var lut16 = BuildLUT16(gamma, gain);
|
|
var img16 = inputImage as Image<Gray, ushort>;
|
|
var result = new Image<Gray, ushort>(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<Gray, TDepth>)!;
|
|
}
|
|
else
|
|
{
|
|
var lut8 = BuildLUT8(gamma, gain);
|
|
var result = (inputImage as Image<Gray, byte>)!.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<Gray, TDepth>)!;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
} |