TURBO-565-浮雕为3D算子
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
// ============================================================================
|
||||
// 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效果处理器
|
||||
/// 通过方向性卷积核模拟光照产生的凹凸立体感,
|
||||
/// 常用于X-ray图像的焊点、空洞等结构的可视化增强。
|
||||
/// </summary>
|
||||
public class EmbossProcessor : ImageProcessorBase
|
||||
{
|
||||
private static readonly ILogger _logger = Log.ForContext<EmbossProcessor>();
|
||||
|
||||
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")));
|
||||
|
||||
Parameters.Add("GrayOffset", new ProcessorParameter(
|
||||
"GrayOffset",
|
||||
LocalizationHelper.GetString("EmbossProcessor_GrayOffset"),
|
||||
typeof(int),
|
||||
128,
|
||||
0,
|
||||
255,
|
||||
LocalizationHelper.GetString("EmbossProcessor_GrayOffset_Desc")));
|
||||
|
||||
_logger.Debug("InitializeParameters");
|
||||
}
|
||||
|
||||
public override Image<Gray, byte> Process(Image<Gray, byte> inputImage)
|
||||
{
|
||||
string direction = GetParameter<string>("Direction");
|
||||
double strength = GetParameter<double>("Strength");
|
||||
double blendRatio = GetParameter<double>("BlendRatio");
|
||||
int grayOffset = GetParameter<int>("GrayOffset");
|
||||
|
||||
// 获取方向性浮雕卷积核
|
||||
float[,] kernelData = GetEmbossKernel(direction, strength);
|
||||
|
||||
// 应用浮雕卷积
|
||||
var kernel = new ConvolutionKernelF(kernelData);
|
||||
var embossed = new Image<Gray, float>(inputImage.Size);
|
||||
CvInvoke.Filter2D(inputImage, embossed, kernel, new Point(-1, -1));
|
||||
|
||||
// 加灰度偏移,使平坦区域呈中灰色
|
||||
var offset = new Image<Gray, float>(inputImage.Size);
|
||||
offset.SetValue(new Gray(grayOffset));
|
||||
var embossedWithOffset = embossed + offset;
|
||||
|
||||
// 裁剪到 [0, 255] 并转为字节
|
||||
var embossedByte = embossedWithOffset.Convert<Gray, byte>();
|
||||
|
||||
// 与原图混合实现伪3D效果
|
||||
Image<Gray, byte> result;
|
||||
if (blendRatio < 0.001)
|
||||
{
|
||||
// 纯浮雕
|
||||
result = embossedByte;
|
||||
}
|
||||
else if (blendRatio > 0.999)
|
||||
{
|
||||
// 纯原图
|
||||
embossedByte.Dispose();
|
||||
result = inputImage.Clone();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Alpha 混合: result = original * blendRatio + embossed * (1 - blendRatio)
|
||||
var floatOriginal = inputImage.Convert<Gray, float>();
|
||||
var floatEmbossed = embossedByte.Convert<Gray, float>();
|
||||
var blended = floatOriginal * blendRatio + floatEmbossed * (1.0 - blendRatio);
|
||||
result = blended.Convert<Gray, byte>();
|
||||
|
||||
floatOriginal.Dispose();
|
||||
floatEmbossed.Dispose();
|
||||
blended.Dispose();
|
||||
embossedByte.Dispose();
|
||||
}
|
||||
|
||||
// 清理
|
||||
kernel.Dispose();
|
||||
embossed.Dispose();
|
||||
offset.Dispose();
|
||||
embossedWithOffset.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 }
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user