规范类名及命名空间名称

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
@@ -0,0 +1,80 @@
// ============================================================================
// Copyright 穢 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// ? GrayscaleProcessor.cs
// 讛膩: 啣漲曇蓮摮琜脣㦛讛蓮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>
/// 啣漲曇蓮摮?
/// </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;
}
}