修复注释乱码
This commit is contained in:
@@ -5,14 +5,14 @@ namespace XP.ImageProcessing.CfgControl;
|
||||
|
||||
/// <summary>
|
||||
/// 本地化辅助类,用于管理多语言资源
|
||||
/// �?ImageProcessing 主项目的语言设置同步
|
||||
/// 与 ImageProcessing 主项目的语言设置同步
|
||||
/// </summary>
|
||||
public static class LocalizationHelper
|
||||
{
|
||||
private static ResourceManager? _resourceManager;
|
||||
|
||||
/// <summary>
|
||||
/// 资源管理�?
|
||||
/// 资源管理器
|
||||
/// </summary>
|
||||
private static ResourceManager ResourceManager
|
||||
{
|
||||
@@ -32,7 +32,7 @@ public static class LocalizationHelper
|
||||
/// 获取本地化字符串
|
||||
/// 使用当前 UI 文化(与主项目同步)
|
||||
/// </summary>
|
||||
/// <param name="key">资源�?/param>
|
||||
/// <param name="key">资源键</param>
|
||||
/// <returns>本地化字符串</returns>
|
||||
public static string GetString(string key)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using XP.ImageProcessing.Core;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using XP.ImageProcessing.Core;
|
||||
|
||||
namespace XP.ImageProcessing.CfgControl;
|
||||
|
||||
@@ -24,7 +24,7 @@ public partial class ProcessorParameterControl : UserControl
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新"未选择算子"的文�?
|
||||
/// 更新"未选择算子"的文本
|
||||
/// </summary>
|
||||
private void UpdateNoProcessorText()
|
||||
{
|
||||
@@ -41,7 +41,7 @@ public partial class ProcessorParameterControl : UserControl
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载算子参数并生�?UI
|
||||
/// 加载算子参数并生成 UI
|
||||
/// </summary>
|
||||
public void LoadProcessor(ImageProcessorBase? processor)
|
||||
{
|
||||
@@ -68,7 +68,7 @@ public partial class ProcessorParameterControl : UserControl
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据参数类型创建对应的控�?
|
||||
/// 根据参数类型创建对应的控件
|
||||
/// </summary>
|
||||
private void CreateParameterControl(ProcessorParameter param)
|
||||
{
|
||||
@@ -88,7 +88,7 @@ public partial class ProcessorParameterControl : UserControl
|
||||
};
|
||||
pnlParameters.Children.Add(label);
|
||||
|
||||
// 根据参数类型创建不同的控�?
|
||||
// 根据参数类型创建不同的控件
|
||||
UIElement? control = null;
|
||||
|
||||
if (param.ValueType == typeof(int))
|
||||
@@ -133,8 +133,8 @@ public partial class ProcessorParameterControl : UserControl
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建整数类型控件(Slider + TextBox 或仅 TextBox�?
|
||||
/// �?MinValue �?MaxValue 都为 null 时,只显示文本框,不显示滑块
|
||||
/// 创建整数类型控件(Slider + TextBox 或仅 TextBox)
|
||||
/// 当 MinValue 和 MaxValue 都为 null 时,只显示文本框,不显示滑块
|
||||
/// </summary>
|
||||
private UIElement CreateIntegerControl(ProcessorParameter param)
|
||||
{
|
||||
@@ -201,8 +201,8 @@ public partial class ProcessorParameterControl : UserControl
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建浮点数类型控件(Slider + TextBox 或仅 TextBox�?
|
||||
/// �?MinValue �?MaxValue 都为 null 时,只显示文本框,不显示滑块
|
||||
/// 创建浮点数类型控件(Slider + TextBox 或仅 TextBox)
|
||||
/// 当 MinValue 和 MaxValue 都为 null 时,只显示文本框,不显示滑块
|
||||
/// </summary>
|
||||
private UIElement CreateDoubleControl(ProcessorParameter param)
|
||||
{
|
||||
@@ -268,7 +268,7 @@ public partial class ProcessorParameterControl : UserControl
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建布尔类型控件(CheckBox�?
|
||||
/// 创建布尔类型控件(CheckBox)
|
||||
/// </summary>
|
||||
private UIElement CreateBooleanControl(ProcessorParameter param)
|
||||
{
|
||||
@@ -295,7 +295,7 @@ public partial class ProcessorParameterControl : UserControl
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建下拉框控件(ComboBox�?
|
||||
/// 创建下拉框控件(ComboBox)
|
||||
/// </summary>
|
||||
private UIElement CreateComboBoxControl(ProcessorParameter param)
|
||||
{
|
||||
@@ -322,7 +322,7 @@ public partial class ProcessorParameterControl : UserControl
|
||||
{
|
||||
_currentProcessor?.SetParameter(param.Name, comboBox.SelectedItem.ToString()!);
|
||||
|
||||
// 如果�?FilterType 参数,重新加载界面以更新参数可见�?
|
||||
// 如果是 FilterType 参数,重新加载界面以更新参数可见性
|
||||
if (param.Name == "FilterType")
|
||||
{
|
||||
LoadProcessor(_currentProcessor);
|
||||
@@ -336,7 +336,7 @@ public partial class ProcessorParameterControl : UserControl
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建文本框控件(TextBox�?
|
||||
/// 创建文本框控件(TextBox)
|
||||
/// </summary>
|
||||
private UIElement CreateTextBoxControl(ProcessorParameter param)
|
||||
{
|
||||
@@ -358,7 +358,7 @@ public partial class ProcessorParameterControl : UserControl
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前配置的算�?
|
||||
/// 获取当前配置的算子
|
||||
/// </summary>
|
||||
public ImageProcessorBase? GetProcessor()
|
||||
{
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
// ============================================================================
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件�? ImageProcessorBase.cs
|
||||
// 描述: 8位图像处理算子基类,定义图像处理算子的通用接口和行�?
|
||||
// 文件名: ImageProcessorBase.cs
|
||||
// 描述: 8位图像处理算子基类,定义图像处理算子的通用接口和行为
|
||||
// 功能:
|
||||
// - 定义算子的基本属性(名称、描述)
|
||||
// - 参数管理(设置、获取、验证)
|
||||
// - ROI(感兴趣区域)处理支�?
|
||||
// - ROI(感兴趣区域)处理支持
|
||||
// - 输出数据管理(用于传递额外信息如轮廓等)
|
||||
// - 为所�?位图像处理算子提供统一的基础框架
|
||||
// - 为所有8位图像处理算子提供统一的基础框架
|
||||
// 设计模式: 模板方法模式
|
||||
// 作�? 李伟 wei.lw.li@hexagon.com
|
||||
// 作者: 李伟 wei.lw.li@hexagon.com
|
||||
// ============================================================================
|
||||
|
||||
using Emgu.CV;
|
||||
@@ -49,7 +49,7 @@ public abstract class ImageProcessorBase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化算子参数(子类实现�?
|
||||
/// 初始化算子参数(子类实现)
|
||||
/// </summary>
|
||||
protected abstract void InitializeParameters();
|
||||
|
||||
@@ -59,7 +59,7 @@ public abstract class ImageProcessorBase
|
||||
public abstract Image<Gray, byte> Process(Image<Gray, byte> inputImage);
|
||||
|
||||
/// <summary>
|
||||
/// 执行图像处理(带矩形ROI支持�?
|
||||
/// 执行图像处理(带矩形ROI支持)
|
||||
/// </summary>
|
||||
public Image<Gray, byte> ProcessWithROI(Image<Gray, byte> inputImage)
|
||||
{
|
||||
@@ -71,7 +71,7 @@ public abstract class ImageProcessorBase
|
||||
|
||||
var processedROI = Process(roiImage);
|
||||
|
||||
// �?ROI 偏移量保存到输出数据中,供轮廓绘制等使用
|
||||
// 将 ROI 偏移量保存到输出数据中,供轮廓绘制等使用
|
||||
OutputData["ROIOffset"] = new System.Drawing.Point(ROI.Value.X, ROI.Value.Y);
|
||||
|
||||
var result = inputImage.Clone();
|
||||
@@ -87,7 +87,7 @@ public abstract class ImageProcessorBase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行图像处理(带多边形ROI掩码支持�?
|
||||
/// 执行图像处理(带多边形ROI掩码支持)
|
||||
/// </summary>
|
||||
public Image<Gray, byte> ProcessWithPolygonROI(Image<Gray, byte> inputImage)
|
||||
{
|
||||
@@ -100,7 +100,7 @@ public abstract class ImageProcessorBase
|
||||
var mask = new Image<Gray, byte>(inputImage.Width, inputImage.Height);
|
||||
mask.SetValue(new Gray(0));
|
||||
|
||||
// 绘制多边形掩码(白色表示ROI区域�?
|
||||
// 绘制多边形掩码(白色表示ROI区域)
|
||||
using (var vop = new VectorOfPoint(PolygonROIPoints))
|
||||
{
|
||||
using (var vvop = new VectorOfVectorOfPoint(vop))
|
||||
@@ -115,12 +115,12 @@ public abstract class ImageProcessorBase
|
||||
// 创建结果图像
|
||||
var result = inputImage.Clone();
|
||||
|
||||
// 使用掩码:ROI内使用处理后的像素,ROI外保持原始像�?
|
||||
// 使用掩码:ROI内使用处理后的像素,ROI外保持原始像素
|
||||
for (int y = 0; y < inputImage.Height; y++)
|
||||
{
|
||||
for (int x = 0; x < inputImage.Width; x++)
|
||||
{
|
||||
if (mask.Data[y, x, 0] > 0) // 在ROI�?
|
||||
if (mask.Data[y, x, 0] > 0) // 在ROI内
|
||||
{
|
||||
result.Data[y, x, 0] = processedImage.Data[y, x, 0];
|
||||
}
|
||||
@@ -137,7 +137,7 @@ public abstract class ImageProcessorBase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有参数列�?
|
||||
/// 获取所有参数列表
|
||||
/// </summary>
|
||||
public List<ProcessorParameter> GetParameters()
|
||||
{
|
||||
@@ -145,7 +145,7 @@ public abstract class ImageProcessorBase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置参数�?
|
||||
/// 设置参数值
|
||||
/// </summary>
|
||||
public void SetParameter(string name, object value)
|
||||
{
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// ��辣�? ProcessorParameter.cs
|
||||
// 文件名: ProcessorParameter.cs
|
||||
// 描述: 图像处理算子参数定义类,用于描述算子的可配置参数
|
||||
// 功能:
|
||||
// - 定义参数的基本属性(名称、类型、默认值)
|
||||
// - 支持参数范围约束(最小值、最大值)
|
||||
// - �舀��帋蜀蝐餃���㺭嚗���厰�厰★嚗?
|
||||
// - 支持枚举类型参数(下拉选项)
|
||||
// - 提供参数描述信息用于UI显示
|
||||
// - 蝏煺�����啁恣��㦤�?
|
||||
// 雿𡏭�? �𦒘� wei.lw.li@hexagon.com
|
||||
// - 统一的参数管理机制
|
||||
// 作者: 李伟 wei.lw.li@hexagon.com
|
||||
// ============================================================================
|
||||
|
||||
namespace XP.ImageProcessing.Core;
|
||||
@@ -18,7 +18,7 @@ namespace XP.ImageProcessing.Core;
|
||||
/// </summary>
|
||||
public class ProcessorParameter
|
||||
{
|
||||
/// <summary>��㺭�滨妍嚗�誨��葉雿輻鍂嚗?/summary>
|
||||
/// <summary>参数名称(代码中使用)</summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>显示名称(UI中显示)</summary>
|
||||
@@ -27,7 +27,7 @@ public class ProcessorParameter
|
||||
/// <summary>参数类型</summary>
|
||||
public Type ValueType { get; set; }
|
||||
|
||||
/// <summary>敶枏��?/summary>
|
||||
/// <summary>当前值</summary>
|
||||
public object Value { get; set; }
|
||||
|
||||
/// <summary>最小值(可选)</summary>
|
||||
|
||||
@@ -5,14 +5,14 @@ namespace XP.ImageProcessing.Processors;
|
||||
|
||||
/// <summary>
|
||||
/// 本地化辅助类,用于管理多语言资源
|
||||
/// ä¸?ImageProcessing 主项目的è¯è¨€è®¾ç½®å�Œæ¥
|
||||
/// 与 ImageProcessing 主项目的语言设置同步
|
||||
/// </summary>
|
||||
public static class LocalizationHelper
|
||||
{
|
||||
private static ResourceManager? _resourceManager;
|
||||
|
||||
/// <summary>
|
||||
/// 资�管��
|
||||
/// 资源管理器
|
||||
/// </summary>
|
||||
private static ResourceManager ResourceManager
|
||||
{
|
||||
@@ -32,7 +32,7 @@ public static class LocalizationHelper
|
||||
/// 获取本地化字符串
|
||||
/// 使用当前 UI 文化(与主项目同步)
|
||||
/// </summary>
|
||||
/// <param name="key">资��/param>
|
||||
/// <param name="key">资源键</param>
|
||||
/// <returns>本地化字符串</returns>
|
||||
public static string GetString(string key)
|
||||
{
|
||||
|
||||
+246
-246
File diff suppressed because it is too large
Load Diff
@@ -1,21 +1,22 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� FilmEffectProcessor.cs
|
||||
// æ��è¿°: 电å�胶片效果算å�ï¼Œæ¨¡æ‹Ÿä¼ ç»ŸX射线胶片的显示效æž?
|
||||
// 文件名: FilmEffectProcessor.cs
|
||||
// 描述: 电子胶片效果算子,模拟传统X射线胶片的显示效果
|
||||
// 功能:
|
||||
// - 窗宽窗�(Window/Level)调�
|
||||
// - 胶片å��转(æ£ç‰?负片ï¼?
|
||||
// - 窗宽窗位(Window/Level)调整
|
||||
// - 胶片反转(正片/负片)
|
||||
// - 多种胶片特性曲线(线性、S曲线、对数、指数)
|
||||
// - 边缘增强(模拟胶片锐化效果)
|
||||
// - 使用查找表(LUTï¼‰åŠ é€Ÿå¤„ç�?
|
||||
// 算法: 窗宽窗ä½�æ˜ å°„ + 特性曲线å�˜æ�?
|
||||
// 作� �伟 wei.lw.li@hexagon.com
|
||||
// - 使用查找表(LUT)加速处理
|
||||
// 算法: 窗宽窗位映射 + 特性曲线变换
|
||||
// 作者: 李伟 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;
|
||||
|
||||
@@ -102,7 +103,7 @@ public class FilmEffectProcessor : ImageProcessorBase
|
||||
double curveStrength = GetParameter<double>("CurveStrength");
|
||||
double edgeEnhance = GetParameter<double>("EdgeEnhance");
|
||||
|
||||
// 构建查找�
|
||||
// 构建查找表
|
||||
BuildLUT(windowCenter, windowWidth, invert, curve, curveStrength);
|
||||
|
||||
// 应用 LUT
|
||||
@@ -149,14 +150,14 @@ public class FilmEffectProcessor : ImageProcessorBase
|
||||
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
// 窗宽窗ä½�æ˜ å°„åˆ?[0, 1]
|
||||
// 窗宽窗位映射到 [0, 1]
|
||||
double normalized;
|
||||
if (ww <= 1)
|
||||
normalized = i >= wc ? 1.0 : 0.0;
|
||||
else
|
||||
normalized = Math.Clamp((i - low) / (high - low), 0.0, 1.0);
|
||||
|
||||
// 应用特性曲�
|
||||
// 应用特性曲线
|
||||
double mapped = curve switch
|
||||
{
|
||||
"Sigmoid" => ApplySigmoid(normalized, strength),
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� PseudoColorProcessor.cs
|
||||
// 文件名: PseudoColorProcessor.cs
|
||||
// 描述: 伪色彩渲染算子,将灰度图像映射为彩色图像
|
||||
// 功能:
|
||||
// - 支持多种 OpenCV 内置色彩映射表(Jet、Hot、Cool、Rainbow 等)
|
||||
// - 可选灰度范围裁剪,突出感兴趣的灰度区间
|
||||
// - å�¯é€‰å��è½¬è‰²å½©æ˜ å°„æ–¹å�?
|
||||
// 算法: 查找表(LUTï¼‰è‰²å½©æ˜ å°?
|
||||
// 作� �伟 wei.lw.li@hexagon.com
|
||||
// - 可选反转色彩映射方向
|
||||
// 算法: 查找表(LUT)色彩映射
|
||||
// 作者: 李伟 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 PseudoColorProcessor : ImageProcessorBase
|
||||
{
|
||||
@@ -82,11 +82,11 @@ public class PseudoColorProcessor : ImageProcessorBase
|
||||
|
||||
OutputData.Clear();
|
||||
|
||||
// �度范围�剪与归一�
|
||||
// 灰度范围裁剪与归一化
|
||||
Image<Gray, byte> normalized;
|
||||
if (minValue > 0 || maxValue < 255)
|
||||
{
|
||||
// å°?[minValue, maxValue] æ˜ å°„åˆ?[0, 255]
|
||||
// 将 [minValue, maxValue] 映射到 [0, 255]
|
||||
normalized = inputImage.Clone();
|
||||
double scale = 255.0 / Math.Max(maxValue - minValue, 1);
|
||||
for (int y = 0; y < normalized.Height; y++)
|
||||
@@ -135,7 +135,7 @@ public class PseudoColorProcessor : ImageProcessorBase
|
||||
|
||||
var colorImage = colorMat.ToImage<Bgr, byte>();
|
||||
|
||||
// 将彩色图åƒ�å˜å…?OutputData,供 UI 显示
|
||||
// 将彩色图像存入 OutputData,供 UI 显示
|
||||
OutputData["PseudoColorImage"] = colorImage;
|
||||
|
||||
_logger.Debug("Process: ColorMap={ColorMap}, MinValue={Min}, MaxValue={Max}, InvertMap={Invert}",
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� GrayscaleProcessor.cs
|
||||
// 文件名: GrayscaleProcessor.cs
|
||||
// 描述: 灰度图转换算子,用于将彩色图像转换为灰度图像
|
||||
// 功能:
|
||||
// - 标准灰度转换(加权平均)
|
||||
// - 平均值法
|
||||
// - 最大值法
|
||||
// - 最小值法
|
||||
// 算法: åŠ æ�ƒå¹³å�‡æ³?Gray = 0.299*R + 0.587*G + 0.114*B
|
||||
// 作� �伟 wei.lw.li@hexagon.com
|
||||
// 算法: 加权平均法 Gray = 0.299*R + 0.587*G + 0.114*B
|
||||
// 作者: 李伟 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 GrayscaleProcessor : ImageProcessorBase
|
||||
{
|
||||
@@ -49,13 +49,13 @@ public class GrayscaleProcessor : ImageProcessorBase
|
||||
{
|
||||
string method = GetParameter<string>("Method");
|
||||
|
||||
// 如果输入已ç»�是ç�°åº¦å›¾ï¼Œæ ¹æ�®æ–¹æ³•进行处ç�?
|
||||
// 如果输入已经是灰度图,根据方法进行处理
|
||||
var result = inputImage.Clone();
|
||||
|
||||
switch (method)
|
||||
{
|
||||
case "Average":
|
||||
// 对于已�是�度的图�,平�值法�改�图�
|
||||
// 对于已经是灰度的图像,平均值法不改变图像
|
||||
break;
|
||||
|
||||
case "Max":
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� MirrorProcessor.cs
|
||||
// æ��è¿°: 镜åƒ�ç®—å�,用于图åƒ�ç¿»è½?
|
||||
// 文件名: MirrorProcessor.cs
|
||||
// 描述: 镜像算子,用于图像翻转
|
||||
// 功能:
|
||||
// - 水平镜像(左右翻转)
|
||||
// - 垂直镜像(上下翻转)
|
||||
// - 对角镜åƒ�(水å¹?åž‚ç›´ç¿»è½¬ï¼Œç‰æ•?80°旋转ï¼?
|
||||
// - 对角镜像(水平+垂直翻转,等效180°旋转)
|
||||
// 算法: 像素坐标映射
|
||||
// 作� �伟 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;
|
||||
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� RotateProcessor.cs
|
||||
// 文件名: RotateProcessor.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 XP.ImageProcessing.Core;
|
||||
|
||||
namespace XP.ImageProcessing.Processors;
|
||||
|
||||
@@ -101,14 +101,14 @@ public class RotateProcessor : ImageProcessorBase
|
||||
|
||||
if (expandCanvas)
|
||||
{
|
||||
// 计算旋转�能容纳整幅图�的画布尺�
|
||||
// 计算旋转后能容纳整幅图像的画布尺寸
|
||||
double rad = Math.Abs(angle * Math.PI / 180.0);
|
||||
double sinA = Math.Abs(Math.Sin(rad));
|
||||
double cosA = Math.Abs(Math.Cos(rad));
|
||||
dstW = (int)Math.Ceiling(srcW * cosA + srcH * sinA);
|
||||
dstH = (int)Math.Ceiling(srcW * sinA + srcH * cosA);
|
||||
|
||||
// 调整旋转矩阵的平移分�,使图�居�
|
||||
// 调整旋转矩阵的平移分量,使图像居中
|
||||
double[] m = new double[6];
|
||||
rotMat.CopyTo(m);
|
||||
m[2] += (dstW - srcW) / 2.0;
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� ThresholdProcessor.cs
|
||||
// 文件名: ThresholdProcessor.cs
|
||||
// 描述: 阈值分割算子,用于图像二值化处理
|
||||
// 功能:
|
||||
// - 固定阈值二值化
|
||||
// - Otsu自动阈值计�
|
||||
// - �调节阈值和最大�
|
||||
// - 将�度图�转�为二值图�
|
||||
// - Otsu自动阈值计算
|
||||
// - 可调节阈值和最大值
|
||||
// - 将灰度图像转换为二值图像
|
||||
// 算法: 阈值分割、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 ThresholdProcessor : ImageProcessorBase
|
||||
{
|
||||
|
||||
@@ -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嚗?
|
||||
// - 憭𡁶��鍦�潭䲮瘜𤏪���餈煾����蝥踵�扼���銝㗇活��anczos嚗?
|
||||
// - 支持任意倍率放大(含小数倍率如 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)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� MorphologyProcessor.cs
|
||||
// 文件名: MorphologyProcessor.cs
|
||||
// 描述: 形态学处理算子,用于二值图像的形态学操作
|
||||
// 功能:
|
||||
// - 腐蚀(Erode):收缩目标区域
|
||||
@@ -8,15 +8,15 @@
|
||||
// - 开运算(Open):先腐蚀后膨胀,去除小目标
|
||||
// - 闭运算(Close):先膨胀后腐蚀,填充小孔洞
|
||||
// 算法: 数学形态学运算
|
||||
// 作� �伟 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 XP.ImageProcessing.Core;
|
||||
|
||||
namespace XP.ImageProcessing.Processors;
|
||||
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� DifferenceProcessor.cs
|
||||
// æ��è¿°: 差分è¿�ç®—ç®—å�,用于边缘检测和å�˜åŒ–检æµ?
|
||||
// 文件名: DifferenceProcessor.cs
|
||||
// 描述: 差分运算算子,用于边缘检测和变化检测
|
||||
// 功能:
|
||||
// - 对图�进行差分��
|
||||
// - 支�水平�垂直和对角线差�
|
||||
// - �用于边缘检�
|
||||
// - �选归一化输�
|
||||
// 算法: åƒ�ç´ çº§å·®åˆ†è¿�ç®?
|
||||
// 作� �伟 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;
|
||||
|
||||
@@ -96,7 +96,7 @@ public class DifferenceProcessor : ImageProcessorBase
|
||||
}
|
||||
else // Both
|
||||
{
|
||||
// 梯度幅� sqrt((dx)^2 + (dy)^2)
|
||||
// 梯度幅值: sqrt((dx)^2 + (dy)^2)
|
||||
for (int y = 0; y < height - 1; y++)
|
||||
{
|
||||
for (int x = 0; x < width - 1; x++)
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� DivisionProcessor.cs
|
||||
// æ��è¿°: 除法è¿�ç®—ç®—å�,用于图åƒ�归一化处ç�?
|
||||
// 文件名: DivisionProcessor.cs
|
||||
// 描述: 除法运算算子,用于图像归一化处理
|
||||
// 功能:
|
||||
// - 对图åƒ�åƒ�ç´ å€¼è¿›è¡Œé™¤æ³•è¿�ç®?
|
||||
// - 对图像像素值进行除法运算
|
||||
// - 支持缩放因子调整
|
||||
// - 可选归一化到0-255范围
|
||||
// - å¸¸ç”¨äºŽèƒŒæ™¯æ ¡æ£å’Œå›¾åƒ�归一åŒ?
|
||||
// 算法: åƒ�ç´ çº§é™¤æ³•è¿�ç®?
|
||||
// 作� �伟 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;
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� IntegralProcessor.cs
|
||||
// æ��è¿°: 积分è¿�ç®—ç®—å�,计算积分图åƒ?
|
||||
// 文件名: IntegralProcessor.cs
|
||||
// 描述: 积分运算算子,计算积分图像
|
||||
// 功能:
|
||||
// - 计算积分图åƒ�ï¼ˆç´¯åŠ å’Œï¼?
|
||||
// - 用于快速区域求�
|
||||
// - 支�归一化输�
|
||||
// - 计算积分图像(累加和)
|
||||
// - 用于快速区域求和
|
||||
// - 支持归一化输出
|
||||
// 算法: 积分图像算法
|
||||
// 作� �伟 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;
|
||||
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� MultiplicationProcessor.cs
|
||||
// æ��è¿°: 乘法è¿�ç®—ç®—å�,用于图åƒ�增å¼?
|
||||
// 文件名: MultiplicationProcessor.cs
|
||||
// 描述: 乘法运算算子,用于图像增强
|
||||
// 功能:
|
||||
// - 对图åƒ�åƒ�ç´ å€¼è¿›è¡Œä¹˜æ³•è¿�ç®?
|
||||
// - 对图像像素值进行乘法运算
|
||||
// - 支持增益调整
|
||||
// - �选归一化输�
|
||||
// - 常用于图�增强和对比度调�
|
||||
// 算法: åƒ�ç´ çº§ä¹˜æ³•è¿�ç®?
|
||||
// 作� �伟 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;
|
||||
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� OrProcessor.cs
|
||||
// 文件名: OrProcessor.cs
|
||||
// 描述: 或运算算子,用于图像逻辑运算
|
||||
// 功能:
|
||||
// - 对图像进行按位或运算
|
||||
// - 支持与固定值或运算
|
||||
// - 可用于图像合并和掩码操作
|
||||
// 算法: 像素级按位或运算
|
||||
// 作� �伟 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 OrProcessor : ImageProcessorBase
|
||||
{
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
// ============================================================================
|
||||
// 文件� AngleMeasurementProcessor.cs
|
||||
// æ��è¿°: 角度测é‡�ç®—å� â€?共端点的两æ�¡ç›´çº¿å¤¹è§’
|
||||
// 文件名: AngleMeasurementProcessor.cs
|
||||
// 描述: 角度测量算子 — 共端点的两条直线夹角
|
||||
// 功能:
|
||||
// - 用户定义三个点:端点(顶点)�射�终点�射�终点
|
||||
// - 计算两�射线之间的夹角(0°~180°�
|
||||
// - 用户定义三个点:端点(顶点)、射线1终点、射线2终点
|
||||
// - 计算两条射线之间的夹角(0°~180°)
|
||||
// - 在图像上绘制两条射线、角度弧线和标注
|
||||
// ============================================================================
|
||||
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.Structure;
|
||||
using XP.ImageProcessing.Core;
|
||||
using Serilog;
|
||||
using System.Drawing;
|
||||
using XP.ImageProcessing.Core;
|
||||
|
||||
namespace XP.ImageProcessing.Processors;
|
||||
|
||||
@@ -27,7 +27,7 @@ public class AngleMeasurementProcessor : ImageProcessorBase
|
||||
|
||||
protected override void InitializeParameters()
|
||||
{
|
||||
// 三个点å��æ ‡ï¼ˆç”±äº¤äº’æŽ§ä»¶æ³¨å…¥ï¼Œä½¿ç”¨ double é�¿å…�å�–整误差ï¼?
|
||||
// 三个点坐标(由交互控件注入,使用 double 避免取整误差)
|
||||
Parameters.Add("VX", new ProcessorParameter("VX", "VX", typeof(double), 250.0, null, null, "") { IsVisible = false });
|
||||
Parameters.Add("VY", new ProcessorParameter("VY", "VY", typeof(double), 250.0, null, null, "") { IsVisible = false });
|
||||
Parameters.Add("AX", new ProcessorParameter("AX", "AX", typeof(double), 100.0, null, null, "") { IsVisible = false });
|
||||
@@ -44,7 +44,7 @@ public class AngleMeasurementProcessor : ImageProcessorBase
|
||||
|
||||
OutputData.Clear();
|
||||
|
||||
// �� VA �VB
|
||||
// 向量 VA 和 VB
|
||||
double vax = ax - vx, vay = ay - vy;
|
||||
double vbx = bx - vx, vby = by - vy;
|
||||
|
||||
@@ -59,11 +59,11 @@ public class AngleMeasurementProcessor : ImageProcessorBase
|
||||
angleDeg = Math.Acos(cosAngle) * 180.0 / Math.PI;
|
||||
}
|
||||
|
||||
// 计算角度弧的起始角和扫过角(用于绘制弧线�
|
||||
// 计算角度弧的起始角和扫过角(用于绘制弧线)
|
||||
double angleA = Math.Atan2(vay, vax) * 180.0 / Math.PI;
|
||||
double angleB = Math.Atan2(vby, vbx) * 180.0 / Math.PI;
|
||||
|
||||
// 确��angleA �angleB 的扫过方�是较�的夹�
|
||||
// 确保从 angleA 到 angleB 的扫过方向是较小的夹角
|
||||
double sweep = angleB - angleA;
|
||||
if (sweep > 180) sweep -= 360;
|
||||
if (sweep < -180) sweep += 360;
|
||||
@@ -84,4 +84,4 @@ public class AngleMeasurementProcessor : ImageProcessorBase
|
||||
|
||||
return inputImage.Clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� BgaVoidRateProcessor.cs
|
||||
// æ��è¿°: BGA 空洞率检测算å�(两æ¥è‡ªåŠ¨æ£€æµ‹æ³•ï¼?
|
||||
// 文件名: BgaVoidRateProcessor.cs
|
||||
// 描述: BGA 空洞率检测算子(两步自动检测法)
|
||||
//
|
||||
// 处理流程:
|
||||
// 第一æ?â€?焊ç�ƒå®šä½�: 高斯模糊 â†?Otsuå��å�‘二值化 â†?é—è¿�ç®?â†?轮廓检æµ?â†?圆度过滤 â†?æ¤åœ†æ‹Ÿå�ˆ
|
||||
// 第二æ?â€?气泡检æµ? 焊ç�ƒè½®å»“掩ç � â†?å�Œé˜ˆå€¼åˆ†å‰?â†?轮廓检æµ?â†?é�¢ç§¯è¿‡æ»¤ â†?气泡率计ç®?
|
||||
// 第一步 — 焊球定位: 高斯模糊 → Otsu反向二值化 → 闭运算 → 轮廓检测 → 圆度过滤 → 椭圆拟合
|
||||
// 第二步 — 气泡检测: 焊球轮廓掩码 → 双阈值分割 → 轮廓检测 → 面积过滤 → 气泡率计算
|
||||
//
|
||||
// 支持多边形ROI限定检测区域,支持IPC-7095标准PASS/FAIL判定
|
||||
// æ£ç‰‡æ¨¡å¼�:焊ç�?暗区域,气泡=亮区åŸ?
|
||||
// 正片模式:焊球=暗区域,气泡=亮区域
|
||||
//
|
||||
// 作� �伟 wei.lw.li@hexagon.com
|
||||
// 作者: 李伟 wei.lw.li@hexagon.com
|
||||
// ============================================================================
|
||||
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.CvEnum;
|
||||
using Emgu.CV.Structure;
|
||||
using Emgu.CV.Util;
|
||||
using XP.ImageProcessing.Core;
|
||||
using Serilog;
|
||||
using System.Drawing;
|
||||
using XP.ImageProcessing.Core;
|
||||
|
||||
namespace XP.ImageProcessing.Processors;
|
||||
|
||||
@@ -43,7 +43,7 @@ public class BgaVoidRateProcessor : ImageProcessorBase
|
||||
LocalizationHelper.GetString("BgaVoidRateProcessor_RoiMode_Desc"),
|
||||
new string[] { "None", "Polygon" }));
|
||||
|
||||
// 多边形ROI点数和å��æ ‡ï¼ˆç”±UI注入,ä¸�å�¯è§�,最多支æŒ?2个点ï¼?
|
||||
// 多边形ROI点数和坐标(由UI注入,不可见,最多支持32个点)
|
||||
Parameters.Add("PolyCount", new ProcessorParameter("PolyCount", "PolyCount", typeof(int), 0, null, null, "") { IsVisible = false });
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
@@ -76,7 +76,7 @@ public class BgaVoidRateProcessor : ImageProcessorBase
|
||||
typeof(double), 0.5, 0.0, 1.0,
|
||||
LocalizationHelper.GetString("BgaVoidRateProcessor_BgaCircularity_Desc")));
|
||||
|
||||
// ── 第二æ¥ï¼šæ°”泡检测å�‚æ•?──
|
||||
// ── 第二步:气泡检测参数 ──
|
||||
Parameters.Add("MinThreshold", new ProcessorParameter(
|
||||
"MinThreshold",
|
||||
LocalizationHelper.GetString("BgaVoidRateProcessor_MinThreshold"),
|
||||
@@ -148,7 +148,7 @@ public class BgaVoidRateProcessor : ImageProcessorBase
|
||||
OutputData["RoiMode"] = roiMode;
|
||||
OutputData["RoiMask"] = roiMask;
|
||||
|
||||
_logger.Debug("BgaVoidRate ä¸¤æ¥æ³? BgaArea=[{Min},{Max}], Blur={Blur}, Circ={Circ}, Thresh=[{TMin},{TMax}]",
|
||||
_logger.Debug("BgaVoidRate 两步法: BgaArea=[{Min},{Max}], Blur={Blur}, Circ={Circ}, Thresh=[{TMin},{TMax}]",
|
||||
bgaMinArea, bgaMaxArea, bgaBlurSize, bgaCircularity, minThresh, maxThresh);
|
||||
|
||||
// ================================================================
|
||||
@@ -156,7 +156,7 @@ public class BgaVoidRateProcessor : ImageProcessorBase
|
||||
// ================================================================
|
||||
var bgaResults = DetectBgaBalls(inputImage, bgaBlurSize, bgaMinArea, bgaMaxArea, bgaCircularity, roiMask);
|
||||
|
||||
_logger.Information("第一æ¥å®Œæˆ? 检测到 {Count} 个BGA焊ç�ƒ", bgaResults.Count);
|
||||
_logger.Information("第一步完成: 检测到 {Count} 个BGA焊球", bgaResults.Count);
|
||||
|
||||
if (bgaResults.Count == 0)
|
||||
{
|
||||
@@ -176,7 +176,7 @@ public class BgaVoidRateProcessor : ImageProcessorBase
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 第二æ¥ï¼šåœ¨æ¯�个焊ç�ƒåŒºåŸŸå†…检测气æ³?
|
||||
// 第二步:在每个焊球区域内检测气泡
|
||||
// ================================================================
|
||||
int totalBgaArea = 0;
|
||||
int totalVoidArea = 0;
|
||||
@@ -193,13 +193,13 @@ public class BgaVoidRateProcessor : ImageProcessorBase
|
||||
double overallVoidRate = totalBgaArea > 0 ? (double)totalVoidArea / totalBgaArea * 100.0 : 0;
|
||||
string classification = overallVoidRate <= voidLimit ? "PASS" : "FAIL";
|
||||
|
||||
// 检查æ¯�个焊ç�ƒæ˜¯å�¦å�•独超æ ?
|
||||
// 检查每个焊球是否单独超标
|
||||
foreach (var bga in bgaResults)
|
||||
{
|
||||
bga.Classification = bga.VoidRate <= voidLimit ? "PASS" : "FAIL";
|
||||
}
|
||||
|
||||
_logger.Information("第二æ¥å®Œæˆ? 总气泡率={VoidRate:F1}%, 气泡æ•?{Count}, 判定={Class}",
|
||||
_logger.Information("第二步完成: 总气泡率={VoidRate:F1}%, 气泡数={Count}, 判定={Class}",
|
||||
overallVoidRate, totalVoidCount, classification);
|
||||
|
||||
// 输出数据
|
||||
@@ -222,7 +222,7 @@ public class BgaVoidRateProcessor : ImageProcessorBase
|
||||
|
||||
/// <summary>
|
||||
/// 第一步:自动检测BGA焊球位置
|
||||
/// 使用Otsu二值化 + 轮廓检æµ?+ 圆度过滤 + æ¤åœ†æ‹Ÿå�ˆ
|
||||
/// 使用Otsu二值化 + 轮廓检测 + 圆度过滤 + 椭圆拟合
|
||||
/// </summary>
|
||||
private List<BgaBallInfo> DetectBgaBalls(Image<Gray, byte> input, int blurSize, int minArea, int maxArea, double minCircularity, Image<Gray, byte>? roiMask)
|
||||
{
|
||||
@@ -233,7 +233,7 @@ public class BgaVoidRateProcessor : ImageProcessorBase
|
||||
var blurred = new Image<Gray, byte>(w, h);
|
||||
CvInvoke.GaussianBlur(input, blurred, new Size(blurSize, blurSize), 0);
|
||||
|
||||
// Otsu自动二值化(X-Rayæ£ç‰‡ï¼šç„Šç�?暗区域)
|
||||
// Otsu自动二值化(X-Ray正片:焊球=暗区域)
|
||||
var binary = new Image<Gray, byte>(w, h);
|
||||
CvInvoke.Threshold(blurred, binary, 0, 255, ThresholdType.Otsu | ThresholdType.BinaryInv);
|
||||
|
||||
@@ -264,7 +264,7 @@ public class BgaVoidRateProcessor : ImageProcessorBase
|
||||
double circularity = 4.0 * Math.PI * area / (perimeter * perimeter);
|
||||
if (circularity < minCircularity) continue;
|
||||
|
||||
// 需è¦�至å°?个点æ‰�能拟å�ˆæ¤åœ†
|
||||
// 需要至少5个点才能拟合椭圆
|
||||
if (contours[i].Size < 5) continue;
|
||||
|
||||
var ellipse = CvInvoke.FitEllipse(contours[i]);
|
||||
@@ -284,7 +284,7 @@ public class BgaVoidRateProcessor : ImageProcessorBase
|
||||
});
|
||||
}
|
||||
|
||||
// 按�积从大到�排�
|
||||
// 按面积从大到小排序
|
||||
results.Sort((a, b) => b.BgaArea.CompareTo(a.BgaArea));
|
||||
for (int i = 0; i < results.Count; i++) results[i].Index = i + 1;
|
||||
|
||||
@@ -296,8 +296,8 @@ public class BgaVoidRateProcessor : ImageProcessorBase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 第二æ¥ï¼šåœ¨å�•个BGA焊ç�ƒåŒºåŸŸå†…检测气æ³?
|
||||
/// 使用焊ç�ƒè½®å»“作为掩ç �,å�Œé˜ˆå€¼åˆ†å‰²æ°”泡区åŸ?
|
||||
/// 第二步:在单个BGA焊球区域内检测气泡
|
||||
/// 使用焊球轮廓作为掩码,双阈值分割气泡区域
|
||||
/// </summary>
|
||||
private void DetectVoidsInBga(Image<Gray, byte> input, BgaBallInfo bga, int minThresh, int maxThresh, int minVoidArea)
|
||||
{
|
||||
@@ -314,7 +314,7 @@ public class BgaVoidRateProcessor : ImageProcessorBase
|
||||
int bgaPixels = CvInvoke.CountNonZero(mask);
|
||||
bga.BgaArea = bgaPixels;
|
||||
|
||||
// å�Œé˜ˆå€¼åˆ†å‰²ï¼ˆæ£ç‰‡æ¨¡å¼�:气æ³?亮,ç�°åº¦åœ¨[minThresh, maxThresh]范围内判为气泡)
|
||||
// 双阈值分割(正片模式:气泡=亮,灰度在[minThresh, maxThresh]范围内判为气泡)
|
||||
var voidImg = new Image<Gray, byte>(w, h);
|
||||
byte[,,] srcData = input.Data;
|
||||
byte[,,] dstData = voidImg.Data;
|
||||
@@ -361,7 +361,7 @@ public class BgaVoidRateProcessor : ImageProcessorBase
|
||||
});
|
||||
}
|
||||
|
||||
// 按�积从大到�排�
|
||||
// 按面积从大到小排序
|
||||
bga.Voids.Sort((a, b) => b.Area.CompareTo(a.Area));
|
||||
for (int i = 0; i < bga.Voids.Count; i++) bga.Voids[i].Index = i + 1;
|
||||
|
||||
@@ -400,4 +400,4 @@ public class VoidInfo
|
||||
public double AreaPercent { get; set; }
|
||||
public Rectangle BoundingBox { get; set; }
|
||||
public Point[] ContourPoints { get; set; } = Array.Empty<Point>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� ContourProcessor.cs
|
||||
// 文件名: ContourProcessor.cs
|
||||
// 描述: 轮廓查找算子,用于检测和分析图像中的轮廓
|
||||
// 功能:
|
||||
// - 检测图åƒ�ä¸çš„外部轮å»?
|
||||
// - 检测图像中的外部轮廓
|
||||
// - 根据面积范围过滤轮廓
|
||||
// - è®¡ç®—è½®å»“çš„å‡ ä½•ç‰¹å¾�(é�¢ç§¯ã€�周长ã€�ä¸å¿ƒã€�外接矩形ç‰ï¼?
|
||||
// - 输出轮廓信æ�¯ä¾›å�Žç»å¤„ç�†ä½¿ç”?
|
||||
// 算法: 基于OpenCV的轮廓检测算�
|
||||
// 作� �伟 wei.lw.li@hexagon.com
|
||||
// - 计算轮廓的几何特征(面积、周长、中心、外接矩形等)
|
||||
// - 输出轮廓信息供后续处理使用
|
||||
// 算法: 基于OpenCV的轮廓检测算法
|
||||
// 作者: 李伟 wei.lw.li@hexagon.com
|
||||
// ============================================================================
|
||||
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.CvEnum;
|
||||
using Emgu.CV.Structure;
|
||||
using Emgu.CV.Util;
|
||||
using XP.ImageProcessing.Core;
|
||||
using Serilog;
|
||||
using System.Drawing;
|
||||
using XP.ImageProcessing.Core;
|
||||
|
||||
namespace XP.ImageProcessing.Processors;
|
||||
|
||||
@@ -117,7 +117,7 @@ public class ContourProcessor : ImageProcessorBase
|
||||
|
||||
OutputData.Clear();
|
||||
|
||||
// 创建输入图�的副本用于处�
|
||||
// 创建输入图像的副本用于处理
|
||||
Image<Gray, byte> processImage = inputImage.Clone();
|
||||
|
||||
// 步骤1:如果启用阈值分割,先进行二值化
|
||||
@@ -128,18 +128,18 @@ public class ContourProcessor : ImageProcessorBase
|
||||
|
||||
if (useOtsu)
|
||||
{
|
||||
// 使用Otsu自动阈�
|
||||
// 使用Otsu自动阈值
|
||||
CvInvoke.Threshold(processImage, thresholdImage, 0, 255, ThresholdType.Otsu);
|
||||
_logger.Debug("Applied Otsu threshold");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 使用固定阈�
|
||||
// 使用固定阈值
|
||||
CvInvoke.Threshold(processImage, thresholdImage, thresholdValue, 255, ThresholdType.Binary);
|
||||
_logger.Debug("Applied binary threshold with value {ThresholdValue}", thresholdValue);
|
||||
}
|
||||
|
||||
// ä¿�å˜é˜ˆå€¼å¤„ç�†å�Žçš„图åƒ�用于调è¯?
|
||||
// 保存阈值处理后的图像用于调试
|
||||
try
|
||||
{
|
||||
string debugPath = Path.Combine("logs", $"contour_threshold_{DateTime.Now:yyyyMMdd_HHmmss}.png");
|
||||
@@ -156,7 +156,7 @@ public class ContourProcessor : ImageProcessorBase
|
||||
processImage = thresholdImage;
|
||||
}
|
||||
|
||||
// æ¥éª¤2ï¼šå¦‚æžœç›®æ ‡æ˜¯é»‘è‰²åŒºåŸŸï¼Œéœ€è¦�å��转图åƒ?
|
||||
// 步骤2:如果目标是黑色区域,需要反转图像
|
||||
bool isBlackTarget = targetColor != null &&
|
||||
(targetColor.Equals("Black", StringComparison.OrdinalIgnoreCase) ||
|
||||
targetColor.Equals("黑色", StringComparison.OrdinalIgnoreCase));
|
||||
@@ -180,7 +180,7 @@ public class ContourProcessor : ImageProcessorBase
|
||||
}
|
||||
}
|
||||
|
||||
// æ¥éª¤3:查找轮å»?
|
||||
// 步骤3:查找轮廓
|
||||
using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
|
||||
{
|
||||
Mat hierarchy = new Mat();
|
||||
|
||||
@@ -1,64 +1,53 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� EllipseDetectionProcessor.cs
|
||||
// æ��è¿°: æ¤åœ†æ£€æµ‹ç®—å�,基于轮廓分æž�å’Œæ¤åœ†æ‹Ÿå�ˆæ£€æµ‹å›¾åƒ�ä¸çš„æ¤åœ?
|
||||
// 文件名: EllipseDetectionProcessor.cs
|
||||
// 描述: 椭圆检测算子,基于轮廓分析和椭圆拟合检测图像中的椭圆
|
||||
// 功能:
|
||||
// - 阈值分�+ 轮廓��
|
||||
// - æ¤åœ†æ‹Ÿå�ˆï¼ˆFitEllipseï¼?
|
||||
// - �积/轴长/离心�拟�误差多维过滤
|
||||
// - 支��阈值分割和 Otsu 自动阈�
|
||||
// 算法: 阈值分�+ OpenCV FitEllipse
|
||||
// 作� �伟 wei.lw.li@hexagon.com
|
||||
// - 阈值分割 + 轮廓提取
|
||||
// - 椭圆拟合(FitEllipse)
|
||||
// - 面积/轴长/离心率/拟合误差多维过滤
|
||||
// - 支持双阈值分割和 Otsu 自动阈值
|
||||
// 算法: 阈值分割 + OpenCV FitEllipse
|
||||
// 作者: 李伟 wei.lw.li@hexagon.com
|
||||
// ============================================================================
|
||||
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.CvEnum;
|
||||
using Emgu.CV.Structure;
|
||||
using Emgu.CV.Util;
|
||||
using XP.ImageProcessing.Core;
|
||||
using Serilog;
|
||||
using System.Drawing;
|
||||
using XP.ImageProcessing.Core;
|
||||
|
||||
namespace XP.ImageProcessing.Processors;
|
||||
|
||||
/// <summary>
|
||||
/// æ¤åœ†æ£€æµ‹ç»“æž?
|
||||
/// 椭圆检测结果
|
||||
/// </summary>
|
||||
public class EllipseInfo
|
||||
{
|
||||
/// <summary>序号</summary>
|
||||
public int Index { get; set; }
|
||||
|
||||
/// <summary>中心点X</summary>
|
||||
public float CenterX { get; set; }
|
||||
|
||||
/// <summary>中心点Y</summary>
|
||||
public float CenterY { get; set; }
|
||||
|
||||
/// <summary>长轴长度</summary>
|
||||
public float MajorAxis { get; set; }
|
||||
|
||||
/// <summary>短轴长度</summary>
|
||||
public float MinorAxis { get; set; }
|
||||
|
||||
/// <summary>旋转角度(度�/summary>
|
||||
/// <summary>旋转角度(度)</summary>
|
||||
public float Angle { get; set; }
|
||||
|
||||
/// <summary>面积</summary>
|
||||
public double Area { get; set; }
|
||||
|
||||
/// <summary>周长</summary>
|
||||
public double Perimeter { get; set; }
|
||||
|
||||
/// <summary>离心çŽ?(0=åœ? 接近1=æ‰�æ¤åœ?</summary>
|
||||
/// <summary>离心率 (0=圆, 接近1=扁椭圆)</summary>
|
||||
public double Eccentricity { get; set; }
|
||||
|
||||
/// <summary>拟合误差(像素)</summary>
|
||||
public double FitError { get; set; }
|
||||
|
||||
/// <summary>轮廓点集</summary>
|
||||
public Point[] ContourPoints { get; set; } = Array.Empty<Point>();
|
||||
|
||||
/// <summary>外接矩形</summary>
|
||||
public Rectangle BoundingBox { get; set; }
|
||||
}
|
||||
@@ -81,7 +70,7 @@ public class EllipseDetector
|
||||
public double MaxFitError { get; set; } = 5.0;
|
||||
public int Thickness { get; set; } = 2;
|
||||
|
||||
/// <summary>执行æ¤åœ†æ£€æµ?/summary>
|
||||
/// <summary>执行椭圆检测</summary>
|
||||
public List<EllipseInfo> Detect(Image<Gray, byte> inputImage, Image<Gray, byte>? roiMask = null)
|
||||
{
|
||||
_logger.Debug("Ellipse detection started: UseOtsu={UseOtsu}, MinThreshold={Min}, MaxThreshold={Max}",
|
||||
@@ -197,7 +186,7 @@ public class EllipseDetector
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// æ¤åœ†æ£€æµ‹ç®—å?
|
||||
/// 椭圆检测算子
|
||||
/// </summary>
|
||||
public class EllipseDetectionProcessor : ImageProcessorBase
|
||||
{
|
||||
@@ -211,7 +200,7 @@ public class EllipseDetectionProcessor : ImageProcessorBase
|
||||
|
||||
protected override void InitializeParameters()
|
||||
{
|
||||
// ── 多边形ROI(由UI注入,最�2个点�──
|
||||
// ── 多边形ROI(由UI注入,最多32个点) ──
|
||||
Parameters.Add("PolyCount", new ProcessorParameter("PolyCount", "PolyCount", typeof(int), 0, null, null, "") { IsVisible = false });
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
@@ -311,4 +300,4 @@ public class EllipseDetectionProcessor : ImageProcessorBase
|
||||
_logger.Information("Ellipse detection completed: detected {Count} ellipses", ellipses.Count);
|
||||
return inputImage.Clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� FillRateProcessor.cs
|
||||
// 文件名: FillRateProcessor.cs
|
||||
// 描述: 通孔填锡率测量算子(倾斜投影几何法),基于四椭圆ROI
|
||||
// 功能:
|
||||
// - æ ·å“�倾斜çº?5°放置,利用投影ä½�移关系计算填锡率
|
||||
// - 四个æ¤åœ†å®šä¹‰ï¼?
|
||||
// - 样品倾斜约45°放置,利用投影位移关系计算填锡率
|
||||
// - 四个椭圆定义:
|
||||
// E1 = 通孔底部轮廓
|
||||
// E2 = 通孔顶部轮廓
|
||||
// E3 = 填锡起点(与E1��,代�%填锡�
|
||||
// E4 = 填锡终点(锡实际填充到的高度�
|
||||
// - 填锡çŽ?= |E4ä¸å¿ƒ - E3ä¸å¿ƒ| / |E2ä¸å¿ƒ - E1ä¸å¿ƒ| × 100%
|
||||
// - çº¯å‡ ä½•æ–¹æ³•ï¼Œä¸�ä¾�èµ–ç�°åº¦åˆ†æž?
|
||||
// - IPC-610 THT 分级判定(Class 1/2/3�
|
||||
// E3 = 填锡起点(与E1重合,代表0%填锡)
|
||||
// E4 = 填锡终点(锡实际填充到的高度)
|
||||
// - 填锡率 = |E4中心 - E3中心| / |E2中心 - E1中心| × 100%
|
||||
// - 纯几何方法,不依赖灰度分析
|
||||
// - IPC-610 THT 分级判定(Class 1/2/3)
|
||||
// 算法: 倾斜投影位移比例
|
||||
// 作� �伟 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;
|
||||
|
||||
@@ -42,7 +42,7 @@ public class FillRateProcessor : ImageProcessorBase
|
||||
// 四个椭圆(由交互控件注入,UI不可见)
|
||||
AddEllipseParams("E1", 200, 250, 60, 50, 0); // 底部
|
||||
AddEllipseParams("E2", 220, 180, 60, 50, 0); // 顶部
|
||||
AddEllipseParams("E3", 200, 250, 60, 50, 0); // 填锡起点�E1�
|
||||
AddEllipseParams("E3", 200, 250, 60, 50, 0); // 填锡起点(=E1)
|
||||
AddEllipseParams("E4", 210, 220, 55, 45, 0); // 填锡终点
|
||||
|
||||
Parameters.Add("THTLimit", new ProcessorParameter(
|
||||
@@ -78,7 +78,7 @@ public class FillRateProcessor : ImageProcessorBase
|
||||
int e3cx = GetParameter<int>("E3_CX"), e3cy = GetParameter<int>("E3_CY");
|
||||
int e4cx = GetParameter<int>("E4_CX"), e4cy = GetParameter<int>("E4_CY");
|
||||
|
||||
// 获å�–æ¤åœ†è½´å�‚数(用于绘制ï¼?
|
||||
// 获取椭圆轴参数(用于绘制)
|
||||
double e1a = GetParameter<double>("E1_A"), e1b = GetParameter<double>("E1_B"), e1ang = GetParameter<double>("E1_Angle");
|
||||
double e2a = GetParameter<double>("E2_A"), e2b = GetParameter<double>("E2_B"), e2ang = GetParameter<double>("E2_Angle");
|
||||
double e3a = GetParameter<double>("E3_A"), e3b = GetParameter<double>("E3_B"), e3ang = GetParameter<double>("E3_Angle");
|
||||
@@ -89,17 +89,17 @@ public class FillRateProcessor : ImageProcessorBase
|
||||
|
||||
OutputData.Clear();
|
||||
|
||||
// 计算通å”全高度的投影ä½�移(E1底部 â†?E2顶部ï¼?
|
||||
// 计算通孔全高度的投影位移(E1底部 → E2顶部)
|
||||
double fullDx = e2cx - e1cx;
|
||||
double fullDy = e2cy - e1cy;
|
||||
double fullDistance = Math.Sqrt(fullDx * fullDx + fullDy * fullDy);
|
||||
|
||||
// 计算填锡高度的投影�移(E3起点 �E4终点�
|
||||
// 计算填锡高度的投影位移(E3起点 → E4终点)
|
||||
double fillDx = e4cx - e3cx;
|
||||
double fillDy = e4cy - e3cy;
|
||||
double fillDistance = Math.Sqrt(fillDx * fillDx + fillDy * fillDy);
|
||||
|
||||
// 填锡�= 填锡�移 / 全高度��
|
||||
// 填锡率 = 填锡位移 / 全高度位移
|
||||
double fillRate = fullDistance > 0 ? (fillDistance / fullDistance) * 100.0 : 0;
|
||||
fillRate = Math.Clamp(fillRate, 0, 100);
|
||||
|
||||
@@ -130,4 +130,4 @@ public class FillRateProcessor : ImageProcessorBase
|
||||
|
||||
return inputImage.Clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件��? LineMeasurementProcessor.cs
|
||||
// 描述: 直线测量算子,用于测量图像中两点之间的距��?
|
||||
// 文件名: LineMeasurementProcessor.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 XP.ImageProcessing.Core;
|
||||
|
||||
namespace XP.ImageProcessing.Processors;
|
||||
|
||||
/// <summary>
|
||||
/// 直线测量算子 - 测量两点之间的距��?
|
||||
/// 直线测量算子 - 测量两点之间的距离
|
||||
/// </summary>
|
||||
public class LineMeasurementProcessor : ImageProcessorBase
|
||||
{
|
||||
@@ -40,28 +41,28 @@ public class LineMeasurementProcessor : ImageProcessorBase
|
||||
LocalizationHelper.GetString("LineMeasurementProcessor_X1"),
|
||||
typeof(int), 100, null, null,
|
||||
LocalizationHelper.GetString("LineMeasurementProcessor_X1_Desc"))
|
||||
{ IsVisible = false });
|
||||
{ IsVisible = false });
|
||||
|
||||
Parameters.Add("Y1", new ProcessorParameter(
|
||||
"Y1",
|
||||
LocalizationHelper.GetString("LineMeasurementProcessor_Y1"),
|
||||
typeof(int), 100, null, null,
|
||||
LocalizationHelper.GetString("LineMeasurementProcessor_Y1_Desc"))
|
||||
{ IsVisible = false });
|
||||
{ IsVisible = false });
|
||||
|
||||
Parameters.Add("X2", new ProcessorParameter(
|
||||
"X2",
|
||||
LocalizationHelper.GetString("LineMeasurementProcessor_X2"),
|
||||
typeof(int), 400, null, null,
|
||||
LocalizationHelper.GetString("LineMeasurementProcessor_X2_Desc"))
|
||||
{ IsVisible = false });
|
||||
{ IsVisible = false });
|
||||
|
||||
Parameters.Add("Y2", new ProcessorParameter(
|
||||
"Y2",
|
||||
LocalizationHelper.GetString("LineMeasurementProcessor_Y2"),
|
||||
typeof(int), 400, null, null,
|
||||
LocalizationHelper.GetString("LineMeasurementProcessor_Y2_Desc"))
|
||||
{ IsVisible = false });
|
||||
{ IsVisible = false });
|
||||
|
||||
Parameters.Add("PixelSize", new ProcessorParameter(
|
||||
"PixelSize",
|
||||
@@ -119,7 +120,7 @@ public class LineMeasurementProcessor : ImageProcessorBase
|
||||
// 计算实际距离
|
||||
double actualDistance = pixelDistance * pixelSize;
|
||||
|
||||
// 计算角度(相对于水平方向��?
|
||||
// 计算角度(相对于水平方向)
|
||||
double angleRad = Math.Atan2(dy, dx);
|
||||
double angleDeg = angleRad * 180.0 / Math.PI;
|
||||
|
||||
@@ -146,4 +147,4 @@ public class LineMeasurementProcessor : ImageProcessorBase
|
||||
|
||||
return inputImage.Clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� PointToLineProcessor.cs
|
||||
// 文件名: PointToLineProcessor.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 XP.ImageProcessing.Core;
|
||||
|
||||
namespace XP.ImageProcessing.Processors;
|
||||
|
||||
@@ -31,7 +32,7 @@ public class PointToLineProcessor : ImageProcessorBase
|
||||
|
||||
protected override void InitializeParameters()
|
||||
{
|
||||
// 直线两端�+ 测�点(由交互控件注入)
|
||||
// 直线两端点 + 测量点(由交互控件注入)
|
||||
Parameters.Add("L1X", new ProcessorParameter("L1X", "L1X", typeof(int), 100, null, null, "") { IsVisible = false });
|
||||
Parameters.Add("L1Y", new ProcessorParameter("L1Y", "L1Y", typeof(int), 200, null, null, "") { IsVisible = false });
|
||||
Parameters.Add("L2X", new ProcessorParameter("L2X", "L2X", typeof(int), 400, null, null, "") { IsVisible = false });
|
||||
@@ -79,7 +80,7 @@ public class PointToLineProcessor : ImageProcessorBase
|
||||
|
||||
if (abLen > 0.001)
|
||||
{
|
||||
// �积求��
|
||||
// 叉积求距离
|
||||
double cross = Math.Abs(abx * (l1y - py) - aby * (l1x - px));
|
||||
pixelDistance = cross / abLen;
|
||||
|
||||
@@ -112,4 +113,4 @@ public class PointToLineProcessor : ImageProcessorBase
|
||||
|
||||
return inputImage.Clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
// ============================================================================
|
||||
// 文件� VoidMeasurementProcessor.cs
|
||||
// 文件名: VoidMeasurementProcessor.cs
|
||||
// 描述: 空隙测量算子
|
||||
//
|
||||
// 处理流程:
|
||||
// 1. 构建多边形ROI掩码,计算ROI面积
|
||||
// 2. 在ROI内进行�阈值分割��气泡区�
|
||||
// 2. 在ROI内进行双阈值分割提取气泡区域
|
||||
// 3. 形态学膨胀合并相邻气泡
|
||||
// 4. 轮廓检测,计算每个气泡面积
|
||||
// 5. 计算空隙�= 总气泡��/ ROI�积
|
||||
// 5. 计算空隙率 = 总气泡面积 / ROI面积
|
||||
// ============================================================================
|
||||
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.CvEnum;
|
||||
using Emgu.CV.Structure;
|
||||
using Emgu.CV.Util;
|
||||
using XP.ImageProcessing.Core;
|
||||
using Serilog;
|
||||
using System.Drawing;
|
||||
using XP.ImageProcessing.Core;
|
||||
|
||||
namespace XP.ImageProcessing.Processors;
|
||||
|
||||
@@ -32,7 +32,7 @@ public class VoidMeasurementProcessor : ImageProcessorBase
|
||||
|
||||
protected override void InitializeParameters()
|
||||
{
|
||||
// ── 多边形ROI(由UI注入,最�2个点�──
|
||||
// ── 多边形ROI(由UI注入,最多32个点) ──
|
||||
Parameters.Add("PolyCount", new ProcessorParameter("PolyCount", "PolyCount", typeof(int), 0, null, null, "") { IsVisible = false });
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
@@ -40,7 +40,7 @@ public class VoidMeasurementProcessor : ImageProcessorBase
|
||||
Parameters.Add($"PolyY{i}", new ProcessorParameter($"PolyY{i}", $"PolyY{i}", typeof(int), 0, null, null, "") { IsVisible = false });
|
||||
}
|
||||
|
||||
// ── 气泡检测��──
|
||||
// ── 气泡检测参数 ──
|
||||
Parameters.Add("MinThreshold", new ProcessorParameter(
|
||||
"MinThreshold",
|
||||
LocalizationHelper.GetString("VoidMeasurementProcessor_MinThreshold"),
|
||||
@@ -109,7 +109,7 @@ public class VoidMeasurementProcessor : ImageProcessorBase
|
||||
}
|
||||
else
|
||||
{
|
||||
// æ— ROI时使用全å›?
|
||||
// 无ROI时使用全图
|
||||
roiMask = new Image<Gray, byte>(w, h);
|
||||
roiMask.SetValue(new Gray(255));
|
||||
}
|
||||
@@ -152,7 +152,7 @@ public class VoidMeasurementProcessor : ImageProcessorBase
|
||||
CvInvoke.BitwiseAnd(voidImg, roiMask, voidImg);
|
||||
}
|
||||
|
||||
// ── 轮廓检�──
|
||||
// ── 轮廓检测 ──
|
||||
using var contours = new VectorOfVectorOfPoint();
|
||||
using var hierarchy = new Mat();
|
||||
CvInvoke.FindContours(voidImg, contours, hierarchy, RetrType.External, ChainApproxMethod.ChainApproxSimple);
|
||||
@@ -183,7 +183,7 @@ public class VoidMeasurementProcessor : ImageProcessorBase
|
||||
});
|
||||
}
|
||||
|
||||
// 按�积从大到�排�
|
||||
// 按面积从大到小排序
|
||||
voids.Sort((a, b) => b.Area.CompareTo(a.Area));
|
||||
for (int i = 0; i < voids.Count; i++) voids[i].Index = i + 1;
|
||||
|
||||
@@ -227,4 +227,4 @@ public class VoidRegionInfo
|
||||
public double AreaPercent { get; set; }
|
||||
public Rectangle BoundingBox { get; set; }
|
||||
public Point[] ContourPoints { get; set; } = Array.Empty<Point>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// ��辣�? BandPassFilterProcessor.cs
|
||||
// �讛膩: 撣阡�𡁏誘瘜W膥蝞堒�嚗𣬚鍂鈭𡡞��笔㦛�誩��?
|
||||
// 文件名: BandPassFilterProcessor.cs
|
||||
// 描述: 带通滤波器算子,用于频域图像处理
|
||||
// 功能:
|
||||
// - �券��煺葉靽萘��孵�憸𤑳���凒��縑�?
|
||||
// - 在频域中保留特定频率范围的信号
|
||||
// - 支持理想、巴特沃斯、高斯三种滤波器类型
|
||||
// - 可调节低频和高频截止频率
|
||||
// - 通过FFT实现频域滤波
|
||||
// 算法: 基于离散傅里叶变换(DFT)的频域滤波
|
||||
// 雿𡏭�? �𦒘� 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 XP.ImageProcessing.Core;
|
||||
|
||||
namespace XP.ImageProcessing.Processors;
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� BilateralFilterProcessor.cs
|
||||
// æ��è¿°: å�Œè¾¹æ»¤æ³¢ç®—å�,用于ä¿�è¾¹é™�å™?
|
||||
// 文件名: BilateralFilterProcessor.cs
|
||||
// 描述: 双边滤波算子,用于保边降噪
|
||||
// 功能:
|
||||
// - 双边滤波
|
||||
// - ��边缘清晰的�时平滑图�
|
||||
// - 保持边缘清晰的同时平滑图像
|
||||
// - 可调节核大小和标准差
|
||||
// 算法: 双边滤波
|
||||
// 作� �伟 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,20 +1,20 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� GaussianBlurProcessor.cs
|
||||
// 文件名: GaussianBlurProcessor.cs
|
||||
// 描述: 高斯模糊算子,用于图像平滑和降噪
|
||||
// 功能:
|
||||
// - é«˜æ–¯æ ¸å�·ç§¯å¹³æ»?
|
||||
// - 高斯核卷积平滑
|
||||
// - 可调节核大小和标准差
|
||||
// - 有效去除高斯噪声
|
||||
// - 保持边缘相对清晰
|
||||
// 算法: 高斯滤波器��
|
||||
// 作� �伟 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.
|
||||
// 文件� HighPassFilterProcessor.cs
|
||||
// 文件名: HighPassFilterProcessor.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;
|
||||
|
||||
/// <summary>
|
||||
/// 高通滤波算å?
|
||||
/// 高通滤波算子
|
||||
/// </summary>
|
||||
public class HighPassFilterProcessor : ImageProcessorBase
|
||||
{
|
||||
@@ -69,7 +69,7 @@ public class HighPassFilterProcessor : ImageProcessorBase
|
||||
Mat dftImage = new Mat();
|
||||
CvInvoke.Dft(complexImage, dftImage, DxtType.Forward);
|
||||
|
||||
// 分离实部和虚�
|
||||
// 分离实部和虚部
|
||||
using (var dftPlanes = new Emgu.CV.Util.VectorOfMat())
|
||||
{
|
||||
CvInvoke.Split(dftImage, dftPlanes);
|
||||
@@ -80,7 +80,7 @@ public class HighPassFilterProcessor : ImageProcessorBase
|
||||
// 创建高通滤波器
|
||||
Mat filter = CreateHighPassFilter(rows, cols, cutoffFrequency);
|
||||
|
||||
// 应用滤波�
|
||||
// 应用滤波器
|
||||
CvInvoke.Multiply(real, filter, real);
|
||||
CvInvoke.Multiply(imag, filter, imag);
|
||||
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� LowPassFilterProcessor.cs
|
||||
// 文件名: LowPassFilterProcessor.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;
|
||||
|
||||
/// <summary>
|
||||
/// 低通滤波算å?
|
||||
/// 低通滤波算子
|
||||
/// </summary>
|
||||
public class LowPassFilterProcessor : ImageProcessorBase
|
||||
{
|
||||
@@ -69,7 +69,7 @@ public class LowPassFilterProcessor : ImageProcessorBase
|
||||
Mat dftImage = new Mat();
|
||||
CvInvoke.Dft(complexImage, dftImage, DxtType.Forward);
|
||||
|
||||
// 分离实部和虚�
|
||||
// 分离实部和虚部
|
||||
using (var dftPlanes = new Emgu.CV.Util.VectorOfMat())
|
||||
{
|
||||
CvInvoke.Split(dftImage, dftPlanes);
|
||||
@@ -80,7 +80,7 @@ public class LowPassFilterProcessor : ImageProcessorBase
|
||||
// 创建低通滤波器
|
||||
Mat filter = CreateLowPassFilter(rows, cols, cutoffFrequency);
|
||||
|
||||
// 应用滤波�
|
||||
// 应用滤波器
|
||||
CvInvoke.Multiply(real, filter, real);
|
||||
CvInvoke.Multiply(imag, filter, imag);
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� MeanFilterProcessor.cs
|
||||
// 文件名: MeanFilterProcessor.cs
|
||||
// 描述: 均值滤波算子,用于图像平滑
|
||||
// 功能:
|
||||
// - �值滤�
|
||||
// - 均值滤波
|
||||
// - 简单快速的平滑方法
|
||||
// - 可调节核大小
|
||||
// 算法: �值滤�
|
||||
// 作� �伟 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 MeanFilterProcessor : ImageProcessorBase
|
||||
{
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� MedianFilterProcessor.cs
|
||||
// 文件名: MedianFilterProcessor.cs
|
||||
// 描述: 中值滤波算子,用于去除椒盐噪声
|
||||
// 功能:
|
||||
// - ä¸å€¼æ»¤æ³?
|
||||
// - 中值滤波
|
||||
// - 有效去除椒盐噪声
|
||||
// - 保持边缘清晰
|
||||
// - 可调节核大小
|
||||
// 算法: ä¸å€¼æ»¤æ³?
|
||||
// 作� �伟 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 MedianFilterProcessor : ImageProcessorBase
|
||||
{
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� ShockFilterProcessor.cs
|
||||
// 文件名: ShockFilterProcessor.cs
|
||||
// 描述: 冲击滤波算子,用于图像锐化和边缘增强
|
||||
// 功能:
|
||||
// - 基于PDE的图���
|
||||
// - 基于PDE的图像锐化
|
||||
// - 增强边缘同时保持平滑区域
|
||||
// - 可调节迭代次数和滤波强度
|
||||
// - 适用于模糊图像的恢复
|
||||
// 算法: 冲击滤波器(Shock Filter)基于偏微分方程
|
||||
// 作� �伟 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.
|
||||
// 文件� HorizontalEdgeProcessor.cs
|
||||
// 文件名: HorizontalEdgeProcessor.cs
|
||||
// 描述: 水平边缘检测算子,专门用于检测水平方向的边缘
|
||||
// 功能:
|
||||
// - 检测水平边�
|
||||
// - 检测水平边缘
|
||||
// - 支持Prewitt和Sobel算子
|
||||
// - 可调节检测灵敏度
|
||||
// - 适用于检测水平线条和纹理
|
||||
// 算法: Prewitt/Sobel水平算子
|
||||
// 作� �伟 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 HorizontalEdgeProcessor : ImageProcessorBase
|
||||
{
|
||||
@@ -92,15 +92,15 @@ public class HorizontalEdgeProcessor : ImageProcessorBase
|
||||
|
||||
private Image<Gray, byte> ApplySobel(Image<Gray, byte> inputImage, double sensitivity, int threshold)
|
||||
{
|
||||
// 使用Sobelç®—å�检测水平边缘(Yæ–¹å�‘导数ï¼?
|
||||
// 使用Sobel算子检测水平边缘(Y方向导数)
|
||||
Image<Gray, float> sobelY = new Image<Gray, float>(inputImage.Size);
|
||||
CvInvoke.Sobel(inputImage, sobelY, DepthType.Cv32F, 0, 1, 3);
|
||||
|
||||
// 转�为�对值并应用���
|
||||
// 转换为绝对值并应用灵敏度
|
||||
Image<Gray, byte> result = new Image<Gray, byte>(inputImage.Size);
|
||||
CvInvoke.ConvertScaleAbs(sobelY, result, sensitivity, 0);
|
||||
|
||||
// 应用阈�
|
||||
// 应用阈值
|
||||
if (threshold > 0)
|
||||
{
|
||||
CvInvoke.Threshold(result, result, threshold, 255, ThresholdType.Binary);
|
||||
@@ -141,10 +141,10 @@ public class HorizontalEdgeProcessor : ImageProcessorBase
|
||||
sum -= inputData[y + 1, x, 0];
|
||||
sum -= inputData[y + 1, x + 1, 0];
|
||||
|
||||
// ��对值并应用���
|
||||
// 取绝对值并应用灵敏度
|
||||
int value = (int)(Math.Abs(sum) * sensitivity);
|
||||
|
||||
// 应用阈�
|
||||
// 应用阈值
|
||||
if (value > threshold)
|
||||
{
|
||||
outputData[y, x, 0] = (byte)Math.Min(255, value);
|
||||
@@ -161,11 +161,11 @@ public class HorizontalEdgeProcessor : ImageProcessorBase
|
||||
|
||||
private Image<Gray, byte> ApplySimple(Image<Gray, byte> inputImage, double sensitivity, int threshold)
|
||||
{
|
||||
// 简å�•差分算å?
|
||||
// 简单差分算子
|
||||
// [ 1 1 1]
|
||||
// [ 0 0 0]
|
||||
// [-1 -1 -1]
|
||||
// 但��更简�
|
||||
// 但权重更简单
|
||||
|
||||
int width = inputImage.Width;
|
||||
int height = inputImage.Height;
|
||||
@@ -182,7 +182,7 @@ public class HorizontalEdgeProcessor : ImageProcessorBase
|
||||
int diff = inputData[y - 1, x, 0] - inputData[y + 1, x, 0];
|
||||
int value = (int)(Math.Abs(diff) * sensitivity);
|
||||
|
||||
// 应用阈�
|
||||
// 应用阈值
|
||||
if (value > threshold)
|
||||
{
|
||||
outputData[y, x, 0] = (byte)Math.Min(255, value);
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// ��辣�? KirschEdgeProcessor.cs
|
||||
// �讛膩: Kirsch颲寧�璉�瘚讠�摮琜��其�璉�瘚见㦛�讛器蝻?
|
||||
// 文件名: KirschEdgeProcessor.cs
|
||||
// 描述: Kirsch边缘检测算子,用于检测图像边缘
|
||||
// 功能:
|
||||
// - Kirsch蝞堒�颲寧�璉�瘚?
|
||||
// - 8銝芣䲮�𤑳�颲寧�璉�瘚?
|
||||
// - Kirsch算子边缘检测
|
||||
// - 8个方向的边缘检测
|
||||
// - 输出最大响应方向的边缘
|
||||
// - 撖孵臁憯唳��笔漲雿?
|
||||
// 蝞埈�: Kirsch蝞堒�嚗?�孵�璅⊥踎嚗?
|
||||
// 雿𡏭�? �𦒘� wei.lw.li@hexagon.com
|
||||
// - 对噪声敏感度低
|
||||
// 算法: Kirsch算子(8方向模板)
|
||||
// 作者: 李伟 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>
|
||||
/// Kirsch颲寧�璉�瘚讠�摮?
|
||||
/// Kirsch边缘检测算子
|
||||
/// </summary>
|
||||
public class KirschEdgeProcessor : ImageProcessorBase
|
||||
{
|
||||
private static readonly ILogger _logger = Log.ForContext<KirschEdgeProcessor>();
|
||||
|
||||
// Kirsch蝞堒��?銝芣䲮�烐芋�?
|
||||
// Kirsch算子的8个方向模板
|
||||
private static readonly int[][,] KirschKernels = new int[8][,]
|
||||
{
|
||||
// N
|
||||
@@ -86,14 +86,14 @@ public class KirschEdgeProcessor : ImageProcessorBase
|
||||
Image<Gray, byte> result = new Image<Gray, byte>(width, height);
|
||||
byte[,,] outputData = result.Data;
|
||||
|
||||
// 撖寞�銝芸�蝝惩��?銝枝irsch璅⊥踎嚗����憭批�摨?
|
||||
// 对每个像素应用8个Kirsch模板,取最大响应
|
||||
for (int y = 1; y < height - 1; y++)
|
||||
{
|
||||
for (int x = 1; x < width - 1; x++)
|
||||
{
|
||||
int maxResponse = 0;
|
||||
|
||||
// 撖?銝芣䲮�穃��怨恣蝞?
|
||||
// 对8个方向分别计算
|
||||
for (int k = 0; k < 8; k++)
|
||||
{
|
||||
int sum = 0;
|
||||
@@ -106,7 +106,7 @@ public class KirschEdgeProcessor : ImageProcessorBase
|
||||
}
|
||||
}
|
||||
|
||||
// �𣇉�撖孵�?
|
||||
// 取绝对值
|
||||
sum = Math.Abs(sum);
|
||||
if (sum > maxResponse)
|
||||
{
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� SobelEdgeProcessor.cs
|
||||
// æ��è¿°: Sobel边缘检测算å�,用于检测图åƒ�è¾¹ç¼?
|
||||
// 文件名: SobelEdgeProcessor.cs
|
||||
// 描述: Sobel边缘检测算子,用于检测图像边缘
|
||||
// 功能:
|
||||
// - Sobelç®—å�边缘检æµ?
|
||||
// - 支�X方��Y方�和组�检�
|
||||
// - Sobel算子边缘检测
|
||||
// - 支持X方向、Y方向和组合检测
|
||||
// - 可调节核大小
|
||||
// - 输出边缘强度�
|
||||
// - 输出边缘强度图
|
||||
// 算法: Sobel算子
|
||||
// 作� �伟 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>
|
||||
/// Sobel边缘检测算å?
|
||||
/// Sobel边缘检测算子
|
||||
/// </summary>
|
||||
public class SobelEdgeProcessor : ImageProcessorBase
|
||||
{
|
||||
@@ -96,7 +96,7 @@ public class SobelEdgeProcessor : ImageProcessorBase
|
||||
// 计算梯度幅值:sqrt(Gx^2 + Gy^2)
|
||||
Image<Gray, float> magnitude = new Image<Gray, float>(inputImage.Size);
|
||||
|
||||
// 手动计算幅�
|
||||
// 手动计算幅值
|
||||
for (int y = 0; y < inputImage.Height; y++)
|
||||
{
|
||||
for (int x = 0; x < inputImage.Width; x++)
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Windows.Controls.Primitives;
|
||||
namespace XP.ImageProcessing.RoiControl
|
||||
{
|
||||
/// <summary>
|
||||
/// ROI控制�?
|
||||
/// ROI控制点
|
||||
/// </summary>
|
||||
public class ControlThumb : Thumb
|
||||
{
|
||||
@@ -21,7 +21,7 @@ namespace XP.ImageProcessing.RoiControl
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 如果样式加载失败,使用默认样�?
|
||||
// 如果样式加载失败,使用默认样式
|
||||
thumbStyle = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using XP.ImageProcessing.RoiControl.Models;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using XP.ImageProcessing.RoiControl.Models;
|
||||
|
||||
namespace XP.ImageProcessing.RoiControl.Controls
|
||||
{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using XP.ImageProcessing.RoiControl.Models;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
@@ -7,7 +8,6 @@ using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
using XP.ImageProcessing.RoiControl.Models;
|
||||
|
||||
namespace XP.ImageProcessing.RoiControl.Controls
|
||||
{
|
||||
@@ -75,14 +75,14 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
||||
|
||||
private void Points_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
// 只在删除或添加顶点时更新Adorner,拖拽时的Replace操作不触发更�?
|
||||
// 只在删除或添加顶点时更新Adorner,拖拽时的Replace操作不触发更新
|
||||
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove ||
|
||||
e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
|
||||
{
|
||||
// Points集合变化时,如果当前选中的是多边形ROI,更新Adorner
|
||||
if (SelectedROI is PolygonROI polygonROI && sender == polygonROI.Points)
|
||||
{
|
||||
// 使用Dispatcher延迟更新,确保UI已经处理完Points的变�?
|
||||
// 使用Dispatcher延迟更新,确保UI已经处理完Points的变化
|
||||
Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
UpdateAdorner();
|
||||
@@ -219,7 +219,7 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
||||
{
|
||||
var control = (PolygonRoiCanvas)d;
|
||||
|
||||
// 更新IsSelected状�?
|
||||
// 更新IsSelected状态
|
||||
if (e.OldValue is ROIShape oldROI)
|
||||
{
|
||||
oldROI.IsSelected = false;
|
||||
@@ -288,7 +288,7 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
||||
// 尝试获取容器
|
||||
var container = itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as ContentPresenter;
|
||||
|
||||
// 如果容器还没生成,尝试强制生�?
|
||||
// 如果容器还没生成,尝试强制生成
|
||||
if (container == null)
|
||||
{
|
||||
// 强制生成容器
|
||||
@@ -298,7 +298,7 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
||||
|
||||
if (container != null)
|
||||
{
|
||||
// 查找实际的形状元素(只支持多边形�?
|
||||
// 查找实际的形状元素(只支持多边形)
|
||||
if (roi is PolygonROI)
|
||||
{
|
||||
return FindVisualChild<Polygon>(container);
|
||||
@@ -334,10 +334,10 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
||||
|
||||
private void Canvas_MouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
// 获取鼠标�?imageDisplayGrid 中的位置
|
||||
// 获取鼠标在 imageDisplayGrid 中的位置
|
||||
Point mousePos = e.GetPosition(imageDisplayGrid);
|
||||
|
||||
// 获取鼠标�?Canvas 中的位置(缩放前�?
|
||||
// 获取鼠标在 Canvas 中的位置(缩放前)
|
||||
Point mousePosOnCanvas = e.GetPosition(mainCanvas);
|
||||
|
||||
double oldZoom = ZoomScale;
|
||||
@@ -364,7 +364,7 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
||||
ZoomScale = newZoom;
|
||||
|
||||
// 调整平移偏移,使鼠标位置保持不变
|
||||
// 新的偏移 = 旧偏�?+ 鼠标位置 - 鼠标位置 * 缩放比例
|
||||
// 新的偏移 = 旧偏移 + 鼠标位置 - 鼠标位置 * 缩放比例
|
||||
PanOffsetX = mousePos.X - (mousePos.X - PanOffsetX) * scale;
|
||||
PanOffsetY = mousePos.Y - (mousePos.Y - PanOffsetY) * scale;
|
||||
}
|
||||
@@ -412,7 +412,7 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
||||
|
||||
private void Canvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
// 右键点击完成多边�?
|
||||
// 右键点击完成多边形
|
||||
OnRightClick();
|
||||
e.Handled = true;
|
||||
}
|
||||
@@ -440,10 +440,10 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
||||
|
||||
if (imageDisplayGrid != null && CanvasWidth > 0 && CanvasHeight > 0)
|
||||
{
|
||||
// 使用 Dispatcher 延迟执行,确保布局已完�?
|
||||
// 使用 Dispatcher 延迟执行,确保布局已完成
|
||||
Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
// 获取图像显示区域的实际尺�?
|
||||
// 获取图像显示区域的实际尺寸
|
||||
double viewportWidth = imageDisplayGrid.ActualWidth;
|
||||
double viewportHeight = imageDisplayGrid.ActualHeight;
|
||||
|
||||
@@ -453,10 +453,10 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
||||
double scaleX = viewportWidth / CanvasWidth;
|
||||
double scaleY = viewportHeight / CanvasHeight;
|
||||
|
||||
// 选择较小的缩放比例,确保图像完全显示在窗口内(保持宽高比�?
|
||||
// 选择较小的缩放比例,确保图像完全显示在窗口内(保持宽高比)
|
||||
ZoomScale = Math.Min(scaleX, scaleY);
|
||||
|
||||
// 居中显示�?Grid �?HorizontalAlignment �?VerticalAlignment 自动处理
|
||||
// 居中显示由 Grid 的 HorizontalAlignment 和 VerticalAlignment 自动处理
|
||||
PanOffsetX = 0;
|
||||
PanOffsetY = 0;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace XP.ImageProcessing.RoiControl.Models
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用于JSON序列化的Points列表(不参与UI绑定�?
|
||||
/// 用于JSON序列化的Points列表(不参与UI绑定)
|
||||
/// </summary>
|
||||
[System.Text.Json.Serialization.JsonPropertyName("PointsList")]
|
||||
public List<Point> PointsList
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace XP.ImageProcessing.RoiControl
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 索引转换为位置标�?
|
||||
/// 索引转换为位置标签
|
||||
/// </summary>
|
||||
public class IndexToPositionConverter : IValueConverter
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace XP.ImageProcessing.RoiControl
|
||||
/// </summary>
|
||||
public class PolygonAdorner : Adorner
|
||||
{
|
||||
private List<ControlThumb> vertexThumbs = new List<ControlThumb>(); // 顶点控制�?
|
||||
private List<ControlThumb> vertexThumbs = new List<ControlThumb>(); // 顶点控制点
|
||||
private VisualCollection visualChildren;
|
||||
private double scaleFactor = 1;
|
||||
private Models.PolygonROI? polygonROI;
|
||||
@@ -28,7 +28,7 @@ namespace XP.ImageProcessing.RoiControl
|
||||
// 使用ROI模型的Points数量而不是Polygon的Points
|
||||
int pointCount = polygonROI?.Points.Count ?? 0;
|
||||
|
||||
// 创建顶点控制�?
|
||||
// 创建顶点控制点
|
||||
for (int i = 0; i < pointCount; i++)
|
||||
{
|
||||
var thumb = new ControlThumb();
|
||||
@@ -80,7 +80,7 @@ namespace XP.ImageProcessing.RoiControl
|
||||
|
||||
private void HandleRightClick(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
// 右键删除顶点(至少保�?个顶点)
|
||||
// 右键删除顶点(至少保留3个顶点)
|
||||
if (polygonROI != null && polygonROI.Points.Count > 3)
|
||||
{
|
||||
Thumb? hitThumb = sender as Thumb;
|
||||
@@ -104,7 +104,7 @@ namespace XP.ImageProcessing.RoiControl
|
||||
{
|
||||
double thumbSize = 12 * scaleFactor;
|
||||
|
||||
// 布局顶点控制�?
|
||||
// 布局顶点控制点
|
||||
for (int i = 0; i < vertexThumbs.Count && i < polygonROI.Points.Count; i++)
|
||||
{
|
||||
vertexThumbs[i].Arrange(new Rect(
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace XP.ImageProcessing.RoiControl
|
||||
// 保存引用以便后续清理
|
||||
_attachedCollections[polygon] = newCollection;
|
||||
|
||||
// 监听Polygon卸载事件以清理资�?
|
||||
// 监听Polygon卸载事件以清理资源
|
||||
polygon.Unloaded += (s, args) =>
|
||||
{
|
||||
if (_attachedCollections.TryGetValue(polygon, out var collection))
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using XP.ImageProcessing.RoiControl.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Windows;
|
||||
using XP.ImageProcessing.RoiControl.Models;
|
||||
|
||||
namespace XP.ImageProcessing.RoiControl
|
||||
{
|
||||
@@ -38,7 +38,7 @@ namespace XP.ImageProcessing.RoiControl
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 序列化ROI列表为JSON字符�?
|
||||
/// 序列化ROI列表为JSON字符串
|
||||
/// </summary>
|
||||
public static string Serialize(IEnumerable<ROIShape> roiList)
|
||||
{
|
||||
@@ -55,7 +55,7 @@ namespace XP.ImageProcessing.RoiControl
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Point类型的JSON转换�?
|
||||
/// Point类型的JSON转换器
|
||||
/// </summary>
|
||||
public class PointConverter : JsonConverter<Point>
|
||||
{
|
||||
@@ -102,7 +102,7 @@ namespace XP.ImageProcessing.RoiControl
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ROIShape多态类型的JSON转换�?
|
||||
/// ROIShape多态类型的JSON转换器
|
||||
/// </summary>
|
||||
public class ROIShapeConverter : JsonConverter<ROIShape>
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using XP.ImageProcessing.RoiControl.Models;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using XP.ImageProcessing.RoiControl.Models;
|
||||
|
||||
namespace XP.ImageProcessing.RoiControl.Converters
|
||||
{
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<ResourceDictionary
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:XP.ImageProcessing.RoiControl.Controls">
|
||||
xmlns:local="clr-namespace:XP.ImageProcessing.RoiControl.Controls"
|
||||
xmlns:models="clr-namespace:XP.ImageProcessing.RoiControl.Models">
|
||||
|
||||
<!-- ControlThumb样式 - 14*14灰色矩形 -->
|
||||
<Style x:Key="AreaControlThumbStyle" TargetType="{x:Type Thumb}">
|
||||
|
||||
Reference in New Issue
Block a user