规范类名及命名空间名称

This commit is contained in:
李伟
2026-04-13 14:35:37 +08:00
parent c430ec229b
commit ace1c70ddf
217 changed files with 1271 additions and 1384 deletions
+1 -4
View File
@@ -1,8 +1,7 @@
using Basler.Pylon; using Basler.Pylon;
using Serilog; using Serilog;
using CameraImageGrabbedEventArgs = XP.Camera.ImageGrabbedEventArgs;
using CameraGrabErrorEventArgs = XP.Camera.GrabErrorEventArgs; using CameraGrabErrorEventArgs = XP.Camera.GrabErrorEventArgs;
using CameraImageGrabbedEventArgs = XP.Camera.ImageGrabbedEventArgs;
namespace XP.Camera; namespace XP.Camera;
@@ -177,7 +176,6 @@ public class BaslerCameraController : ICameraController
} }
} }
/// <inheritdoc /> /// <inheritdoc />
public void ExecuteSoftwareTrigger() public void ExecuteSoftwareTrigger()
{ {
@@ -460,7 +458,6 @@ public class BaslerCameraController : ICameraController
} }
} }
/// <summary> /// <summary>
/// ConnectionLost 事件处理。在 pylon SDK 事件线程上调用。 /// ConnectionLost 事件处理。在 pylon SDK 事件线程上调用。
/// </summary> /// </summary>
+30 -9
View File
@@ -3,23 +3,44 @@ namespace XP.Camera;
/// <summary>所有相机相关错误的基类异常。</summary> /// <summary>所有相机相关错误的基类异常。</summary>
public class CameraException : Exception public class CameraException : Exception
{ {
public CameraException() { } public CameraException()
public CameraException(string message) : base(message) { } { }
public CameraException(string message, Exception innerException) : base(message, innerException) { }
public CameraException(string message) : base(message)
{
}
public CameraException(string message, Exception innerException) : base(message, innerException)
{
}
} }
/// <summary>当相机连接意外断开时抛出的异常。</summary> /// <summary>当相机连接意外断开时抛出的异常。</summary>
public class ConnectionLostException : CameraException public class ConnectionLostException : CameraException
{ {
public ConnectionLostException() { } public ConnectionLostException()
public ConnectionLostException(string message) : base(message) { } { }
public ConnectionLostException(string message, Exception innerException) : base(message, innerException) { }
public ConnectionLostException(string message) : base(message)
{
}
public ConnectionLostException(string message, Exception innerException) : base(message, innerException)
{
}
} }
/// <summary>当系统中无可用相机设备时抛出的异常。</summary> /// <summary>当系统中无可用相机设备时抛出的异常。</summary>
public class DeviceNotFoundException : CameraException public class DeviceNotFoundException : CameraException
{ {
public DeviceNotFoundException() { } public DeviceNotFoundException()
public DeviceNotFoundException(string message) : base(message) { } { }
public DeviceNotFoundException(string message, Exception innerException) : base(message, innerException) { }
public DeviceNotFoundException(string message) : base(message)
{
}
public DeviceNotFoundException(string message, Exception innerException) : base(message, innerException)
{
}
} }
+11
View File
@@ -28,18 +28,29 @@ public interface ICameraController : IDisposable
void StopGrabbing(); void StopGrabbing();
double GetExposureTime(); double GetExposureTime();
void SetExposureTime(double microseconds); void SetExposureTime(double microseconds);
double GetGain(); double GetGain();
void SetGain(double value); void SetGain(double value);
int GetWidth(); int GetWidth();
void SetWidth(int value); void SetWidth(int value);
int GetHeight(); int GetHeight();
void SetHeight(int value); void SetHeight(int value);
string GetPixelFormat(); string GetPixelFormat();
void SetPixelFormat(string format); void SetPixelFormat(string format);
event EventHandler<ImageGrabbedEventArgs> ImageGrabbed; event EventHandler<ImageGrabbedEventArgs> ImageGrabbed;
event EventHandler<GrabErrorEventArgs> GrabError; event EventHandler<GrabErrorEventArgs> GrabError;
event EventHandler ConnectionLost; event EventHandler ConnectionLost;
} }
@@ -1,18 +1,18 @@
using System.Globalization; using System.Globalization;
using System.Resources; using System.Resources;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.CfgControl;
/// <summary> /// <summary>
/// 本地化辅助类,用于管理多语言资源 /// 本地化辅助类,用于管理多语言资源
/// ImageProcessing 主项目的语言设置同步 /// ?ImageProcessing 主项目的语言设置同步
/// </summary> /// </summary>
public static class LocalizationHelper public static class LocalizationHelper
{ {
private static ResourceManager? _resourceManager; private static ResourceManager? _resourceManager;
/// <summary> /// <summary>
/// 资源管理 /// 资源管理?
/// </summary> /// </summary>
private static ResourceManager ResourceManager private static ResourceManager ResourceManager
{ {
@@ -21,7 +21,7 @@ public static class LocalizationHelper
if (_resourceManager == null) if (_resourceManager == null)
{ {
_resourceManager = new ResourceManager( _resourceManager = new ResourceManager(
"ImageProcessing.Processors.Resources.Resources", "XP.ImageProcessing.CfgControl.Resources.Resources",
typeof(LocalizationHelper).Assembly); typeof(LocalizationHelper).Assembly);
} }
return _resourceManager; return _resourceManager;
@@ -32,7 +32,7 @@ public static class LocalizationHelper
/// 获取本地化字符串 /// 获取本地化字符串
/// 使用当前 UI 文化(与主项目同步) /// 使用当前 UI 文化(与主项目同步)
/// </summary> /// </summary>
/// <param name="key">资源键</param> /// <param name="key">资源?/param>
/// <returns>本地化字符串</returns> /// <returns>本地化字符串</returns>
public static string GetString(string key) public static string GetString(string key)
{ {
@@ -1,4 +1,4 @@
<UserControl x:Class="ImageProcessing.Controls.ProcessorParameterControl" <UserControl x:Class="XP.ImageProcessing.CfgControl.ProcessorParameterControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@@ -1,8 +1,8 @@
using ImageProcessing.Core;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Controls; namespace XP.ImageProcessing.CfgControl;
/// <summary> /// <summary>
/// 通用参数配置 UserControl /// 通用参数配置 UserControl
@@ -24,7 +24,7 @@ public partial class ProcessorParameterControl : UserControl
} }
/// <summary> /// <summary>
/// 更新"未选择算子"的文 /// 更新"未选择算子"的文?
/// </summary> /// </summary>
private void UpdateNoProcessorText() private void UpdateNoProcessorText()
{ {
@@ -41,7 +41,7 @@ public partial class ProcessorParameterControl : UserControl
} }
/// <summary> /// <summary>
/// 加载算子参数并生UI /// 加载算子参数并生?UI
/// </summary> /// </summary>
public void LoadProcessor(ImageProcessorBase? processor) public void LoadProcessor(ImageProcessorBase? processor)
{ {
@@ -68,7 +68,7 @@ public partial class ProcessorParameterControl : UserControl
} }
/// <summary> /// <summary>
/// 根据参数类型创建对应的控 /// 根据参数类型创建对应的控?
/// </summary> /// </summary>
private void CreateParameterControl(ProcessorParameter param) private void CreateParameterControl(ProcessorParameter param)
{ {
@@ -88,7 +88,7 @@ public partial class ProcessorParameterControl : UserControl
}; };
pnlParameters.Children.Add(label); pnlParameters.Children.Add(label);
// 根据参数类型创建不同的控 // 根据参数类型创建不同的控?
UIElement? control = null; UIElement? control = null;
if (param.ValueType == typeof(int)) if (param.ValueType == typeof(int))
@@ -133,8 +133,8 @@ public partial class ProcessorParameterControl : UserControl
} }
/// <summary> /// <summary>
/// 创建整数类型控件(Slider + TextBox 或仅 TextBox /// 创建整数类型控件(Slider + TextBox 或仅 TextBox?
/// MinValue MaxValue 都为 null 时,只显示文本框,不显示滑块 /// ?MinValue ?MaxValue 都为 null 时,只显示文本框,不显示滑块
/// </summary> /// </summary>
private UIElement CreateIntegerControl(ProcessorParameter param) private UIElement CreateIntegerControl(ProcessorParameter param)
{ {
@@ -201,8 +201,8 @@ public partial class ProcessorParameterControl : UserControl
} }
/// <summary> /// <summary>
/// 创建浮点数类型控件(Slider + TextBox 或仅 TextBox /// 创建浮点数类型控件(Slider + TextBox 或仅 TextBox?
/// MinValue MaxValue 都为 null 时,只显示文本框,不显示滑块 /// ?MinValue ?MaxValue 都为 null 时,只显示文本框,不显示滑块
/// </summary> /// </summary>
private UIElement CreateDoubleControl(ProcessorParameter param) private UIElement CreateDoubleControl(ProcessorParameter param)
{ {
@@ -268,7 +268,7 @@ public partial class ProcessorParameterControl : UserControl
} }
/// <summary> /// <summary>
/// 创建布尔类型控件(CheckBox /// 创建布尔类型控件(CheckBox?
/// </summary> /// </summary>
private UIElement CreateBooleanControl(ProcessorParameter param) private UIElement CreateBooleanControl(ProcessorParameter param)
{ {
@@ -295,7 +295,7 @@ public partial class ProcessorParameterControl : UserControl
} }
/// <summary> /// <summary>
/// 创建下拉框控件(ComboBox /// 创建下拉框控件(ComboBox?
/// </summary> /// </summary>
private UIElement CreateComboBoxControl(ProcessorParameter param) private UIElement CreateComboBoxControl(ProcessorParameter param)
{ {
@@ -322,7 +322,7 @@ public partial class ProcessorParameterControl : UserControl
{ {
_currentProcessor?.SetParameter(param.Name, comboBox.SelectedItem.ToString()!); _currentProcessor?.SetParameter(param.Name, comboBox.SelectedItem.ToString()!);
// 如果FilterType 参数,重新加载界面以更新参数可见 // 如果?FilterType 参数,重新加载界面以更新参数可见?
if (param.Name == "FilterType") if (param.Name == "FilterType")
{ {
LoadProcessor(_currentProcessor); LoadProcessor(_currentProcessor);
@@ -336,7 +336,7 @@ public partial class ProcessorParameterControl : UserControl
} }
/// <summary> /// <summary>
/// 创建文本框控件(TextBox /// 创建文本框控件(TextBox?
/// </summary> /// </summary>
private UIElement CreateTextBoxControl(ProcessorParameter param) private UIElement CreateTextBoxControl(ProcessorParameter param)
{ {
@@ -358,7 +358,7 @@ public partial class ProcessorParameterControl : UserControl
} }
/// <summary> /// <summary>
/// 获取当前配置的算 /// 获取当前配置的算?
/// </summary> /// </summary>
public ImageProcessorBase? GetProcessor() public ImageProcessorBase? GetProcessor()
{ {
@@ -5,6 +5,8 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<UseWPF>true</UseWPF> <UseWPF>true</UseWPF>
<RootNamespace>XP.ImageProcessing.CfgControl</RootNamespace>
<AssemblyName>XP.ImageProcessing.CfgControl</AssemblyName>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -23,7 +25,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ImageProcessing.Core\ImageProcessing.Core.csproj" /> <ProjectReference Include="..\XP.ImageProcessing.Core\XP.ImageProcessing.Core.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -1,22 +1,22 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: ImageProcessorBase.cs // 文件? ImageProcessorBase.cs
// 描述: 8位图像处理算子基类,定义图像处理算子的通用接口和行 // 描述: 8位图像处理算子基类,定义图像处理算子的通用接口和行?
// 功能: // 功能:
// - 定义算子的基本属性(名称、描述) // - 定义算子的基本属性(名称、描述)
// - 参数管理(设置、获取、验证) // - 参数管理(设置、获取、验证)
// - ROI(感兴趣区域)处理支 // - ROI(感兴趣区域)处理支?
// - 输出数据管理(用于传递额外信息如轮廓等) // - 输出数据管理(用于传递额外信息如轮廓等)
// - 为所有8位图像处理算子提供统一的基础框架 // - 为所?位图像处理算子提供统一的基础框架
// 设计模式: 模板方法模式 // 设计模式: 模板方法模式
// 作者: 李伟 wei.lw.li@hexagon.com // 作? 李伟 wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using Emgu.CV.Util; using Emgu.CV.Util;
namespace ImageProcessing.Core; namespace XP.ImageProcessing.Core;
/// <summary> /// <summary>
/// 图像处理算子基类 /// 图像处理算子基类
@@ -49,7 +49,7 @@ public abstract class ImageProcessorBase
} }
/// <summary> /// <summary>
/// 初始化算子参数(子类实现 /// 初始化算子参数(子类实现?
/// </summary> /// </summary>
protected abstract void InitializeParameters(); protected abstract void InitializeParameters();
@@ -59,7 +59,7 @@ public abstract class ImageProcessorBase
public abstract Image<Gray, byte> Process(Image<Gray, byte> inputImage); public abstract Image<Gray, byte> Process(Image<Gray, byte> inputImage);
/// <summary> /// <summary>
/// 执行图像处理(带矩形ROI支持 /// 执行图像处理(带矩形ROI支持?
/// </summary> /// </summary>
public Image<Gray, byte> ProcessWithROI(Image<Gray, byte> inputImage) public Image<Gray, byte> ProcessWithROI(Image<Gray, byte> inputImage)
{ {
@@ -71,7 +71,7 @@ public abstract class ImageProcessorBase
var processedROI = Process(roiImage); var processedROI = Process(roiImage);
// ROI 偏移量保存到输出数据中,供轮廓绘制等使用 // ?ROI 偏移量保存到输出数据中,供轮廓绘制等使用
OutputData["ROIOffset"] = new System.Drawing.Point(ROI.Value.X, ROI.Value.Y); OutputData["ROIOffset"] = new System.Drawing.Point(ROI.Value.X, ROI.Value.Y);
var result = inputImage.Clone(); var result = inputImage.Clone();
@@ -87,7 +87,7 @@ public abstract class ImageProcessorBase
} }
/// <summary> /// <summary>
/// 执行图像处理(带多边形ROI掩码支持 /// 执行图像处理(带多边形ROI掩码支持?
/// </summary> /// </summary>
public Image<Gray, byte> ProcessWithPolygonROI(Image<Gray, byte> inputImage) 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); var mask = new Image<Gray, byte>(inputImage.Width, inputImage.Height);
mask.SetValue(new Gray(0)); mask.SetValue(new Gray(0));
// 绘制多边形掩码(白色表示ROI区域 // 绘制多边形掩码(白色表示ROI区域?
using (var vop = new VectorOfPoint(PolygonROIPoints)) using (var vop = new VectorOfPoint(PolygonROIPoints))
{ {
using (var vvop = new VectorOfVectorOfPoint(vop)) using (var vvop = new VectorOfVectorOfPoint(vop))
@@ -115,12 +115,12 @@ public abstract class ImageProcessorBase
// 创建结果图像 // 创建结果图像
var result = inputImage.Clone(); var result = inputImage.Clone();
// 使用掩码:ROI内使用处理后的像素,ROI外保持原始像 // 使用掩码:ROI内使用处理后的像素,ROI外保持原始像?
for (int y = 0; y < inputImage.Height; y++) for (int y = 0; y < inputImage.Height; y++)
{ {
for (int x = 0; x < inputImage.Width; x++) 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]; result.Data[y, x, 0] = processedImage.Data[y, x, 0];
} }
@@ -137,7 +137,7 @@ public abstract class ImageProcessorBase
} }
/// <summary> /// <summary>
/// 获取所有参数列 /// 获取所有参数列?
/// </summary> /// </summary>
public List<ProcessorParameter> GetParameters() public List<ProcessorParameter> GetParameters()
{ {
@@ -145,7 +145,7 @@ public abstract class ImageProcessorBase
} }
/// <summary> /// <summary>
/// 设置参数 /// 设置参数?
/// </summary> /// </summary>
public void SetParameter(string name, object value) public void SetParameter(string name, object value)
{ {
@@ -1,24 +1,24 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: ProcessorParameter.cs // 文件å? ProcessorParameter.cs
// 描述: 图像处理算子参数定义类,用于描述算子的可配置参数 // 描述: 图像处理算子参数定义类,用于描述算子的可配置参数
// 功能: // 功能:
// - 定义参数的基本属性(名称、类型、默认值) // - 定义参数的基本属性(名称、类型、默认值)
// - 支持参数范围约束(最小值、最大值) // - 支持参数范围约束(最小值、最大值)
// - 支持枚举类型参数(下拉选项) // - æ”¯æŒæžšä¸¾ç±»åž‹å‚数(下拉选项ï¼?
// - 提供参数描述信息用于UI显示 // - 提供参数描述信息用于UI显示
// - 统一的参数管理机制 // - ç»Ÿä¸€çš„å‚æ•°ç®¡ç†æœºåˆ?
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
namespace ImageProcessing.Core; namespace XP.ImageProcessing.Core;
/// <summary> /// <summary>
/// 图像处理算子参数定义 /// 图像处理算子参数定义
/// </summary> /// </summary>
public class ProcessorParameter public class ProcessorParameter
{ {
/// <summary>参数名称(代码中使用)</summary> /// <summary>傿•°å称(代ç ä¸­ä½¿ç”¨ï¼?/summary>
public string Name { get; set; } public string Name { get; set; }
/// <summary>显示名称(UI中显示)</summary> /// <summary>显示名称(UI中显示)</summary>
@@ -27,7 +27,7 @@ public class ProcessorParameter
/// <summary>参数类型</summary> /// <summary>参数类型</summary>
public Type ValueType { get; set; } public Type ValueType { get; set; }
/// <summary>当前值</summary> /// <summary>当å‰å€?/summary>
public object Value { get; set; } public object Value { get; set; }
/// <summary>最小值(可选)</summary> /// <summary>最小值(可选)</summary>
@@ -4,6 +4,8 @@
<TargetFramework>net8.0-windows</TargetFramework> <TargetFramework>net8.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<RootNamespace>XP.ImageProcessing.Core</RootNamespace>
<AssemblyName>XP.ImageProcessing.Core</AssemblyName>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -1,18 +1,18 @@
using System.Globalization; using System.Globalization;
using System.Resources; using System.Resources;
namespace ImageProcessing.Controls; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 本地化辅助类,用于管理多语言资源 /// 本地化辅助类,用于管理多语言资源
/// ImageProcessing 主项目的语言设置同步 /// ä¸?ImageProcessing ä¸»é¡¹ç›®çš„è¯­è¨€è®¾ç½®åŒæ­¥
/// </summary> /// </summary>
public static class LocalizationHelper public static class LocalizationHelper
{ {
private static ResourceManager? _resourceManager; private static ResourceManager? _resourceManager;
/// <summary> /// <summary>
/// 资源管理器 /// 资æºç®¡ç†å™?
/// </summary> /// </summary>
private static ResourceManager ResourceManager private static ResourceManager ResourceManager
{ {
@@ -21,7 +21,7 @@ public static class LocalizationHelper
if (_resourceManager == null) if (_resourceManager == null)
{ {
_resourceManager = new ResourceManager( _resourceManager = new ResourceManager(
"ImageProcessing.Controls.Resources.Resources", "XP.ImageProcessing.Processors.Resources.Resources",
typeof(LocalizationHelper).Assembly); typeof(LocalizationHelper).Assembly);
} }
return _resourceManager; return _resourceManager;
@@ -32,7 +32,7 @@ public static class LocalizationHelper
/// 获取本地化字符串 /// 获取本地化字符串
/// 使用当前 UI 文化(与主项目同步) /// 使用当前 UI 文化(与主项目同步)
/// </summary> /// </summary>
/// <param name="key">资源键</param> /// <param name="key">资æºé”?/param>
/// <returns>本地化字符串</returns> /// <returns>本地化字符串</returns>
public static string GetString(string key) public static string GetString(string key)
{ {
@@ -5,6 +5,8 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<RootNamespace>XP.ImageProcessing.Processors</RootNamespace>
<AssemblyName>XP.ImageProcessing.Processors</AssemblyName>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -28,7 +30,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ImageProcessing.Core\ImageProcessing.Core.csproj" /> <ProjectReference Include="..\XP.ImageProcessing.Core\XP.ImageProcessing.Core.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -1,24 +1,23 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: FilmEffectProcessor.cs // 文件å? FilmEffectProcessor.cs
// 描述: 电子胶片效果算子,模拟传统X射线胶片的显示效果 // æè¿°: 电å­èƒ¶ç‰‡æ•ˆæžœç®—å­ï¼Œæ¨¡æ‹Ÿä¼ ç»ŸX射线胶片的显示效æž?
// 功能: // 功能:
// - 窗宽窗位(Window/Level)调整 // - 窗宽窗ä½ï¼ˆWindow/Level)调æ•?
// - 胶片反转(正片/负片) // - 胶片å转(正ç‰?负片ï¼?
// - 多种胶片特性曲线(线性、S曲线、对数、指数) // - 多种胶片特性曲线(线性、S曲线、对数、指数)
// - 边缘增强(模拟胶片锐化效果) // - 边缘增强(模拟胶片锐化效果)
// - 使用查找表(LUT)加速处理 // - 使用查找表(LUT)加速处ç?
// 算法: 窗宽窗位映射 + 特性曲线变换 // 算法: çª—å®½çª—ä½æ˜ å°„ + ç‰¹æ€§æ›²çº¿å˜æ?
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 电子胶片效果算子 /// 电子胶片效果算子
@@ -103,7 +102,7 @@ public class FilmEffectProcessor : ImageProcessorBase
double curveStrength = GetParameter<double>("CurveStrength"); double curveStrength = GetParameter<double>("CurveStrength");
double edgeEnhance = GetParameter<double>("EdgeEnhance"); double edgeEnhance = GetParameter<double>("EdgeEnhance");
// 构建查找表 // 构建查找è¡?
BuildLUT(windowCenter, windowWidth, invert, curve, curveStrength); BuildLUT(windowCenter, windowWidth, invert, curve, curveStrength);
// 应用 LUT // 应用 LUT
@@ -150,14 +149,14 @@ public class FilmEffectProcessor : ImageProcessorBase
for (int i = 0; i < 256; i++) for (int i = 0; i < 256; i++)
{ {
// 窗宽窗位映射到 [0, 1] // çª—å®½çª—ä½æ˜ å°„åˆ?[0, 1]
double normalized; double normalized;
if (ww <= 1) if (ww <= 1)
normalized = i >= wc ? 1.0 : 0.0; normalized = i >= wc ? 1.0 : 0.0;
else else
normalized = Math.Clamp((i - low) / (high - low), 0.0, 1.0); normalized = Math.Clamp((i - low) / (high - low), 0.0, 1.0);
// 应用特性曲线 // 应用特性曲çº?
double mapped = curve switch double mapped = curve switch
{ {
"Sigmoid" => ApplySigmoid(normalized, strength), "Sigmoid" => ApplySigmoid(normalized, strength),
@@ -1,25 +1,25 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: PseudoColorProcessor.cs // 文件å? PseudoColorProcessor.cs
// 描述: 伪色彩渲染算子,将灰度图像映射为彩色图像 // 描述: 伪色彩渲染算子,将灰度图像映射为彩色图像
// 功能: // 功能:
// - 支持多种 OpenCV 内置色彩映射表(Jet、Hot、Cool、Rainbow 等) // - 支持多种 OpenCV 内置色彩映射表(Jet、Hot、Cool、Rainbow 等)
// - 可选灰度范围裁剪,突出感兴趣的灰度区间 // - 可选灰度范围裁剪,突出感兴趣的灰度区间
// - 可选反转色彩映射方向 // - å¯é€‰å转色彩映射方å?
// 算法: 查找表(LUT)色彩映射 // 算法: 查找表(LUT)色彩映å°?
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.CvEnum; using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 伪色彩渲染算子 /// 伪色彩渲染算å­?
/// </summary> /// </summary>
public class PseudoColorProcessor : ImageProcessorBase public class PseudoColorProcessor : ImageProcessorBase
{ {
@@ -82,11 +82,11 @@ public class PseudoColorProcessor : ImageProcessorBase
OutputData.Clear(); OutputData.Clear();
// 灰度范围裁剪与归一化 // ç°åº¦èŒƒå›´è£å‰ªä¸Žå½’一åŒ?
Image<Gray, byte> normalized; Image<Gray, byte> normalized;
if (minValue > 0 || maxValue < 255) if (minValue > 0 || maxValue < 255)
{ {
// [minValue, maxValue] 映射到 [0, 255] // å°?[minValue, maxValue] 映射åˆ?[0, 255]
normalized = inputImage.Clone(); normalized = inputImage.Clone();
double scale = 255.0 / Math.Max(maxValue - minValue, 1); double scale = 255.0 / Math.Max(maxValue - minValue, 1);
for (int y = 0; y < normalized.Height; y++) for (int y = 0; y < normalized.Height; y++)
@@ -135,7 +135,7 @@ public class PseudoColorProcessor : ImageProcessorBase
var colorImage = colorMat.ToImage<Bgr, byte>(); var colorImage = colorMat.ToImage<Bgr, byte>();
// 将彩色图像存入 OutputData,供 UI 显示 // 将彩色图åƒå­˜å…?OutputData,供 UI 显示
OutputData["PseudoColorImage"] = colorImage; OutputData["PseudoColorImage"] = colorImage;
_logger.Debug("Process: ColorMap={ColorMap}, MinValue={Min}, MaxValue={Max}, InvertMap={Invert}", _logger.Debug("Process: ColorMap={ColorMap}, MinValue={Min}, MaxValue={Max}, InvertMap={Invert}",
@@ -1,25 +1,25 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: GrayscaleProcessor.cs // 文件å? GrayscaleProcessor.cs
// 描述: 灰度图转换算子,用于将彩色图像转换为灰度图像 // 描述: 灰度图转换算子,用于将彩色图像转换为灰度图像
// 功能: // 功能:
// - 标准灰度转换(加权平均) // - 标准灰度转换(加权平均)
// - 平均值法 // - 平均值法
// - 最大值法 // - 最大值法
// - 最小值法 // - 最小值法
// 算法: 加权平均法 Gray = 0.299*R + 0.587*G + 0.114*B // 算法: 加æƒå¹³å‡æ³?Gray = 0.299*R + 0.587*G + 0.114*B
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 灰度图转换算子 /// ç°åº¦å›¾è½¬æ¢ç®—å­?
/// </summary> /// </summary>
public class GrayscaleProcessor : ImageProcessorBase public class GrayscaleProcessor : ImageProcessorBase
{ {
@@ -49,13 +49,13 @@ public class GrayscaleProcessor : ImageProcessorBase
{ {
string method = GetParameter<string>("Method"); string method = GetParameter<string>("Method");
// 如果输入已经是灰度图,根据方法进行处理 // å¦‚æžœè¾“å…¥å·²ç»æ˜¯ç°åº¦å›¾ï¼Œæ ¹æ®æ–¹æ³•进行处ç?
var result = inputImage.Clone(); var result = inputImage.Clone();
switch (method) switch (method)
{ {
case "Average": case "Average":
// 对于已经是灰度的图像,平均值法不改变图像 // å¯¹äºŽå·²ç»æ˜¯ç°åº¦çš„图åƒï¼Œå¹³å‡å€¼æ³•䏿”¹å˜å›¾åƒ?
break; break;
case "Max": case "Max":
@@ -1,22 +1,22 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: MirrorProcessor.cs // 文件å? MirrorProcessor.cs
// 描述: 镜像算子,用于图像翻转 // æè¿°: 镜åƒç®—å­ï¼Œç”¨äºŽå›¾åƒç¿»è½?
// 功能: // 功能:
// - 水平镜像(左右翻转) // - 水平镜像(左右翻转)
// - 垂直镜像(上下翻转) // - 垂直镜像(上下翻转)
// - 对角镜像(水平+垂直翻转,等效180°旋转) // - 对角镜åƒï¼ˆæ°´å¹?垂直翻转,等æ•?80°旋转ï¼?
// 算法: 像素坐标映射 // 算法: 像素坐标映射
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.CvEnum; using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 镜像算子 /// 镜像算子
@@ -1,24 +1,24 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 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;
using Emgu.CV.CvEnum; using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using System.Drawing; using System.Drawing;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 图像旋转算子 /// 图像旋转算子
@@ -101,14 +101,14 @@ public class RotateProcessor : ImageProcessorBase
if (expandCanvas) if (expandCanvas)
{ {
// 计算旋转后能容纳整幅图像的画布尺寸 // 计算旋转åŽèƒ½å®¹çº³æ•´å¹…图åƒçš„画布尺å¯?
double rad = Math.Abs(angle * Math.PI / 180.0); double rad = Math.Abs(angle * Math.PI / 180.0);
double sinA = Math.Abs(Math.Sin(rad)); double sinA = Math.Abs(Math.Sin(rad));
double cosA = Math.Abs(Math.Cos(rad)); double cosA = Math.Abs(Math.Cos(rad));
dstW = (int)Math.Ceiling(srcW * cosA + srcH * sinA); dstW = (int)Math.Ceiling(srcW * cosA + srcH * sinA);
dstH = (int)Math.Ceiling(srcW * sinA + srcH * cosA); dstH = (int)Math.Ceiling(srcW * sinA + srcH * cosA);
// 调整旋转矩阵的平移分量,使图像居中 // 调整旋转矩阵的平移分é‡ï¼Œä½¿å›¾åƒå±…ä¸?
double[] m = new double[6]; double[] m = new double[6];
rotMat.CopyTo(m); rotMat.CopyTo(m);
m[2] += (dstW - srcW) / 2.0; m[2] += (dstW - srcW) / 2.0;
@@ -1,26 +1,26 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: ThresholdProcessor.cs // 文件å? ThresholdProcessor.cs
// 描述: 阈值分割算子,用于图像二值化处理 // 描述: 阈值分割算子,用于图像二值化处理
// 功能: // 功能:
// - 固定阈值二值化 // - 固定阈值二值化
// - Otsu自动阈值计算 // - Otsu自动阈值计ç®?
// - 可调节阈值和最大值 // - å¯è°ƒèŠ‚é˜ˆå€¼å’Œæœ€å¤§å€?
// - 将灰度图像转换为二值图像 // - å°†ç°åº¦å›¾åƒè½¬æ¢ä¸ºäºŒå€¼å›¾åƒ?
// 算法: 阈值分割、Otsu算法 // 算法: 阈值分割、Otsu算法
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.CvEnum; using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 阈值分割算子 /// 阈值分割算å­?
/// </summary> /// </summary>
public class ThresholdProcessor : ImageProcessorBase public class ThresholdProcessor : ImageProcessorBase
{ {
@@ -1,26 +1,25 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: ColorLayerProcessor.cs // サカ蜷? ColorLayerProcessor.cs
// 描述: 色彩分层算子,将灰度图像按亮度区间分层 // 謠剰ソー: 濶イ蠖ゥ蛻アらョ怜ュ撰シ悟ー蠎ヲ蝗セ蜒乗潔莠ョ蠎ヲ蛹コ髣エ蛻ア?
// 功能: // 功能:
// - 将灰度图像按指定层数均匀分层 // - 将灰度图像按指定层数均匀分层
// - 支持自定义分层数(2~16层) // - 謾ッ謖∬螳壻ケ牙螻よ焚?~16螻ゑシ
// - 支持均匀分层和基于 Otsu 的自适应分层 // - 謾ッ謖∝插蛹€蛻アょ柱蝓コ莠?Otsu 逧騾ょコ泌
// - 可选保留原始灰度或映射为等间距灰度 // - 可选保留原始灰度或映射为等间距灰度
// 算法: 灰度量化 / 多阈值分割 // 邂玲ウ: 轣ー蠎ヲ驥丞喧 / 螟夐蛟シ蛻?
// 作者: 李伟 wei.lw.li@hexagon.com // 菴懆€? 譚惹シ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 色彩分层算子,将灰度图像按亮度区间分为多个层级 /// 濶イ蠖ゥ蛻アらョ怜ュ撰シ悟ー蠎ヲ蝗セ蜒乗潔莠ョ蠎ヲ蛹コ髣エ蛻クコ螟壻クェ螻らコ?
/// </summary> /// </summary>
public class ColorLayerProcessor : ImageProcessorBase public class ColorLayerProcessor : ImageProcessorBase
{ {
@@ -89,12 +88,12 @@ public class ColorLayerProcessor : ImageProcessorBase
_logger.Debug("Process: Layers={Layers}, Method={Method}, OutputMode={OutputMode}, TargetLayer={TargetLayer}", _logger.Debug("Process: Layers={Layers}, Method={Method}, OutputMode={OutputMode}, TargetLayer={TargetLayer}",
layers, method, outputMode, targetLayer); layers, method, outputMode, targetLayer);
// 计算分层阈值 // 隶。邂怜螻る蛟?
byte[] thresholds = method == "Otsu" byte[] thresholds = method == "Otsu"
? ComputeOtsuMultiThresholds(inputImage, layers) ? ComputeOtsuMultiThresholds(inputImage, layers)
: ComputeUniformThresholds(layers); : ComputeUniformThresholds(layers);
// 计算每层的输出灰度值 // 隶。邂玲ッ丞アら噪霎灘轣ー蠎ヲ蛟?
byte[] layerValues = ComputeLayerValues(thresholds, layers, outputMode); byte[] layerValues = ComputeLayerValues(thresholds, layers, outputMode);
// 应用分层映射 // 应用分层映射
@@ -106,7 +105,7 @@ public class ColorLayerProcessor : ImageProcessorBase
if (targetLayer == 0) if (targetLayer == 0)
{ {
// 输出全部层 // 霎灘蜈ィ驛ィ螻?
Parallel.For(0, height, y => Parallel.For(0, height, y =>
{ {
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
@@ -119,8 +118,8 @@ public class ColorLayerProcessor : ImageProcessorBase
} }
else else
{ {
// 只输出指定层:选中层为 255(白),其余为 0(黑) // 蜿ェ霎灘ョ壼アゑシ夐€我クュ螻ゆクコ 255育區会シ悟菴吩ク?0磯サ托シ?
int target = targetLayer - 1; // 参数从1开始,内部索引从0开始 int target = targetLayer - 1; // 蜿よ焚莉?蠑€蟋具シ悟驛ィ邏「蠑穂サ?蠑€蟋?
Parallel.For(0, height, y => Parallel.For(0, height, y =>
{ {
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
@@ -137,7 +136,7 @@ public class ColorLayerProcessor : ImageProcessorBase
} }
/// <summary> /// <summary>
/// 均匀分层阈值:将 [0, 255] 等分 /// 劇蛻アる蛟シ壼ー?[0, 255] 遲牙
/// </summary> /// </summary>
private static byte[] ComputeUniformThresholds(int layers) private static byte[] ComputeUniformThresholds(int layers)
{ {
@@ -153,7 +152,7 @@ public class ColorLayerProcessor : ImageProcessorBase
/// </summary> /// </summary>
private static byte[] ComputeOtsuMultiThresholds(Image<Gray, byte> image, int layers) private static byte[] ComputeOtsuMultiThresholds(Image<Gray, byte> image, int layers)
{ {
// 计算直方图 // 隶。邂礼峩譁ケ蝗?
int[] histogram = new int[256]; int[] histogram = new int[256];
var data = image.Data; var data = image.Data;
int h = image.Height, w = image.Width; int h = image.Height, w = image.Width;
@@ -176,7 +175,7 @@ public class ColorLayerProcessor : ImageProcessorBase
if (layers <= 1 || low >= high) if (layers <= 1 || low >= high)
return; return;
// [low, high] 范围内找 Otsu 阈值 // 蝨?[low, high] 峩蜀 Otsu 髦亥€?
long totalPixels = 0; long totalPixels = 0;
long totalSum = 0; long totalSum = 0;
for (int i = low; i <= high; i++) for (int i = low; i <= high; i++)
@@ -220,7 +219,7 @@ public class ColorLayerProcessor : ImageProcessorBase
} }
/// <summary> /// <summary>
/// 计算每层的输出灰度值 /// 隶。邂玲ッ丞アら噪霎灘轣ー蠎ヲ蛟?
/// </summary> /// </summary>
private static byte[] ComputeLayerValues(byte[] thresholds, int layers, string outputMode) private static byte[] ComputeLayerValues(byte[] thresholds, int layers, string outputMode)
{ {
@@ -233,7 +232,7 @@ public class ColorLayerProcessor : ImageProcessorBase
} }
else // MidValue else // MidValue
{ {
// 每层取区间中值 // 豈丞アょ叙蛹コ髣エ荳ュ蛟?
values[0] = (byte)(thresholds.Length > 0 ? thresholds[0] / 2 : 128); values[0] = (byte)(thresholds.Length > 0 ? thresholds[0] / 2 : 128);
for (int i = 1; i < layers - 1; i++) for (int i = 1; i < layers - 1; i++)
values[i] = (byte)((thresholds[i - 1] + thresholds[i]) / 2); values[i] = (byte)((thresholds[i - 1] + thresholds[i]) / 2);
@@ -243,7 +242,7 @@ public class ColorLayerProcessor : ImageProcessorBase
} }
/// <summary> /// <summary>
/// 根据阈值数组确定像素所属层级 /// 譬ケ謐ョ髦亥€シ謨ー扈。ョ螳壼ワ邏謇€螻槫アらコ?
/// </summary> /// </summary>
private static int GetLayerIndex(byte pixel, byte[] thresholds) private static int GetLayerIndex(byte pixel, byte[] thresholds)
{ {
@@ -1,26 +1,26 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: ContrastProcessor.cs // ? ContrastProcessor.cs
// 描述: 对比度调整算子,用于增强图像对比度 // 讛膩: 撖寞摨西摮琜憓𧼮撩撖寞摨?
// 功能: // 功能:
// - 线性对比度和亮度调整 // - 蝥踵批笆瘥𥪜漲䔶漁摨西?
// - 自动对比度拉伸 // - 芸𢆡撖寞摨行隡?
// - CLAHE(对比度受限自适应直方图均衡化) // - CLAHE笆瘥𥪜漲湔䲮銵∪嚗?
// - 支持多种对比度增强方法 // - 憭𡁶撖寞摨血撘箸䲮瘜?
// 算法: 线性变换、直方图均衡化、CLAHE // 算法: 线性变换、直方图均衡化、CLAHE
// 作者: 李伟 wei.lw.li@hexagon.com // 雿𡏭? 𦒘 wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using System.Drawing; using System.Drawing;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 对比度调整算子 /// 撖寞摨西摮?
/// </summary> /// </summary>
public class ContrastProcessor : ImageProcessorBase public class ContrastProcessor : ImageProcessorBase
{ {
@@ -1,22 +1,22 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: GammaProcessor.cs // 文件å? GammaProcessor.cs
// 描述: Gamma校正算子,用于调整图像亮度和对比度 // æè¿°: Gamma校正算å­ï¼Œç”¨äºŽè°ƒæ•´å›¾åƒäº®åº¦å’Œå¯¹æ¯”åº?
// 功能: // 功能:
// - Gamma非线性校正 // - Gammaéžçº¿æ€§æ ¡æ­?
// - 增益调整 // - 增益调整
// - 使用查找表(LUT)加速处理 // - 使用查找表(LUT)加速处ç?
// - 适用于图像显示和亮度调整 // - 适用于图像显示和亮度调整
// 算法: Gamma校正公式 output = (input^(1/gamma)) * gain // 算法: Gamma校正公式 output = (input^(1/gamma)) * gain
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// Gamma校正算子 /// Gamma校正算子
@@ -1,26 +1,26 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: HDREnhancementProcessor.cs // 文件å? HDREnhancementProcessor.cs
// 描述: 高动态范围(HDR)图像增强算子 // æè¿°: 高动æ€èŒƒå›´ï¼ˆHDR)图åƒå¢žå¼ºç®—å­?
// 功能: // 功能:
// - 局部色调映射(Local Tone Mapping // - 局部色调映射(Local Tone Mappingï¼?
// - 自适应对数映射(Adaptive Logarithmic Mapping // - 自适应对数映射(Adaptive Logarithmic Mappingï¼?
// - Drago色调映射 // - Drago色调映射
// - 双边滤波色调映射 // - 双边滤波色调映射
// - 增强图像暗部和亮部细节 // - å¢žå¼ºå›¾åƒæš—部和亮部细èŠ?
// 算法: 基于色调映射的HDR增强 // 算法: 基于色调映射的HDR增强
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 高动态范围图像增强算子 /// 高动æ€èŒƒå›´å›¾åƒå¢žå¼ºç®—å­?
/// </summary> /// </summary>
public class HDREnhancementProcessor : ImageProcessorBase public class HDREnhancementProcessor : ImageProcessorBase
{ {
@@ -138,8 +138,8 @@ public class HDREnhancementProcessor : ImageProcessorBase
} }
/// <summary> /// <summary>
/// 局部色调映射 /// 局部色调映å°?
/// 将图像分解为基础层(光照)和细节层,分别处理后合成 /// 将图åƒåˆ†è§£ä¸ºåŸºç¡€å±‚(光照)和细节层,分别处ç†åŽåˆæˆ?
/// Base = GaussianBlur(log(I)) /// Base = GaussianBlur(log(I))
/// Detail = log(I) - Base /// Detail = log(I) - Base
/// Output = exp(Base_compressed + Detail * boost) /// Output = exp(Base_compressed + Detail * boost)
@@ -156,22 +156,22 @@ public class HDREnhancementProcessor : ImageProcessorBase
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
floatImage.Data[y, x, 0] = floatImage.Data[y, x, 0] / 255.0f + 0.001f; floatImage.Data[y, x, 0] = floatImage.Data[y, x, 0] / 255.0f + 0.001f;
// 对数域 // 对数åŸ?
var logImage = new Image<Gray, float>(width, height); var logImage = new Image<Gray, float>(width, height);
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
logImage.Data[y, x, 0] = (float)Math.Log(floatImage.Data[y, x, 0]); logImage.Data[y, x, 0] = (float)Math.Log(floatImage.Data[y, x, 0]);
// 基础层:大尺度高斯模糊提取光照分量 // 基础层:大尺度高斯模糊æå–光照分é‡?
int kernelSize = (int)(sigmaSpace * 6) | 1; int kernelSize = (int)(sigmaSpace * 6) | 1;
if (kernelSize < 3) kernelSize = 3; if (kernelSize < 3) kernelSize = 3;
var baseLayer = new Image<Gray, float>(width, height); var baseLayer = new Image<Gray, float>(width, height);
CvInvoke.GaussianBlur(logImage, baseLayer, new System.Drawing.Size(kernelSize, kernelSize), sigmaSpace); CvInvoke.GaussianBlur(logImage, baseLayer, new System.Drawing.Size(kernelSize, kernelSize), sigmaSpace);
// 细节层 // 细节å±?
var detailLayer = logImage - baseLayer; var detailLayer = logImage - baseLayer;
// 压缩基础层的动态范围 // 压缩基础层的动æ€èŒƒå›?
double baseMin = double.MaxValue, baseMax = double.MinValue; double baseMin = double.MaxValue, baseMax = double.MinValue;
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
@@ -200,7 +200,7 @@ public class HDREnhancementProcessor : ImageProcessorBase
} }
} }
// 合成:压缩后的基础层 + 增强的细节层 // åˆæˆï¼šåŽ‹ç¼©åŽçš„基础å±?+ 增强的细节层
var combined = new Image<Gray, float>(width, height); var combined = new Image<Gray, float>(width, height);
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
@@ -287,7 +287,7 @@ public class HDREnhancementProcessor : ImageProcessorBase
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
floatImage.Data[y, x, 0] /= 255.0f; floatImage.Data[y, x, 0] /= 255.0f;
// 计算全局最大亮度 // 计算全局最大亮åº?
float globalMax = 0; float globalMax = 0;
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
@@ -364,7 +364,7 @@ public class HDREnhancementProcessor : ImageProcessorBase
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
floatImage.Data[y, x, 0] /= 255.0f; floatImage.Data[y, x, 0] /= 255.0f;
// 全局最大亮度 // 全局最大亮åº?
float maxLum = 0; float maxLum = 0;
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
@@ -410,7 +410,7 @@ public class HDREnhancementProcessor : ImageProcessorBase
/// <summary> /// <summary>
/// 双边滤波色调映射 /// 双边滤波色调映射
/// 使用双边滤波分离基础层和细节层 /// 使用åŒè¾¹æ»¤æ³¢åˆ†ç¦»åŸºç¡€å±‚和细节å±?
/// 双边滤波保边特性使得细节层更加精确 /// 双边滤波保边特性使得细节层更加精确
/// </summary> /// </summary>
private Image<Gray, byte> BilateralToneMapping(Image<Gray, byte> inputImage, private Image<Gray, byte> BilateralToneMapping(Image<Gray, byte> inputImage,
@@ -419,20 +419,20 @@ public class HDREnhancementProcessor : ImageProcessorBase
int width = inputImage.Width; int width = inputImage.Width;
int height = inputImage.Height; int height = inputImage.Height;
// 转换为浮点并取对数 // 转æ¢ä¸ºæµ®ç‚¹å¹¶å–对æ•?
var floatImage = inputImage.Convert<Gray, float>(); var floatImage = inputImage.Convert<Gray, float>();
var logImage = new Image<Gray, float>(width, height); var logImage = new Image<Gray, float>(width, height);
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
logImage.Data[y, x, 0] = (float)Math.Log(floatImage.Data[y, x, 0] / 255.0f + 0.001); logImage.Data[y, x, 0] = (float)Math.Log(floatImage.Data[y, x, 0] / 255.0f + 0.001);
// 双边滤波提取基础层(保边平滑) // åŒè¾¹æ»¤æ³¢æå–基础层(ä¿è¾¹å¹³æ»‘ï¼?
int diameter = (int)(sigmaSpace * 2) | 1; int diameter = (int)(sigmaSpace * 2) | 1;
if (diameter < 3) diameter = 3; if (diameter < 3) diameter = 3;
if (diameter > 31) diameter = 31; if (diameter > 31) diameter = 31;
var baseLayer = new Image<Gray, float>(width, height); var baseLayer = new Image<Gray, float>(width, height);
// 转换为 byte 进行双边滤波,再转回 float // 转æ¢ä¸?byte 进行åŒè¾¹æ»¤æ³¢ï¼Œå†è½¬å›ž float
var logNorm = NormalizeToByteImage(logImage); var logNorm = NormalizeToByteImage(logImage);
var baseNorm = new Image<Gray, byte>(width, height); var baseNorm = new Image<Gray, byte>(width, height);
CvInvoke.BilateralFilter(logNorm, baseNorm, diameter, sigmaColor, sigmaSpace); CvInvoke.BilateralFilter(logNorm, baseNorm, diameter, sigmaColor, sigmaSpace);
@@ -454,10 +454,10 @@ public class HDREnhancementProcessor : ImageProcessorBase
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
baseLayer.Data[y, x, 0] = (float)(baseNorm.Data[y, x, 0] / 255.0 * logRange + logMin); baseLayer.Data[y, x, 0] = (float)(baseNorm.Data[y, x, 0] / 255.0 * logRange + logMin);
// 细节层 = 对数图像 - 基础层 // 细节å±?= å¯¹æ•°å›¾åƒ - 基础å±?
var detailLayer = logImage - baseLayer; var detailLayer = logImage - baseLayer;
// 压缩基础层 // 压缩基础å±?
double baseMin = double.MaxValue, baseMax = double.MinValue; double baseMin = double.MaxValue, baseMax = double.MinValue;
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
@@ -1,22 +1,21 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 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;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 层次增强算子,基于多尺度高斯差分对不同尺度的图像细节进行独立增强 /// 层次增强算子,基于多尺度高斯差分对不同尺度的图像细节进行独立增强
@@ -106,16 +105,16 @@ public class HierarchicalEnhancementProcessor : ImageProcessorBase
int w = inputImage.Width; int w = inputImage.Width;
// === 多尺度高斯差分分解(全部在原始分辨率上操作,无需金字塔上下采样) === // === 多尺度高斯差分分解(全部在原始分辨率上操作,无需金字塔上下采样) ===
// 用递增 sigma 的高斯模糊生成平滑层序列:G0(原图), G1, G2, ..., G_n(基础层) // 逕ィ騾貞「 sigma ォ俶民讓。邉顔函謌仙ケウ貊大アょコ丞哦0(蜴溷崟), G1, G2, ..., G_n(蝓コ遑€螻?
// 细节层 D_i = G_i - G_{i+1} // 鰍螻?D_i = G_i - G_{i+1}
// 重建:output = sum(D_i * gain_i) + G_n * baseGain // 重建:output = sum(D_i * gain_i) + G_n * baseGain
// 计算每层的高斯 sigma(指数递增) // 隶。邂玲ッ丞アら噪鬮俶?sigma域欠謨ー騾貞「橸シ?
var sigmas = new double[levels]; var sigmas = new double[levels];
for (int i = 0; i < levels; i++) for (int i = 0; i < levels; i++)
sigmas[i] = Math.Pow(2, i + 1); // 2, 4, 8, 16, ... sigmas[i] = Math.Pow(2, i + 1); // 2, 4, 8, 16, ...
// 生成平滑层序列(float 数组,避免 Emgu float Image 的问题) // 逕滓蟷ウ貊大アょコ丞loat 謨ー扈シ碁∩蜈?Emgu float Image 琉鬚假シ
var smoothLayers = new float[levels + 1][]; // [0]=原图, [1..n]=高斯模糊 var smoothLayers = new float[levels + 1][]; // [0]=原图, [1..n]=高斯模糊
smoothLayers[0] = new float[h * w]; smoothLayers[0] = new float[h * w];
var srcData = inputImage.Data; var srcData = inputImage.Data;
@@ -132,7 +131,7 @@ public class HierarchicalEnhancementProcessor : ImageProcessorBase
if (ksize < 3) ksize = 3; if (ksize < 3) ksize = 3;
using var src = new Image<Gray, byte>(w, h); using var src = new Image<Gray, byte>(w, h);
// 从上一层 float byte 做高斯模糊 // 莉惹ク贋ク€螻?float 霓?byte 蛛夐ォ俶民讓。邉?
var prevLayer = smoothLayers[i]; var prevLayer = smoothLayers[i];
var sd = src.Data; var sd = src.Data;
Parallel.For(0, h, y => Parallel.For(0, h, y =>
@@ -181,7 +180,7 @@ public class HierarchicalEnhancementProcessor : ImageProcessorBase
var result = new Image<Gray, byte>(w, h); var result = new Image<Gray, byte>(w, h);
var resultData = result.Data; var resultData = result.Data;
// 预转换 gains float // スャ謐?gains 荳?float
var fGains = new float[levels]; var fGains = new float[levels];
for (int i = 0; i < levels; i++) for (int i = 0; i < levels; i++)
fGains[i] = (float)gains[i]; fGains[i] = (float)gains[i];
@@ -1,22 +1,22 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: HistogramEqualizationProcessor.cs // 文件å? HistogramEqualizationProcessor.cs
// 描述: 直方图均衡化算子,用于增强图像对比度 // 描述: 直方图均衡化算子,用于增强图像对比度
// 功能: // 功能:
// - 全局直方图均衡化 // - 全局直方图均衡化
// - 自适应直方图均衡化(CLAHE // - 自适应直方图å‡è¡¡åŒ–(CLAHEï¼?
// - 限制对比度增强 // - é™åˆ¶å¯¹æ¯”度增å¼?
// - 改善图像的整体对比度 // - 改善图像的整体对比度
// 算法: 直方图均衡化、CLAHE // 算法: 直方图均衡化、CLAHE
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 直方图均衡化算子 /// 直方图均衡化算子
@@ -122,7 +122,7 @@ public class HistogramEqualizationProcessor : ImageProcessorBase
var limited = floatTile + diff * Math.Min(clipLimit / 10.0, 1.0); var limited = floatTile + diff * Math.Min(clipLimit / 10.0, 1.0);
var limitedByte = limited.Convert<Gray, byte>(); var limitedByte = limited.Convert<Gray, byte>();
// 复制到结果图像 // å¤åˆ¶åˆ°ç»“果图åƒ?
result.ROI = roi; result.ROI = roi;
limitedByte.CopyTo(result); limitedByte.CopyTo(result);
result.ROI = System.Drawing.Rectangle.Empty; result.ROI = System.Drawing.Rectangle.Empty;
@@ -1,27 +1,27 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 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;
using Emgu.CV.CvEnum; using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using System.Drawing; using System.Drawing;
using System.Text; using System.Text;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 直方图叠加算子,计算灰度直方图并以蓝色柱状图绘制到结果图像左上角,同时输出统计表格 /// 直方图å åŠ ç®—å­ï¼Œè®¡ç®—ç°åº¦ç›´æ–¹å›¾å¹¶ä»¥è“色柱状图绘制到结果图åƒå·¦ä¸Šè§’ï¼ŒåŒæ—¶è¾“出统计表æ ?
/// </summary> /// </summary>
public class HistogramOverlayProcessor : ImageProcessorBase public class HistogramOverlayProcessor : ImageProcessorBase
{ {
@@ -29,10 +29,11 @@ public class HistogramOverlayProcessor : ImageProcessorBase
// 固定参数 // 固定参数
private const int ChartWidth = 256; // 柱状图绘图区宽度 private const int ChartWidth = 256; // 柱状图绘图区宽度
private const int ChartHeight = 200; // 柱状图绘图区高度 private const int ChartHeight = 200; // 柱状图绘图区高度
private const int AxisMarginLeft = 50; // Y轴标签预留宽度 private const int AxisMarginLeft = 50; // Y轴标签预留宽åº?
private const int AxisMarginBottom = 25; // X轴标签预留高度 private const int AxisMarginBottom = 25; // X轴标签预留高åº?
private const int Padding = 8; // 背景额外内边距 private const int Padding = 8; // 背景é¢å¤–内边è·?
private const int PaddingRight = 25; // 右侧额外内边距(容纳X轴末尾刻度文字) private const int PaddingRight = 25; // 右侧额外内边距(容纳X轴末尾刻度文字)
private const int Margin = 10; // 距图像左上角边距 private const int Margin = 10; // 距图像左上角边距
private const float BgAlpha = 0.6f; private const float BgAlpha = 0.6f;
@@ -47,7 +48,7 @@ public class HistogramOverlayProcessor : ImageProcessorBase
protected override void InitializeParameters() protected override void InitializeParameters()
{ {
// 无可调参数 // æ— å¯è°ƒå‚æ•?
} }
public override Image<Gray, byte> Process(Image<Gray, byte> inputImage) public override Image<Gray, byte> Process(Image<Gray, byte> inputImage)
@@ -56,7 +57,7 @@ public class HistogramOverlayProcessor : ImageProcessorBase
int w = inputImage.Width; int w = inputImage.Width;
var srcData = inputImage.Data; var srcData = inputImage.Data;
// === 1. 计算灰度直方图 === // === 1. 计算ç°åº¦ç›´æ–¹å›?===
var hist = new int[256]; var hist = new int[256];
for (int y = 0; y < h; y++) for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++) for (int x = 0; x < w; x++)
@@ -95,15 +96,15 @@ public class HistogramOverlayProcessor : ImageProcessorBase
// === 3. 输出表格数据 === // === 3. 输出表格数据 ===
var sb = new StringBuilder(); var sb = new StringBuilder();
sb.AppendLine("=== 灰度直方图统计 ==="); sb.AppendLine("=== ç°åº¦ç›´æ–¹å›¾ç»Ÿè®?===");
sb.AppendLine($"图像尺寸: {w} x {h}"); sb.AppendLine($"图像尺寸: {w} x {h}");
sb.AppendLine($"总像素数: {totalPixels}"); sb.AppendLine($"总像素数: {totalPixels}");
sb.AppendLine($"最小灰度: {minVal}"); sb.AppendLine($"最å°ç°åº? {minVal}");
sb.AppendLine($"最大灰度: {maxVal}"); sb.AppendLine($"最大ç°åº? {maxVal}");
sb.AppendLine($"平均灰度: {mean:F2}"); sb.AppendLine($"平均灰度: {mean:F2}");
sb.AppendLine($"中位灰度: {medianVal}"); sb.AppendLine($"中位灰度: {medianVal}");
sb.AppendLine($"众数灰度: {modeVal} (出现 {modeCount} 次)"); sb.AppendLine($"ä¼—æ•°ç°åº¦: {modeVal} (出现 {modeCount} æ¬?");
sb.AppendLine($"标准差: {stdDev:F2}"); sb.AppendLine($"标准å·? {stdDev:F2}");
sb.AppendLine(); sb.AppendLine();
sb.AppendLine("灰度值\t像素数\t占比(%)"); sb.AppendLine("灰度值\t像素数\t占比(%)");
for (int i = 0; i < 256; i++) for (int i = 0; i < 256; i++)
@@ -119,8 +120,8 @@ public class HistogramOverlayProcessor : ImageProcessorBase
var colorImage = inputImage.Convert<Bgr, byte>(); var colorImage = inputImage.Convert<Bgr, byte>();
var colorData = colorImage.Data; var colorData = colorImage.Data;
// 布局:背景区域包含 Padding + Y轴标签 + 绘图区 + Padding(水平) // 布局:背景区域包å?Padding + Yè½´æ ‡ç­?+ 绘图åŒ?+ Padding(水平)
// Padding + 绘图区 + X轴标签 + Padding(垂直) // Padding + 绘图åŒ?+ Xè½´æ ‡ç­?+ Padding(垂直)
int totalW = Padding + AxisMarginLeft + ChartWidth + PaddingRight; int totalW = Padding + AxisMarginLeft + ChartWidth + PaddingRight;
int totalH = Padding + ChartHeight + AxisMarginBottom + Padding; int totalH = Padding + ChartHeight + AxisMarginBottom + Padding;
int bgW = Math.Min(totalW, w - Margin); int bgW = Math.Min(totalW, w - Margin);
@@ -132,7 +133,7 @@ public class HistogramOverlayProcessor : ImageProcessorBase
int plotH = Math.Min(ChartHeight, bgH - Padding - AxisMarginBottom - Padding); int plotH = Math.Min(ChartHeight, bgH - Padding - AxisMarginBottom - Padding);
if (plotW <= 0 || plotH <= 0) goto SkipOverlay; if (plotW <= 0 || plotH <= 0) goto SkipOverlay;
// 绘图区左上角在图像中的坐标 // 绘图区左上角在图åƒä¸­çš„åæ ?
int plotX0 = Margin + Padding + AxisMarginLeft; int plotX0 = Margin + Padding + AxisMarginLeft;
int plotY0 = Margin + Padding; int plotY0 = Margin + Padding;
@@ -163,7 +164,7 @@ public class HistogramOverlayProcessor : ImageProcessorBase
} }
}); });
// 绘制蓝色柱状图 // 绘制è“色柱状å›?
Parallel.For(0, plotH, dy => Parallel.For(0, plotH, dy =>
{ {
int imgY = plotY0 + dy; int imgY = plotY0 + dy;
@@ -187,7 +188,7 @@ public class HistogramOverlayProcessor : ImageProcessorBase
} }
}); });
// === 5. 绘制坐标轴线和刻度标注 === // === 5. ç»˜åˆ¶åæ ‡è½´çº¿å’Œåˆ»åº¦æ ‡æ³?===
var white = new MCvScalar(255, 255, 255); var white = new MCvScalar(255, 255, 255);
var gray = new MCvScalar(180, 180, 180); var gray = new MCvScalar(180, 180, 180);
@@ -203,7 +204,7 @@ public class HistogramOverlayProcessor : ImageProcessorBase
new Point(plotX0 + plotW, plotY0 + plotH), new Point(plotX0 + plotW, plotY0 + plotH),
white, 1); white, 1);
// X轴刻度: 0, 64, 128, 192, 255 // X轴刻åº? 0, 64, 128, 192, 255
int[] xTicks = { 0, 64, 128, 192, 255 }; int[] xTicks = { 0, 64, 128, 192, 255 };
foreach (int tick in xTicks) foreach (int tick in xTicks)
{ {
@@ -219,7 +220,7 @@ public class HistogramOverlayProcessor : ImageProcessorBase
FontFace.HersheySimplex, FontScale, white, FontThickness); FontFace.HersheySimplex, FontScale, white, FontThickness);
} }
// Y轴刻度: 0%, 25%, 50%, 75%, 100% // Y轴刻åº? 0%, 25%, 50%, 75%, 100%
for (int i = 0; i <= 4; i++) for (int i = 0; i <= 4; i++)
{ {
int val = maxCount * i / 4; int val = maxCount * i / 4;
@@ -255,7 +256,7 @@ public class HistogramOverlayProcessor : ImageProcessorBase
} }
/// <summary> /// <summary>
/// 格式化像素计数为紧凑字符串(如 12345 "12.3K" /// æ ¼å¼åŒ–åƒç´ è®¡æ•°ä¸ºç´§å‡‘字符串(å¦?12345 â†?"12.3K"ï¼?
/// </summary> /// </summary>
private static string FormatCount(int count) private static string FormatCount(int count)
{ {
@@ -1,6 +1,6 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: RetinexProcessor.cs // 文件å? RetinexProcessor.cs
// 描述: 基于Retinex的多尺度阴影校正算子 // 描述: 基于Retinex的多尺度阴影校正算子
// 功能: // 功能:
// - 单尺度Retinex (SSR) // - 单尺度Retinex (SSR)
@@ -8,19 +8,19 @@
// - 带色彩恢复的多尺度Retinex (MSRCR) // - 带色彩恢复的多尺度Retinex (MSRCR)
// - 光照不均匀校正 // - 光照不均匀校正
// - 阴影去除 // - 阴影去除
// 算法: Retinex理论 - 将图像分解为反射分量和光照分量 // 算法: Retinexç†è®º - 将图åƒåˆ†è§£ä¸ºå射分é‡å’Œå…‰ç…§åˆ†é‡?
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// Retinex多尺度阴影校正算子 /// Retinex多尺度阴影校正算å­?
/// </summary> /// </summary>
public class RetinexProcessor : ImageProcessorBase public class RetinexProcessor : ImageProcessorBase
{ {
@@ -145,7 +145,7 @@ public class RetinexProcessor : ImageProcessorBase
// 高斯模糊得到光照分量 // 高斯模糊得到光照分量
Image<Gray, float> blurred = new Image<Gray, float>(inputImage.Size); 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; if (kernelSize < 3) kernelSize = 3;
CvInvoke.GaussianBlur(floatImage, blurred, new System.Drawing.Size(kernelSize, kernelSize), sigma); 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) // R = log(I) - log(I*G)
Image<Gray, float> retinex = logImage - logBlurred; Image<Gray, float> retinex = logImage - logBlurred;
// 应用增益和偏移 // 应用增益和åç§?
retinex = retinex * gain + offset; retinex = retinex * gain + offset;
// 归一化到0-255 // 归一化到0-255
@@ -183,7 +183,7 @@ public class RetinexProcessor : ImageProcessorBase
/// </summary> /// </summary>
private Image<Gray, byte> MultiScaleRetinex(Image<Gray, byte> inputImage, double[] sigmas, double gain, int offset) private Image<Gray, byte> MultiScaleRetinex(Image<Gray, byte> inputImage, double[] sigmas, double gain, int offset)
{ {
// 转换为浮点图像 // 转æ¢ä¸ºæµ®ç‚¹å›¾åƒ?
Image<Gray, float> floatImage = inputImage.Convert<Gray, float>(); Image<Gray, float> floatImage = inputImage.Convert<Gray, float>();
floatImage = floatImage + 1.0f; floatImage = floatImage + 1.0f;
@@ -197,7 +197,7 @@ public class RetinexProcessor : ImageProcessorBase
} }
} }
// 累加多个尺度的结果 // 累加多个尺度的结æž?
Image<Gray, float> msrResult = new Image<Gray, float>(inputImage.Size); Image<Gray, float> msrResult = new Image<Gray, float>(inputImage.Size);
msrResult.SetZero(); msrResult.SetZero();
@@ -229,10 +229,10 @@ public class RetinexProcessor : ImageProcessorBase
// 平均 // 平均
msrResult = msrResult / sigmas.Length; msrResult = msrResult / sigmas.Length;
// 应用增益和偏移 // 应用增益和åç§?
msrResult = msrResult * gain + offset; msrResult = msrResult * gain + offset;
// 归一化 // 归一åŒ?
Image<Gray, byte> result = NormalizeToByteImage(msrResult); Image<Gray, byte> result = NormalizeToByteImage(msrResult);
floatImage.Dispose(); floatImage.Dispose();
@@ -244,14 +244,14 @@ public class RetinexProcessor : ImageProcessorBase
/// <summary> /// <summary>
/// 带色彩恢复的多尺度Retinex (MSRCR) /// 带色彩恢复的多尺度Retinex (MSRCR)
/// 对于灰度图像,使用简化版本 /// 对于ç°åº¦å›¾åƒï¼Œä½¿ç”¨ç®€åŒ–版æœ?
/// </summary> /// </summary>
private Image<Gray, byte> MultiScaleRetinexCR(Image<Gray, byte> inputImage, double[] sigmas, double gain, int offset) private Image<Gray, byte> MultiScaleRetinexCR(Image<Gray, byte> inputImage, double[] sigmas, double gain, int offset)
{ {
// 先执行MSR // 先执行MSR
Image<Gray, byte> msrResult = MultiScaleRetinex(inputImage, sigmas, gain, offset); Image<Gray, byte> msrResult = MultiScaleRetinex(inputImage, sigmas, gain, offset);
// 对于灰度图像,色彩恢复简化为对比度增强 // 对于ç°åº¦å›¾åƒï¼Œè‰²å½©æ¢å¤ç®€åŒ–为对比度增å¼?
Image<Gray, float> floatMsr = msrResult.Convert<Gray, float>(); Image<Gray, float> floatMsr = msrResult.Convert<Gray, float>();
Image<Gray, float> floatInput = inputImage.Convert<Gray, float>(); Image<Gray, float> floatInput = inputImage.Convert<Gray, float>();
@@ -285,7 +285,7 @@ public class RetinexProcessor : ImageProcessorBase
/// </summary> /// </summary>
private Image<Gray, byte> NormalizeToByteImage(Image<Gray, float> floatImage) private Image<Gray, byte> NormalizeToByteImage(Image<Gray, float> floatImage)
{ {
// 找到最小值和最大值 // 找到最å°å€¼å’Œæœ€å¤§å€?
double minVal = double.MaxValue; double minVal = double.MaxValue;
double maxVal = double.MinValue; double maxVal = double.MinValue;
@@ -1,23 +1,23 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 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;
using Emgu.CV.CvEnum; using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 锐化算子 /// 锐化算子
@@ -94,7 +94,7 @@ public class SharpenProcessor : ImageProcessorBase
var laplacian = new Image<Gray, float>(inputImage.Size); var laplacian = new Image<Gray, float>(inputImage.Size);
CvInvoke.Laplacian(inputImage, laplacian, DepthType.Cv32F, 1); CvInvoke.Laplacian(inputImage, laplacian, DepthType.Cv32F, 1);
// 转换为字节类型 // 转æ¢ä¸ºå­—节类åž?
var laplacianByte = laplacian.Convert<Gray, byte>(); var laplacianByte = laplacian.Convert<Gray, byte>();
// 将拉普拉斯结果加到原图上进行锐化 // 将拉普拉斯结果加到原图上进行锐化
@@ -124,10 +124,10 @@ public class SharpenProcessor : ImageProcessorBase
var floatBlurred = blurred.Convert<Gray, float>(); var floatBlurred = blurred.Convert<Gray, float>();
var detail = floatInput - floatBlurred; var detail = floatInput - floatBlurred;
// 将细节加回原图 // 将细节加回原å›?
var sharpened = floatInput + detail * strength; var sharpened = floatInput + detail * strength;
// 转换回字节类型 // 转æ¢å›žå­—节类åž?
var result = sharpened.Convert<Gray, byte>(); var result = sharpened.Convert<Gray, byte>();
blurred.Dispose(); blurred.Dispose();
@@ -1,27 +1,27 @@
// ============================================================================ // ============================================================================
// Copyright © 2016-2025 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2016-2025 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: SubPixelZoomProcessor.cs // ? SubPixelZoomProcessor.cs
// 描述: 亚像素放大算子,通过高质量插值实现图像的亚像素级放大 // 描述: 亚像素放大算子,通过高质量插值实现图像的亚像素级放大
// 功能: // 功能:
// - 支持任意倍率放大(含小数倍率如 1.5x、2.3x // - 隞餅曉之嚗鉄撠𤩺㺭憒?1.5x?.3x嚗?
// - 多种插值方法(最近邻、双线性、双三次、Lanczos // - 憭𡁶潭䲮瘜𤏪餈煾蝥踵銝㗇活anczos嚗?
// - 可选锐化补偿(抵消插值模糊) // - 可选锐化补偿(抵消插值模糊)
// - 可选指定输出尺寸 // - 摰朞箏偕撖?
// 算法: 基于 OpenCV Resize 的高质量插值放大 // 蝞埈: OpenCV Resize 韐券潭𦆮憭?
// 作者: 李伟 wei.lw.li@hexagon.com // 雿𡏭? 𦒘 wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.CvEnum; using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using System.Drawing; using System.Drawing;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 亚像素放大算子 /// 鈭𡁜蝝䭾𦆮憭抒摮?
/// </summary> /// </summary>
public class SubPixelZoomProcessor : ImageProcessorBase public class SubPixelZoomProcessor : ImageProcessorBase
{ {
@@ -104,7 +104,7 @@ public class SubPixelZoomProcessor : ImageProcessorBase
if (sharpenAfter) if (sharpenAfter)
{ {
// Unsharp Masking: result = result + strength * (result - blur) // 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); using var blurred = result.SmoothGaussian(ksize);
for (int y = 0; y < newHeight; y++) for (int y = 0; y < newHeight; y++)
@@ -1,27 +1,26 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: SuperResolutionProcessor.cs // ? SuperResolutionProcessor.cs
// 描述: 基于深度学习的超分辨率算子 // 讛膩: 瘛勗漲摮虫摮?
// 功能: // 功能:
// - 支持 EDSR FSRCNN 超分辨率模型(ONNX 格式) // - EDSR ?FSRCNN 颲函璅∪嚗㇉NNX 嚗?
// - 支持 2x、3x、4x 放大倍率 // - 2x?x?x 曉之
// - 灰度图像自动转换为三通道输入,推理后转回灰度 // - 灰度图像自动转换为三通道输入,推理后转回灰度
// - 模型文件自动搜索,支持自定义路径 // - 模型文件自动搜索,支持自定义路径
// - 使用 Microsoft.ML.OnnxRuntime 进行推理 // - 使用 Microsoft.ML.OnnxRuntime 进行推理
// 算法: EDSR (Enhanced Deep Residual SR) / FSRCNN (Fast SR CNN) // 算法: 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;
using Emgu.CV.CvEnum; using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime;
using Microsoft.ML.OnnxRuntime.Tensors; using Microsoft.ML.OnnxRuntime.Tensors;
using Serilog; using Serilog;
using System.IO; using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 基于深度学习的超分辨率算子(EDSR / FSRCNN),使用 ONNX Runtime 推理 /// 基于深度学习的超分辨率算子(EDSR / FSRCNN),使用 ONNX Runtime 推理
@@ -30,8 +29,9 @@ public class SuperResolutionProcessor : ImageProcessorBase
{ {
private static readonly ILogger _logger = Log.ForContext<SuperResolutionProcessor>(); private static readonly ILogger _logger = Log.ForContext<SuperResolutionProcessor>();
// 会话缓存,避免重复加载 // 隡朞蝻枏嚗屸憭滚頧?
private static InferenceSession? _cachedSession; private static InferenceSession? _cachedSession;
private static string _cachedModelKey = string.Empty; private static string _cachedModelKey = string.Empty;
public SuperResolutionProcessor() public SuperResolutionProcessor()
@@ -76,17 +76,17 @@ public class SuperResolutionProcessor : ImageProcessorBase
{ {
_logger.Error("Model file not found: {Model}_x{Scale}.onnx", model, scale); _logger.Error("Model file not found: {Model}_x{Scale}.onnx", model, scale);
throw new FileNotFoundException( throw new FileNotFoundException(
$"超分辨率模型文件未找到: {model}_x{scale}.onnx\n" + $"颲函璅∪芣𪄳? {model}_x{scale}.onnx\n" +
$"请将模型文件放置到以下任一目录:\n" + $"请将模型文件放置到以下任一目录:\n" +
$" 1. 程序目录/Models/\n" + $" 1. 程序目录/Models/\n" +
$" 2. 程序目录/\n" + $" 2. 程序目录/\n" +
$"模型需要 ONNX 格式。\n" + $"璅∪閬?ONNX n" +
$"可使用 tf2onnx .pb 转换:\n" + $"臭蝙?tf2onnx 隞?.pb 頧祆揢:\n" +
$" pip install tf2onnx\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"); $" python -m tf2onnx.convert --input {model}_x{scale}.pb --output {model}_x{scale}.onnx --inputs input:0 --outputs output:0");
} }
// 加载或复用会话 // 㰘蝸霂?
string modelKey = $"{model}_{scale}"; string modelKey = $"{model}_{scale}";
InferenceSession session; InferenceSession session;
if (_cachedModelKey == modelKey && _cachedSession != null) if (_cachedModelKey == modelKey && _cachedSession != null)
@@ -111,7 +111,7 @@ public class SuperResolutionProcessor : ImageProcessorBase
session = new InferenceSession(modelPath, options); session = new InferenceSession(modelPath, options);
_cachedSession = session; _cachedSession = session;
_cachedModelKey = modelKey; _cachedModelKey = modelKey;
// 记录实际使用的 Execution Provider // 霈啣摰鮋雿輻鍂?Execution Provider
var providers = session.ModelMetadata?.CustomMetadataMap; var providers = session.ModelMetadata?.CustomMetadataMap;
_logger.Information("Loaded ONNX model: {ModelPath}, Providers: {Providers}", _logger.Information("Loaded ONNX model: {ModelPath}, Providers: {Providers}",
modelPath, string.Join(", ", session.GetType().Name)); modelPath, string.Join(", ", session.GetType().Name));
@@ -134,7 +134,7 @@ public class SuperResolutionProcessor : ImageProcessorBase
} }
/// <summary> /// <summary>
/// 单次推理(小图或 FSRCNN /// 閙活 FSRCNN嚗?
/// </summary> /// </summary>
private Image<Gray, byte> ProcessSingle(InferenceSession session, Image<Gray, byte> inputImage, int scale) 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(); string inputName = session.InputMetadata.Keys.First();
var inputMeta = session.InputMetadata[inputName]; var inputMeta = session.InputMetadata[inputName];
int[] dims = inputMeta.Dimensions; int[] dims = inputMeta.Dimensions;
// dims 格式: [1, H, W, C] (NHWC)C 可能是 1 或 3 // dims : [1, H, W, C] (NHWC)嚗龦 ?1 ?3
int inputChannels = dims[^1]; // 最后一维是通道数 int inputChannels = dims[^1]; // 𦒘蝏湔糓𡁻?
// 构建输入 tensor: [1, H, W, C] (NHWC) // 构建输入 tensor: [1, H, W, C] (NHWC)
// 使用底层数组 + Parallel.For 避免逐元素索引开销 // 使用底层数组 + Parallel.For 避免逐元素索引开销
@@ -195,13 +195,13 @@ public class SuperResolutionProcessor : ImageProcessorBase
using var results = session.Run(inputs); using var results = session.Run(inputs);
var outputTensor = results.First().AsTensor<float>(); 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; var shape = outputTensor.Dimensions;
int outC = shape[1]; int outC = shape[1];
int outH = shape[2]; int outH = shape[2];
int outW = shape[3]; int outW = shape[3];
// 转换为灰度图像 // 頧祆揢銝箇摨血㦛?
// 使用 Parallel.For + 直接内存操作 // 使用 Parallel.For + 直接内存操作
Image<Gray, byte> result; Image<Gray, byte> result;
if (outC == 1) if (outC == 1)
@@ -217,7 +217,7 @@ public class SuperResolutionProcessor : ImageProcessorBase
} }
else else
{ {
// EDSR: 三通道输出 [1, 3, outH, outW] → 灰度 // EDSR: 銝厰𡁻颲枏枂 [1, 3, outH, outW] ?啣漲
// 直接计算灰度值,跳过中间 BGR 图像分配 // 直接计算灰度值,跳过中间 BGR 图像分配
result = new Image<Gray, byte>(outW, outH); result = new Image<Gray, byte>(outW, outH);
var outData = result.Data; var outData = result.Data;
@@ -241,13 +241,13 @@ public class SuperResolutionProcessor : ImageProcessorBase
} }
/// <summary> /// <summary>
/// 分块推理(大图 EDSR),将图像切成小块分别推理后拼接 /// ?EDSR嚗㚁𣂼急綫潭𦻖
/// </summary> /// </summary>
private Image<Gray, byte> ProcessTiled(InferenceSession session, Image<Gray, byte> inputImage, int scale, int tileSize) private Image<Gray, byte> ProcessTiled(InferenceSession session, Image<Gray, byte> inputImage, int scale, int tileSize)
{ {
int h = inputImage.Height; int h = inputImage.Height;
int w = inputImage.Width; int w = inputImage.Width;
int overlap = 8; // 重叠像素,减少拼接边缘伪影 int overlap = 8; // 撠烐𣄽亥器蝻䀝憚敶?
var result = new Image<Gray, byte>(w * scale, h * scale); var result = new Image<Gray, byte>(w * scale, h * scale);
@@ -290,7 +290,7 @@ public class SuperResolutionProcessor : ImageProcessorBase
} }
/// <summary> /// <summary>
/// 查找模型文件,按优先级搜索多个目录(.onnx 格式) /// 交𪄳璅∪辣嚗峕隡睃蝥扳蝝W銝芰𤌍敶𤏪.onnx 嚗?
/// </summary> /// </summary>
private static string FindModelFile(string model, int scale) private static string FindModelFile(string model, int scale)
{ {
@@ -1,6 +1,6 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: MorphologyProcessor.cs // 文件å? MorphologyProcessor.cs
// 描述: 形态学处理算子,用于二值图像的形态学操作 // 描述: 形态学处理算子,用于二值图像的形态学操作
// 功能: // 功能:
// - 腐蚀(Erode):收缩目标区域 // - 腐蚀(Erode):收缩目标区域
@@ -8,17 +8,17 @@
// - 开运算(Open):先腐蚀后膨胀,去除小目标 // - 开运算(Open):先腐蚀后膨胀,去除小目标
// - 闭运算(Close):先膨胀后腐蚀,填充小孔洞 // - 闭运算(Close):先膨胀后腐蚀,填充小孔洞
// 算法: 数学形态学运算 // 算法: 数学形态学运算
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.CvEnum; using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using System.Drawing; using System.Drawing;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 形态学处理算子 /// 形态学处理算子
@@ -1,23 +1,23 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 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;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using System.Drawing; using System.Drawing;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 差分运算算子 /// 差分运算算子
@@ -96,7 +96,7 @@ public class DifferenceProcessor : ImageProcessorBase
} }
else // Both else // Both
{ {
// 梯度幅值: sqrt((dx)^2 + (dy)^2) // 梯度幅å€? sqrt((dx)^2 + (dy)^2)
for (int y = 0; y < height - 1; y++) for (int y = 0; y < height - 1; y++)
{ {
for (int x = 0; x < width - 1; x++) for (int x = 0; x < width - 1; x++)
@@ -1,23 +1,23 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: DivisionProcessor.cs // 文件å? DivisionProcessor.cs
// 描述: 除法运算算子,用于图像归一化处理 // æè¿°: 除法è¿ç®—ç®—å­ï¼Œç”¨äºŽå›¾åƒå½’一化处ç?
// 功能: // 功能:
// - 对图像像素值进行除法运算 // - 对图åƒåƒç´ å€¼è¿›è¡Œé™¤æ³•è¿ç®?
// - 支持缩放因子调整 // - 支持缩放因子调整
// - 可选归一化到0-255范围 // - 可选归一化到0-255范围
// - 常用于背景校正和图像归一化 // - 常用于背景校正和图åƒå½’一åŒ?
// 算法: 像素级除法运算 // 算法: åƒç´ çº§é™¤æ³•è¿ç®?
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using System.Drawing; using System.Drawing;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 除法运算算子 /// 除法运算算子
@@ -1,22 +1,22 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 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;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using System.Drawing; using System.Drawing;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 积分运算算子 /// 积分运算算子
@@ -1,23 +1,23 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 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;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using System.Drawing; using System.Drawing;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 乘法运算算子 /// 乘法运算算子
@@ -1,24 +1,24 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 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;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 或运算算子 /// 或è¿ç®—ç®—å­?
/// </summary> /// </summary>
public class OrProcessor : ImageProcessorBase public class OrProcessor : ImageProcessorBase
{ {
@@ -1,19 +1,19 @@
// ============================================================================ // ============================================================================
// 文件名: AngleMeasurementProcessor.cs // 文件å? AngleMeasurementProcessor.cs
// 描述: 角度测量算子 — 共端点的两条直线夹角 // æè¿°: 角度测é‡ç®—å­ â€?共端点的两æ¡ç›´çº¿å¤¹è§’
// 功能: // 功能:
// - 用户定义三个点:端点(顶点)、射线1终点、射线2终点 // - 用户定义三个点:端点(顶点)ã€å°„çº?终点ã€å°„çº?终点
// - 计算两条射线之间的夹角(0°~180°) // - 计算两æ¡å°„线之间的夹角(0°~180°ï¼?
// - 在图像上绘制两条射线、角度弧线和标注 // - 在图像上绘制两条射线、角度弧线和标注
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using System.Drawing; using System.Drawing;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
public class AngleMeasurementProcessor : ImageProcessorBase public class AngleMeasurementProcessor : ImageProcessorBase
{ {
@@ -27,7 +27,7 @@ public class AngleMeasurementProcessor : ImageProcessorBase
protected override void InitializeParameters() protected override void InitializeParameters()
{ {
// 三个点坐标(由交互控件注入,使用 double 避免取整误差) // ä¸‰ä¸ªç‚¹åæ ‡ï¼ˆç”±äº¤äº’控件注入,使用 double é¿å…å–æ•´è¯¯å·®ï¼?
Parameters.Add("VX", new ProcessorParameter("VX", "VX", typeof(double), 250.0, null, null, "") { IsVisible = false }); 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("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 }); 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(); OutputData.Clear();
// 向量 VA VB // å‘é‡ VA å’?VB
double vax = ax - vx, vay = ay - vy; double vax = ax - vx, vay = ay - vy;
double vbx = bx - vx, vby = by - vy; double vbx = bx - vx, vby = by - vy;
@@ -59,11 +59,11 @@ public class AngleMeasurementProcessor : ImageProcessorBase
angleDeg = Math.Acos(cosAngle) * 180.0 / Math.PI; angleDeg = Math.Acos(cosAngle) * 180.0 / Math.PI;
} }
// 计算角度弧的起始角和扫过角(用于绘制弧线) // 计算角度弧的起始角和扫过角(用于绘制弧线ï¼?
double angleA = Math.Atan2(vay, vax) * 180.0 / Math.PI; double angleA = Math.Atan2(vay, vax) * 180.0 / Math.PI;
double angleB = Math.Atan2(vby, vbx) * 180.0 / Math.PI; double angleB = Math.Atan2(vby, vbx) * 180.0 / Math.PI;
// 确保从 angleA angleB 的扫过方向是较小的夹角 // ç¡®ä¿ä»?angleA åˆ?angleB çš„æ‰«è¿‡æ–¹å‘æ˜¯è¾ƒå°çš„夹è§?
double sweep = angleB - angleA; double sweep = angleB - angleA;
if (sweep > 180) sweep -= 360; if (sweep > 180) sweep -= 360;
if (sweep < -180) sweep += 360; if (sweep < -180) sweep += 360;
@@ -1,27 +1,27 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: BgaVoidRateProcessor.cs // 文件å? BgaVoidRateProcessor.cs
// 描述: BGA 空洞率检测算子(两步自动检测法) // æè¿°: BGA 空洞率检测算å­ï¼ˆä¸¤æ­¥è‡ªåŠ¨æ£€æµ‹æ³•ï¼?
// //
// 处理流程: // 处理流程:
// 第一步 — 焊球定位: 高斯模糊 → Otsu反向二值化 → 闭运算 → 轮廓检测 → 圆度过滤 → 椭圆拟合 // 第一æ­?â€?焊çƒå®šä½: 高斯模糊 â†?Otsuåå‘二值化 â†?é—­è¿ç®?â†?轮廓检æµ?â†?圆度过滤 â†?椭圆拟åˆ
// 第二步 — 气泡检测: 焊球轮廓掩码 → 双阈值分割 → 轮廓检测 → 面积过滤 → 气泡率计算 // 第二æ­?â€?气泡检æµ? 焊çƒè½®å»“æŽ©ç  â†?åŒé˜ˆå€¼åˆ†å‰?â†?轮廓检æµ?â†?é¢ç§¯è¿‡æ»¤ â†?气泡率计ç®?
// //
// 支持多边形ROI限定检测区域,支持IPC-7095标准PASS/FAIL判定 // 支持多边形ROI限定检测区域,支持IPC-7095标准PASS/FAIL判定
// 正片模式:焊球=暗区域,气泡=亮区域 // 正片模å¼ï¼šç„Šç?暗区域,气泡=亮区åŸ?
// //
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.CvEnum; using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using Emgu.CV.Util; using Emgu.CV.Util;
using ImageProcessing.Core;
using Serilog; using Serilog;
using System.Drawing; using System.Drawing;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
public class BgaVoidRateProcessor : ImageProcessorBase public class BgaVoidRateProcessor : ImageProcessorBase
{ {
@@ -43,7 +43,7 @@ public class BgaVoidRateProcessor : ImageProcessorBase
LocalizationHelper.GetString("BgaVoidRateProcessor_RoiMode_Desc"), LocalizationHelper.GetString("BgaVoidRateProcessor_RoiMode_Desc"),
new string[] { "None", "Polygon" })); new string[] { "None", "Polygon" }));
// 多边形ROI点数和坐标(由UI注入,不可见,最多支持32个点) // 多边形ROIç‚¹æ•°å’Œåæ ‡ï¼ˆç”±UI注入,ä¸å¯è§ï¼Œæœ€å¤šæ”¯æŒ?2个点ï¼?
Parameters.Add("PolyCount", new ProcessorParameter("PolyCount", "PolyCount", typeof(int), 0, null, null, "") { IsVisible = false }); Parameters.Add("PolyCount", new ProcessorParameter("PolyCount", "PolyCount", typeof(int), 0, null, null, "") { IsVisible = false });
for (int i = 0; i < 32; i++) for (int i = 0; i < 32; i++)
{ {
@@ -76,7 +76,7 @@ public class BgaVoidRateProcessor : ImageProcessorBase
typeof(double), 0.5, 0.0, 1.0, typeof(double), 0.5, 0.0, 1.0,
LocalizationHelper.GetString("BgaVoidRateProcessor_BgaCircularity_Desc"))); LocalizationHelper.GetString("BgaVoidRateProcessor_BgaCircularity_Desc")));
// ── 第二步:气泡检测参数 ── // ── ç¬¬äºŒæ­¥ï¼šæ°”æ³¡æ£€æµ‹å‚æ•?──
Parameters.Add("MinThreshold", new ProcessorParameter( Parameters.Add("MinThreshold", new ProcessorParameter(
"MinThreshold", "MinThreshold",
LocalizationHelper.GetString("BgaVoidRateProcessor_MinThreshold"), LocalizationHelper.GetString("BgaVoidRateProcessor_MinThreshold"),
@@ -148,7 +148,7 @@ public class BgaVoidRateProcessor : ImageProcessorBase
OutputData["RoiMode"] = roiMode; OutputData["RoiMode"] = roiMode;
OutputData["RoiMask"] = roiMask; 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); bgaMinArea, bgaMaxArea, bgaBlurSize, bgaCircularity, minThresh, maxThresh);
// ================================================================ // ================================================================
@@ -156,7 +156,7 @@ public class BgaVoidRateProcessor : ImageProcessorBase
// ================================================================ // ================================================================
var bgaResults = DetectBgaBalls(inputImage, bgaBlurSize, bgaMinArea, bgaMaxArea, bgaCircularity, roiMask); 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) if (bgaResults.Count == 0)
{ {
@@ -176,7 +176,7 @@ public class BgaVoidRateProcessor : ImageProcessorBase
} }
// ================================================================ // ================================================================
// 第二步:在每个焊球区域内检测气泡 // 第二步:在æ¯ä¸ªç„ŠçƒåŒºåŸŸå†…检测气æ³?
// ================================================================ // ================================================================
int totalBgaArea = 0; int totalBgaArea = 0;
int totalVoidArea = 0; int totalVoidArea = 0;
@@ -193,13 +193,13 @@ public class BgaVoidRateProcessor : ImageProcessorBase
double overallVoidRate = totalBgaArea > 0 ? (double)totalVoidArea / totalBgaArea * 100.0 : 0; double overallVoidRate = totalBgaArea > 0 ? (double)totalVoidArea / totalBgaArea * 100.0 : 0;
string classification = overallVoidRate <= voidLimit ? "PASS" : "FAIL"; string classification = overallVoidRate <= voidLimit ? "PASS" : "FAIL";
// 检查每个焊球是否单独超标 // 检查æ¯ä¸ªç„Šçƒæ˜¯å¦å•独超æ ?
foreach (var bga in bgaResults) foreach (var bga in bgaResults)
{ {
bga.Classification = bga.VoidRate <= voidLimit ? "PASS" : "FAIL"; bga.Classification = bga.VoidRate <= voidLimit ? "PASS" : "FAIL";
} }
_logger.Information("第二步完成: 总气泡率={VoidRate:F1}%, 气泡数={Count}, 判定={Class}", _logger.Information("第二步完æˆ? 总气泡率={VoidRate:F1}%, 气泡æ•?{Count}, 判定={Class}",
overallVoidRate, totalVoidCount, classification); overallVoidRate, totalVoidCount, classification);
// 输出数据 // 输出数据
@@ -222,7 +222,7 @@ public class BgaVoidRateProcessor : ImageProcessorBase
/// <summary> /// <summary>
/// 第一步:自动检测BGA焊球位置 /// 第一步:自动检测BGA焊球位置
/// 使用Otsu二值化 + 轮廓检测 + 圆度过滤 + 椭圆拟合 /// 使用Otsu二值化 + 轮廓检æµ?+ 圆度过滤 + 椭圆拟åˆ
/// </summary> /// </summary>
private List<BgaBallInfo> DetectBgaBalls(Image<Gray, byte> input, int blurSize, int minArea, int maxArea, double minCircularity, Image<Gray, byte>? roiMask) 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); var blurred = new Image<Gray, byte>(w, h);
CvInvoke.GaussianBlur(input, blurred, new Size(blurSize, blurSize), 0); CvInvoke.GaussianBlur(input, blurred, new Size(blurSize, blurSize), 0);
// Otsu自动二值化(X-Ray正片:焊球=暗区域) // Otsu自动二值化(X-Ray正片:焊ç?暗区域)
var binary = new Image<Gray, byte>(w, h); var binary = new Image<Gray, byte>(w, h);
CvInvoke.Threshold(blurred, binary, 0, 255, ThresholdType.Otsu | ThresholdType.BinaryInv); 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); double circularity = 4.0 * Math.PI * area / (perimeter * perimeter);
if (circularity < minCircularity) continue; if (circularity < minCircularity) continue;
// 需要至少5个点才能拟合椭圆 // 需è¦è‡³å°?个点æ‰èƒ½æ‹Ÿåˆæ¤­åœ†
if (contours[i].Size < 5) continue; if (contours[i].Size < 5) continue;
var ellipse = CvInvoke.FitEllipse(contours[i]); var ellipse = CvInvoke.FitEllipse(contours[i]);
@@ -284,7 +284,7 @@ public class BgaVoidRateProcessor : ImageProcessorBase
}); });
} }
// 按面积从大到小排序 // 按é¢ç§¯ä»Žå¤§åˆ°å°æŽ’åº?
results.Sort((a, b) => b.BgaArea.CompareTo(a.BgaArea)); results.Sort((a, b) => b.BgaArea.CompareTo(a.BgaArea));
for (int i = 0; i < results.Count; i++) results[i].Index = i + 1; for (int i = 0; i < results.Count; i++) results[i].Index = i + 1;
@@ -296,8 +296,8 @@ public class BgaVoidRateProcessor : ImageProcessorBase
} }
/// <summary> /// <summary>
/// 第二步:在单个BGA焊球区域内检测气泡 /// 第二步:在å•个BGA焊çƒåŒºåŸŸå†…检测气æ³?
/// 使用焊球轮廓作为掩码,双阈值分割气泡区域 /// 使用焊çƒè½®å»“作为掩ç ï¼ŒåŒé˜ˆå€¼åˆ†å‰²æ°”泡区åŸ?
/// </summary> /// </summary>
private void DetectVoidsInBga(Image<Gray, byte> input, BgaBallInfo bga, int minThresh, int maxThresh, int minVoidArea) 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); int bgaPixels = CvInvoke.CountNonZero(mask);
bga.BgaArea = bgaPixels; bga.BgaArea = bgaPixels;
// 双阈值分割(正片模式:气泡=亮,灰度在[minThresh, maxThresh]范围内判为气泡) // åŒé˜ˆå€¼åˆ†å‰²ï¼ˆæ­£ç‰‡æ¨¡å¼ï¼šæ°”æ³?亮,ç°åº¦åœ¨[minThresh, maxThresh]范围内判为气泡)
var voidImg = new Image<Gray, byte>(w, h); var voidImg = new Image<Gray, byte>(w, h);
byte[,,] srcData = input.Data; byte[,,] srcData = input.Data;
byte[,,] dstData = voidImg.Data; byte[,,] dstData = voidImg.Data;
@@ -361,7 +361,7 @@ public class BgaVoidRateProcessor : ImageProcessorBase
}); });
} }
// 按面积从大到小排序 // 按é¢ç§¯ä»Žå¤§åˆ°å°æŽ’åº?
bga.Voids.Sort((a, b) => b.Area.CompareTo(a.Area)); 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; for (int i = 0; i < bga.Voids.Count; i++) bga.Voids[i].Index = i + 1;
@@ -1,25 +1,25 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: ContourProcessor.cs // 文件å? ContourProcessor.cs
// 描述: 轮廓查找算子,用于检测和分析图像中的轮廓 // 描述: 轮廓查找算子,用于检测和分析图像中的轮廓
// 功能: // 功能:
// - 检测图像中的外部轮廓 // - 检测图åƒä¸­çš„外部轮å»?
// - 根据面积范围过滤轮廓 // - 根据面积范围过滤轮廓
// - 计算轮廓的几何特征(面积、周长、中心、外接矩形等) // - 计算轮廓的几何特å¾ï¼ˆé¢ç§¯ã€å‘¨é•¿ã€ä¸­å¿ƒã€å¤–接矩形等ï¼?
// - 输出轮廓信息供后续处理使用 // - 输出轮廓信æ¯ä¾›åŽç»­å¤„ç†ä½¿ç”?
// 算法: 基于OpenCV的轮廓检测算法 // 算法: 基于OpenCV的轮廓检测算æ³?
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.CvEnum; using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using Emgu.CV.Util; using Emgu.CV.Util;
using ImageProcessing.Core;
using Serilog; using Serilog;
using System.Drawing; using System.Drawing;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 轮廓查找算子 /// 轮廓查找算子
@@ -117,7 +117,7 @@ public class ContourProcessor : ImageProcessorBase
OutputData.Clear(); OutputData.Clear();
// 创建输入图像的副本用于处理 // 创建输入图åƒçš„副本用于处ç?
Image<Gray, byte> processImage = inputImage.Clone(); Image<Gray, byte> processImage = inputImage.Clone();
// 步骤1:如果启用阈值分割,先进行二值化 // 步骤1:如果启用阈值分割,先进行二值化
@@ -128,18 +128,18 @@ public class ContourProcessor : ImageProcessorBase
if (useOtsu) if (useOtsu)
{ {
// 使用Otsu自动阈值 // 使用Otsu自动阈å€?
CvInvoke.Threshold(processImage, thresholdImage, 0, 255, ThresholdType.Otsu); CvInvoke.Threshold(processImage, thresholdImage, 0, 255, ThresholdType.Otsu);
_logger.Debug("Applied Otsu threshold"); _logger.Debug("Applied Otsu threshold");
} }
else else
{ {
// 使用固定阈值 // 使用固定阈å€?
CvInvoke.Threshold(processImage, thresholdImage, thresholdValue, 255, ThresholdType.Binary); CvInvoke.Threshold(processImage, thresholdImage, thresholdValue, 255, ThresholdType.Binary);
_logger.Debug("Applied binary threshold with value {ThresholdValue}", thresholdValue); _logger.Debug("Applied binary threshold with value {ThresholdValue}", thresholdValue);
} }
// 保存阈值处理后的图像用于调试 // ä¿å­˜é˜ˆå€¼å¤„ç†åŽçš„图åƒç”¨äºŽè°ƒè¯?
try try
{ {
string debugPath = Path.Combine("logs", $"contour_threshold_{DateTime.Now:yyyyMMdd_HHmmss}.png"); string debugPath = Path.Combine("logs", $"contour_threshold_{DateTime.Now:yyyyMMdd_HHmmss}.png");
@@ -156,7 +156,7 @@ public class ContourProcessor : ImageProcessorBase
processImage = thresholdImage; processImage = thresholdImage;
} }
// 步骤2:如果目标是黑色区域,需要反转图像 // 步骤2:如果目标是黑色区域,需è¦å转图åƒ?
bool isBlackTarget = targetColor != null && bool isBlackTarget = targetColor != null &&
(targetColor.Equals("Black", StringComparison.OrdinalIgnoreCase) || (targetColor.Equals("Black", StringComparison.OrdinalIgnoreCase) ||
targetColor.Equals("黑色", StringComparison.OrdinalIgnoreCase)); targetColor.Equals("黑色", StringComparison.OrdinalIgnoreCase));
@@ -180,7 +180,7 @@ public class ContourProcessor : ImageProcessorBase
} }
} }
// 步骤3:查找轮廓 // 步骤3:查找轮å»?
using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint()) using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
{ {
Mat hierarchy = new Mat(); Mat hierarchy = new Mat();
@@ -1,53 +1,64 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: EllipseDetectionProcessor.cs // 文件å? EllipseDetectionProcessor.cs
// 描述: 椭圆检测算子,基于轮廓分析和椭圆拟合检测图像中的椭圆 // æè¿°: 椭圆检测算å­ï¼ŒåŸºäºŽè½®å»“分æžå’Œæ¤­åœ†æ‹Ÿåˆæ£€æµ‹å›¾åƒä¸­çš„æ¤­åœ?
// 功能: // 功能:
// - 阈值分割 + 轮廓提取 // - 阈值分å‰?+ 轮廓æå
// - 椭圆拟合(FitEllipse // - 椭圆拟åˆï¼ˆFitEllipseï¼?
// - 面积/轴长/离心率/拟合误差多维过滤 // - é¢ç§¯/è½´é•¿/离心çŽ?拟åˆè¯¯å·®å¤šç»´è¿‡æ»¤
// - 支持双阈值分割和 Otsu 自动阈值 // - 支æŒåŒé˜ˆå€¼åˆ†å‰²å’Œ Otsu 自动阈å€?
// 算法: 阈值分割 + OpenCV FitEllipse // 算法: 阈值分å‰?+ OpenCV FitEllipse
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.CvEnum; using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using Emgu.CV.Util; using Emgu.CV.Util;
using ImageProcessing.Core;
using Serilog; using Serilog;
using System.Drawing; using System.Drawing;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 椭圆检测结果 /// 椭圆检测结æž?
/// </summary> /// </summary>
public class EllipseInfo public class EllipseInfo
{ {
/// <summary>序号</summary> /// <summary>序号</summary>
public int Index { get; set; } public int Index { get; set; }
/// <summary>中心点X</summary> /// <summary>中心点X</summary>
public float CenterX { get; set; } public float CenterX { get; set; }
/// <summary>中心点Y</summary> /// <summary>中心点Y</summary>
public float CenterY { get; set; } public float CenterY { get; set; }
/// <summary>长轴长度</summary> /// <summary>长轴长度</summary>
public float MajorAxis { get; set; } public float MajorAxis { get; set; }
/// <summary>短轴长度</summary> /// <summary>短轴长度</summary>
public float MinorAxis { get; set; } public float MinorAxis { get; set; }
/// <summary>旋转角度(度)</summary>
/// <summary>旋转角度(度�/summary>
public float Angle { get; set; } public float Angle { get; set; }
/// <summary>面积</summary> /// <summary>面积</summary>
public double Area { get; set; } public double Area { get; set; }
/// <summary>周长</summary> /// <summary>周长</summary>
public double Perimeter { get; set; } public double Perimeter { get; set; }
/// <summary>离心率 (0=圆, 接近1=扁椭圆)</summary>
/// <summary>离心çŽ?(0=åœ? 接近1=æ‰æ¤­åœ?</summary>
public double Eccentricity { get; set; } public double Eccentricity { get; set; }
/// <summary>拟合误差(像素)</summary> /// <summary>拟合误差(像素)</summary>
public double FitError { get; set; } public double FitError { get; set; }
/// <summary>轮廓点集</summary> /// <summary>轮廓点集</summary>
public Point[] ContourPoints { get; set; } = Array.Empty<Point>(); public Point[] ContourPoints { get; set; } = Array.Empty<Point>();
/// <summary>外接矩形</summary> /// <summary>外接矩形</summary>
public Rectangle BoundingBox { get; set; } public Rectangle BoundingBox { get; set; }
} }
@@ -70,7 +81,7 @@ public class EllipseDetector
public double MaxFitError { get; set; } = 5.0; public double MaxFitError { get; set; } = 5.0;
public int Thickness { get; set; } = 2; public int Thickness { get; set; } = 2;
/// <summary>执行椭圆检测</summary> /// <summary>执行椭圆检æµ?/summary>
public List<EllipseInfo> Detect(Image<Gray, byte> inputImage, Image<Gray, byte>? roiMask = null) public List<EllipseInfo> Detect(Image<Gray, byte> inputImage, Image<Gray, byte>? roiMask = null)
{ {
_logger.Debug("Ellipse detection started: UseOtsu={UseOtsu}, MinThreshold={Min}, MaxThreshold={Max}", _logger.Debug("Ellipse detection started: UseOtsu={UseOtsu}, MinThreshold={Min}, MaxThreshold={Max}",
@@ -186,7 +197,7 @@ public class EllipseDetector
} }
/// <summary> /// <summary>
/// 椭圆检测算子 /// 椭圆检测算å­?
/// </summary> /// </summary>
public class EllipseDetectionProcessor : ImageProcessorBase public class EllipseDetectionProcessor : ImageProcessorBase
{ {
@@ -200,7 +211,7 @@ public class EllipseDetectionProcessor : ImageProcessorBase
protected override void InitializeParameters() protected override void InitializeParameters()
{ {
// ── 多边形ROI(由UI注入,最多32个点) ── // ── 多边形ROI(由UI注入,最å¤?2个点ï¼?──
Parameters.Add("PolyCount", new ProcessorParameter("PolyCount", "PolyCount", typeof(int), 0, null, null, "") { IsVisible = false }); Parameters.Add("PolyCount", new ProcessorParameter("PolyCount", "PolyCount", typeof(int), 0, null, null, "") { IsVisible = false });
for (int i = 0; i < 32; i++) for (int i = 0; i < 32; i++)
{ {
@@ -1,28 +1,28 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: FillRateProcessor.cs // 文件å? FillRateProcessor.cs
// 描述: 通孔填锡率测量算子(倾斜投影几何法),基于四椭圆ROI // 描述: 通孔填锡率测量算子(倾斜投影几何法),基于四椭圆ROI
// 功能: // 功能:
// - 样品倾斜约45°放置,利用投影位移关系计算填锡率 // - æ ·å“倾斜çº?5°放置,利用投影ä½ç§»å…³ç³»è®¡ç®—填锡率
// - 四个椭圆定义: // - 四个椭圆定义ï¼?
// E1 = 通孔底部轮廓 // E1 = 通孔底部轮廓
// E2 = 通孔顶部轮廓 // E2 = 通孔顶部轮廓
// E3 = 填锡起点(与E1重合,代表0%填锡) // E3 = 填锡起点(与E1é‡åˆï¼Œä»£è¡?%填锡ï¼?
// E4 = 填锡终点(锡实际填充到的高度) // E4 = 填锡终点(锡实际填充到的高度ï¼?
// - 填锡率 = |E4中心 - E3中心| / |E2中心 - E1中心| × 100% // - 填锡çŽ?= |E4中心 - E3中心| / |E2中心 - E1中心| × 100%
// - 纯几何方法,不依赖灰度分析 // - 纯几何方法,ä¸ä¾èµ–ç°åº¦åˆ†æž?
// - IPC-610 THT 分级判定(Class 1/2/3 // - IPC-610 THT 分级判定(Class 1/2/3ï¼?
// 算法: 倾斜投影位移比例 // 算法: 倾斜投影位移比例
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using System.Drawing; using System.Drawing;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 通孔填锡率测量算子(倾斜投影几何法) /// 通孔填锡率测量算子(倾斜投影几何法)
@@ -42,7 +42,7 @@ public class FillRateProcessor : ImageProcessorBase
// 四个椭圆(由交互控件注入,UI不可见) // 四个椭圆(由交互控件注入,UI不可见)
AddEllipseParams("E1", 200, 250, 60, 50, 0); // 底部 AddEllipseParams("E1", 200, 250, 60, 50, 0); // 底部
AddEllipseParams("E2", 220, 180, 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); // 填锡终点 AddEllipseParams("E4", 210, 220, 55, 45, 0); // 填锡终点
Parameters.Add("THTLimit", new ProcessorParameter( 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 e3cx = GetParameter<int>("E3_CX"), e3cy = GetParameter<int>("E3_CY");
int e4cx = GetParameter<int>("E4_CX"), e4cy = GetParameter<int>("E4_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 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 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"); 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(); OutputData.Clear();
// 计算通孔全高度的投影位移(E1底部 → E2顶部) // 计算通孔全高度的投影ä½ç§»ï¼ˆE1底部 â†?E2顶部ï¼?
double fullDx = e2cx - e1cx; double fullDx = e2cx - e1cx;
double fullDy = e2cy - e1cy; double fullDy = e2cy - e1cy;
double fullDistance = Math.Sqrt(fullDx * fullDx + fullDy * fullDy); double fullDistance = Math.Sqrt(fullDx * fullDx + fullDy * fullDy);
// 计算填锡高度的投影位移(E3起点 → E4终点) // 计算填锡高度的投影ä½ç§»ï¼ˆE3起点 â†?E4终点ï¼?
double fillDx = e4cx - e3cx; double fillDx = e4cx - e3cx;
double fillDy = e4cy - e3cy; double fillDy = e4cy - e3cy;
double fillDistance = Math.Sqrt(fillDx * fillDx + fillDy * fillDy); double fillDistance = Math.Sqrt(fillDx * fillDx + fillDy * fillDy);
// 填锡率 = 填锡位移 / 全高度位移 // 填锡çŽ?= 填锡ä½ç§» / 全高度ä½ç§?
double fillRate = fullDistance > 0 ? (fillDistance / fullDistance) * 100.0 : 0; double fillRate = fullDistance > 0 ? (fillDistance / fullDistance) * 100.0 : 0;
fillRate = Math.Clamp(fillRate, 0, 100); fillRate = Math.Clamp(fillRate, 0, 100);
@@ -1,28 +1,27 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 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;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using System.Drawing; using System.Drawing;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 直线测量算子 - 测量两点之间的距 /// 直线测量算子 - 测量两点之间的距?
/// </summary> /// </summary>
public class LineMeasurementProcessor : ImageProcessorBase public class LineMeasurementProcessor : ImageProcessorBase
{ {
@@ -120,7 +119,7 @@ public class LineMeasurementProcessor : ImageProcessorBase
// 计算实际距离 // 计算实际距离
double actualDistance = pixelDistance * pixelSize; double actualDistance = pixelDistance * pixelSize;
// 计算角度(相对于水平方向 // 计算角度(相对于水平方向?
double angleRad = Math.Atan2(dy, dx); double angleRad = Math.Atan2(dy, dx);
double angleDeg = angleRad * 180.0 / Math.PI; double angleDeg = angleRad * 180.0 / Math.PI;
@@ -1,24 +1,23 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 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;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using System.Drawing; using System.Drawing;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
public class PointToLineProcessor : ImageProcessorBase public class PointToLineProcessor : ImageProcessorBase
{ {
@@ -32,7 +31,7 @@ public class PointToLineProcessor : ImageProcessorBase
protected override void InitializeParameters() protected override void InitializeParameters()
{ {
// 直线两端点 + 测量点(由交互控件注入) // 直线两端ç‚?+ 测é‡ç‚¹ï¼ˆç”±äº¤äº’控件注入)
Parameters.Add("L1X", new ProcessorParameter("L1X", "L1X", typeof(int), 100, null, null, "") { IsVisible = false }); 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("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 }); Parameters.Add("L2X", new ProcessorParameter("L2X", "L2X", typeof(int), 400, null, null, "") { IsVisible = false });
@@ -80,7 +79,7 @@ public class PointToLineProcessor : ImageProcessorBase
if (abLen > 0.001) if (abLen > 0.001)
{ {
// 叉积求距离 // å‰ç§¯æ±‚è·ç¦?
double cross = Math.Abs(abx * (l1y - py) - aby * (l1x - px)); double cross = Math.Abs(abx * (l1y - py) - aby * (l1x - px));
pixelDistance = cross / abLen; pixelDistance = cross / abLen;
@@ -1,24 +1,24 @@
// ============================================================================ // ============================================================================
// 文件名: VoidMeasurementProcessor.cs // 文件å? VoidMeasurementProcessor.cs
// 描述: 空隙测量算子 // 描述: 空隙测量算子
// //
// 处理流程: // 处理流程:
// 1. 构建多边形ROI掩码,计算ROI面积 // 1. 构建多边形ROI掩码,计算ROI面积
// 2. 在ROI内进行双阈值分割提取气泡区域 // 2. 在ROI内进行åŒé˜ˆå€¼åˆ†å‰²æå–气泡区åŸ?
// 3. 形态学膨胀合并相邻气泡 // 3. 形态学膨胀合并相邻气泡
// 4. 轮廓检测,计算每个气泡面积 // 4. 轮廓检测,计算每个气泡面积
// 5. 计算空隙率 = 总气泡面积 / ROI面积 // 5. 计算空隙çŽ?= 总气泡é¢ç§?/ ROIé¢ç§¯
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.CvEnum; using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using Emgu.CV.Util; using Emgu.CV.Util;
using ImageProcessing.Core;
using Serilog; using Serilog;
using System.Drawing; using System.Drawing;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
public class VoidMeasurementProcessor : ImageProcessorBase public class VoidMeasurementProcessor : ImageProcessorBase
{ {
@@ -32,7 +32,7 @@ public class VoidMeasurementProcessor : ImageProcessorBase
protected override void InitializeParameters() protected override void InitializeParameters()
{ {
// ── 多边形ROI(由UI注入,最多32个点) ── // ── 多边形ROI(由UI注入,最å¤?2个点ï¼?──
Parameters.Add("PolyCount", new ProcessorParameter("PolyCount", "PolyCount", typeof(int), 0, null, null, "") { IsVisible = false }); Parameters.Add("PolyCount", new ProcessorParameter("PolyCount", "PolyCount", typeof(int), 0, null, null, "") { IsVisible = false });
for (int i = 0; i < 32; i++) 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($"PolyY{i}", new ProcessorParameter($"PolyY{i}", $"PolyY{i}", typeof(int), 0, null, null, "") { IsVisible = false });
} }
// ── 气泡检测参数 ── // ── æ°”æ³¡æ£€æµ‹å‚æ•?──
Parameters.Add("MinThreshold", new ProcessorParameter( Parameters.Add("MinThreshold", new ProcessorParameter(
"MinThreshold", "MinThreshold",
LocalizationHelper.GetString("VoidMeasurementProcessor_MinThreshold"), LocalizationHelper.GetString("VoidMeasurementProcessor_MinThreshold"),
@@ -109,7 +109,7 @@ public class VoidMeasurementProcessor : ImageProcessorBase
} }
else else
{ {
// 无ROI时使用全图 // æ— ROI时使用全å›?
roiMask = new Image<Gray, byte>(w, h); roiMask = new Image<Gray, byte>(w, h);
roiMask.SetValue(new Gray(255)); roiMask.SetValue(new Gray(255));
} }
@@ -152,7 +152,7 @@ public class VoidMeasurementProcessor : ImageProcessorBase
CvInvoke.BitwiseAnd(voidImg, roiMask, voidImg); CvInvoke.BitwiseAnd(voidImg, roiMask, voidImg);
} }
// ── 轮廓检测 ── // ── 轮廓检æµ?──
using var contours = new VectorOfVectorOfPoint(); using var contours = new VectorOfVectorOfPoint();
using var hierarchy = new Mat(); using var hierarchy = new Mat();
CvInvoke.FindContours(voidImg, contours, hierarchy, RetrType.External, ChainApproxMethod.ChainApproxSimple); 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)); voids.Sort((a, b) => b.Area.CompareTo(a.Area));
for (int i = 0; i < voids.Count; i++) voids[i].Index = i + 1; for (int i = 0; i < voids.Count; i++) voids[i].Index = i + 1;
@@ -1,24 +1,24 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: BandPassFilterProcessor.cs // ? BandPassFilterProcessor.cs
// 描述: 带通滤波器算子,用于频域图像处理 // 讛膩: 撣阡𡁏誘瘜W膥蝞堒嚗𣬚鍂鈭𡡞笔㦛?
// 功能: // 功能:
// - 在频域中保留特定频率范围的信号 // - 煺葉靽萘憸𤑳?
// - 支持理想、巴特沃斯、高斯三种滤波器类型 // - 支持理想、巴特沃斯、高斯三种滤波器类型
// - 可调节低频和高频截止频率 // - 可调节低频和高频截止频率
// - 通过FFT实现频域滤波 // - 通过FFT实现频域滤波
// 算法: 基于离散傅里叶变换(DFT)的频域滤波 // 算法: 基于离散傅里叶变换(DFT)的频域滤波
// 作者: 李伟 wei.lw.li@hexagon.com // 雿𡏭? 𦒘 wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.CvEnum; using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using System.Drawing; using System.Drawing;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 带通滤波器算子 /// 带通滤波器算子
@@ -1,21 +1,21 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 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;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 双边滤波算子 /// 双边滤波算子
@@ -1,22 +1,22 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 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;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 高斯模糊算子 /// 高斯模糊算子
@@ -1,26 +1,26 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 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;
using Emgu.CV.CvEnum; using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 高通滤波算子 /// 高通滤波算å­?
/// </summary> /// </summary>
public class HighPassFilterProcessor : ImageProcessorBase public class HighPassFilterProcessor : ImageProcessorBase
{ {
@@ -69,7 +69,7 @@ public class HighPassFilterProcessor : ImageProcessorBase
Mat dftImage = new Mat(); Mat dftImage = new Mat();
CvInvoke.Dft(complexImage, dftImage, DxtType.Forward); CvInvoke.Dft(complexImage, dftImage, DxtType.Forward);
// 分离实部和虚部 // 分离实部和虚éƒ?
using (var dftPlanes = new Emgu.CV.Util.VectorOfMat()) using (var dftPlanes = new Emgu.CV.Util.VectorOfMat())
{ {
CvInvoke.Split(dftImage, dftPlanes); CvInvoke.Split(dftImage, dftPlanes);
@@ -80,7 +80,7 @@ public class HighPassFilterProcessor : ImageProcessorBase
// 创建高通滤波器 // 创建高通滤波器
Mat filter = CreateHighPassFilter(rows, cols, cutoffFrequency); Mat filter = CreateHighPassFilter(rows, cols, cutoffFrequency);
// 应用滤波器 // 应用滤波å™?
CvInvoke.Multiply(real, filter, real); CvInvoke.Multiply(real, filter, real);
CvInvoke.Multiply(imag, filter, imag); CvInvoke.Multiply(imag, filter, imag);
@@ -1,26 +1,26 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 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;
using Emgu.CV.CvEnum; using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 低通滤波算子 /// 低通滤波算å­?
/// </summary> /// </summary>
public class LowPassFilterProcessor : ImageProcessorBase public class LowPassFilterProcessor : ImageProcessorBase
{ {
@@ -69,7 +69,7 @@ public class LowPassFilterProcessor : ImageProcessorBase
Mat dftImage = new Mat(); Mat dftImage = new Mat();
CvInvoke.Dft(complexImage, dftImage, DxtType.Forward); CvInvoke.Dft(complexImage, dftImage, DxtType.Forward);
// 分离实部和虚部 // 分离实部和虚éƒ?
using (var dftPlanes = new Emgu.CV.Util.VectorOfMat()) using (var dftPlanes = new Emgu.CV.Util.VectorOfMat())
{ {
CvInvoke.Split(dftImage, dftPlanes); CvInvoke.Split(dftImage, dftPlanes);
@@ -80,7 +80,7 @@ public class LowPassFilterProcessor : ImageProcessorBase
// 创建低通滤波器 // 创建低通滤波器
Mat filter = CreateLowPassFilter(rows, cols, cutoffFrequency); Mat filter = CreateLowPassFilter(rows, cols, cutoffFrequency);
// 应用滤波器 // 应用滤波å™?
CvInvoke.Multiply(real, filter, real); CvInvoke.Multiply(real, filter, real);
CvInvoke.Multiply(imag, filter, imag); CvInvoke.Multiply(imag, filter, imag);
@@ -1,25 +1,25 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 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;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using System.Drawing; using System.Drawing;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 均值滤波算子 /// å‡å€¼æ»¤æ³¢ç®—å­?
/// </summary> /// </summary>
public class MeanFilterProcessor : ImageProcessorBase public class MeanFilterProcessor : ImageProcessorBase
{ {
@@ -1,25 +1,25 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // 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;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 中值滤波算子 /// 中值滤波算å­?
/// </summary> /// </summary>
public class MedianFilterProcessor : ImageProcessorBase public class MedianFilterProcessor : ImageProcessorBase
{ {
@@ -1,22 +1,22 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: ShockFilterProcessor.cs // 文件å? ShockFilterProcessor.cs
// 描述: 冲击滤波算子,用于图像锐化和边缘增强 // 描述: 冲击滤波算子,用于图像锐化和边缘增强
// 功能: // 功能:
// - 基于PDE的图像锐化 // - 基于PDE的图åƒé”åŒ?
// - 增强边缘同时保持平滑区域 // - 增强边缘同时保持平滑区域
// - 可调节迭代次数和滤波强度 // - 可调节迭代次数和滤波强度
// - 适用于模糊图像的恢复 // - 适用于模糊图像的恢复
// 算法: 冲击滤波器(Shock Filter)基于偏微分方程 // 算法: 冲击滤波器(Shock Filter)基于偏微分方程
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 冲击滤波算子 /// 冲击滤波算子
@@ -1,26 +1,26 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: HorizontalEdgeProcessor.cs // 文件å? HorizontalEdgeProcessor.cs
// 描述: 水平边缘检测算子,专门用于检测水平方向的边缘 // 描述: 水平边缘检测算子,专门用于检测水平方向的边缘
// 功能: // 功能:
// - 检测水平边缘 // - 检测水平边ç¼?
// - 支持Prewitt和Sobel算子 // - 支持Prewitt和Sobel算子
// - 可调节检测灵敏度 // - 可调节检测灵敏度
// - 适用于检测水平线条和纹理 // - 适用于检测水平线条和纹理
// 算法: Prewitt/Sobel水平算子 // 算法: Prewitt/Sobel水平算子
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.CvEnum; using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// 水平边缘检测算子 /// 水平边缘检测算å­?
/// </summary> /// </summary>
public class HorizontalEdgeProcessor : ImageProcessorBase 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) 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); Image<Gray, float> sobelY = new Image<Gray, float>(inputImage.Size);
CvInvoke.Sobel(inputImage, sobelY, DepthType.Cv32F, 0, 1, 3); CvInvoke.Sobel(inputImage, sobelY, DepthType.Cv32F, 0, 1, 3);
// 转换为绝对值并应用灵敏度 // 转æ¢ä¸ºç»å¯¹å€¼å¹¶åº”ç”¨çµæ•åº?
Image<Gray, byte> result = new Image<Gray, byte>(inputImage.Size); Image<Gray, byte> result = new Image<Gray, byte>(inputImage.Size);
CvInvoke.ConvertScaleAbs(sobelY, result, sensitivity, 0); CvInvoke.ConvertScaleAbs(sobelY, result, sensitivity, 0);
// 应用阈值 // 应用阈å€?
if (threshold > 0) if (threshold > 0)
{ {
CvInvoke.Threshold(result, result, threshold, 255, ThresholdType.Binary); 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, 0];
sum -= inputData[y + 1, x + 1, 0]; sum -= inputData[y + 1, x + 1, 0];
// 取绝对值并应用灵敏度 // å–ç»å¯¹å€¼å¹¶åº”ç”¨çµæ•åº?
int value = (int)(Math.Abs(sum) * sensitivity); int value = (int)(Math.Abs(sum) * sensitivity);
// 应用阈值 // 应用阈å€?
if (value > threshold) if (value > threshold)
{ {
outputData[y, x, 0] = (byte)Math.Min(255, value); 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) private Image<Gray, byte> ApplySimple(Image<Gray, byte> inputImage, double sensitivity, int threshold)
{ {
// 简单差分算子 // 简å•差分算å­?
// [ 1 1 1] // [ 1 1 1]
// [ 0 0 0] // [ 0 0 0]
// [-1 -1 -1] // [-1 -1 -1]
// 但权重更简单 // 但æƒé‡æ›´ç®€å?
int width = inputImage.Width; int width = inputImage.Width;
int height = inputImage.Height; 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 diff = inputData[y - 1, x, 0] - inputData[y + 1, x, 0];
int value = (int)(Math.Abs(diff) * sensitivity); int value = (int)(Math.Abs(diff) * sensitivity);
// 应用阈值 // 应用阈å€?
if (value > threshold) if (value > threshold)
{ {
outputData[y, x, 0] = (byte)Math.Min(255, value); outputData[y, x, 0] = (byte)Math.Min(255, value);
@@ -1,31 +1,31 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: KirschEdgeProcessor.cs // 文件å? KirschEdgeProcessor.cs
// 描述: Kirsch边缘检测算子,用于检测图像边缘 // æè¿°: Kirsch边缘检测算å­ï¼Œç”¨äºŽæ£€æµ‹å›¾åƒè¾¹ç¼?
// 功能: // 功能:
// - Kirsch算子边缘检测 // - Kirschç®—å­è¾¹ç¼˜æ£€æµ?
// - 8个方向的边缘检测 // - 8个方å‘的边缘检æµ?
// - 输出最大响应方向的边缘 // - 输出最大响应方向的边缘
// - 对噪声敏感度低 // - å¯¹å™ªå£°æ•æ„Ÿåº¦ä½?
// 算法: Kirsch算子(8方向模板) // 算法: Kirschç®—å­ï¼?æ–¹å‘æ¨¡æ¿ï¼?
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// Kirsch边缘检测算子 /// Kirsch边缘检测算å­?
/// </summary> /// </summary>
public class KirschEdgeProcessor : ImageProcessorBase public class KirschEdgeProcessor : ImageProcessorBase
{ {
private static readonly ILogger _logger = Log.ForContext<KirschEdgeProcessor>(); private static readonly ILogger _logger = Log.ForContext<KirschEdgeProcessor>();
// Kirsch算子的8个方向模板 // Kirschç®—å­çš?ä¸ªæ–¹å‘æ¨¡æ?
private static readonly int[][,] KirschKernels = new int[8][,] private static readonly int[][,] KirschKernels = new int[8][,]
{ {
// N // N
@@ -86,14 +86,14 @@ public class KirschEdgeProcessor : ImageProcessorBase
Image<Gray, byte> result = new Image<Gray, byte>(width, height); Image<Gray, byte> result = new Image<Gray, byte>(width, height);
byte[,,] outputData = result.Data; byte[,,] outputData = result.Data;
// 对每个像素应用8个Kirsch模板,取最大响应 // 对æ¯ä¸ªåƒç´ åº”ç”?个Kirsch模æ¿ï¼Œå–最大å“åº?
for (int y = 1; y < height - 1; y++) for (int y = 1; y < height - 1; y++)
{ {
for (int x = 1; x < width - 1; x++) for (int x = 1; x < width - 1; x++)
{ {
int maxResponse = 0; int maxResponse = 0;
// 对8个方向分别计算 // å¯?个方å‘分别计ç®?
for (int k = 0; k < 8; k++) for (int k = 0; k < 8; k++)
{ {
int sum = 0; int sum = 0;
@@ -106,7 +106,7 @@ public class KirschEdgeProcessor : ImageProcessorBase
} }
} }
// 取绝对值 // å–ç»å¯¹å€?
sum = Math.Abs(sum); sum = Math.Abs(sum);
if (sum > maxResponse) if (sum > maxResponse)
{ {
@@ -1,26 +1,26 @@
// ============================================================================ // ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved. // Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件名: SobelEdgeProcessor.cs // 文件å? SobelEdgeProcessor.cs
// 描述: Sobel边缘检测算子,用于检测图像边缘 // æè¿°: Sobel边缘检测算å­ï¼Œç”¨äºŽæ£€æµ‹å›¾åƒè¾¹ç¼?
// 功能: // 功能:
// - Sobel算子边缘检测 // - Sobelç®—å­è¾¹ç¼˜æ£€æµ?
// - 支持X方向、Y方向和组合检测 // - 支æŒXæ–¹å‘ã€Yæ–¹å‘å’Œç»„åˆæ£€æµ?
// - 可调节核大小 // - 可调节核大小
// - 输出边缘强度图 // - 输出边缘强度å›?
// 算法: Sobel算子 // 算法: Sobel算子
// 作者: 李伟 wei.lw.li@hexagon.com // 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================ // ============================================================================
using Emgu.CV; using Emgu.CV;
using Emgu.CV.CvEnum; using Emgu.CV.CvEnum;
using Emgu.CV.Structure; using Emgu.CV.Structure;
using ImageProcessing.Core;
using Serilog; using Serilog;
using XP.ImageProcessing.Core;
namespace ImageProcessing.Processors; namespace XP.ImageProcessing.Processors;
/// <summary> /// <summary>
/// Sobel边缘检测算子 /// Sobel边缘检测算å­?
/// </summary> /// </summary>
public class SobelEdgeProcessor : ImageProcessorBase public class SobelEdgeProcessor : ImageProcessorBase
{ {
@@ -96,7 +96,7 @@ public class SobelEdgeProcessor : ImageProcessorBase
// 计算梯度幅值:sqrt(Gx^2 + Gy^2) // 计算梯度幅值:sqrt(Gx^2 + Gy^2)
Image<Gray, float> magnitude = new Image<Gray, float>(inputImage.Size); Image<Gray, float> magnitude = new Image<Gray, float>(inputImage.Size);
// 手动计算幅值 // 手动计算幅å€?
for (int y = 0; y < inputImage.Height; y++) for (int y = 0; y < inputImage.Height; y++)
{ {
for (int x = 0; x < inputImage.Width; x++) for (int x = 0; x < inputImage.Width; x++)
@@ -2,10 +2,10 @@ using System;
using System.Windows; using System.Windows;
using System.Windows.Controls.Primitives; using System.Windows.Controls.Primitives;
namespace ImageROIControl namespace XP.ImageProcessing.RoiControl
{ {
/// <summary> /// <summary>
/// ROI控制 /// ROI控制?
/// </summary> /// </summary>
public class ControlThumb : Thumb public class ControlThumb : Thumb
{ {
@@ -16,12 +16,12 @@ namespace ImageROIControl
try try
{ {
ResourceDictionary dictionary = new ResourceDictionary(); ResourceDictionary dictionary = new ResourceDictionary();
dictionary.Source = new Uri("pack://application:,,,/ImageROIControl;component/Themes/Generic.xaml", UriKind.Absolute); dictionary.Source = new Uri("pack://application:,,,/XP.ImageProcessing.RoiControl;component/Themes/Generic.xaml", UriKind.Absolute);
thumbStyle = (Style?)dictionary["AreaControlThumbStyle"]; thumbStyle = (Style?)dictionary["AreaControlThumbStyle"];
} }
catch catch
{ {
// 如果样式加载失败,使用默认样 // 如果样式加载失败,使用默认样?
thumbStyle = null; thumbStyle = null;
} }
} }
@@ -1,12 +1,12 @@
using ImageROIControl.Models;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using XP.ImageProcessing.RoiControl.Models;
namespace ImageROIControl.Controls namespace XP.ImageProcessing.RoiControl.Controls
{ {
/// <summary> /// <summary>
/// 图像ROI画布控件,支持图像显示、ROI编辑、缩放和平移 /// 图像ROI画布控件,支持图像显示、ROI编辑、缩放和平移
@@ -1,12 +1,12 @@
<UserControl x:Class="ImageROIControl.Controls.PolygonRoiCanvas" <UserControl x:Class="XP.ImageProcessing.RoiControl.Controls.PolygonRoiCanvas"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ImageROIControl.Controls" xmlns:local="clr-namespace:XP.ImageProcessing.RoiControl.Controls"
xmlns:models="clr-namespace:ImageROIControl.Models" xmlns:models="clr-namespace:XP.ImageProcessing.RoiControl.Models"
xmlns:converters="clr-namespace:ImageROIControl.Converters" xmlns:converters="clr-namespace:XP.ImageProcessing.RoiControl.Converters"
xmlns:behaviors="clr-namespace:ImageROIControl" xmlns:behaviors="clr-namespace:XP.ImageProcessing.RoiControl"
mc:Ignorable="d" mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" d:DesignHeight="450" d:DesignWidth="800"
x:Name="root" x:Name="root"
@@ -1,4 +1,3 @@
using ImageROIControl.Models;
using System; using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Collections.Specialized; using System.Collections.Specialized;
@@ -8,8 +7,9 @@ using System.Windows.Documents;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Shapes; using System.Windows.Shapes;
using XP.ImageProcessing.RoiControl.Models;
namespace ImageROIControl.Controls namespace XP.ImageProcessing.RoiControl.Controls
{ {
public partial class PolygonRoiCanvas : UserControl public partial class PolygonRoiCanvas : UserControl
{ {
@@ -75,14 +75,14 @@ namespace ImageROIControl.Controls
private void Points_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) private void Points_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{ {
// 只在删除或添加顶点时更新Adorner,拖拽时的Replace操作不触发更 // 只在删除或添加顶点时更新Adorner,拖拽时的Replace操作不触发更?
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove || if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove ||
e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{ {
// Points集合变化时,如果当前选中的是多边形ROI,更新Adorner // Points集合变化时,如果当前选中的是多边形ROI,更新Adorner
if (SelectedROI is PolygonROI polygonROI && sender == polygonROI.Points) if (SelectedROI is PolygonROI polygonROI && sender == polygonROI.Points)
{ {
// 使用Dispatcher延迟更新,确保UI已经处理完Points的变 // 使用Dispatcher延迟更新,确保UI已经处理完Points的变?
Dispatcher.BeginInvoke(new Action(() => Dispatcher.BeginInvoke(new Action(() =>
{ {
UpdateAdorner(); UpdateAdorner();
@@ -219,7 +219,7 @@ namespace ImageROIControl.Controls
{ {
var control = (PolygonRoiCanvas)d; var control = (PolygonRoiCanvas)d;
// 更新IsSelected状 // 更新IsSelected状?
if (e.OldValue is ROIShape oldROI) if (e.OldValue is ROIShape oldROI)
{ {
oldROI.IsSelected = false; oldROI.IsSelected = false;
@@ -288,7 +288,7 @@ namespace ImageROIControl.Controls
// 尝试获取容器 // 尝试获取容器
var container = itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as ContentPresenter; var container = itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as ContentPresenter;
// 如果容器还没生成,尝试强制生 // 如果容器还没生成,尝试强制生?
if (container == null) if (container == null)
{ {
// 强制生成容器 // 强制生成容器
@@ -298,7 +298,7 @@ namespace ImageROIControl.Controls
if (container != null) if (container != null)
{ {
// 查找实际的形状元素(只支持多边形 // 查找实际的形状元素(只支持多边形?
if (roi is PolygonROI) if (roi is PolygonROI)
{ {
return FindVisualChild<Polygon>(container); return FindVisualChild<Polygon>(container);
@@ -334,10 +334,10 @@ namespace ImageROIControl.Controls
private void Canvas_MouseWheel(object sender, MouseWheelEventArgs e) private void Canvas_MouseWheel(object sender, MouseWheelEventArgs e)
{ {
// 获取鼠标imageDisplayGrid 中的位置 // 获取鼠标?imageDisplayGrid 中的位置
Point mousePos = e.GetPosition(imageDisplayGrid); Point mousePos = e.GetPosition(imageDisplayGrid);
// 获取鼠标Canvas 中的位置(缩放前 // 获取鼠标?Canvas 中的位置(缩放前?
Point mousePosOnCanvas = e.GetPosition(mainCanvas); Point mousePosOnCanvas = e.GetPosition(mainCanvas);
double oldZoom = ZoomScale; double oldZoom = ZoomScale;
@@ -364,7 +364,7 @@ namespace ImageROIControl.Controls
ZoomScale = newZoom; ZoomScale = newZoom;
// 调整平移偏移,使鼠标位置保持不变 // 调整平移偏移,使鼠标位置保持不变
// 新的偏移 = 旧偏+ 鼠标位置 - 鼠标位置 * 缩放比例 // 新的偏移 = 旧偏?+ 鼠标位置 - 鼠标位置 * 缩放比例
PanOffsetX = mousePos.X - (mousePos.X - PanOffsetX) * scale; PanOffsetX = mousePos.X - (mousePos.X - PanOffsetX) * scale;
PanOffsetY = mousePos.Y - (mousePos.Y - PanOffsetY) * scale; PanOffsetY = mousePos.Y - (mousePos.Y - PanOffsetY) * scale;
} }
@@ -412,7 +412,7 @@ namespace ImageROIControl.Controls
private void Canvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e) private void Canvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{ {
// 右键点击完成多边 // 右键点击完成多边?
OnRightClick(); OnRightClick();
e.Handled = true; e.Handled = true;
} }
@@ -440,10 +440,10 @@ namespace ImageROIControl.Controls
if (imageDisplayGrid != null && CanvasWidth > 0 && CanvasHeight > 0) if (imageDisplayGrid != null && CanvasWidth > 0 && CanvasHeight > 0)
{ {
// 使用 Dispatcher 延迟执行,确保布局已完 // 使用 Dispatcher 延迟执行,确保布局已完?
Dispatcher.BeginInvoke(new Action(() => Dispatcher.BeginInvoke(new Action(() =>
{ {
// 获取图像显示区域的实际尺 // 获取图像显示区域的实际尺?
double viewportWidth = imageDisplayGrid.ActualWidth; double viewportWidth = imageDisplayGrid.ActualWidth;
double viewportHeight = imageDisplayGrid.ActualHeight; double viewportHeight = imageDisplayGrid.ActualHeight;
@@ -453,10 +453,10 @@ namespace ImageROIControl.Controls
double scaleX = viewportWidth / CanvasWidth; double scaleX = viewportWidth / CanvasWidth;
double scaleY = viewportHeight / CanvasHeight; double scaleY = viewportHeight / CanvasHeight;
// 选择较小的缩放比例,确保图像完全显示在窗口内(保持宽高比 // 选择较小的缩放比例,确保图像完全显示在窗口内(保持宽高比?
ZoomScale = Math.Min(scaleX, scaleY); ZoomScale = Math.Min(scaleX, scaleY);
// 居中显示Grid HorizontalAlignment VerticalAlignment 自动处理 // 居中显示?Grid ?HorizontalAlignment ?VerticalAlignment 自动处理
PanOffsetX = 0; PanOffsetX = 0;
PanOffsetY = 0; PanOffsetY = 0;
} }
@@ -5,7 +5,7 @@ using System.ComponentModel;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Windows; using System.Windows;
namespace ImageROIControl.Models namespace XP.ImageProcessing.RoiControl.Models
{ {
/// <summary> /// <summary>
/// ROI形状类型 /// ROI形状类型
@@ -68,7 +68,7 @@ namespace ImageROIControl.Models
} }
/// <summary> /// <summary>
/// 用于JSON序列化的Points列表(不参与UI绑定 /// 用于JSON序列化的Points列表(不参与UI绑定?
/// </summary> /// </summary>
[System.Text.Json.Serialization.JsonPropertyName("PointsList")] [System.Text.Json.Serialization.JsonPropertyName("PointsList")]
public List<Point> PointsList public List<Point> PointsList
@@ -6,7 +6,7 @@ using System.Windows;
using System.Windows.Data; using System.Windows.Data;
using System.Windows.Media; using System.Windows.Media;
namespace ImageROIControl namespace XP.ImageProcessing.RoiControl
{ {
/// <summary> /// <summary>
/// 将Point列表转换为PointCollection,支持ObservableCollection变化通知 /// 将Point列表转换为PointCollection,支持ObservableCollection变化通知
@@ -47,7 +47,7 @@ namespace ImageROIControl
} }
/// <summary> /// <summary>
/// 索引转换为位置标 /// 索引转换为位置标?
/// </summary> /// </summary>
public class IndexToPositionConverter : IValueConverter public class IndexToPositionConverter : IValueConverter
{ {
@@ -6,14 +6,14 @@ using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Shapes; using System.Windows.Shapes;
namespace ImageROIControl namespace XP.ImageProcessing.RoiControl
{ {
/// <summary> /// <summary>
/// 多边形装饰器,用于编辑多边形顶点 /// 多边形装饰器,用于编辑多边形顶点
/// </summary> /// </summary>
public class PolygonAdorner : Adorner public class PolygonAdorner : Adorner
{ {
private List<ControlThumb> vertexThumbs = new List<ControlThumb>(); // 顶点控制 private List<ControlThumb> vertexThumbs = new List<ControlThumb>(); // 顶点控制?
private VisualCollection visualChildren; private VisualCollection visualChildren;
private double scaleFactor = 1; private double scaleFactor = 1;
private Models.PolygonROI? polygonROI; private Models.PolygonROI? polygonROI;
@@ -28,7 +28,7 @@ namespace ImageROIControl
// 使用ROI模型的Points数量而不是Polygon的Points // 使用ROI模型的Points数量而不是Polygon的Points
int pointCount = polygonROI?.Points.Count ?? 0; int pointCount = polygonROI?.Points.Count ?? 0;
// 创建顶点控制 // 创建顶点控制?
for (int i = 0; i < pointCount; i++) for (int i = 0; i < pointCount; i++)
{ {
var thumb = new ControlThumb(); var thumb = new ControlThumb();
@@ -80,7 +80,7 @@ namespace ImageROIControl
private void HandleRightClick(object sender, MouseButtonEventArgs e) private void HandleRightClick(object sender, MouseButtonEventArgs e)
{ {
// 右键删除顶点(至少保留3个顶点) // 右键删除顶点(至少保?个顶点)
if (polygonROI != null && polygonROI.Points.Count > 3) if (polygonROI != null && polygonROI.Points.Count > 3)
{ {
Thumb? hitThumb = sender as Thumb; Thumb? hitThumb = sender as Thumb;
@@ -104,7 +104,7 @@ namespace ImageROIControl
{ {
double thumbSize = 12 * scaleFactor; double thumbSize = 12 * scaleFactor;
// 布局顶点控制 // 布局顶点控制?
for (int i = 0; i < vertexThumbs.Count && i < polygonROI.Points.Count; i++) for (int i = 0; i < vertexThumbs.Count && i < polygonROI.Points.Count; i++)
{ {
vertexThumbs[i].Arrange(new Rect( vertexThumbs[i].Arrange(new Rect(
@@ -6,7 +6,7 @@ using System.Windows;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Shapes; using System.Windows.Shapes;
namespace ImageROIControl namespace XP.ImageProcessing.RoiControl
{ {
/// <summary> /// <summary>
/// 多边形Points附加行为,支持ObservableCollection绑定 /// 多边形Points附加行为,支持ObservableCollection绑定
@@ -58,7 +58,7 @@ namespace ImageROIControl
// 保存引用以便后续清理 // 保存引用以便后续清理
_attachedCollections[polygon] = newCollection; _attachedCollections[polygon] = newCollection;
// 监听Polygon卸载事件以清理资 // 监听Polygon卸载事件以清理资?
polygon.Unloaded += (s, args) => polygon.Unloaded += (s, args) =>
{ {
if (_attachedCollections.TryGetValue(polygon, out var collection)) if (_attachedCollections.TryGetValue(polygon, out var collection))
@@ -1,12 +1,12 @@
using ImageROIControl.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using System.Windows; using System.Windows;
using XP.ImageProcessing.RoiControl.Models;
namespace ImageROIControl namespace XP.ImageProcessing.RoiControl
{ {
/// <summary> /// <summary>
/// ROI序列化工具类 /// ROI序列化工具类
@@ -38,7 +38,7 @@ namespace ImageROIControl
} }
/// <summary> /// <summary>
/// 序列化ROI列表为JSON字符 /// 序列化ROI列表为JSON字符?
/// </summary> /// </summary>
public static string Serialize(IEnumerable<ROIShape> roiList) public static string Serialize(IEnumerable<ROIShape> roiList)
{ {
@@ -55,7 +55,7 @@ namespace ImageROIControl
} }
/// <summary> /// <summary>
/// Point类型的JSON转换 /// Point类型的JSON转换?
/// </summary> /// </summary>
public class PointConverter : JsonConverter<Point> public class PointConverter : JsonConverter<Point>
{ {
@@ -102,7 +102,7 @@ namespace ImageROIControl
} }
/// <summary> /// <summary>
/// ROIShape多态类型的JSON转换 /// ROIShape多态类型的JSON转换?
/// </summary> /// </summary>
public class ROIShapeConverter : JsonConverter<ROIShape> public class ROIShapeConverter : JsonConverter<ROIShape>
{ {
@@ -1,10 +1,10 @@
using ImageROIControl.Models;
using System; using System;
using System.Globalization; using System.Globalization;
using System.Windows; using System.Windows;
using System.Windows.Data; using System.Windows.Data;
using XP.ImageProcessing.RoiControl.Models;
namespace ImageROIControl.Converters namespace XP.ImageProcessing.RoiControl.Converters
{ {
public class ROITypeToVisibilityConverter : IValueConverter public class ROITypeToVisibilityConverter : IValueConverter
{ {
@@ -1,8 +1,7 @@
<ResourceDictionary <ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ImageROIControl.Controls" xmlns:local="clr-namespace:XP.ImageProcessing.RoiControl.Controls">
xmlns:models="clr-namespace:ImageROIControl.Models">
<!-- ControlThumb样式 - 14*14灰色矩形 --> <!-- ControlThumb样式 - 14*14灰色矩形 -->
<Style x:Key="AreaControlThumbStyle" TargetType="{x:Type Thumb}"> <Style x:Key="AreaControlThumbStyle" TargetType="{x:Type Thumb}">
@@ -4,8 +4,10 @@
<TargetFramework>net8.0-windows</TargetFramework> <TargetFramework>net8.0-windows</TargetFramework>
<UseWPF>true</UseWPF> <UseWPF>true</UseWPF>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<RootNamespace>XP.ImageProcessing.RoiControl</RootNamespace>
<AssemblyName>XP.ImageProcessing.RoiControl</AssemblyName>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageId>ImageROIControl</PackageId> <PackageId>XP.ImageProcessing.RoiControl</PackageId>
<Version>1.0.0</Version> <Version>1.0.0</Version>
<Authors>Your Name</Authors> <Authors>Your Name</Authors>
<Company>Your Company</Company> <Company>Your Company</Company>
@@ -1,8 +1,8 @@
using FsCheck;
using FsCheck.Fluent;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using FsCheck;
using FsCheck.Fluent;
using XplorePlane.Models; using XplorePlane.Models;
namespace XplorePlane.Tests.Generators namespace XplorePlane.Tests.Generators
@@ -1,6 +1,6 @@
using System;
using FsCheck; using FsCheck;
using FsCheck.Fluent; using FsCheck.Fluent;
using System;
using XplorePlane.Models; using XplorePlane.Models;
namespace XplorePlane.Tests.Generators namespace XplorePlane.Tests.Generators
+7 -8
View File
@@ -1,24 +1,23 @@
using System.Windows; using Moq;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using ImageProcessing.Core; using XP.ImageProcessing.Core;
using Moq;
using XplorePlane.Services; using XplorePlane.Services;
using System;
namespace XplorePlane.Tests.Helpers namespace XplorePlane.Tests.Helpers
{ {
/// <summary> /// <summary>
/// 测试辅助工具:创建 Mock 和测试用图像 /// 测试辅助工具:创å»?Mock 和测试用图åƒ
/// </summary> /// </summary>
internal static class TestHelpers internal static class TestHelpers
{ {
public static readonly string[] DefaultKeys = { "Blur", "Sharpen", "Threshold" }; public static readonly string[] DefaultKeys = { "Blur", "Sharpen", "Threshold" };
/// <summary> /// <summary>
/// 创建一个 1x1 像素的 BitmapSource,用于测试 /// 创建一ä¸?1x1 åƒç´ çš?BitmapSource,用于测è¯?
/// </summary> /// </summary>
public static BitmapSource CreateTestBitmap(int width = 4, int height = 4) public static BitmapSource CreateTestBitmap(int width = 4, int height = 4)
{ {
@@ -32,13 +31,13 @@ namespace XplorePlane.Tests.Helpers
} }
/// <summary> /// <summary>
/// 创建一个超大图像(用于测试预览缩放) /// 创建一个超大图åƒï¼ˆç”¨äºŽæµ‹è¯•预览缩放ï¼?
/// </summary> /// </summary>
public static BitmapSource CreateLargeBitmap(int width = 4096, int height = 4096) public static BitmapSource CreateLargeBitmap(int width = 4096, int height = 4096)
=> CreateTestBitmap(width, height); => CreateTestBitmap(width, height);
/// <summary> /// <summary>
/// 创建标准 Mock IImageProcessingService,注册 DefaultKeys 中的算子 /// 创建标准 Mock IImageProcessingService,注å†?DefaultKeys 中的算å­
/// </summary> /// </summary>
public static Mock<IImageProcessingService> CreateMockImageService( public static Mock<IImageProcessingService> CreateMockImageService(
string[]? keys = null, string[]? keys = null,
+1 -1
View File
@@ -1,7 +1,7 @@
using System; using System;
using XplorePlane.Models;
using Xunit; using Xunit;
using Xunit.Abstractions; using Xunit.Abstractions;
using XplorePlane.Models;
namespace XplorePlane.Tests.Models namespace XplorePlane.Tests.Models
{ {
@@ -1,7 +1,7 @@
using Xunit;
using XplorePlane.ViewModels;
using XplorePlane.Tests.Helpers;
using System; using System;
using XplorePlane.Tests.Helpers;
using XplorePlane.ViewModels;
using Xunit;
namespace XplorePlane.Tests.Pipeline namespace XplorePlane.Tests.Pipeline
{ {
@@ -1,10 +1,10 @@
using Moq; using Moq;
using Xunit;
using XP.Common.Logging.Interfaces; using XP.Common.Logging.Interfaces;
using XplorePlane.Models; using XplorePlane.Models;
using XplorePlane.Services; using XplorePlane.Services;
using XplorePlane.ViewModels;
using XplorePlane.Tests.Helpers; using XplorePlane.Tests.Helpers;
using XplorePlane.ViewModels;
using Xunit;
namespace XplorePlane.Tests.Pipeline namespace XplorePlane.Tests.Pipeline
{ {
@@ -1,14 +1,14 @@
using Moq; using Moq;
using Xunit; using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using XplorePlane.Services; using XplorePlane.Services;
using XplorePlane.ViewModels;
using XplorePlane.Tests.Helpers; using XplorePlane.Tests.Helpers;
using System.Threading.Tasks; using XplorePlane.ViewModels;
using System; using Xunit;
using System.Linq;
using System.Collections.Generic;
using System.Threading;
namespace XplorePlane.Tests.Pipeline namespace XplorePlane.Tests.Pipeline
{ {
@@ -1,10 +1,10 @@
using Xunit; using System;
using System.IO;
using System.Threading.Tasks;
using XplorePlane.Models; using XplorePlane.Models;
using XplorePlane.Services; using XplorePlane.Services;
using XplorePlane.Tests.Helpers; using XplorePlane.Tests.Helpers;
using System.Threading.Tasks; using Xunit;
using System.IO;
using System;
namespace XplorePlane.Tests.Pipeline namespace XplorePlane.Tests.Pipeline
{ {
@@ -2,18 +2,17 @@ using FsCheck;
using FsCheck.Fluent; using FsCheck.Fluent;
using FsCheck.Xunit; using FsCheck.Xunit;
using Moq; using Moq;
using Xunit;
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using XP.Common.Logging.Interfaces; using XP.Common.Logging.Interfaces;
using XplorePlane.Models; using XplorePlane.Models;
using XplorePlane.Services; using XplorePlane.Services;
using XplorePlane.ViewModels;
using XplorePlane.Tests.Helpers; using XplorePlane.Tests.Helpers;
using XplorePlane.ViewModels;
namespace XplorePlane.Tests.Pipeline namespace XplorePlane.Tests.Pipeline
{ {
@@ -1,12 +1,12 @@
using Moq;
using System; using System;
using System.Windows; using System.Windows;
using Moq;
using XP.Common.Logging.Interfaces; using XP.Common.Logging.Interfaces;
using Xunit;
using Xunit.Abstractions;
using XP.Hardware.RaySource.Services; using XP.Hardware.RaySource.Services;
using XplorePlane.Models; using XplorePlane.Models;
using XplorePlane.Services.AppState; using XplorePlane.Services.AppState;
using Xunit;
using Xunit.Abstractions;
namespace XplorePlane.Tests.Services namespace XplorePlane.Tests.Services
{ {
@@ -1,14 +1,14 @@
using Moq;
using System; using System;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using Moq;
using XP.Common.Logging.Interfaces; using XP.Common.Logging.Interfaces;
using Xunit;
using Xunit.Abstractions;
using XplorePlane.Models; using XplorePlane.Models;
using XplorePlane.Services; using XplorePlane.Services;
using XplorePlane.Services.AppState; using XplorePlane.Services.AppState;
using XplorePlane.Services.Recipe; using XplorePlane.Services.Recipe;
using Xunit;
using Xunit.Abstractions;
namespace XplorePlane.Tests.Services namespace XplorePlane.Tests.Services
{ {
+4 -4
View File
@@ -9,13 +9,13 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XplorePlane.Tests", "Xplore
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XP.Camera", "XP.Camera\XP.Camera.csproj", "{82762CDE-48CC-4E28-ABEC-1FC752BACEF4}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XP.Camera", "XP.Camera\XP.Camera.csproj", "{82762CDE-48CC-4E28-ABEC-1FC752BACEF4}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessing.Core", "ImageProcessing.Core\ImageProcessing.Core.csproj", "{01EDC1D8-F6BC-2677-AE59-89BA3FC2C74F}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XP.ImageProcessing.Core", "XP.ImageProcessing.Core\XP.ImageProcessing.Core.csproj", "{01EDC1D8-F6BC-2677-AE59-89BA3FC2C74F}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessing.Processors", "ImageProcessing.Processors\ImageProcessing.Processors.csproj", "{2687E12E-3053-E1C6-5268-E4FF547EC212}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XP.ImageProcessing.Processors", "XP.ImageProcessing.Processors\XP.ImageProcessing.Processors.csproj", "{2687E12E-3053-E1C6-5268-E4FF547EC212}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessing.Controls", "ImageProcessing.Controls\ImageProcessing.Controls.csproj", "{9460CF45-8A25-9770-03AF-4602A2FFF016}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XP.ImageProcessing.CfgControl", "XP.ImageProcessing.CfgControl\XP.ImageProcessing.CfgControl.csproj", "{9460CF45-8A25-9770-03AF-4602A2FFF016}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageROIControl", "ImageROIControl\ImageROIControl.csproj", "{57061533-EC58-1B1C-3862-9164BC73C806}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XP.ImageProcessing.RoiControl", "XP.ImageProcessing.RoiControl\XP.ImageProcessing.RoiControl.csproj", "{57061533-EC58-1B1C-3862-9164BC73C806}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ExternalLibraries", "ExternalLibraries", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ExternalLibraries", "ExternalLibraries", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
+6 -6
View File
@@ -32,13 +32,13 @@
<add key="Sqlite:EnableSqlLogging" value="false" /> <add key="Sqlite:EnableSqlLogging" value="false" />
<!-- 探测器配置 --> <!-- 探测器配置 -->
<add key="Detector.Type" value="Varex4343"/> <add key="Detector.Type" value="Varex4343" />
<add key="Detector.IPAddress" value="192.168.1.101"/> <add key="Detector.IPAddress" value="192.168.1.101" />
<add key="Detector.Port" value="8080"/> <add key="Detector.Port" value="8080" />
<!-- PLC 配置 --> <!-- PLC 配置 -->
<add key="PLC.Type" value="B&amp;R"/> <add key="PLC.Type" value="B&amp;R" />
<add key="PLC.StationName" value="PLC_STATION"/> <add key="PLC.StationName" value="PLC_STATION" />
<add key="PLC.ConnectionTimeout" value="5000"/> <add key="PLC.ConnectionTimeout" value="5000" />
</appSettings> </appSettings>
</configuration> </configuration>
+1 -2
View File
@@ -1,7 +1,6 @@
<Application x:Class="XplorePlane.App" <Application x:Class="XplorePlane.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
xmlns:local="clr-namespace:XplorePlane">
<Application.Resources> <Application.Resources>
<ResourceDictionary> <ResourceDictionary>
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
+19 -24
View File
@@ -1,40 +1,35 @@
using System; using Prism.DryIoc;
using Prism.Ioc;
using Prism.Modularity;
using Serilog;
using System;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Windows; using System.Windows;
using Telerik.Windows.Controls; using Telerik.Windows.Controls;
using XplorePlane.Views; using XP.Camera;
using XplorePlane.ViewModels; using XP.Common.Database.Implementations;
using XP.Common.Database.Interfaces;
using XP.Common.Dump.Configs;
using XP.Common.Dump.Implementations;
using XP.Common.Dump.Interfaces;
using XP.Common.Localization.Configs;
using XP.Common.Localization.Extensions;
using XP.Common.Localization.Implementations;
using XP.Common.Localization.Interfaces;
using XP.Hardware.RaySource.Services;
using XplorePlane.Services; using XplorePlane.Services;
using XplorePlane.Services.AppState; using XplorePlane.Services.AppState;
using XplorePlane.Services.Camera;
using XplorePlane.Services.Cnc; using XplorePlane.Services.Cnc;
using XplorePlane.Services.Matrix; using XplorePlane.Services.Matrix;
using XplorePlane.Services.Measurement; using XplorePlane.Services.Measurement;
using XplorePlane.Services.Recipe; using XplorePlane.Services.Recipe;
using XplorePlane.Services.Camera; using XplorePlane.ViewModels;
using XplorePlane.ViewModels.Cnc; using XplorePlane.ViewModels.Cnc;
using XplorePlane.Views;
using XplorePlane.Views.Cnc; using XplorePlane.Views.Cnc;
using XP.Camera;
using Prism.Ioc;
using Prism.DryIoc;
using Prism.Modularity;
using Serilog;
using XP.Common.Module;
using XP.Common.Configs;
using XP.Common.Database.Interfaces;
using XP.Common.Database.Implementations;
using XP.Common.Localization.Configs;
using XP.Common.Localization.Implementations;
using XP.Common.Localization.Interfaces;
using XP.Common.Localization.Extensions;
using XP.Common.Dump.Configs;
using XP.Common.Dump.Implementations;
using XP.Common.Dump.Interfaces;
using XP.Hardware.RaySource.Module;
using XP.Hardware.RaySource.Services;
using XP.Hardware.RaySource.Abstractions;
using XP.Hardware.RaySource.Factories;
namespace XplorePlane namespace XplorePlane
{ {
@@ -1,4 +0,0 @@
{
"Language": "zh-CN",
"LogLevel": "Debug"
}
@@ -1,106 +0,0 @@
"\n"
"General configuration for OpenCV 4.9.0 =====================================\n"
" Version control: 4.9.0-265-g79534d600a\n"
"\n"
" Extra modules:\n"
" Location (extra): G:/bb/cv_x64/build/build_x86_64/../opencv_contrib/modules\n"
" Version control (extra): 4.9.0-66-g61e23082\n"
"\n"
" Platform:\n"
" Timestamp: 2024-04-27T12:51:52Z\n"
" Host: Windows 10.0.22000 AMD64\n"
" CMake: 3.23.0\n"
" CMake generator: Visual Studio 17 2022\n"
" CMake build tool: C:/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/amd64/MSBuild.exe\n"
" MSVC: 1939\n"
" Configuration: Debug Release MinSizeRel RelWithDebInfo\n"
"\n"
" CPU/HW features:\n"
" Baseline: SSE SSE2 SSE3\n"
" requested: SSE3\n"
"\n"
" C/C++:\n"
" Built as dynamic libs?: NO\n"
" C++ standard: 11\n"
" C++ Compiler: C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.39.33519/bin/Hostx64/x64/cl.exe (ver 19.39.33523.0)\n"
" C++ flags (Release): /DWIN32 /D_WINDOWS /W4 /GR /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi /fp:precise /EHa /wd4127 /wd4251 /wd4324 /wd4275 /wd4512 /wd4589 /wd4819 /MP /MD /O2 /Ob2 /DNDEBUG \n"
" C++ flags (Debug): /DWIN32 /D_WINDOWS /W4 /GR /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi /fp:precise /EHa /wd4127 /wd4251 /wd4324 /wd4275 /wd4512 /wd4589 /wd4819 /MP /MDd /Zi /Ob0 /Od /RTC1 \n"
" C Compiler: C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.39.33519/bin/Hostx64/x64/cl.exe\n"
" C flags (Release): /DWIN32 /D_WINDOWS /W3 /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi /fp:precise /MP /MD /O2 /Ob2 /DNDEBUG \n"
" C flags (Debug): /DWIN32 /D_WINDOWS /W3 /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi /fp:precise /MP /MDd /Zi /Ob0 /Od /RTC1 \n"
" Linker flags (Release): /machine:x64 /INCREMENTAL:NO \n"
" Linker flags (Debug): /machine:x64 /debug /INCREMENTAL \n"
" ccache: NO\n"
" Precompiled headers: YES\n"
" Extra dependencies: wsock32 comctl32 gdi32 ole32 setupapi ws2_32 G:/bb/cv_x64/build/build_x86_64/install/lib/freetype.lib G:/bb/cv_x64/build/build_x86_64/install/lib/harfbuzz.lib G:/bb/cv_x64/build/build_x86_64/install/lib/libhdf5.lib\n"
" 3rdparty dependencies: libprotobuf ade ittnotify libjpeg-turbo libwebp libpng libtiff libopenjp2 IlmImf zlib\n"
"\n"
" OpenCV modules:\n"
" To be built: alphamat aruco bgsegm bioinspired calib3d ccalib core datasets dnn dnn_objdetect dnn_superres dpm face features2d flann freetype fuzzy gapi hdf hfs highgui img_hash imgcodecs imgproc intensity_transform line_descriptor mcc ml objdetect optflow phase_unwrapping photo plot quality rapid reg rgbd saliency shape stereo stitching structured_light superres surface_matching text tracking ts video videoio videostab wechat_qrcode xfeatures2d ximgproc xobjdetect xphoto\n"
" Disabled: java python_bindings_generator python_tests world\n"
" Disabled by dependency: -\n"
" Unavailable: cannops cudaarithm cudabgsegm cudacodec cudafeatures2d cudafilters cudaimgproc cudalegacy cudaobjdetect cudaoptflow cudastereo cudawarping cudev cvv julia matlab ovis python2 python3 sfm viz\n"
" Applications: perf_tests\n"
" Documentation: NO\n"
" Non-free algorithms: NO\n"
"\n"
" Windows RT support: NO\n"
"\n"
" GUI: WIN32UI\n"
" Win32 UI: YES\n"
" VTK support: NO\n"
"\n"
" Media I/O: \n"
" ZLib: build (ver 1.3)\n"
" JPEG: build-libjpeg-turbo (ver 2.1.3-62)\n"
" SIMD Support Request: YES\n"
" SIMD Support: NO\n"
" WEBP: build (ver encoder: 0x020f)\n"
" PNG: build (ver 1.6.37)\n"
" TIFF: build (ver 42 - 4.2.0)\n"
" JPEG 2000: build (ver 2.5.0)\n"
" OpenEXR: build (ver 2.3.0)\n"
" HDR: YES\n"
" SUNRASTER: YES\n"
" PXM: YES\n"
" PFM: YES\n"
"\n"
" Video I/O:\n"
" DC1394: NO\n"
" FFMPEG: YES (prebuilt binaries)\n"
" avcodec: YES (58.134.100)\n"
" avformat: YES (58.76.100)\n"
" avutil: YES (56.70.100)\n"
" swscale: YES (5.9.100)\n"
" avresample: YES (4.0.0)\n"
" GStreamer: NO\n"
" DirectShow: YES\n"
" Media Foundation: YES\n"
" DXVA: YES\n"
"\n"
" Parallel framework: Concurrency\n"
"\n"
" Trace: YES (with Intel ITT)\n"
"\n"
" Other third-party libraries:\n"
" Eigen: YES (ver 3.4.0)\n"
" Custom HAL: NO\n"
" Protobuf: build (3.19.1)\n"
" Flatbuffers: builtin/3rdparty (23.5.9)\n"
"\n"
" OpenCL: YES (NVD3D11)\n"
" Include path: G:/bb/cv_x64/build/opencv/3rdparty/include/opencl/1.2\n"
" Link libraries: Dynamic load\n"
"\n"
" Python (for build): C:/python-virt/python37/python.exe\n"
"\n"
" Java: \n"
" ant: NO\n"
" Java: YES (ver 1.8.0.202)\n"
" JNI: C:/Program Files/Microsoft/jdk-11.0.16.101-hotspot/include C:/Program Files/Microsoft/jdk-11.0.16.101-hotspot/include/win32 C:/Program Files/Microsoft/jdk-11.0.16.101-hotspot/include\n"
" Java wrappers: NO\n"
" Java tests: NO\n"
"\n"
" Install to: G:/bb/cv_x64/build/build_x86_64/install\n"
"-----------------------------------------------------------------\n"
"\n"

Some files were not shown because too many files have changed in this diff Show More