Files
XplorePlane/XP.ImageProcessing.Processors/图像变换/ThresholdProcessor.cs
T

109 lines
3.6 KiB
C#

// ============================================================================
// 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 XP.ImageProcessing.Core;
using Serilog;
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)
{
CvInvoke.Threshold(inputImage, result, minThreshold, 255, ThresholdType.Otsu);
_logger.Debug("Process: UseOtsu = true");
}
else
{
int height = inputImage.Height;
int width = inputImage.Width;
unsafe
{
byte* srcPtr = (byte*)inputImage.Mat.DataPointer;
byte* dstPtr = (byte*)result.Mat.DataPointer;
int srcStep = inputImage.Mat.Step;
int dstStep = result.Mat.Step;
for (int y = 0; y < height; y++)
{
byte* srcRow = srcPtr + y * srcStep;
byte* dstRow = dstPtr + y * dstStep;
for (int x = 0; x < width; x++)
{
byte val = srcRow[x];
dstRow[x] = (val >= minThreshold && val <= maxThreshold) ? (byte)255 : (byte)0;
}
}
}
_logger.Debug("Process: MinThreshold = {MinThreshold}, MaxThreshold = {MaxThreshold}",
minThreshold, maxThreshold);
}
return result;
}
}