规范类名及命名空间名称
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
// ============================================================================
|
||||
// Copyright 穢 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// ��辣�? GrayscaleProcessor.cs
|
||||
// �讛膩: �啣漲�曇蓮�Y�摮琜��其�撠�蔗�脣㦛�讛蓮�V蛹�啣漲�曉�
|
||||
// �蠘�:
|
||||
// - ����啣漲頧祆揢嚗����像���
|
||||
// - 撟喳��潭�
|
||||
// - ��憭批�潭�
|
||||
// - ��撠誩�潭�
|
||||
// 蝞埈�: �䭾�撟喳�瘜?Gray = 0.299*R + 0.587*G + 0.114*B
|
||||
// 雿𡏭�? �𦒘� wei.lw.li@hexagon.com
|
||||
// ============================================================================
|
||||
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.Structure;
|
||||
using Serilog;
|
||||
using XP.ImageProcessing.Core;
|
||||
|
||||
namespace XP.ImageProcessing.Processors;
|
||||
|
||||
/// <summary>
|
||||
/// �啣漲�曇蓮�Y�摮?
|
||||
/// </summary>
|
||||
public class GrayscaleProcessor : ImageProcessorBase
|
||||
{
|
||||
private static readonly ILogger _logger = Log.ForContext<GrayscaleProcessor>();
|
||||
|
||||
public GrayscaleProcessor()
|
||||
{
|
||||
Name = LocalizationHelper.GetString("GrayscaleProcessor_Name");
|
||||
Description = LocalizationHelper.GetString("GrayscaleProcessor_Description");
|
||||
}
|
||||
|
||||
protected override void InitializeParameters()
|
||||
{
|
||||
Parameters.Add("Method", new ProcessorParameter(
|
||||
"Method",
|
||||
LocalizationHelper.GetString("GrayscaleProcessor_Method"),
|
||||
typeof(string),
|
||||
"Weighted",
|
||||
null,
|
||||
null,
|
||||
LocalizationHelper.GetString("GrayscaleProcessor_Method_Desc"),
|
||||
new string[] { "Weighted", "Average", "Max", "Min" }));
|
||||
_logger.Debug("InitializeParameters");
|
||||
}
|
||||
|
||||
public override Image<Gray, byte> Process(Image<Gray, byte> inputImage)
|
||||
{
|
||||
string method = GetParameter<string>("Method");
|
||||
|
||||
// 憒��颲枏�撌脩��舐�摨血㦛嚗峕覔�格䲮瘜閗�銵���?
|
||||
var result = inputImage.Clone();
|
||||
|
||||
switch (method)
|
||||
{
|
||||
case "Average":
|
||||
// 撖嫣�撌脩��舐�摨衣��曉�嚗�像���潭�銝齿㺿�睃㦛�?
|
||||
break;
|
||||
|
||||
case "Max":
|
||||
// 憓𧼮撩鈭桀漲
|
||||
result = result * 1.2;
|
||||
break;
|
||||
|
||||
case "Min":
|
||||
// �滢�鈭桀漲
|
||||
result = result * 0.8;
|
||||
break;
|
||||
|
||||
case "Weighted":
|
||||
default:
|
||||
// 靽脲���甅
|
||||
break;
|
||||
}
|
||||
|
||||
_logger.Debug("Process: Method = {Method}", method);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� MirrorProcessor.cs
|
||||
// æ��è¿°: 镜åƒ�ç®—å�,用于图åƒ�ç¿»è½?
|
||||
// 功能:
|
||||
// - 水平镜�(左�翻转)
|
||||
// - 垂直镜�(上下翻转)
|
||||
// - 对角镜åƒ�(水å¹?åž‚ç›´ç¿»è½¬ï¼Œç‰æ•?80°旋转ï¼?
|
||||
// 算法: åƒ�ç´ å��æ ‡æ˜ å°„
|
||||
// 作� �伟 wei.lw.li@hexagon.com
|
||||
// ============================================================================
|
||||
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.CvEnum;
|
||||
using Emgu.CV.Structure;
|
||||
using Serilog;
|
||||
using XP.ImageProcessing.Core;
|
||||
|
||||
namespace XP.ImageProcessing.Processors;
|
||||
|
||||
/// <summary>
|
||||
/// 镜åƒ�ç®—å�
|
||||
/// </summary>
|
||||
public class MirrorProcessor : ImageProcessorBase
|
||||
{
|
||||
private static readonly ILogger _logger = Log.ForContext<MirrorProcessor>();
|
||||
|
||||
public MirrorProcessor()
|
||||
{
|
||||
Name = LocalizationHelper.GetString("MirrorProcessor_Name");
|
||||
Description = LocalizationHelper.GetString("MirrorProcessor_Description");
|
||||
}
|
||||
|
||||
protected override void InitializeParameters()
|
||||
{
|
||||
Parameters.Add("Direction", new ProcessorParameter(
|
||||
"Direction",
|
||||
LocalizationHelper.GetString("MirrorProcessor_Direction"),
|
||||
typeof(string),
|
||||
"Horizontal",
|
||||
null,
|
||||
null,
|
||||
LocalizationHelper.GetString("MirrorProcessor_Direction_Desc"),
|
||||
new string[] { "Horizontal", "Vertical", "Both" }));
|
||||
|
||||
_logger.Debug("InitializeParameters");
|
||||
}
|
||||
|
||||
public override Image<Gray, byte> Process(Image<Gray, byte> inputImage)
|
||||
{
|
||||
string direction = GetParameter<string>("Direction");
|
||||
|
||||
var result = inputImage.Clone();
|
||||
|
||||
FlipType flipType = direction switch
|
||||
{
|
||||
"Vertical" => FlipType.Vertical,
|
||||
"Both" => FlipType.Both,
|
||||
_ => FlipType.Horizontal
|
||||
};
|
||||
|
||||
CvInvoke.Flip(inputImage, result, flipType);
|
||||
|
||||
_logger.Debug("Process: Direction = {Direction}", direction);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� RotateProcessor.cs
|
||||
// æ��è¿°: 图åƒ�旋转算å�
|
||||
// 功能:
|
||||
// - 任�角度旋转
|
||||
// - 支���原始尺寸或自适应扩展画布
|
||||
// - �选背景填充�
|
||||
// - 支��线性��
|
||||
// 算法: 仿射��旋转
|
||||
// 作� �伟 wei.lw.li@hexagon.com
|
||||
// ============================================================================
|
||||
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.CvEnum;
|
||||
using Emgu.CV.Structure;
|
||||
using Serilog;
|
||||
using System.Drawing;
|
||||
using XP.ImageProcessing.Core;
|
||||
|
||||
namespace XP.ImageProcessing.Processors;
|
||||
|
||||
/// <summary>
|
||||
/// 图åƒ�旋转算å�
|
||||
/// </summary>
|
||||
public class RotateProcessor : ImageProcessorBase
|
||||
{
|
||||
private static readonly ILogger _logger = Log.ForContext<RotateProcessor>();
|
||||
|
||||
public RotateProcessor()
|
||||
{
|
||||
Name = LocalizationHelper.GetString("RotateProcessor_Name");
|
||||
Description = LocalizationHelper.GetString("RotateProcessor_Description");
|
||||
}
|
||||
|
||||
protected override void InitializeParameters()
|
||||
{
|
||||
Parameters.Add("Angle", new ProcessorParameter(
|
||||
"Angle",
|
||||
LocalizationHelper.GetString("RotateProcessor_Angle"),
|
||||
typeof(double),
|
||||
90.0,
|
||||
-360.0,
|
||||
360.0,
|
||||
LocalizationHelper.GetString("RotateProcessor_Angle_Desc")));
|
||||
|
||||
Parameters.Add("ExpandCanvas", new ProcessorParameter(
|
||||
"ExpandCanvas",
|
||||
LocalizationHelper.GetString("RotateProcessor_ExpandCanvas"),
|
||||
typeof(bool),
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
LocalizationHelper.GetString("RotateProcessor_ExpandCanvas_Desc")));
|
||||
|
||||
Parameters.Add("BackgroundValue", new ProcessorParameter(
|
||||
"BackgroundValue",
|
||||
LocalizationHelper.GetString("RotateProcessor_BackgroundValue"),
|
||||
typeof(int),
|
||||
0,
|
||||
0,
|
||||
255,
|
||||
LocalizationHelper.GetString("RotateProcessor_BackgroundValue_Desc")));
|
||||
|
||||
Parameters.Add("Interpolation", new ProcessorParameter(
|
||||
"Interpolation",
|
||||
LocalizationHelper.GetString("RotateProcessor_Interpolation"),
|
||||
typeof(string),
|
||||
"Bilinear",
|
||||
null,
|
||||
null,
|
||||
LocalizationHelper.GetString("RotateProcessor_Interpolation_Desc"),
|
||||
new string[] { "Nearest", "Bilinear", "Bicubic" }));
|
||||
|
||||
_logger.Debug("InitializeParameters");
|
||||
}
|
||||
|
||||
public override Image<Gray, byte> Process(Image<Gray, byte> inputImage)
|
||||
{
|
||||
double angle = GetParameter<double>("Angle");
|
||||
bool expandCanvas = GetParameter<bool>("ExpandCanvas");
|
||||
int bgValue = GetParameter<int>("BackgroundValue");
|
||||
string interpolation = GetParameter<string>("Interpolation");
|
||||
|
||||
Inter interMethod = interpolation switch
|
||||
{
|
||||
"Nearest" => Inter.Nearest,
|
||||
"Bicubic" => Inter.Cubic,
|
||||
_ => Inter.Linear
|
||||
};
|
||||
|
||||
int srcW = inputImage.Width;
|
||||
int srcH = inputImage.Height;
|
||||
PointF center = new PointF(srcW / 2.0f, srcH / 2.0f);
|
||||
|
||||
// 获�旋转矩阵
|
||||
using var rotMat = new Mat();
|
||||
CvInvoke.GetRotationMatrix2D(center, angle, 1.0, rotMat);
|
||||
|
||||
int dstW, dstH;
|
||||
|
||||
if (expandCanvas)
|
||||
{
|
||||
// 计算旋转�能容纳整幅图�的画布尺�
|
||||
double rad = Math.Abs(angle * Math.PI / 180.0);
|
||||
double sinA = Math.Abs(Math.Sin(rad));
|
||||
double cosA = Math.Abs(Math.Cos(rad));
|
||||
dstW = (int)Math.Ceiling(srcW * cosA + srcH * sinA);
|
||||
dstH = (int)Math.Ceiling(srcW * sinA + srcH * cosA);
|
||||
|
||||
// 调整旋转矩阵的平移分�,使图�居�
|
||||
double[] m = new double[6];
|
||||
rotMat.CopyTo(m);
|
||||
m[2] += (dstW - srcW) / 2.0;
|
||||
m[5] += (dstH - srcH) / 2.0;
|
||||
|
||||
// 写回矩阵
|
||||
using var adjusted = new Mat(2, 3, Emgu.CV.CvEnum.DepthType.Cv64F, 1);
|
||||
System.Runtime.InteropServices.Marshal.Copy(m, 0, adjusted.DataPointer, 6);
|
||||
|
||||
var result = new Image<Gray, byte>(dstW, dstH, new Gray(bgValue));
|
||||
CvInvoke.WarpAffine(inputImage, result, adjusted, new Size(dstW, dstH),
|
||||
interMethod, Warp.Default, BorderType.Constant, new MCvScalar(bgValue));
|
||||
|
||||
_logger.Debug("Process: Angle={Angle}, ExpandCanvas=true, Size={W}x{H}", angle, dstW, dstH);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
dstW = srcW;
|
||||
dstH = srcH;
|
||||
var result = new Image<Gray, byte>(dstW, dstH, new Gray(bgValue));
|
||||
CvInvoke.WarpAffine(inputImage, result, rotMat, new Size(dstW, dstH),
|
||||
interMethod, Warp.Default, BorderType.Constant, new MCvScalar(bgValue));
|
||||
|
||||
_logger.Debug("Process: Angle={Angle}, ExpandCanvas=false", angle);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
// ============================================================================
|
||||
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
|
||||
// 文件� ThresholdProcessor.cs
|
||||
// æ��è¿°: 阈值分割算å�,用于图åƒ�二值化处ç�†
|
||||
// 功能:
|
||||
// - 固定阈值二值化
|
||||
// - Otsu自动阈值计�
|
||||
// - �调节阈值和最大�
|
||||
// - 将�度图�转�为二值图�
|
||||
// 算法: 阈值分割�Otsu算法
|
||||
// 作� �伟 wei.lw.li@hexagon.com
|
||||
// ============================================================================
|
||||
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.CvEnum;
|
||||
using Emgu.CV.Structure;
|
||||
using Serilog;
|
||||
using XP.ImageProcessing.Core;
|
||||
|
||||
namespace XP.ImageProcessing.Processors;
|
||||
|
||||
/// <summary>
|
||||
/// 阈值分割算å?
|
||||
/// </summary>
|
||||
public class ThresholdProcessor : ImageProcessorBase
|
||||
{
|
||||
private static readonly ILogger _logger = Log.ForContext<ThresholdProcessor>();
|
||||
|
||||
public ThresholdProcessor()
|
||||
{
|
||||
Name = LocalizationHelper.GetString("ThresholdProcessor_Name");
|
||||
Description = LocalizationHelper.GetString("ThresholdProcessor_Description");
|
||||
}
|
||||
|
||||
protected override void InitializeParameters()
|
||||
{
|
||||
Parameters.Add("MinThreshold", new ProcessorParameter(
|
||||
"MinThreshold",
|
||||
LocalizationHelper.GetString("ThresholdProcessor_MinThreshold"),
|
||||
typeof(int),
|
||||
64,
|
||||
0,
|
||||
255,
|
||||
LocalizationHelper.GetString("ThresholdProcessor_MinThreshold_Desc")));
|
||||
|
||||
Parameters.Add("MaxThreshold", new ProcessorParameter(
|
||||
"MaxThreshold",
|
||||
LocalizationHelper.GetString("ThresholdProcessor_MaxThreshold"),
|
||||
typeof(int),
|
||||
192,
|
||||
0,
|
||||
255,
|
||||
LocalizationHelper.GetString("ThresholdProcessor_MaxThreshold_Desc")));
|
||||
|
||||
Parameters.Add("UseOtsu", new ProcessorParameter(
|
||||
"UseOtsu",
|
||||
LocalizationHelper.GetString("ThresholdProcessor_UseOtsu"),
|
||||
typeof(bool),
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
LocalizationHelper.GetString("ThresholdProcessor_UseOtsu_Desc")));
|
||||
_logger.Debug("InitializeParameters");
|
||||
}
|
||||
|
||||
public override Image<Gray, byte> Process(Image<Gray, byte> inputImage)
|
||||
{
|
||||
int minThreshold = GetParameter<int>("MinThreshold");
|
||||
int maxThreshold = GetParameter<int>("MaxThreshold");
|
||||
bool useOtsu = GetParameter<bool>("UseOtsu");
|
||||
|
||||
var result = new Image<Gray, byte>(inputImage.Size);
|
||||
|
||||
if (useOtsu)
|
||||
{
|
||||
// 使用Otsu算法
|
||||
CvInvoke.Threshold(inputImage, result, minThreshold, 255, ThresholdType.Otsu);
|
||||
_logger.Debug("Process: UseOtsu = true");
|
||||
}
|
||||
else
|
||||
{
|
||||
// �阈值分割:介于MinThreshold和MaxThreshold之间的为�景(255),其他为背景(0)
|
||||
byte[,,] inputData = inputImage.Data;
|
||||
byte[,,] outputData = result.Data;
|
||||
|
||||
int height = inputImage.Height;
|
||||
int width = inputImage.Width;
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
byte pixelValue = inputData[y, x, 0];
|
||||
outputData[y, x, 0] = (pixelValue >= minThreshold && pixelValue <= maxThreshold)
|
||||
? (byte)255
|
||||
: (byte)0;
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Debug("Process: MinThreshold = {MinThreshold}, MaxThreshold = {MaxThreshold}",
|
||||
minThreshold, maxThreshold);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user