Files
OrpaonVision/OrpaonVision.Core/PlacementJudgment/IPlacementJudgmentService.cs
2026-04-06 22:04:05 +08:00

964 lines
25 KiB
C#

using OrpaonVision.Core.LayerRecognition;
using OrpaonVision.Core.PartRecognition;
using OrpaonVision.Core.PositionValidation;
using OrpaonVision.Core.Results;
namespace OrpaonVision.Core.PlacementJudgment;
/// <summary>
/// 到位判定服务接口。
/// </summary>
public interface IPlacementJudgmentService
{
/// <summary>
/// 判定部件到位状态。
/// </summary>
/// <param name="parts">部件列表。</param>
/// <param name="judgmentRules">判定规则列表。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>到位判定结果。</returns>
Task<Result<PlacementJudgmentResult>> JudgePlacementAsync(IReadOnlyList<MappedPart> parts, IReadOnlyList<PlacementJudgmentRule> judgmentRules, CancellationToken cancellationToken = default);
/// <summary>
/// 判定面积到位状态。
/// </summary>
/// <param name="parts">部件列表。</param>
/// <param name="expectedAreas">期望面积列表。</param>
/// <param name="tolerance">面积容差(百分比)。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>面积判定结果。</returns>
Task<Result<AreaJudgmentResult>> JudgeAreaAsync(IReadOnlyList<MappedPart> parts, IReadOnlyList<ExpectedArea> expectedAreas, double tolerance, CancellationToken cancellationToken = default);
/// <summary>
/// 判定位置偏差到位状态。
/// </summary>
/// <param name="parts">部件列表。</param>
/// <param name="expectedPositions">期望位置列表。</param>
/// <param name="tolerance">位置容差。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>位置偏差判定结果。</returns>
Task<Result<PositionDeviationJudgmentResult>> JudgePositionDeviationAsync(IReadOnlyList<MappedPart> parts, IReadOnlyList<ExpectedPosition> expectedPositions, double tolerance, CancellationToken cancellationToken = default);
/// <summary>
/// 判定稳定帧到位状态。
/// </summary>
/// <param name="frameHistory">帧历史记录。</param>
/// <param name="stabilityRules">稳定性规则列表。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>稳定帧判定结果。</returns>
Task<Result<StabilityJudgmentResult>> JudgeStabilityAsync(IReadOnlyList<InferenceResultDto> frameHistory, IReadOnlyList<StabilityRule> stabilityRules, CancellationToken cancellationToken = default);
/// <summary>
/// 复合到位判定。
/// </summary>
/// <param name="parts">部件列表。</param>
/// <param name="frameHistory">帧历史记录。</param>
/// <param name="compositeRules">复合判定规则列表。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>复合判定结果。</returns>
Task<Result<CompositeJudgmentResult>> JudgeCompositeAsync(IReadOnlyList<MappedPart> parts, IReadOnlyList<InferenceResultDto> frameHistory, IReadOnlyList<CompositeJudgmentRule> compositeRules, CancellationToken cancellationToken = default);
/// <summary>
/// 批量到位判定。
/// </summary>
/// <param name="parts">部件列表。</param>
/// <param name="frameHistory">帧历史记录。</param>
/// <param name="judgmentRules">判定规则列表。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>批量判定结果。</returns>
Task<Result<BatchJudgmentResult>> BatchJudgeAsync(IReadOnlyList<MappedPart> parts, IReadOnlyList<InferenceResultDto> frameHistory, IReadOnlyList<PlacementJudgmentRule> judgmentRules, CancellationToken cancellationToken = default);
/// <summary>
/// 获取到位判定统计信息。
/// </summary>
/// <param name="startTime">开始时间。</param>
/// <param name="endTime">结束时间。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>统计信息。</returns>
Task<Result<PlacementJudgmentStatistics>> GetJudgmentStatisticsAsync(DateTime startTime, DateTime endTime, CancellationToken cancellationToken = default);
/// <summary>
/// 创建到位判定规则。
/// </summary>
/// <param name="rule">判定规则。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>创建结果。</returns>
Task<Result<PlacementJudgmentRule>> CreateJudgmentRuleAsync(PlacementJudgmentRule rule, CancellationToken cancellationToken = default);
/// <summary>
/// 更新到位判定规则。
/// </summary>
/// <param name="rule">判定规则。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>更新结果。</returns>
Task<Result> UpdateJudgmentRuleAsync(PlacementJudgmentRule rule, CancellationToken cancellationToken = default);
/// <summary>
/// 删除到位判定规则。
/// </summary>
/// <param name="ruleId">规则ID。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>删除结果。</returns>
Task<Result> DeleteJudgmentRuleAsync(Guid ruleId, CancellationToken cancellationToken = default);
/// <summary>
/// 获取到位判定规则列表。
/// </summary>
/// <param name="productTypeCode">产品类型编码(可选)。</param>
/// <param name="layerNumber">层级编号(可选)。</param>
/// <param name="judgmentType">判定类型(可选)。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>规则列表。</returns>
Task<Result<IReadOnlyList<PlacementJudgmentRule>>> GetJudgmentRulesAsync(string? productTypeCode = null, int? layerNumber = null, PlacementJudgmentType? judgmentType = null, CancellationToken cancellationToken = default);
}
/// <summary>
/// 到位判定结果。
/// </summary>
public sealed class PlacementJudgmentResult
{
/// <summary>
/// 是否通过判定。
/// </summary>
public bool IsPlaced { get; init; }
/// <summary>
/// 总体置信度。
/// </summary>
public double OverallConfidence { get; init; }
/// <summary>
/// 判定时间。
/// </summary>
public DateTime JudgmentTimeUtc { get; init; }
/// <summary>
/// 部件判定结果列表。
/// </summary>
public IReadOnlyList<PartJudgmentResult> PartJudgmentResults { get; init; } = Array.Empty<PartJudgmentResult>();
/// <summary>
/// 未到位部件列表。
/// </summary>
public IReadOnlyList<MappedPart> UnplacedParts { get; init; } = Array.Empty<MappedPart>();
/// <summary>
/// 判定详情。
/// </summary>
public string? Details { get; init; }
/// <summary>
/// 扩展属性。
/// </summary>
public Dictionary<string, object> ExtendedProperties { get; init; } = new();
}
/// <summary>
/// 部件判定结果。
/// </summary>
public sealed class PartJudgmentResult
{
/// <summary>
/// 部件信息。
/// </summary>
public MappedPart Part { get; init; } = new();
/// <summary>
/// 是否到位。
/// </summary>
public bool IsPlaced { get; init; }
/// <summary>
/// 到位置信度。
/// </summary>
public double PlacementConfidence { get; init; }
/// <summary>
/// 面积判定结果。
/// </summary>
public AreaJudgmentResult? AreaResult { get; init; }
/// <summary>
/// 位置偏差判定结果。
/// </summary>
public PositionDeviationJudgmentResult? PositionResult { get; init; }
/// <summary>
/// 稳定性判定结果。
/// </summary>
public StabilityJudgmentResult? StabilityResult { get; init; }
/// <summary>
/// 判定质量。
/// </summary>
public JudgmentQuality JudgmentQuality { get; init; }
/// <summary>
/// 判定详情。
/// </summary>
public string? Details { get; init; }
/// <summary>
/// 扩展属性。
/// </summary>
public Dictionary<string, object> ExtendedProperties { get; init; } = new();
}
/// <summary>
/// 面积判定结果。
/// </summary>
public sealed class AreaJudgmentResult
{
/// <summary>
/// 是否通过面积判定。
/// </summary>
public bool IsAreaValid { get; init; }
/// <summary>
/// 实际面积。
/// </summary>
public double ActualArea { get; init; }
/// <summary>
/// 期望面积。
/// </summary>
public double ExpectedArea { get; init; }
/// <summary>
/// 面积偏差(百分比)。
/// </summary>
public double AreaDeviation { get; init; }
/// <summary>
/// 允许的面积容差。
/// </summary>
public double AllowedTolerance { get; init; }
/// <summary>
/// 面积判定时间。
/// </summary>
public DateTime JudgmentTimeUtc { get; init; }
/// <summary>
/// 判定详情。
/// </summary>
public string? Details { get; init; }
/// <summary>
/// 扩展属性。
/// </summary>
public Dictionary<string, object> ExtendedProperties { get; init; } = new();
}
/// <summary>
/// 位置偏差判定结果。
/// </summary>
public sealed class PositionDeviationJudgmentResult
{
/// <summary>
/// 是否通过位置偏差判定。
/// </summary>
public bool IsPositionValid { get; init; }
/// <summary>
/// 实际位置。
/// </summary>
public Point ActualPosition { get; init; }
/// <summary>
/// 期望位置。
/// </summary>
public Point ExpectedPosition { get; init; }
/// <summary>
/// 位置偏差。
/// </summary>
public double PositionDeviation { get; init; }
/// <summary>
/// 允许的位置容差。
/// </summary>
public double AllowedTolerance { get; init; }
/// <summary>
/// 位置判定时间。
/// </summary>
public DateTime JudgmentTimeUtc { get; init; }
/// <summary>
/// 判定详情。
/// </summary>
public string? Details { get; init; }
/// <summary>
/// 扩展属性。
/// </summary>
public Dictionary<string, object> ExtendedProperties { get; init; } = new();
}
/// <summary>
/// 稳定性判定结果。
/// </summary>
public sealed class StabilityJudgmentResult
{
/// <summary>
/// 是否通过稳定性判定。
/// </summary>
public bool IsStable { get; init; }
/// <summary>
/// 稳定性分数。
/// </summary>
public double StabilityScore { get; init; }
/// <summary>
/// 稳定帧数量。
/// </summary>
public int StableFrameCount { get; init; }
/// <summary>
/// 总帧数量。
/// </summary>
public int TotalFrameCount { get; init; }
/// <summary>
/// 稳定性阈值。
/// </summary>
public double StabilityThreshold { get; init; }
/// <summary>
/// 位置变化率。
/// </summary>
public double PositionChangeRate { get; init; }
/// <summary>
/// 面积变化率。
/// </summary>
public double AreaChangeRate { get; init; }
/// <summary>
/// 置信度变化率。
/// </summary>
public double ConfidenceChangeRate { get; init; }
/// <summary>
/// 稳定性判定时间。
/// </summary>
public DateTime JudgmentTimeUtc { get; init; }
/// <summary>
/// 判定详情。
/// </summary>
public string? Details { get; init; }
/// <summary>
/// 扩展属性。
/// </summary>
public Dictionary<string, object> ExtendedProperties { get; init; } = new();
}
/// <summary>
/// 复合判定结果。
/// </summary>
public sealed class CompositeJudgmentResult
{
/// <summary>
/// 是否通过复合判定。
/// </summary>
public bool IsCompositeValid { get; init; }
/// <summary>
/// 复合置信度。
/// </summary>
public double CompositeConfidence { get; init; }
/// <summary>
/// 面积判定结果。
/// </summary>
public AreaJudgmentResult? AreaResult { get; init; }
/// <summary>
/// 位置偏差判定结果。
/// </summary>
public PositionDeviationJudgmentResult? PositionResult { get; init; }
/// <summary>
/// 稳定性判定结果。
/// </summary>
public StabilityJudgmentResult? StabilityResult { get; init; }
/// <summary>
/// 加权分数。
/// </summary>
public double WeightedScore { get; init; }
/// <summary>
/// 判定策略。
/// </summary>
public CompositeJudgmentStrategy JudgmentStrategy { get; init; }
/// <summary>
/// 复合判定时间。
/// </summary>
public DateTime JudgmentTimeUtc { get; init; }
/// <summary>
/// 判定详情。
/// </summary>
public string? Details { get; init; }
/// <summary>
/// 扩展属性。
/// </summary>
public Dictionary<string, object> ExtendedProperties { get; init; } = new();
}
/// <summary>
/// 批量判定结果。
/// </summary>
public sealed class BatchJudgmentResult
{
/// <summary>
/// 判定结果列表。
/// </summary>
public IReadOnlyList<PlacementJudgmentResult> JudgmentResults { get; init; } = Array.Empty<PlacementJudgmentResult>();
/// <summary>
/// 总规则数量。
/// </summary>
public int TotalRules { get; init; }
/// <summary>
/// 通过的规则数量。
/// </summary>
public int PassedRules { get; init; }
/// <summary>
/// 失败的规则数量。
/// </summary>
public int FailedRules { get; init; }
/// <summary>
/// 总体通过率。
/// </summary>
public double OverallPassRate => TotalRules > 0 ? (double)PassedRules / TotalRules * 100 : 0.0;
/// <summary>
/// 批量处理时间。
/// </summary>
public DateTime BatchProcessingTimeUtc { get; init; }
/// <summary>
/// 总耗时(毫秒)。
/// </summary>
public long TotalElapsedMs { get; init; }
/// <summary>
/// 判定详情。
/// </summary>
public string? Details { get; init; }
/// <summary>
/// 扩展属性。
/// </summary>
public Dictionary<string, object> ExtendedProperties { get; init; } = new();
}
/// <summary>
/// 到位判定统计信息。
/// </summary>
public sealed class PlacementJudgmentStatistics
{
/// <summary>
/// 总判定次数。
/// </summary>
public int TotalJudgments { get; init; }
/// <summary>
/// 成功判定次数。
/// </summary>
public int SuccessfulJudgments { get; init; }
/// <summary>
/// 失败判定次数。
/// </summary>
public int FailedJudgments { get; init; }
/// <summary>
/// 总体成功率。
/// </summary>
public double OverallSuccessRate => TotalJudgments > 0 ? (double)SuccessfulJudgments / TotalJudgments * 100 : 0.0;
/// <summary>
/// 按判定类型分组的统计。
/// </summary>
public Dictionary<PlacementJudgmentType, JudgmentTypeStatistics> ByJudgmentType { get; init; } = new();
/// <summary>
/// 按部件类型分组的统计。
/// </summary>
public Dictionary<PartType, PartTypeJudgmentStatistics> ByPartType { get; init; } = new();
/// <summary>
/// 按产品类型分组的统计。
/// </summary>
public Dictionary<string, ProductTypeJudgmentStatistics> ByProductType { get; init; } = new();
/// <summary>
/// 按层级分组的统计。
/// </summary>
public Dictionary<int, LayerJudgmentStatistics> ByLayer { get; init; } = new();
/// <summary>
/// 统计开始时间。
/// </summary>
public DateTime StartTimeUtc { get; init; }
/// <summary>
/// 统计结束时间。
/// </summary>
public DateTime EndTimeUtc { get; init; }
}
/// <summary>
/// 判定类型统计。
/// </summary>
public sealed class JudgmentTypeStatistics
{
/// <summary>
/// 判定类型。
/// </summary>
public PlacementJudgmentType JudgmentType { get; init; }
/// <summary>
/// 判定次数。
/// </summary>
public int JudgmentCount { get; init; }
/// <summary>
/// 成功次数。
/// </summary>
public int SuccessCount { get; init; }
/// <summary>
/// 成功率。
/// </summary>
public double SuccessRate => JudgmentCount > 0 ? (double)SuccessCount / JudgmentCount * 100 : 0.0;
/// <summary>
/// 平均耗时(毫秒)。
/// </summary>
public double AverageElapsedMs { get; init; }
}
/// <summary>
/// 部件类型判定统计。
/// </summary>
public sealed class PartTypeJudgmentStatistics
{
/// <summary>
/// 部件类型。
/// </summary>
public PartType PartType { get; init; }
/// <summary>
/// 判定次数。
/// </summary>
public int JudgmentCount { get; init; }
/// <summary>
/// 成功次数。
/// </summary>
public int SuccessCount { get; init; }
/// <summary>
/// 成功率。
/// </summary>
public double SuccessRate => JudgmentCount > 0 ? (double)SuccessCount / JudgmentCount * 100 : 0.0;
/// <summary>
/// 平均置信度。
/// </summary>
public double AverageConfidence { get; init; }
}
/// <summary>
/// 产品类型判定统计。
/// </summary>
public sealed class ProductTypeJudgmentStatistics
{
/// <summary>
/// 产品类型编码。
/// </summary>
public string ProductTypeCode { get; init; } = string.Empty;
/// <summary>
/// 判定次数。
/// </summary>
public int JudgmentCount { get; init; }
/// <summary>
/// 成功次数。
/// </summary>
public int SuccessCount { get; init; }
/// <summary>
/// 成功率。
/// </summary>
public double SuccessRate => JudgmentCount > 0 ? (double)SuccessCount / JudgmentCount * 100 : 0.0;
/// <summary>
/// 平均置信度。
/// </summary>
public double AverageConfidence { get; init; }
}
/// <summary>
/// 层级判定统计。
/// </summary>
public sealed class LayerJudgmentStatistics
{
/// <summary>
/// 层级编号。
/// </summary>
public int LayerNumber { get; init; }
/// <summary>
/// 判定次数。
/// </summary>
public int JudgmentCount { get; init; }
/// <summary>
/// 成功次数。
/// </summary>
public int SuccessCount { get; init; }
/// <summary>
/// 成功率。
/// </summary>
public double SuccessRate => JudgmentCount > 0 ? (double)SuccessCount / JudgmentCount * 100 : 0.0;
/// <summary>
/// 平均置信度。
/// </summary>
public double AverageConfidence { get; init; }
}
/// <summary>
/// 到位判定规则。
/// </summary>
public sealed class PlacementJudgmentRule
{
/// <summary>
/// 规则ID。
/// </summary>
public Guid RuleId { get; init; }
/// <summary>
/// 规则名称。
/// </summary>
public string RuleName { get; init; } = string.Empty;
/// <summary>
/// 规则描述。
/// </summary>
public string RuleDescription { get; init; } = string.Empty;
/// <summary>
/// 产品类型编码。
/// </summary>
public string ProductTypeCode { get; init; } = string.Empty;
/// <summary>
/// 层级编号。
/// </summary>
public int LayerNumber { get; init; }
/// <summary>
/// 判定类型。
/// </summary>
public PlacementJudgmentType JudgmentType { get; init; }
/// <summary>
/// 面积容差(百分比)。
/// </summary>
public double AreaTolerance { get; init; }
/// <summary>
/// 位置容差。
/// </summary>
public double PositionTolerance { get; init; }
/// <summary>
/// 稳定性阈值。
/// </summary>
public double StabilityThreshold { get; init; }
/// <summary>
/// 稳定帧窗口大小。
/// </summary>
public int StabilityWindowSize { get; init; }
/// <summary>
/// 复合判定策略。
/// </summary>
public CompositeJudgmentStrategy CompositeStrategy { get; init; }
/// <summary>
/// 权重配置。
/// </summary>
public JudgmentWeights Weights { get; init; } = new();
/// <summary>
/// 是否启用。
/// </summary>
public bool IsEnabled { get; init; } = true;
/// <summary>
/// 优先级。
/// </summary>
public int Priority { get; init; } = 1;
/// <summary>
/// 创建时间。
/// </summary>
public DateTime CreatedAtUtc { get; init; }
/// <summary>
/// 更新时间。
/// </summary>
public DateTime UpdatedAtUtc { get; init; }
/// <summary>
/// 版本号。
/// </summary>
public string Version { get; init; } = "1.0";
/// <summary>
/// 扩展属性。
/// </summary>
public Dictionary<string, object> ExtendedProperties { get; init; } = new();
}
/// <summary>
/// 权重配置。
/// </summary>
public sealed class JudgmentWeights
{
/// <summary>
/// 面积权重。
/// </summary>
public double AreaWeight { get; init; } = 0.3;
/// <summary>
/// 位置权重。
/// </summary>
public double PositionWeight { get; init; } = 0.4;
/// <summary>
/// 稳定性权重。
/// </summary>
public double StabilityWeight { get; init; } = 0.3;
/// <summary>
/// 验证权重总和是否为1。
/// </summary>
public bool IsValid => Math.Abs(AreaWeight + PositionWeight + StabilityWeight - 1.0) < 0.001;
}
/// <summary>
/// 期望面积。
/// </summary>
public sealed class ExpectedArea
{
/// <summary>
/// 面积ID。
/// </summary>
public Guid AreaId { get; init; }
/// <summary>
/// 期望面积。
/// </summary>
public double ExpectedAreaValue { get; init; }
/// <summary>
/// 期望部件类型。
/// </summary>
public PartType? ExpectedPartType { get; init; }
/// <summary>
/// 期望部件编码。
/// </summary>
public string? ExpectedPartCode { get; init; }
/// <summary>
/// 面积权重。
/// </summary>
public double Weight { get; init; } = 1.0;
/// <summary>
/// 扩展属性。
/// </summary>
public Dictionary<string, object> ExtendedProperties { get; init; } = new();
}
/// <summary>
/// 稳定性规则。
/// </summary>
public sealed class StabilityRule
{
/// <summary>
/// 规则ID。
/// </summary>
public Guid RuleId { get; init; }
/// <summary>
/// 规则名称。
/// </summary>
public string RuleName { get; init; } = string.Empty;
/// <summary>
/// 稳定性阈值。
/// </summary>
public double StabilityThreshold { get; init; }
/// <summary>
/// 窗口大小。
/// </summary>
public int WindowSize { get; init; }
/// <summary>
/// 位置变化阈值。
/// </summary>
public double PositionChangeThreshold { get; init; }
/// <summary>
/// 面积变化阈值。
/// </summary>
public double AreaChangeThreshold { get; init; }
/// <summary>
/// 置信度变化阈值。
/// </summary>
public double ConfidenceChangeThreshold { get; init; }
/// <summary>
/// 扩展属性。
/// </summary>
public Dictionary<string, object> ExtendedProperties { get; init; } = new();
}
/// <summary>
/// 复合判定规则。
/// </summary>
public sealed class CompositeJudgmentRule
{
/// <summary>
/// 规则ID。
/// </summary>
public Guid RuleId { get; init; }
/// <summary>
/// 规则名称。
/// </summary>
public string RuleName { get; init; } = string.Empty;
/// <summary>
/// 判定策略。
/// </summary>
public CompositeJudgmentStrategy Strategy { get; init; }
/// <summary>
/// 权重配置。
/// </summary>
public JudgmentWeights Weights { get; init; } = new();
/// <summary>
/// 最小通过条件。
/// </summary>
public int MinimumPassConditions { get; init; } = 2;
/// <summary>
/// 扩展属性。
/// </summary>
public Dictionary<string, object> ExtendedProperties { get; init; } = new();
}
/// <summary>
/// 到位判定类型枚举。
/// </summary>
public enum PlacementJudgmentType
{
/// <summary>
/// 面积判定。
/// </summary>
Area = 0,
/// <summary>
/// 位置偏差判定。
/// </summary>
PositionDeviation = 1,
/// <summary>
/// 稳定性判定。
/// </summary>
Stability = 2,
/// <summary>
/// 复合判定。
/// </summary>
Composite = 3
}
/// <summary>
/// 判定质量枚举。
/// </summary>
public enum JudgmentQuality
{
/// <summary>
/// 优秀。
/// </summary>
Excellent = 0,
/// <summary>
/// 良好。
/// </summary>
Good = 1,
/// <summary>
/// 一般。
/// </summary>
Fair = 2,
/// <summary>
/// 较差。
/// </summary>
Poor = 3
}
/// <summary>
/// 复合判定策略枚举。
/// </summary>
public enum CompositeJudgmentStrategy
{
/// <summary>
/// 全部通过。
/// </summary>
AllPass = 0,
/// <summary>
/// 任意通过。
/// </summary>
AnyPass = 1,
/// <summary>
/// 加权平均。
/// </summary>
WeightedAverage = 2,
/// <summary>
/// 最小通过数量。
/// </summary>
MinimumPass = 3
}