Files
XplorePlane/XP.ImageProcessing.Processors/图像增强/EmbossProcessor.cs
T
wei.lw.li 7768c086ea feat: 图像增强/变换算子标记高级参数+默认值优化
高级参数标记:Contrast(Contrast,Brightness,UseCLAHE,ClipLimit)、
Gamma(Gain)、Sharpen(Method,KernelSize)、Emboss(BlendRatio,GrayOffset)、
HistogramEq(Method,TileSize)、HDR(Method,Saturation,SigmaSpace,SigmaColor,Bias)、
Hierarchical(BaseGain,ClipLimit)、Retinex(Method,Sigma1/2/3,Offset)、
Rotate(ExpandCanvas,BackgroundValue,Interpolation)

默认值优化(适配平面CT DR图像):
- Sharpen: Laplacian→UnsharpMask(对噪声更温和)
- HistogramEq: Global→CLAHE(局部对比度更优)
- Contrast: AutoContrast默认开启
2026-08-12 09:25:34 +08:00

204 lines
7.3 KiB
C#

// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: EmbossProcessor.cs
// 描述: 浮雕伪3D效果处理器,模拟Viscom X-ray检测软件中的浮雕显示效果
// 功能:
// - 方向性浮雕(8个方向可选)
// - 可调节浮雕深度(强度)
// - 可选灰度偏移(中灰基底)
// - 支持与原图混合,实现伪3D立体感
// 算法: 方向性卷积核 + 灰度偏移 + Alpha混合
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using XP.ImageProcessing.Core;
using Serilog;
using System.Drawing;
namespace XP.ImageProcessing.Processors;
/// <summary>
/// 浮雕伪3D效果处理器(支持 8 位和 16 位灰度图像)
/// 通过方向性卷积核模拟光照产生的凹凸立体感,
/// 常用于X-ray图像的焊点、空洞等结构的可视化增强。
/// </summary>
public class EmbossProcessor<TDepth> : ImageProcessorBase<TDepth>
where TDepth : struct, IComparable
{
private static readonly ILogger _logger = Log.ForContext<EmbossProcessor<TDepth>>();
public EmbossProcessor()
{
Name = LocalizationHelper.GetString("EmbossProcessor_Name");
Description = LocalizationHelper.GetString("EmbossProcessor_Description");
}
protected override void InitializeParameters()
{
Parameters.Add("Direction", new ProcessorParameter(
"Direction",
LocalizationHelper.GetString("EmbossProcessor_Direction"),
typeof(string),
"TopLeft",
null,
null,
LocalizationHelper.GetString("EmbossProcessor_Direction_Desc"),
new string[] { "TopLeft", "Top", "TopRight", "Left", "Right", "BottomLeft", "Bottom", "BottomRight" }));
Parameters.Add("Strength", new ProcessorParameter(
"Strength",
LocalizationHelper.GetString("EmbossProcessor_Strength"),
typeof(double),
1.0,
0.1,
5.0,
LocalizationHelper.GetString("EmbossProcessor_Strength_Desc")));
Parameters.Add("BlendRatio", new ProcessorParameter(
"BlendRatio",
LocalizationHelper.GetString("EmbossProcessor_BlendRatio"),
typeof(double),
0.5,
0.0,
1.0,
LocalizationHelper.GetString("EmbossProcessor_BlendRatio_Desc")) { IsAdvanced = true });
Parameters.Add("GrayOffset", new ProcessorParameter(
"GrayOffset",
LocalizationHelper.GetString("EmbossProcessor_GrayOffset"),
typeof(int),
128,
0,
255,
LocalizationHelper.GetString("EmbossProcessor_GrayOffset_Desc")) { IsAdvanced = true });
_logger.Debug("InitializeParameters");
}
public override Image<Gray, TDepth> Process(Image<Gray, TDepth> inputImage)
{
string direction = GetParameter<string>("Direction");
double strength = GetParameter<double>("Strength");
double blendRatio = GetParameter<double>("BlendRatio");
int grayOffset = GetParameter<int>("GrayOffset");
// 灰度偏移参数按 8 位语义定义,16 位时按比例放大
if (typeof(TDepth) == typeof(ushort)) grayOffset *= 256;
grayOffset = Math.Clamp(grayOffset, 0, MaxPixelValue);
// 获取方向性浮雕卷积核
float[,] kernelData = GetEmbossKernel(direction, strength);
// 全程 float 运算,保留位深精度
var floatInput = inputImage.Convert<Gray, float>();
// 应用浮雕卷积
using var kernel = new ConvolutionKernelF(kernelData);
var embossed = new Image<Gray, float>(inputImage.Size);
CvInvoke.Filter2D(floatInput, embossed, kernel, new Point(-1, -1));
// 加灰度偏移,使平坦区域呈中灰色
var embossedWithOffset = embossed + grayOffset;
Image<Gray, float> resultFloat;
if (blendRatio < 0.001)
{
// 纯浮雕
resultFloat = embossedWithOffset.Clone();
}
else if (blendRatio > 0.999)
{
// 纯原图
resultFloat = floatInput.Clone();
}
else
{
// Alpha 混合: result = original * blendRatio + embossed * (1 - blendRatio)
// 浮雕分量先 clamp 到有效范围,模拟原 8 位实现中转字节的截断语义
var embossedClamped = PixelDepthHelper.FromFloatImageClamped<TDepth>(embossedWithOffset).Convert<Gray, float>();
resultFloat = floatInput * blendRatio + embossedClamped * (1.0 - blendRatio);
embossedClamped.Dispose();
}
var result = PixelDepthHelper.FromFloatImageClamped<TDepth>(resultFloat);
floatInput.Dispose();
embossed.Dispose();
embossedWithOffset.Dispose();
resultFloat.Dispose();
_logger.Debug("Process: Direction={Direction}, Strength={Strength}, BlendRatio={BlendRatio}, GrayOffset={GrayOffset}",
direction, strength, blendRatio, grayOffset);
return result;
}
/// <summary>
/// 根据方向和强度生成 3x3 浮雕卷积核
/// </summary>
private static float[,] GetEmbossKernel(string direction, double strength)
{
float s = (float)strength;
return direction switch
{
"TopLeft" => new float[,]
{
{ -2 * s, -1 * s, 0 },
{ -1 * s, 1, 1 * s },
{ 0, 1 * s, 2 * s }
},
"Top" => new float[,]
{
{ -1 * s, -1 * s, -1 * s },
{ 0, 1, 0 },
{ 1 * s, 1 * s, 1 * s }
},
"TopRight" => new float[,]
{
{ 0, -1 * s, -2 * s },
{ 1 * s, 1, -1 * s },
{ 2 * s, 1 * s, 0 }
},
"Left" => new float[,]
{
{ -1 * s, 0, 1 * s },
{ -1 * s, 1, 1 * s },
{ -1 * s, 0, 1 * s }
},
"Right" => new float[,]
{
{ 1 * s, 0, -1 * s },
{ 1 * s, 1, -1 * s },
{ 1 * s, 0, -1 * s }
},
"BottomLeft" => new float[,]
{
{ 0, 1 * s, 2 * s },
{ -1 * s, 1, 1 * s },
{ -2 * s, -1 * s, 0 }
},
"Bottom" => new float[,]
{
{ 1 * s, 1 * s, 1 * s },
{ 0, 1, 0 },
{ -1 * s, -1 * s, -1 * s }
},
"BottomRight" => new float[,]
{
{ 2 * s, 1 * s, 0 },
{ 1 * s, 1, -1 * s },
{ 0, -1 * s, -2 * s }
},
_ => new float[,]
{
{ -2 * s, -1 * s, 0 },
{ -1 * s, 1, 1 * s },
{ 0, 1 * s, 2 * s }
}
};
}
}