合并图像处理库,删除图像lib库
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件名: HierarchicalEnhancementProcessor.cs
|
||||
// 描述: 层次增强算子,基于多尺度高斯分解对不同尺度细节独立增强
|
||||
// 功能:
|
||||
// - 将图像分解为多层细节层 + 基础层
|
||||
// - 对每层细节独立控制增益
|
||||
// - 支持基础层亮度调整和对比度限制
|
||||
// 算法: 多尺度高斯差分分解与重建
|
||||
// 作者: 李伟 wei.lw.li@hexagon.com
|
||||
// ============================================================================
|
||||
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.CvEnum;
|
||||
using Emgu.CV.Structure;
|
||||
using ImageProcessing.Core;
|
||||
using Serilog;
|
||||
|
||||
namespace ImageProcessing.Processors;
|
||||
|
||||
/// <summary>
|
||||
/// 层次增强算子,基于多尺度高斯差分对不同尺度的图像细节进行独立增强
|
||||
/// </summary>
|
||||
public class HierarchicalEnhancementProcessor : ImageProcessorBase
|
||||
{
|
||||
private static readonly ILogger _logger = Log.ForContext<HierarchicalEnhancementProcessor>();
|
||||
|
||||
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<Gray, byte> Process(Image<Gray, byte> inputImage)
|
||||
{
|
||||
int levels = GetParameter<int>("Levels");
|
||||
double fineGain = GetParameter<double>("FineGain");
|
||||
double mediumGain = GetParameter<double>("MediumGain");
|
||||
double coarseGain = GetParameter<double>("CoarseGain");
|
||||
double baseGain = GetParameter<double>("BaseGain");
|
||||
double clipLimit = GetParameter<double>("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<Gray, byte>(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<Gray, byte>(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<Gray, byte>(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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user