修复注释乱码

This commit is contained in:
李伟
2026-04-14 17:11:31 +08:00
parent b8bcefc84b
commit cd03e30bb8
58 changed files with 761 additions and 767 deletions
@@ -1,25 +1,26 @@
// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// サカ蜷? ColorLayerProcessor.cs
// 謠剰ソー: 濶イ蠖ゥ蛻アらョ怜ュ撰シ悟ー蠎ヲ蝗セ蜒乗潔莠ョ蠎ヲ蛹コ髣エ蛻ア?
// 文件名: ColorLayerProcessor.cs
// 描述: 色彩分层算子,将灰度图像按亮度区间分层
// 功能:
// - 将灰度图像按指定层数均匀分层
// - 謾ッ謖∬螳壻ケ牙螻よ焚?~16螻ゑシ
// - 謾ッ謖∝插蛹€蛻アょ柱蝓コ莠?Otsu 逧騾ょコ泌
// - 支持自定义分层数(2~16层)
// - 支持均匀分层和基于 Otsu 的自适应分层
// - 可选保留原始灰度或映射为等间距灰度
// 邂玲ウ: 轣ー蠎ヲ驥丞喧 / 螟夐蛟シ蛻?
// 菴懆€? 譚惹シ wei.lw.li@hexagon.com
// 算法: 灰度量化 / 多阈值分割
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Serilog;
using XP.ImageProcessing.Core;
using Serilog;
namespace XP.ImageProcessing.Processors;
/// <summary>
/// 濶イ蠖ゥ蛻アらョ怜ュ撰シ悟ー蠎ヲ蝗セ蜒乗潔莠ョ蠎ヲ蛹コ髣エ蛻クコ螟壻クェ螻らコ?
/// 色彩分层算子,将灰度图像按亮度区间分为多个层级
/// </summary>
public class ColorLayerProcessor : ImageProcessorBase
{
@@ -88,12 +89,12 @@ public class ColorLayerProcessor : ImageProcessorBase
_logger.Debug("Process: Layers={Layers}, Method={Method}, OutputMode={OutputMode}, TargetLayer={TargetLayer}",
layers, method, outputMode, targetLayer);
// 隶。邂怜螻る蛟?
// 计算分层阈值
byte[] thresholds = method == "Otsu"
? ComputeOtsuMultiThresholds(inputImage, layers)
: ComputeUniformThresholds(layers);
// 隶。邂玲ッ丞アら噪霎灘轣ー蠎ヲ蛟?
// 计算每层的输出灰度值
byte[] layerValues = ComputeLayerValues(thresholds, layers, outputMode);
// 应用分层映射
@@ -105,7 +106,7 @@ public class ColorLayerProcessor : ImageProcessorBase
if (targetLayer == 0)
{
// 霎灘蜈ィ驛ィ螻?
// 输出全部层
Parallel.For(0, height, y =>
{
for (int x = 0; x < width; x++)
@@ -118,8 +119,8 @@ public class ColorLayerProcessor : ImageProcessorBase
}
else
{
// 蜿ェ霎灘ョ壼アゑシ夐€我クュ螻ゆクコ 255育區会シ悟菴吩ク?0磯サ托シ?
int target = targetLayer - 1; // 蜿よ焚莉?蠑€蟋具シ悟驛ィ邏「蠑穂サ?蠑€蟋?
// 只输出指定层:选中层为 255(白),其余为 0(黑)
int target = targetLayer - 1; // 参数从1开始,内部索引从0开始
Parallel.For(0, height, y =>
{
for (int x = 0; x < width; x++)
@@ -136,7 +137,7 @@ public class ColorLayerProcessor : ImageProcessorBase
}
/// <summary>
/// 劇蛻アる蛟シ壼ー?[0, 255] 遲牙
/// 均匀分层阈值:将 [0, 255] 等分
/// </summary>
private static byte[] ComputeUniformThresholds(int layers)
{
@@ -152,7 +153,7 @@ public class ColorLayerProcessor : ImageProcessorBase
/// </summary>
private static byte[] ComputeOtsuMultiThresholds(Image<Gray, byte> image, int layers)
{
// 隶。邂礼峩譁ケ蝗?
// 计算直方图
int[] histogram = new int[256];
var data = image.Data;
int h = image.Height, w = image.Width;
@@ -175,7 +176,7 @@ public class ColorLayerProcessor : ImageProcessorBase
if (layers <= 1 || low >= high)
return;
// 蝨?[low, high] 峩蜀 Otsu 髦亥€?
// [low, high] 范围内找 Otsu 阈值
long totalPixels = 0;
long totalSum = 0;
for (int i = low; i <= high; i++)
@@ -219,7 +220,7 @@ public class ColorLayerProcessor : ImageProcessorBase
}
/// <summary>
/// 隶。邂玲ッ丞アら噪霎灘轣ー蠎ヲ蛟?
/// 计算每层的输出灰度值
/// </summary>
private static byte[] ComputeLayerValues(byte[] thresholds, int layers, string outputMode)
{
@@ -232,7 +233,7 @@ public class ColorLayerProcessor : ImageProcessorBase
}
else // MidValue
{
// 豈丞アょ叙蛹コ髣エ荳ュ蛟?
// 每层取区间中值
values[0] = (byte)(thresholds.Length > 0 ? thresholds[0] / 2 : 128);
for (int i = 1; i < layers - 1; i++)
values[i] = (byte)((thresholds[i - 1] + thresholds[i]) / 2);
@@ -242,7 +243,7 @@ public class ColorLayerProcessor : ImageProcessorBase
}
/// <summary>
/// 譬ケ謐ョ髦亥€シ謨ー扈。ョ螳壼ワ邏謇€螻槫アらコ?
/// 根据阈值数组确定像素所属层级
/// </summary>
private static int GetLayerIndex(byte pixel, byte[] thresholds)
{
@@ -1,26 +1,26 @@
// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// ? ContrastProcessor.cs
// 讛膩: 撖寞摨西摮琜憓𧼮撩撖寞摨?
// 文件名: ContrastProcessor.cs
// 描述: 对比度调整算子,用于增强图像对比度
// 功能:
// - 蝥踵批笆瘥𥪜漲䔶漁摨西?
// - 芸𢆡撖寞摨行隡?
// - CLAHE笆瘥𥪜漲湔䲮銵∪嚗?
// - 憭𡁶撖寞摨血撘箸䲮瘜?
// - 线性对比度和亮度调整
// - 自动对比度拉伸
// - CLAHE(对比度受限自适应直方图均衡化)
// - 支持多种对比度增强方法
// 算法: 线性变换、直方图均衡化、CLAHE
// 雿𡏭? 𦒘 wei.lw.li@hexagon.com
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.Structure;
using XP.ImageProcessing.Core;
using Serilog;
using System.Drawing;
using XP.ImageProcessing.Core;
namespace XP.ImageProcessing.Processors;
/// <summary>
/// 撖寞摨西摮?
/// 对比度调整算子
/// </summary>
public class ContrastProcessor : ImageProcessorBase
{
@@ -1,20 +1,20 @@
// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件å? GammaProcessor.cs
// æè¿°: Gamma校正算å­ï¼Œç”¨äºŽè°ƒæ•´å›¾åƒäº®åº¦å’Œå¯¹æ¯”åº?
// 文件名: GammaProcessor.cs
// 描述: Gamma校正算子,用于调整图像亮度和对比度
// 功能:
// - Gammaéžçº¿æ€§æ ¡æ­?
// - Gamma非线性校正
// - 增益调整
// - 使用查找表(LUT)加速处ç?
// - 使用查找表(LUT)加速处理
// - 适用于图像显示和亮度调整
// 算法: Gamma校正公式 output = (input^(1/gamma)) * gain
// 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.Structure;
using Serilog;
using XP.ImageProcessing.Core;
using Serilog;
namespace XP.ImageProcessing.Processors;
@@ -1,26 +1,26 @@
// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件å? HDREnhancementProcessor.cs
// æè¿°: 高动æ€èŒƒå›´ï¼ˆHDR)图åƒå¢žå¼ºç®—å­?
// 文件名: HDREnhancementProcessor.cs
// 描述: 高动态范围(HDR)图像增强算子
// 功能:
// - 局部色调映射(Local Tone Mapping�
// - 自适应对数映射(Adaptive Logarithmic Mapping�
// - 局部色调映射(Local Tone Mapping
// - 自适应对数映射(Adaptive Logarithmic Mapping
// - Drago色调映射
// - 双边滤波色调映射
// - å¢žå¼ºå›¾åƒæš—部和亮部细èŠ?
// - 增强图像暗部和亮部细节
// 算法: 基于色调映射的HDR增强
// 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.Structure;
using Serilog;
using XP.ImageProcessing.Core;
using Serilog;
namespace XP.ImageProcessing.Processors;
/// <summary>
/// 高动æ€èŒƒå›´å›¾åƒå¢žå¼ºç®—å­?
/// 高动态范围图像增强算子
/// </summary>
public class HDREnhancementProcessor : ImageProcessorBase
{
@@ -138,8 +138,8 @@ public class HDREnhancementProcessor : ImageProcessorBase
}
/// <summary>
/// 局部色调映�
/// 将图åƒåˆ†è§£ä¸ºåŸºç¡€å±‚(光照)和细节层,分别处ç†åŽåˆæˆ?
/// 局部色调映射
/// 将图像分解为基础层(光照)和细节层,分别处理后合成
/// Base = GaussianBlur(log(I))
/// Detail = log(I) - Base
/// Output = exp(Base_compressed + Detail * boost)
@@ -156,22 +156,22 @@ public class HDREnhancementProcessor : ImageProcessorBase
for (int x = 0; x < width; x++)
floatImage.Data[y, x, 0] = floatImage.Data[y, x, 0] / 255.0f + 0.001f;
// 对数�
// 对数域
var logImage = new Image<Gray, float>(width, height);
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
logImage.Data[y, x, 0] = (float)Math.Log(floatImage.Data[y, x, 0]);
// 基础层:大尺度高斯模糊æå–光照分é‡?
// 基础层:大尺度高斯模糊提取光照分量
int kernelSize = (int)(sigmaSpace * 6) | 1;
if (kernelSize < 3) kernelSize = 3;
var baseLayer = new Image<Gray, float>(width, height);
CvInvoke.GaussianBlur(logImage, baseLayer, new System.Drawing.Size(kernelSize, kernelSize), sigmaSpace);
// 细节�
// 细节层
var detailLayer = logImage - baseLayer;
// 压缩基础层的动æ€èŒƒå›?
// 压缩基础层的动态范围
double baseMin = double.MaxValue, baseMax = double.MinValue;
for (int y = 0; y < height; y++)
{
@@ -200,7 +200,7 @@ public class HDREnhancementProcessor : ImageProcessorBase
}
}
// åˆæˆï¼šåŽ‹ç¼©åŽçš„基础å±?+ 增强的细节层
// 合成:压缩后的基础层 + 增强的细节层
var combined = new Image<Gray, float>(width, height);
for (int y = 0; y < height; y++)
{
@@ -287,7 +287,7 @@ public class HDREnhancementProcessor : ImageProcessorBase
for (int x = 0; x < width; x++)
floatImage.Data[y, x, 0] /= 255.0f;
// 计算全局最大亮�
// 计算全局最大亮度
float globalMax = 0;
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
@@ -364,7 +364,7 @@ public class HDREnhancementProcessor : ImageProcessorBase
for (int x = 0; x < width; x++)
floatImage.Data[y, x, 0] /= 255.0f;
// 全局最大亮�
// 全局最大亮度
float maxLum = 0;
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
@@ -410,7 +410,7 @@ public class HDREnhancementProcessor : ImageProcessorBase
/// <summary>
/// 双边滤波色调映射
/// 使用åŒè¾¹æ»¤æ³¢åˆ†ç¦»åŸºç¡€å±‚和细节å±?
/// 使用双边滤波分离基础层和细节层
/// 双边滤波保边特性使得细节层更加精确
/// </summary>
private Image<Gray, byte> BilateralToneMapping(Image<Gray, byte> inputImage,
@@ -419,20 +419,20 @@ public class HDREnhancementProcessor : ImageProcessorBase
int width = inputImage.Width;
int height = inputImage.Height;
// 转æ¢ä¸ºæµ®ç‚¹å¹¶å–对æ•?
// 转换为浮点并取对数
var floatImage = inputImage.Convert<Gray, float>();
var logImage = new Image<Gray, float>(width, height);
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
logImage.Data[y, x, 0] = (float)Math.Log(floatImage.Data[y, x, 0] / 255.0f + 0.001);
// åŒè¾¹æ»¤æ³¢æå–基础层(ä¿è¾¹å¹³æ»‘ï¼?
// 双边滤波提取基础层(保边平滑)
int diameter = (int)(sigmaSpace * 2) | 1;
if (diameter < 3) diameter = 3;
if (diameter > 31) diameter = 31;
var baseLayer = new Image<Gray, float>(width, height);
// 转æ¢ä¸?byte 进行åŒè¾¹æ»¤æ³¢ï¼Œå†è½¬å›ž float
// 转换为 byte 进行双边滤波,再转回 float
var logNorm = NormalizeToByteImage(logImage);
var baseNorm = new Image<Gray, byte>(width, height);
CvInvoke.BilateralFilter(logNorm, baseNorm, diameter, sigmaColor, sigmaSpace);
@@ -454,10 +454,10 @@ public class HDREnhancementProcessor : ImageProcessorBase
for (int x = 0; x < width; x++)
baseLayer.Data[y, x, 0] = (float)(baseNorm.Data[y, x, 0] / 255.0 * logRange + logMin);
// 细节å±?= å¯¹æ•°å›¾åƒ - 基础å±?
// 细节层 = 对数图像 - 基础层
var detailLayer = logImage - baseLayer;
// 压缩基础�
// 压缩基础层
double baseMin = double.MaxValue, baseMax = double.MinValue;
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
@@ -1,19 +1,20 @@
// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// サカ蜷? HierarchicalEnhancementProcessor.cs
// 謠剰ソー: 螻よャ。蠅槫シコ邂怜ュ撰シ悟渕莠主、壼ーコ蠎ヲ鬮俶民蛻ァ」蟇ケ荳榊酔蟆コ蠎ヲ扈鰍迢ャ遶句「槫シ?
// 文件名: HierarchicalEnhancementProcessor.cs
// 描述: 层次增强算子,基于多尺度高斯分解对不同尺度细节独立增强
// 功能:
// - 崟蜒丞隗」荳コ螟壼アらサ鰍螻?+ 蝓コ遑€螻?
// - 蟇ケ豈丞アらサ鰍迢ャ遶区而蛻カ蠅樒?
// - 謾ッ謖∝渕遑€螻ゆコョ蠎ヲ隹紛蜥悟ッケ豈泌コヲ髯仙?
// - 将图像分解为多层细节层 + 基础层
// - 对每层细节独立控制增益
// - 支持基础层亮度调整和对比度限制
// 算法: 多尺度高斯差分分解与重建
// 菴懆€? 譚惹シ wei.lw.li@hexagon.com
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Serilog;
using XP.ImageProcessing.Core;
using Serilog;
namespace XP.ImageProcessing.Processors;
@@ -105,16 +106,16 @@ public class HierarchicalEnhancementProcessor : ImageProcessorBase
int w = inputImage.Width;
// === 多尺度高斯差分分解(全部在原始分辨率上操作,无需金字塔上下采样) ===
// 逕ィ騾貞「 sigma ォ俶民讓。邉顔函謌仙ケウ貊大アょコ丞哦0(蜴溷崟), G1, G2, ..., G_n(蝓コ遑€螻?
// 鰍螻?D_i = G_i - G_{i+1}
// 用递增 sigma 的高斯模糊生成平滑层序列:G0(原图), G1, G2, ..., G_n(基础层)
// 细节层 D_i = G_i - G_{i+1}
// 重建:output = sum(D_i * gain_i) + G_n * baseGain
// 隶。邂玲ッ丞アら噪鬮俶?sigma域欠謨ー騾貞「橸シ?
// 计算每层的高斯 sigma(指数递增)
var sigmas = new double[levels];
for (int i = 0; i < levels; i++)
sigmas[i] = Math.Pow(2, i + 1); // 2, 4, 8, 16, ...
// 逕滓蟷ウ貊大アょコ丞loat 謨ー扈シ碁∩蜈?Emgu float Image 琉鬚假シ
// 生成平滑层序列(float 数组,避免 Emgu float Image 的问题)
var smoothLayers = new float[levels + 1][]; // [0]=原图, [1..n]=高斯模糊
smoothLayers[0] = new float[h * w];
var srcData = inputImage.Data;
@@ -131,7 +132,7 @@ public class HierarchicalEnhancementProcessor : ImageProcessorBase
if (ksize < 3) ksize = 3;
using var src = new Image<Gray, byte>(w, h);
// 莉惹ク贋ク€螻?float 霓?byte 蛛夐ォ俶民讓。邉?
// 从上一层 float byte 做高斯模糊
var prevLayer = smoothLayers[i];
var sd = src.Data;
Parallel.For(0, h, y =>
@@ -180,7 +181,7 @@ public class HierarchicalEnhancementProcessor : ImageProcessorBase
var result = new Image<Gray, byte>(w, h);
var resultData = result.Data;
// スャ謐?gains 荳?float
// 预转换 gains float
var fGains = new float[levels];
for (int i = 0; i < levels; i++)
fGains[i] = (float)gains[i];
@@ -209,4 +210,4 @@ public class HierarchicalEnhancementProcessor : ImageProcessorBase
_logger.Debug("Process completed: {Levels} levels, output={W}x{H}", levels, w, h);
return result;
}
}
}
@@ -1,20 +1,20 @@
// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件å? HistogramEqualizationProcessor.cs
// 文件名: HistogramEqualizationProcessor.cs
// 描述: 直方图均衡化算子,用于增强图像对比度
// 功能:
// - 全局直方图均衡化
// - 自适应直方图å‡è¡¡åŒ–(CLAHEï¼?
// - é™åˆ¶å¯¹æ¯”度增å¼?
// - 自适应直方图均衡化(CLAHE
// - 限制对比度增强
// - 改善图像的整体对比度
// 算法: 直方图均衡化、CLAHE
// 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.Structure;
using Serilog;
using XP.ImageProcessing.Core;
using Serilog;
namespace XP.ImageProcessing.Processors;
@@ -122,7 +122,7 @@ public class HistogramEqualizationProcessor : ImageProcessorBase
var limited = floatTile + diff * Math.Min(clipLimit / 10.0, 1.0);
var limitedByte = limited.Convert<Gray, byte>();
// å¤åˆ¶åˆ°ç»“果图åƒ?
// 复制到结果图像
result.ROI = roi;
limitedByte.CopyTo(result);
result.ROI = System.Drawing.Rectangle.Empty;
@@ -1,27 +1,27 @@
// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// ? HistogramOverlayProcessor.cs
// 文件名: HistogramOverlayProcessor.cs
// 描述: 直方图叠加算子,计算灰度直方图并以蓝色柱状图绘制到结果图像左上角
// 功能:
// - 计算输入图像的灰度直方图
// - 孵㦛蝏睃銝箄𤩺梁𠶖撌虫閫?
// - 颲枏枂湔䲮霈∟”潭㺭?
// 蝞埈: 啣漲湔䲮霈?+ 敶抵𠧧
// 雿𡏭? 𦒘 wei.lw.li@hexagon.com
// - 将直方图绘制为蓝色半透明柱状图叠加到图像左上角
// - 输出直方图统计表格数据
// 算法: 灰度直方图统计 + 彩色图像叠加
// 作者: 李伟 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;
using System.Text;
using XP.ImageProcessing.Core;
namespace XP.ImageProcessing.Processors;
/// <summary>
/// 湔䲮摮琜霈∠啣漲湔䲮曉僎隞亥嗅㦛蝏睃𨅯㦛誩椰銝𡃏霈∟”?
/// 直方图叠加算子,计算灰度直方图并以蓝色柱状图绘制到结果图像左上角,同时输出统计表格
/// </summary>
public class HistogramOverlayProcessor : ImageProcessorBase
{
@@ -29,11 +29,10 @@ public class HistogramOverlayProcessor : ImageProcessorBase
// 固定参数
private const int ChartWidth = 256; // 柱状图绘图区宽度
private const int ChartHeight = 200; // 柱状图绘图区高度
private const int AxisMarginLeft = 50; // Y頧湔蝑暸坔捐摨?
private const int AxisMarginBottom = 25; // X頧湔蝑暸摨?
private const int Padding = 8; // 峕艶憸嘥器頝?
private const int AxisMarginLeft = 50; // Y轴标签预留宽度
private const int AxisMarginBottom = 25; // X轴标签预留高度
private const int Padding = 8; // 背景额外内边距
private const int PaddingRight = 25; // 右侧额外内边距(容纳X轴末尾刻度文字)
private const int Margin = 10; // 距图像左上角边距
private const float BgAlpha = 0.6f;
@@ -48,7 +47,7 @@ public class HistogramOverlayProcessor : ImageProcessorBase
protected override void InitializeParameters()
{
// 惩虾靚?
// 无可调参数
}
public override Image<Gray, byte> Process(Image<Gray, byte> inputImage)
@@ -57,7 +56,7 @@ public class HistogramOverlayProcessor : ImageProcessorBase
int w = inputImage.Width;
var srcData = inputImage.Data;
// === 1. 霈∠啣漲湔䲮?===
// === 1. 计算灰度直方图 ===
var hist = new int[256];
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++)
@@ -96,15 +95,15 @@ public class HistogramOverlayProcessor : ImageProcessorBase
// === 3. 输出表格数据 ===
var sb = new StringBuilder();
sb.AppendLine("=== 啣漲湔䲮霈?===");
sb.AppendLine("=== 灰度直方图统计 ===");
sb.AppendLine($"图像尺寸: {w} x {h}");
sb.AppendLine($"总像素数: {totalPixels}");
sb.AppendLine($"撠讐摨? {minVal}");
sb.AppendLine($"憭抒摨? {maxVal}");
sb.AppendLine($"最小灰度: {minVal}");
sb.AppendLine($"最大灰度: {maxVal}");
sb.AppendLine($"平均灰度: {mean:F2}");
sb.AppendLine($"中位灰度: {medianVal}");
sb.AppendLine($"隡埈㺭啣漲: {modeVal} (箇緵 {modeCount} 甈?");
sb.AppendLine($"撌? {stdDev:F2}");
sb.AppendLine($"众数灰度: {modeVal} (出现 {modeCount} 次)");
sb.AppendLine($"标准差: {stdDev:F2}");
sb.AppendLine();
sb.AppendLine("灰度值\t像素数\t占比(%)");
for (int i = 0; i < 256; i++)
@@ -120,8 +119,8 @@ public class HistogramOverlayProcessor : ImageProcessorBase
var colorImage = inputImage.Convert<Bgr, byte>();
var colorData = colorImage.Data;
// 嚗朞臬躹?Padding + Y頧湔蝑?+ 蝏睃㦛?+ Padding偌撟喉
// Padding + 蝏睃㦛?+ X頧湔蝑?+ Padding
// 布局:背景区域包含 Padding + Y轴标签 + 绘图区 + Padding(水平)
// Padding + 绘图区 + X轴标签 + Padding(垂直)
int totalW = Padding + AxisMarginLeft + ChartWidth + PaddingRight;
int totalH = Padding + ChartHeight + AxisMarginBottom + Padding;
int bgW = Math.Min(totalW, w - Margin);
@@ -133,7 +132,7 @@ public class HistogramOverlayProcessor : ImageProcessorBase
int plotH = Math.Min(ChartHeight, bgH - Padding - AxisMarginBottom - Padding);
if (plotW <= 0 || plotH <= 0) goto SkipOverlay;
// 蝏睃㦛箏椰銝𡃏典㦛譍葉?
// 绘图区左上角在图像中的坐标
int plotX0 = Margin + Padding + AxisMarginLeft;
int plotY0 = Margin + Padding;
@@ -164,7 +163,7 @@ public class HistogramOverlayProcessor : ImageProcessorBase
}
});
// 蝏睃肽𠧧梁𠶖?
// 绘制蓝色柱状图
Parallel.For(0, plotH, dy =>
{
int imgY = plotY0 + dy;
@@ -188,7 +187,7 @@ public class HistogramOverlayProcessor : ImageProcessorBase
}
});
// === 5. 蝏睃頧渡瑪摨行瘜?===
// === 5. 绘制坐标轴线和刻度标注 ===
var white = new MCvScalar(255, 255, 255);
var gray = new MCvScalar(180, 180, 180);
@@ -204,7 +203,7 @@ public class HistogramOverlayProcessor : ImageProcessorBase
new Point(plotX0 + plotW, plotY0 + plotH),
white, 1);
// X頧游摨? 0, 64, 128, 192, 255
// X轴刻度: 0, 64, 128, 192, 255
int[] xTicks = { 0, 64, 128, 192, 255 };
foreach (int tick in xTicks)
{
@@ -220,7 +219,7 @@ public class HistogramOverlayProcessor : ImageProcessorBase
FontFace.HersheySimplex, FontScale, white, FontThickness);
}
// Y頧游摨? 0%, 25%, 50%, 75%, 100%
// Y轴刻度: 0%, 25%, 50%, 75%, 100%
for (int i = 0; i <= 4; i++)
{
int val = maxCount * i / 4;
@@ -248,7 +247,7 @@ public class HistogramOverlayProcessor : ImageProcessorBase
}
}
SkipOverlay:
SkipOverlay:
OutputData["PseudoColorImage"] = colorImage;
_logger.Debug("Process completed: histogram overlay, mean={Mean:F2}, stdDev={Std:F2}", mean, stdDev);
@@ -256,7 +255,7 @@ public class HistogramOverlayProcessor : ImageProcessorBase
}
/// <summary>
/// 蝝㰘恣唬蛹蝝批摮㛖泵銝莎憒?12345 ?"12.3K"嚗?
/// 格式化像素计数为紧凑字符串(如 12345 "12.3K"
/// </summary>
private static string FormatCount(int count)
{
@@ -264,4 +263,4 @@ public class HistogramOverlayProcessor : ImageProcessorBase
if (count >= 1_000) return $"{count / 1_000.0:F1}K";
return count.ToString();
}
}
}
@@ -1,6 +1,6 @@
// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件å? RetinexProcessor.cs
// 文件名: RetinexProcessor.cs
// 描述: 基于Retinex的多尺度阴影校正算子
// 功能:
// - 单尺度Retinex (SSR)
@@ -8,19 +8,19 @@
// - 带色彩恢复的多尺度Retinex (MSRCR)
// - 光照不均匀校正
// - 阴影去除
// 算法: Retinexç†è®º - 将图åƒåˆ†è§£ä¸ºå射分é‡å’Œå…‰ç…§åˆ†é‡?
// 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// 算法: Retinex理论 - 将图像分解为反射分量和光照分量
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.Structure;
using Serilog;
using XP.ImageProcessing.Core;
using Serilog;
namespace XP.ImageProcessing.Processors;
/// <summary>
/// Retinex多尺度阴影校正算�
/// Retinex多尺度阴影校正算子
/// </summary>
public class RetinexProcessor : ImageProcessorBase
{
@@ -145,7 +145,7 @@ public class RetinexProcessor : ImageProcessorBase
// 高斯模糊得到光照分量
Image<Gray, float> blurred = new Image<Gray, float>(inputImage.Size);
int kernelSize = (int)(sigma * 6) | 1; // ç¡®ä¿ä¸ºå¥‡æ•?
int kernelSize = (int)(sigma * 6) | 1; // 确保为奇数
if (kernelSize < 3) kernelSize = 3;
CvInvoke.GaussianBlur(floatImage, blurred, new System.Drawing.Size(kernelSize, kernelSize), sigma);
@@ -162,7 +162,7 @@ public class RetinexProcessor : ImageProcessorBase
// R = log(I) - log(I*G)
Image<Gray, float> retinex = logImage - logBlurred;
// 应用增益和åç§?
// 应用增益和偏移
retinex = retinex * gain + offset;
// 归一化到0-255
@@ -183,7 +183,7 @@ public class RetinexProcessor : ImageProcessorBase
/// </summary>
private Image<Gray, byte> MultiScaleRetinex(Image<Gray, byte> inputImage, double[] sigmas, double gain, int offset)
{
// 转æ¢ä¸ºæµ®ç‚¹å›¾åƒ?
// 转换为浮点图像
Image<Gray, float> floatImage = inputImage.Convert<Gray, float>();
floatImage = floatImage + 1.0f;
@@ -197,7 +197,7 @@ public class RetinexProcessor : ImageProcessorBase
}
}
// 累加多个尺度的结�
// 累加多个尺度的结果
Image<Gray, float> msrResult = new Image<Gray, float>(inputImage.Size);
msrResult.SetZero();
@@ -229,10 +229,10 @@ public class RetinexProcessor : ImageProcessorBase
// 平均
msrResult = msrResult / sigmas.Length;
// 应用增益和åç§?
// 应用增益和偏移
msrResult = msrResult * gain + offset;
// 归一�
// 归一化
Image<Gray, byte> result = NormalizeToByteImage(msrResult);
floatImage.Dispose();
@@ -244,14 +244,14 @@ public class RetinexProcessor : ImageProcessorBase
/// <summary>
/// 带色彩恢复的多尺度Retinex (MSRCR)
/// 对于ç°åº¦å›¾åƒï¼Œä½¿ç”¨ç®€åŒ–版æœ?
/// 对于灰度图像,使用简化版本
/// </summary>
private Image<Gray, byte> MultiScaleRetinexCR(Image<Gray, byte> inputImage, double[] sigmas, double gain, int offset)
{
// 先执行MSR
Image<Gray, byte> msrResult = MultiScaleRetinex(inputImage, sigmas, gain, offset);
// 对于ç°åº¦å›¾åƒï¼Œè‰²å½©æ¢å¤ç®€åŒ–为对比度增å¼?
// 对于灰度图像,色彩恢复简化为对比度增强
Image<Gray, float> floatMsr = msrResult.Convert<Gray, float>();
Image<Gray, float> floatInput = inputImage.Convert<Gray, float>();
@@ -285,7 +285,7 @@ public class RetinexProcessor : ImageProcessorBase
/// </summary>
private Image<Gray, byte> NormalizeToByteImage(Image<Gray, float> floatImage)
{
// 找到最å°å€¼å’Œæœ€å¤§å€?
// 找到最小值和最大值
double minVal = double.MaxValue;
double maxVal = double.MinValue;
@@ -1,21 +1,21 @@
// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件å? SharpenProcessor.cs
// 文件名: SharpenProcessor.cs
// 描述: 锐化算子,用于增强图像边缘和细节
// 功能:
// - 拉普拉斯锐化
// - éžé”化掩蔽(Unsharp Maskingï¼?
// - å¯è°ƒèŠ‚é”化强åº?
// - 支æŒå¤šç§é”化æ ?
// - 非锐化掩蔽(Unsharp Masking
// - 可调节锐化强度
// - 支持多种锐化核
// 算法: 拉普拉斯算子、非锐化掩蔽
// 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Serilog;
using XP.ImageProcessing.Core;
using Serilog;
namespace XP.ImageProcessing.Processors;
@@ -94,7 +94,7 @@ public class SharpenProcessor : ImageProcessorBase
var laplacian = new Image<Gray, float>(inputImage.Size);
CvInvoke.Laplacian(inputImage, laplacian, DepthType.Cv32F, 1);
// 转æ¢ä¸ºå­—节类åž?
// 转换为字节类型
var laplacianByte = laplacian.Convert<Gray, byte>();
// 将拉普拉斯结果加到原图上进行锐化
@@ -124,10 +124,10 @@ public class SharpenProcessor : ImageProcessorBase
var floatBlurred = blurred.Convert<Gray, float>();
var detail = floatInput - floatBlurred;
// 将细节加回原�
// 将细节加回原图
var sharpened = floatInput + detail * strength;
// 转æ¢å›žå­—节类åž?
// 转换回字节类型
var result = sharpened.Convert<Gray, byte>();
blurred.Dispose();
@@ -1,27 +1,27 @@
// ============================================================================
// Copyright © 2016-2025 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件å? SubPixelZoomProcessor.cs
// 文件名: SubPixelZoomProcessor.cs
// 描述: 亚像素放大算子,通过高质量插值实现图像的亚像素级放大
// 功能:
// - 支æŒä»»æ„å€çŽ‡æ”¾å¤§ï¼ˆå«å°æ•°å€çއå¦?1.5xã€?.3xï¼?
// - å¤šç§æ’值方法(最近邻ã€åŒçº¿æ€§ã€åŒä¸‰æ¬¡ã€Lanczosï¼?
// - 支持任意倍率放大(含小数倍率如 1.5x、2.3x)
// - 多种插值方法(最近邻、双线性、双三次、Lanczos
// - 可选锐化补偿(抵消插值模糊)
// - å¯é€‰æŒ‡å®šè¾“出尺å¯?
// 算法: 基于 OpenCV Resize çš„é«˜è´¨é‡æ’值放å¤?
// 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// - 可选指定输出尺寸
// 算法: 基于 OpenCV Resize 的高质量插值放大
// 作者: 李伟 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;
using XP.ImageProcessing.Core;
namespace XP.ImageProcessing.Processors;
/// <summary>
/// 亚åƒç´ æ”¾å¤§ç®—å­?
/// 亚像素放大算子
/// </summary>
public class SubPixelZoomProcessor : ImageProcessorBase
{
@@ -104,7 +104,7 @@ public class SubPixelZoomProcessor : ImageProcessorBase
if (sharpenAfter)
{
// Unsharp Masking: result = result + strength * (result - blur)
int ksize = Math.Max(3, (int)(scaleFactor * 2) | 1); // 奇数�
int ksize = Math.Max(3, (int)(scaleFactor * 2) | 1); // 奇数核
using var blurred = result.SmoothGaussian(ksize);
for (int y = 0; y < newHeight; y++)
@@ -124,4 +124,4 @@ public class SubPixelZoomProcessor : ImageProcessorBase
return result;
}
}
}
@@ -1,24 +1,25 @@
// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// ? SuperResolutionProcessor.cs
// 讛膩: 瘛勗漲摮虫摮?
// 文件名: SuperResolutionProcessor.cs
// 描述: 基于深度学习的超分辨率算子
// 功能:
// - EDSR ?FSRCNN 颲函璅∪嚗㇉NNX 嚗?
// - 2x?x?x 曉之
// - 支持 EDSR FSRCNN 超分辨率模型(ONNX 格式)
// - 支持 2x、3x、4x 放大倍率
// - 灰度图像自动转换为三通道输入,推理后转回灰度
// - 模型文件自动搜索,支持自定义路径
// - 使用 Microsoft.ML.OnnxRuntime 进行推理
// 算法: EDSR (Enhanced Deep Residual SR) / FSRCNN (Fast SR CNN)
// 雿𡏭? 𦒘 wei.lw.li@hexagon.com
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using XP.ImageProcessing.Core;
using Microsoft.ML.OnnxRuntime;
using Microsoft.ML.OnnxRuntime.Tensors;
using Serilog;
using XP.ImageProcessing.Core;
using System.IO;
namespace XP.ImageProcessing.Processors;
@@ -29,9 +30,8 @@ public class SuperResolutionProcessor : ImageProcessorBase
{
private static readonly ILogger _logger = Log.ForContext<SuperResolutionProcessor>();
// 隡朞蝻枏嚗屸憭滚頧?
// 会话缓存,避免重复加载
private static InferenceSession? _cachedSession;
private static string _cachedModelKey = string.Empty;
public SuperResolutionProcessor()
@@ -76,17 +76,17 @@ public class SuperResolutionProcessor : ImageProcessorBase
{
_logger.Error("Model file not found: {Model}_x{Scale}.onnx", model, scale);
throw new FileNotFoundException(
$"颲函璅∪芣𪄳? {model}_x{scale}.onnx\n" +
$"超分辨率模型文件未找到: {model}_x{scale}.onnx\n" +
$"请将模型文件放置到以下任一目录:\n" +
$" 1. 程序目录/Models/\n" +
$" 2. 程序目录/\n" +
$"璅∪閬?ONNX n" +
$"臭蝙?tf2onnx 隞?.pb 頧祆揢:\n" +
$"模型需要 ONNX 格式。\n" +
$"可使用 tf2onnx .pb 转换:\n" +
$" pip install tf2onnx\n" +
$" python -m tf2onnx.convert --input {model}_x{scale}.pb --output {model}_x{scale}.onnx --inputs input:0 --outputs output:0");
}
// 㰘蝸霂?
// 加载或复用会话
string modelKey = $"{model}_{scale}";
InferenceSession session;
if (_cachedModelKey == modelKey && _cachedSession != null)
@@ -111,7 +111,7 @@ public class SuperResolutionProcessor : ImageProcessorBase
session = new InferenceSession(modelPath, options);
_cachedSession = session;
_cachedModelKey = modelKey;
// 霈啣摰鮋雿輻鍂?Execution Provider
// 记录实际使用的 Execution Provider
var providers = session.ModelMetadata?.CustomMetadataMap;
_logger.Information("Loaded ONNX model: {ModelPath}, Providers: {Providers}",
modelPath, string.Join(", ", session.GetType().Name));
@@ -134,7 +134,7 @@ public class SuperResolutionProcessor : ImageProcessorBase
}
/// <summary>
/// 閙活 FSRCNN嚗?
/// 单次推理(小图或 FSRCNN
/// </summary>
private Image<Gray, byte> ProcessSingle(InferenceSession session, Image<Gray, byte> inputImage, int scale)
{
@@ -145,8 +145,8 @@ public class SuperResolutionProcessor : ImageProcessorBase
string inputName = session.InputMetadata.Keys.First();
var inputMeta = session.InputMetadata[inputName];
int[] dims = inputMeta.Dimensions;
// dims : [1, H, W, C] (NHWC)嚗龦 ?1 ?3
int inputChannels = dims[^1]; // 𦒘蝏湔糓𡁻?
// dims 格式: [1, H, W, C] (NHWC)C 可能是 1 或 3
int inputChannels = dims[^1]; // 最后一维是通道数
// 构建输入 tensor: [1, H, W, C] (NHWC)
// 使用底层数组 + Parallel.For 避免逐元素索引开销
@@ -178,7 +178,7 @@ public class SuperResolutionProcessor : ImageProcessorBase
for (int x = 0; x < w; x++)
{
int px = rowOffset + x * 3;
buf[px] = imgData[y, x, 0];
buf[px] = imgData[y, x, 0];
buf[px + 1] = imgData[y, x, 1];
buf[px + 2] = imgData[y, x, 2];
}
@@ -195,13 +195,13 @@ public class SuperResolutionProcessor : ImageProcessorBase
using var results = session.Run(inputs);
var outputTensor = results.First().AsTensor<float>();
// 颲枏枂 shape: [1, C, H*scale, W*scale] (NCHW嚗峕芋餈?Transpose)
// 输出 shape: [1, C, H*scale, W*scale] (NCHW,模型输出经过 Transpose)
var shape = outputTensor.Dimensions;
int outC = shape[1];
int outH = shape[2];
int outW = shape[3];
// 頧祆揢銝箇摨血㦛?
// 转换为灰度图像
// 使用 Parallel.For + 直接内存操作
Image<Gray, byte> result;
if (outC == 1)
@@ -217,7 +217,7 @@ public class SuperResolutionProcessor : ImageProcessorBase
}
else
{
// EDSR: 銝厰𡁻颲枏枂 [1, 3, outH, outW] ?啣漲
// EDSR: 三通道输出 [1, 3, outH, outW] → 灰度
// 直接计算灰度值,跳过中间 BGR 图像分配
result = new Image<Gray, byte>(outW, outH);
var outData = result.Data;
@@ -241,13 +241,13 @@ public class SuperResolutionProcessor : ImageProcessorBase
}
/// <summary>
/// ?EDSR嚗㚁𣂼急綫潭𦻖
/// 分块推理(大图 EDSR),将图像切成小块分别推理后拼接
/// </summary>
private Image<Gray, byte> ProcessTiled(InferenceSession session, Image<Gray, byte> inputImage, int scale, int tileSize)
{
int h = inputImage.Height;
int w = inputImage.Width;
int overlap = 8; // 撠烐𣄽亥器蝻䀝憚敶?
int overlap = 8; // 重叠像素,减少拼接边缘伪影
var result = new Image<Gray, byte>(w * scale, h * scale);
@@ -290,7 +290,7 @@ public class SuperResolutionProcessor : ImageProcessorBase
}
/// <summary>
/// 交𪄳璅∪辣嚗峕隡睃蝥扳蝝W銝芰𤌍敶𤏪.onnx 嚗?
/// 查找模型文件,按优先级搜索多个目录(.onnx 格式)
/// </summary>
private static string FindModelFile(string model, int scale)
{