Files
XplorePlane/XP.ImageProcessing.Processors/检测分析/LineMeasurementProcessor.cs
T
2026-04-13 14:36:18 +08:00

149 lines
5.8 KiB
C#

// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// 文件å? LineMeasurementProcessor.cs
// æè¿°: 直线测é‡ç®—å­ï¼Œç”¨äºŽæµ‹é‡å›¾åƒä¸­ä¸¤ç‚¹ä¹‹é—´çš„è·ç¦?
// 功能:
// - ç”¨æˆ·æŒ‡å®šä¸¤ä¸ªç‚¹åæ ‡ï¼ˆåƒç´ åæ ‡ï¼?
// - 计算两点之间的欧æ°è·ç¦»ï¼ˆåƒç´ å•ä½ï¼?
// - 支æŒåƒç´ å°ºå¯¸æ ‡å®šï¼Œè¾“出实际物ç†è·ç¦?
// - 在图åƒä¸Šç»˜åˆ¶æµ‹é‡çº¿å’Œæ ‡æ³¨
// - 输出测é‡ç»“果供åŽç»­å¤„ç†ä½¿ç”?
// 算法: 欧æ°è·ç¦»è®¡ç®—
// 作è€? æŽä¼Ÿ wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.Structure;
using Serilog;
using System.Drawing;
using XP.ImageProcessing.Core;
namespace XP.ImageProcessing.Processors;
/// <summary>
/// 直线测é‡ç®—å­ - 测é‡ä¸¤ç‚¹ä¹‹é—´çš„è·ç¦?
/// </summary>
public class LineMeasurementProcessor : ImageProcessorBase
{
private static readonly ILogger _logger = Log.ForContext<LineMeasurementProcessor>();
public LineMeasurementProcessor()
{
Name = LocalizationHelper.GetString("LineMeasurementProcessor_Name");
Description = LocalizationHelper.GetString("LineMeasurementProcessor_Description");
}
protected override void InitializeParameters()
{
Parameters.Add("X1", new ProcessorParameter(
"X1",
LocalizationHelper.GetString("LineMeasurementProcessor_X1"),
typeof(int), 100, null, null,
LocalizationHelper.GetString("LineMeasurementProcessor_X1_Desc"))
{ IsVisible = false });
Parameters.Add("Y1", new ProcessorParameter(
"Y1",
LocalizationHelper.GetString("LineMeasurementProcessor_Y1"),
typeof(int), 100, null, null,
LocalizationHelper.GetString("LineMeasurementProcessor_Y1_Desc"))
{ IsVisible = false });
Parameters.Add("X2", new ProcessorParameter(
"X2",
LocalizationHelper.GetString("LineMeasurementProcessor_X2"),
typeof(int), 400, null, null,
LocalizationHelper.GetString("LineMeasurementProcessor_X2_Desc"))
{ IsVisible = false });
Parameters.Add("Y2", new ProcessorParameter(
"Y2",
LocalizationHelper.GetString("LineMeasurementProcessor_Y2"),
typeof(int), 400, null, null,
LocalizationHelper.GetString("LineMeasurementProcessor_Y2_Desc"))
{ IsVisible = false });
Parameters.Add("PixelSize", new ProcessorParameter(
"PixelSize",
LocalizationHelper.GetString("LineMeasurementProcessor_PixelSize"),
typeof(double), 1.0, null, null,
LocalizationHelper.GetString("LineMeasurementProcessor_PixelSize_Desc")));
Parameters.Add("Unit", new ProcessorParameter(
"Unit",
LocalizationHelper.GetString("LineMeasurementProcessor_Unit"),
typeof(string), "px", null, null,
LocalizationHelper.GetString("LineMeasurementProcessor_Unit_Desc"),
new string[] { "px", "mm", "μm", "cm" }));
Parameters.Add("Thickness", new ProcessorParameter(
"Thickness",
LocalizationHelper.GetString("LineMeasurementProcessor_Thickness"),
typeof(int), 2, 1, 10,
LocalizationHelper.GetString("LineMeasurementProcessor_Thickness_Desc")));
Parameters.Add("ShowLabel", new ProcessorParameter(
"ShowLabel",
LocalizationHelper.GetString("LineMeasurementProcessor_ShowLabel"),
typeof(bool), true, null, null,
LocalizationHelper.GetString("LineMeasurementProcessor_ShowLabel_Desc")));
}
public override Image<Gray, byte> Process(Image<Gray, byte> inputImage)
{
int x1 = GetParameter<int>("X1");
int y1 = GetParameter<int>("Y1");
int x2 = GetParameter<int>("X2");
int y2 = GetParameter<int>("Y2");
double pixelSize = GetParameter<double>("PixelSize");
string unit = GetParameter<string>("Unit");
int thickness = GetParameter<int>("Thickness");
bool showLabel = GetParameter<bool>("ShowLabel");
_logger.Debug("LineMeasurement: ({X1},{Y1}) -> ({X2},{Y2}), PixelSize={PixelSize}, Unit={Unit}",
x1, y1, x2, y2, pixelSize, unit);
OutputData.Clear();
// é™åˆ¶å标在图åƒèŒƒå›´å†…
x1 = Math.Clamp(x1, 0, inputImage.Width - 1);
y1 = Math.Clamp(y1, 0, inputImage.Height - 1);
x2 = Math.Clamp(x2, 0, inputImage.Width - 1);
y2 = Math.Clamp(y2, 0, inputImage.Height - 1);
// 计算åƒç´ è·ç¦»
double dx = x2 - x1;
double dy = y2 - y1;
double pixelDistance = Math.Sqrt(dx * dx + dy * dy);
// 计算实际è·ç¦»
double actualDistance = pixelDistance * pixelSize;
// 计算角度(相对于水平方å‘ï¼?
double angleRad = Math.Atan2(dy, dx);
double angleDeg = angleRad * 180.0 / Math.PI;
// 存储测é‡ç»“æžœ
OutputData["MeasurementType"] = "Line";
OutputData["Point1"] = new Point(x1, y1);
OutputData["Point2"] = new Point(x2, y2);
OutputData["PixelDistance"] = pixelDistance;
OutputData["ActualDistance"] = actualDistance;
OutputData["Unit"] = unit;
OutputData["Angle"] = angleDeg;
OutputData["Thickness"] = thickness;
OutputData["ShowLabel"] = showLabel;
// 构建测é‡ä¿¡æ¯æ–‡æœ¬
string distanceText = unit == "px"
? $"{pixelDistance:F2} px"
: $"{actualDistance:F4} {unit} ({pixelDistance:F2} px)";
OutputData["MeasurementText"] = distanceText;
_logger.Information("LineMeasurement completed: Distance={Distance}, Angle={Angle:F2}°",
distanceText, angleDeg);
return inputImage.Clone();
}
}