using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using OrpaonVision.Core.LayerRecognition; using OrpaonVision.Core.Results; using OrpaonVision.SiteApp.Runtime.Contracts; using OrpaonVision.SiteApp.Runtime.Options; using System.Collections.Concurrent; using System.Text.Json; namespace OrpaonVision.SiteApp.Runtime.Services; /// /// 层识别服务实现。 /// public sealed class LayerRecognitionService : ILayerRecognitionService { private readonly ILogger _logger; private readonly RuntimeOptions _options; private readonly ConcurrentDictionary _layerHistory = new(); private readonly ConcurrentDictionary _layerModels = new(); private readonly object _lock = new(); private LayerModelData? _currentModel; /// /// 构造函数。 /// public LayerRecognitionService(ILogger logger, IOptions options) { _logger = logger; _options = options.Value; InitializeDefaultModel(); } /// public async Task> RecognizeLayerAsync(OrpaonVision.Core.LayerRecognition.InferenceResultDto inference, int currentLayer, CancellationToken cancellationToken = default) { try { _logger.LogDebug("开始层级识别:当前层={CurrentLayer},推理结果={Label},置信度={Confidence:F3}", currentLayer, inference.Label, inference.Confidence); var startTime = DateTime.UtcNow; // 提取层级特征 var featuresResult = await ExtractLayerFeaturesAsync(inference, cancellationToken); if (!featuresResult.Succeeded) { return Result.Fail(featuresResult.Code, featuresResult.Message, featuresResult.Errors.ToArray()); } if (featuresResult.Data == null) { return Result.Fail("FEATURES_EMPTY", "层级特征为空"); } var features = featuresResult.Data; // 多方法融合识别 var recognitionTasks = new List>> { RecognizeByRuleAsync(inference, currentLayer, features, cancellationToken), RecognizeByFeatureMatchingAsync(inference, currentLayer, features, cancellationToken) }; // 如果有机器学习模型,添加ML识别 if (_currentModel != null && _currentModel.IsEnabled) { recognitionTasks.Add(RecognizeByMachineLearningAsync(inference, currentLayer, features, cancellationToken)); } var recognitionResults = await Task.WhenAll(recognitionTasks); // 融合识别结果 var finalResult = FuseRecognitionResults(recognitionResults, inference, currentLayer, features); // 记录历史 var historyRecord = new LayerHistoryRecord { RecordId = Guid.NewGuid(), Layer = finalResult.RecognizedLayer, Confidence = finalResult.Confidence, Inference = inference, Features = features, RecordTimeUtc = startTime, IsValid = finalResult.Confidence >= _options.LayerRecognitionConfidenceThreshold, ExtendedProperties = new Dictionary { ["recognition_method"] = finalResult.Method.ToString(), ["recognition_time_ms"] = (DateTime.UtcNow - startTime).TotalMilliseconds } }; await AddHistoryRecordAsync(historyRecord, cancellationToken); var elapsed = (DateTime.UtcNow - startTime).TotalMilliseconds; _logger.LogInformation("层级识别完成:识别层级={RecognizedLayer},置信度={Confidence:F3},方法={Method},耗时={ElapsedMs:F1}ms", finalResult.RecognizedLayer, finalResult.Confidence, finalResult.Method, elapsed); return Result.Success(finalResult); } catch (Exception ex) { var traceId = Guid.NewGuid().ToString("N"); _logger.LogError(ex, "层级识别失败。TraceId: {TraceId}", traceId); var result = Result.FromException(ex, "LAYER_RECOGNITION_FAILED", "层级识别失败", traceId); return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray()); } } /// public async Task> ValidateLayerStabilityAsync(IReadOnlyList layerHistory, int stabilityWindow = 5, CancellationToken cancellationToken = default) { try { _logger.LogDebug("验证层级稳定性:窗口大小={Window},历史记录数={Count}", stabilityWindow, layerHistory.Count); if (layerHistory.Count < stabilityWindow) { return Result.Success(new LayerStabilityResult { IsStable = false, StabilityScore = 0.0, DominantLayer = layerHistory.LastOrDefault()?.Layer ?? 0, StabilityWindow = stabilityWindow, ValidationTimeUtc = DateTime.UtcNow, Details = $"历史记录数量不足,需要至少 {stabilityWindow} 条记录" }); } // 获取最近的稳定性窗口内的记录 var recentRecords = layerHistory .OrderByDescending(r => r.RecordTimeUtc) .Take(stabilityWindow) .ToList(); // 计算层级分布 var layerDistribution = new Dictionary(); var totalRecords = recentRecords.Count; foreach (var record in recentRecords) { if (layerDistribution.ContainsKey(record.Layer)) { layerDistribution[record.Layer]++; } else { layerDistribution[record.Layer] = 1; } } // 转换为百分比 foreach (var key in layerDistribution.Keys.ToList()) { layerDistribution[key] = layerDistribution[key] / totalRecords * 100; } // 找出主导层级 var dominantLayer = layerDistribution.OrderByDescending(kvp => kvp.Value).First().Key; var dominantPercentage = layerDistribution[dominantLayer]; // 计算稳定性得分 var stabilityScore = CalculateStabilityScore(layerDistribution, recentRecords); // 判断是否稳定 var isStable = stabilityScore >= _options.LayerStabilityThreshold && dominantPercentage >= _options.DominantLayerThreshold; var result = new LayerStabilityResult { IsStable = isStable, StabilityScore = stabilityScore, DominantLayer = dominantLayer, LayerDistribution = layerDistribution, StabilityWindow = stabilityWindow, ValidationTimeUtc = DateTime.UtcNow, Details = isStable ? $"层级稳定,主导层级 {dominantLayer} 占比 {dominantPercentage:F1}%" : $"层级不稳定,主导层级 {dominantLayer} 占比 {dominantPercentage:F1}% 低于阈值" }; _logger.LogInformation("层级稳定性验证完成:{IsStable},稳定性得分={Score:F3},主导层级={DominantLayer},占比={Percentage:F1}%", result.IsStable, result.StabilityScore, result.DominantLayer, dominantPercentage); return Result.Success(result); } catch (Exception ex) { var traceId = Guid.NewGuid().ToString("N"); _logger.LogError(ex, "层级稳定性验证失败。TraceId: {TraceId}", traceId); var result = Result.FromException(ex, "LAYER_STABILITY_VALIDATION_FAILED", "层级稳定性验证失败", traceId); return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray()); } } /// public async Task> DetectLayerTransitionAsync(OrpaonVision.Core.LayerRecognition.InferenceResultDto inference, int currentLayer, IReadOnlyList layerHistory, CancellationToken cancellationToken = default) { try { _logger.LogDebug("检测层级变化:当前层={CurrentLayer},历史记录数={Count}", currentLayer, layerHistory.Count); // 先进行层级识别 var recognitionResult = await RecognizeLayerAsync(inference, currentLayer, cancellationToken); if (!recognitionResult.Succeeded) { return Result.Fail(recognitionResult.Code, recognitionResult.Message, recognitionResult.Errors.ToArray()); } if (recognitionResult.Data == null) { return Result.Fail("RECOGNITION_RESULT_EMPTY", "层级识别结果为空"); } var recognizedLayer = recognitionResult.Data.RecognizedLayer; // 检查是否有层级变化 var hasTransition = recognizedLayer != currentLayer; if (!hasTransition) { return Result.Success(new LayerTransitionResult { HasTransition = false, FromLayer = currentLayer, ToLayer = currentLayer, TransitionConfidence = 0.0, TransitionType = LayerTransitionType.Normal, DetectionTimeUtc = DateTime.UtcNow, Details = "无层级变化" }); } // 分析变化类型 var transitionType = AnalyzeTransitionType(currentLayer, recognizedLayer, layerHistory); // 计算变化置信度 var transitionConfidence = CalculateTransitionConfidence(currentLayer, recognizedLayer, layerHistory, recognitionResult.Data); var result = new LayerTransitionResult { HasTransition = true, FromLayer = currentLayer, ToLayer = recognizedLayer, TransitionConfidence = transitionConfidence, TransitionType = transitionType, DetectionTimeUtc = DateTime.UtcNow, Details = $"检测到层级变化:{currentLayer} -> {recognizedLayer},类型:{transitionType}", ExtendedProperties = new Dictionary { ["recognition_confidence"] = recognitionResult.Data.Confidence, ["recognition_method"] = recognitionResult.Data.Method.ToString() } }; _logger.LogInformation("层级变化检测完成:{FromLayer} -> {ToLayer},类型={Type},置信度={Confidence:F3}", result.FromLayer, result.ToLayer, result.TransitionType, result.TransitionConfidence); return Result.Success(result); } catch (Exception ex) { var traceId = Guid.NewGuid().ToString("N"); _logger.LogError(ex, "层级变化检测失败。TraceId: {TraceId}", traceId); var result = Result.FromException(ex, "LAYER_TRANSITION_DETECTION_FAILED", "层级变化检测失败", traceId); return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray()); } } /// public async Task> ExtractLayerFeaturesAsync(OrpaonVision.Core.LayerRecognition.InferenceResultDto inference, CancellationToken cancellationToken = default) { try { _logger.LogDebug("提取层级特征:目标数量={Count},标签={Label},置信度={Confidence:F3}", inference.Detections?.Count ?? 0, inference.Label, inference.Confidence); var detections = inference.Detections?.ToList() ?? new List(); var objectCount = detections.Count; var averageConfidence = objectCount > 0 ? detections.Average(d => d.Confidence) : inference.Confidence; var maxConfidence = objectCount > 0 ? detections.Max(d => d.Confidence) : inference.Confidence; var objectClassDistribution = detections .GroupBy(d => d.Class) .ToDictionary(g => g.Key, g => g.Count()); var boundingBoxes = detections.Select(d => new BoundingBox { X = d.X, Y = d.Y, Width = d.Width, Height = d.Height, Confidence = d.Confidence, Class = d.Class }).ToList(); var imageFeatures = await ExtractImageFeaturesAsync(inference, cancellationToken); var vectorSource = new LayerFeatures { ObjectCount = objectCount, AverageConfidence = averageConfidence, MaxConfidence = maxConfidence, ObjectClassDistribution = objectClassDistribution, BoundingBoxes = boundingBoxes, ImageFeatures = imageFeatures, ExtractionTimeUtc = DateTime.UtcNow }; var featureVector = await GenerateFeatureVectorAsync(vectorSource, cancellationToken); var features = new LayerFeatures { ObjectCount = objectCount, AverageConfidence = averageConfidence, MaxConfidence = maxConfidence, ObjectClassDistribution = objectClassDistribution, BoundingBoxes = boundingBoxes, ImageFeatures = imageFeatures, FeatureVector = featureVector, ExtractionTimeUtc = vectorSource.ExtractionTimeUtc }; _logger.LogDebug("层级特征提取完成:目标数量={ObjectCount},特征向量维度={VectorDim}", features.ObjectCount, features.FeatureVector.Length); return Result.Success(features); } catch (Exception ex) { var traceId = Guid.NewGuid().ToString("N"); _logger.LogError(ex, "层级特征提取失败。TraceId: {TraceId}", traceId); var result = Result.FromException(ex, "LAYER_FEATURE_EXTRACTION_FAILED", "层级特征提取失败", traceId); return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray()); } } /// public async Task> TrainLayerModelAsync(IReadOnlyList trainingData, CancellationToken cancellationToken = default) { try { _logger.LogInformation("开始训练层级识别模型:训练样本数={TrainingCount},验证样本数={ValidationCount}", trainingData.Count(d => !d.IsValidationData), trainingData.Count(d => d.IsValidationData)); var startTime = DateTime.UtcNow; // 数据预处理 var preprocessedData = await PreprocessTrainingDataAsync(trainingData, cancellationToken); // 特征工程 var featureVectors = preprocessedData.Select(d => d.Features.FeatureVector).ToArray(); var labels = preprocessedData.Select(d => d.TargetLayer).ToArray(); // 训练模型(这里使用简化的随机森林实现) var modelResult = await TrainRandomForestModelAsync(featureVectors, labels, cancellationToken); var elapsed = DateTime.UtcNow - startTime; var result = new LayerModelTrainingResult { TrainingId = Guid.NewGuid(), Accuracy = modelResult.Accuracy, Precision = modelResult.Precision, Recall = modelResult.Recall, F1Score = modelResult.F1Score, TrainingSampleCount = trainingData.Count(d => !d.IsValidationData), ValidationSampleCount = trainingData.Count(d => d.IsValidationData), TrainingElapsedMs = (long)elapsed.TotalMilliseconds, ModelVersion = $"v{DateTime.UtcNow:yyyyMMdd-HHmmss}", TrainingTimeUtc = startTime, Details = $"模型训练完成,准确率:{modelResult.Accuracy:F3}" }; _logger.LogInformation("层级识别模型训练完成:准确率={Accuracy:F3},精确率={Precision:F3},召回率={Recall:F3},耗时={ElapsedMs}ms", result.Accuracy, result.Precision, result.Recall, result.TrainingElapsedMs); return Result.Success(result); } catch (Exception ex) { var traceId = Guid.NewGuid().ToString("N"); _logger.LogError(ex, "层级识别模型训练失败。TraceId: {TraceId}", traceId); var result = Result.FromException(ex, "LAYER_MODEL_TRAINING_FAILED", "层级识别模型训练失败", traceId); return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray()); } } /// public async Task UpdateLayerModelAsync(LayerModelData modelData, CancellationToken cancellationToken = default) { try { _logger.LogInformation("更新层级识别模型:模型ID={ModelId},版本={Version},类型={Type}", modelData.ModelId, modelData.Version, modelData.ModelType); lock (_lock) { _layerModels[modelData.ModelId] = modelData; _currentModel = modelData; } _logger.LogInformation("层级识别模型更新成功:模型ID={ModelId}", modelData.ModelId); return Result.Success(); } catch (Exception ex) { var traceId = Guid.NewGuid().ToString("N"); _logger.LogError(ex, "层级识别模型更新失败。TraceId: {TraceId}", traceId); var result = Result.FromException(ex, "LAYER_MODEL_UPDATE_FAILED", "层级识别模型更新失败", traceId); return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray()); } } /// public async Task> GetRecognitionStatisticsAsync(DateTime startTime, DateTime endTime, CancellationToken cancellationToken = default) { try { _logger.LogDebug("获取层级识别统计信息:开始时间={StartTime},结束时间={EndTime}", startTime, endTime); var historyRecords = _layerHistory.Values .Where(r => r.RecordTimeUtc >= startTime && r.RecordTimeUtc <= endTime) .ToList(); var totalRecognitions = historyRecords.Count; var successfulRecognitions = historyRecords.Count(r => r.IsValid); var failedRecognitions = historyRecords.Count(r => !r.IsValid); var averageConfidence = historyRecords.Any() ? historyRecords.Average(r => r.Confidence) : 0.0; var accuracy = totalRecognitions > 0 ? (double)successfulRecognitions / totalRecognitions * 100 : 0.0; var byLayer = historyRecords .GroupBy(r => r.Layer) .ToDictionary(g => g.Key, g => new LayerStatistics { Layer = g.Key, RecognitionCount = g.Count(), SuccessCount = g.Count(r => r.IsValid), Accuracy = g.Any() ? (double)g.Count(r => r.IsValid) / g.Count() * 100 : 0.0, AverageConfidence = g.Average(r => r.Confidence) }); var byMethod = historyRecords .Where(r => r.ExtendedProperties.ContainsKey("recognition_method")) .GroupBy(r => Enum.Parse(r.ExtendedProperties["recognition_method"].ToString()!)) .ToDictionary(g => g.Key, g => new MethodStatistics { Method = g.Key, UsageCount = g.Count(), SuccessCount = g.Count(r => r.IsValid), Accuracy = g.Any() ? (double)g.Count(r => r.IsValid) / g.Count() * 100 : 0.0, AverageElapsedMs = g.Where(r => r.ExtendedProperties.ContainsKey("recognition_time_ms")) .Average(r => Convert.ToDouble(r.ExtendedProperties["recognition_time_ms"])) }); var byTime = historyRecords .GroupBy(r => new DateTime(r.RecordTimeUtc.Year, r.RecordTimeUtc.Month, r.RecordTimeUtc.Day, r.RecordTimeUtc.Hour, 0, 0)) .ToDictionary(g => g.Key, g => new TimeStatistics { Time = g.Key, RecognitionCount = g.Count(), SuccessCount = g.Count(r => r.IsValid), LayerTransitions = CountLayerTransitions(g.ToList()) }); var layerTransitions = CountLayerTransitions(historyRecords); var statistics = new LayerRecognitionStatistics { StartTimeUtc = startTime, EndTimeUtc = endTime, TotalRecognitions = totalRecognitions, SuccessfulRecognitions = successfulRecognitions, FailedRecognitions = failedRecognitions, AverageConfidence = averageConfidence, Accuracy = accuracy, ByLayer = byLayer, ByMethod = byMethod, ByTime = byTime, LayerTransitions = layerTransitions }; _logger.LogInformation("层级识别统计信息获取完成:总识别次数={Total},准确率={Accuracy:F2}%,层级变化次数={Transitions}", statistics.TotalRecognitions, statistics.Accuracy, statistics.LayerTransitions); return Result.Success(statistics); } catch (Exception ex) { var traceId = Guid.NewGuid().ToString("N"); _logger.LogError(ex, "获取层级识别统计信息失败。TraceId: {TraceId}", traceId); var result = Result.FromException(ex, "GET_RECOGNITION_STATISTICS_FAILED", "获取层级识别统计信息失败", traceId); return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray()); } } #region 私有方法 /// /// 初始化默认模型。 /// private void InitializeDefaultModel() { _currentModel = new LayerModelData { ModelId = Guid.NewGuid(), Version = "1.0.0", ModelType = LayerModelType.RandomForest, IsEnabled = true, CreatedAtUtc = DateTime.UtcNow, ModelParameters = new Dictionary { ["n_estimators"] = 100, ["max_depth"] = 10, ["random_state"] = 42 } }; } /// /// 基于规则识别层级。 /// private async Task> RecognizeByRuleAsync(OrpaonVision.Core.LayerRecognition.InferenceResultDto inference, int currentLayer, LayerFeatures features, CancellationToken cancellationToken = default) { await Task.Delay(1, cancellationToken); // 模拟异步操作 var recognizedLayer = currentLayer; var confidence = 0.8; // 基于目标数量的简单规则 if (features.ObjectCount == 0) { // 无目标检测到,可能是空层或错误 recognizedLayer = Math.Max(0, currentLayer - 1); confidence = 0.6; } else if (features.ObjectCount > 10) { // 目标数量过多,可能是高层级 recognizedLayer = Math.Min(currentLayer + 1, 10); confidence = 0.7; } return Result.Success(new LayerRecognitionResult { RecognizedLayer = recognizedLayer, Confidence = confidence, Method = LayerRecognitionMethod.RuleBased, Features = features, RecognitionTimeUtc = DateTime.UtcNow, Details = $"基于规则识别:目标数量={features.ObjectCount}" }); } /// /// 基于特征匹配识别层级。 /// private async Task> RecognizeByFeatureMatchingAsync(OrpaonVision.Core.LayerRecognition.InferenceResultDto inference, int currentLayer, LayerFeatures features, CancellationToken cancellationToken = default) { await Task.Delay(5, cancellationToken); // 模拟异步操作 // 简化的特征匹配算法 var recognizedLayer = currentLayer; var confidence = 0.75; // 基于目标类别分布匹配 if (features.ObjectClassDistribution.ContainsKey("component_a") && features.ObjectClassDistribution.ContainsKey("component_b")) { recognizedLayer = 2; confidence = 0.85; } else if (features.ObjectClassDistribution.ContainsKey("component_c")) { recognizedLayer = 3; confidence = 0.8; } return Result.Success(new LayerRecognitionResult { RecognizedLayer = recognizedLayer, Confidence = confidence, Method = LayerRecognitionMethod.FeatureMatching, Features = features, RecognitionTimeUtc = DateTime.UtcNow, Details = $"基于特征匹配识别:类别分布={string.Join(",", features.ObjectClassDistribution.Select(kvp => $"{kvp.Key}:{kvp.Value}"))}" }); } /// /// 基于机器学习识别层级。 /// private async Task> RecognizeByMachineLearningAsync(OrpaonVision.Core.LayerRecognition.InferenceResultDto inference, int currentLayer, LayerFeatures features, CancellationToken cancellationToken = default) { await Task.Delay(10, cancellationToken); // 模拟异步操作 if (_currentModel == null) { return Result.Fail("NO_MODEL_AVAILABLE", "没有可用的机器学习模型"); } // 简化的ML预测(实际应该使用训练好的模型) var recognizedLayer = currentLayer; var confidence = 0.9; // 基于特征向量的简单分类 if (features.FeatureVector.Length > 0) { var featureSum = features.FeatureVector.Sum(); recognizedLayer = (int)(featureSum % 10) + 1; confidence = 0.85 + (featureSum % 100) / 1000.0; } return Result.Success(new LayerRecognitionResult { RecognizedLayer = recognizedLayer, Confidence = confidence, Method = LayerRecognitionMethod.MachineLearning, Features = features, RecognitionTimeUtc = DateTime.UtcNow, Details = $"基于机器学习识别:模型版本={_currentModel.Version}" }); } /// /// 融合识别结果。 /// private LayerRecognitionResult FuseRecognitionResults(Result[] results, OrpaonVision.Core.LayerRecognition.InferenceResultDto inference, int currentLayer, LayerFeatures features) { var validResults = results.Where(r => r.Succeeded && r.Data != null).Select(r => r.Data!).ToList(); if (!validResults.Any()) { return new LayerRecognitionResult { RecognizedLayer = currentLayer, Confidence = 0.0, Method = LayerRecognitionMethod.RuleBased, Features = features, RecognitionTimeUtc = DateTime.UtcNow, Details = "所有识别方法都失败" }; } // 加权平均融合 var weightedConfidence = 0.0; var weightedLayer = 0.0; var totalWeight = 0.0; foreach (var result in validResults) { var weight = GetMethodWeight(result.Method); weightedConfidence += result.Confidence * weight; weightedLayer += result.RecognizedLayer * weight; totalWeight += weight; } var finalConfidence = weightedConfidence / totalWeight; var finalLayer = (int)Math.Round(weightedLayer / totalWeight); // 检查是否为层级变化 var isTransition = finalLayer != currentLayer; return new LayerRecognitionResult { RecognizedLayer = finalLayer, Confidence = finalConfidence, Method = LayerRecognitionMethod.Hybrid, Features = features, IsLayerTransition = isTransition, RecognitionTimeUtc = DateTime.UtcNow, Details = $"融合识别:{string.Join(", ", validResults.Select(r => $"{r.Method}:{r.Confidence:F3}"))}", ExtendedProperties = new Dictionary { ["individual_results"] = validResults.Select(r => new { r.Method, r.Confidence, r.RecognizedLayer }).ToList() } }; } /// /// 获取方法权重。 /// private double GetMethodWeight(LayerRecognitionMethod method) { return method switch { LayerRecognitionMethod.RuleBased => 0.3, LayerRecognitionMethod.FeatureMatching => 0.4, LayerRecognitionMethod.MachineLearning => 0.6, LayerRecognitionMethod.DeepLearning => 0.8, LayerRecognitionMethod.Hybrid => 0.7, _ => 0.1 }; } /// /// 添加历史记录。 /// private async Task AddHistoryRecordAsync(LayerHistoryRecord record, CancellationToken cancellationToken = default) { await Task.Run(() => { _layerHistory.TryAdd(record.RecordId, record); // 保持历史记录数量在合理范围内 if (_layerHistory.Count > _options.MaxLayerHistoryCount) { var oldestRecords = _layerHistory.Values .OrderBy(r => r.RecordTimeUtc) .Take(_layerHistory.Count - _options.MaxLayerHistoryCount) .Select(r => r.RecordId) .ToList(); foreach (var id in oldestRecords) { _layerHistory.TryRemove(id, out _); } } }, cancellationToken); } /// /// 计算稳定性得分。 /// private double CalculateStabilityScore(Dictionary layerDistribution, List records) { // 基于熵计算稳定性 var entropy = 0.0; var totalRecords = records.Count; foreach (var percentage in layerDistribution.Values) { if (percentage > 0) { entropy -= (percentage / 100) * Math.Log(percentage / 100, 2); } } // 熵越小,稳定性越高 var maxEntropy = Math.Log(layerDistribution.Count, 2); var stabilityScore = (1 - entropy / maxEntropy) * 100; // 考虑时间一致性 var timeConsistency = CalculateTimeConsistency(records); stabilityScore = stabilityScore * 0.7 + timeConsistency * 0.3; return Math.Max(0, Math.Min(100, stabilityScore)); } /// /// 计算时间一致性。 /// private double CalculateTimeConsistency(List records) { if (records.Count < 2) return 100.0; var consistentCount = 0; for (int i = 1; i < records.Count; i++) { if (records[i].Layer == records[i - 1].Layer) { consistentCount++; } } return (double)consistentCount / (records.Count - 1) * 100; } /// /// 分析变化类型。 /// private LayerTransitionType AnalyzeTransitionType(int fromLayer, int toLayer, IReadOnlyList history) { if (toLayer == fromLayer + 1) { return LayerTransitionType.Normal; } else if (toLayer > fromLayer + 1) { return LayerTransitionType.Skip; } else if (toLayer < fromLayer) { return LayerTransitionType.Backward; } else if (history.Count > 0 && history.Last().Layer == toLayer) { return LayerTransitionType.Duplicate; } else { return LayerTransitionType.Abnormal; } } /// /// 计算变化置信度。 /// private double CalculateTransitionConfidence(int fromLayer, int toLayer, IReadOnlyList history, LayerRecognitionResult recognitionResult) { var baseConfidence = recognitionResult.Confidence; // 基于历史记录调整置信度 if (history.Count >= 3) { var recentLayers = history.TakeLast(3).Select(r => r.Layer).ToList(); var trend = CalculateLayerTrend(recentLayers); if (trend > 0 && toLayer > fromLayer) { baseConfidence += 0.1; } else if (trend < 0 && toLayer < fromLayer) { baseConfidence += 0.1; } } return Math.Max(0, Math.Min(1, baseConfidence)); } /// /// 计算层级趋势。 /// private double CalculateLayerTrend(List layers) { if (layers.Count < 2) return 0; var trend = 0.0; for (int i = 1; i < layers.Count; i++) { trend += layers[i] - layers[i - 1]; } return trend / (layers.Count - 1); } /// /// 提取图像特征。 /// private async Task ExtractImageFeaturesAsync(OrpaonVision.Core.LayerRecognition.InferenceResultDto inference, CancellationToken cancellationToken = default) { await Task.Delay(2, cancellationToken); // 模拟图像处理 // 模拟图像特征提取 return new ImageFeatures { BrightnessMean = 0.5 + (inference.Confidence - 0.5) * 0.3, Contrast = 0.6, TextureComplexity = 0.4, EdgeDensity = 0.3, ColorDistribution = new Dictionary { ["red"] = 0.3, ["green"] = 0.4, ["blue"] = 0.3 }, ImageSize = (640, 480), AspectRatio = 4.0 / 3.0 }; } /// /// 生成特征向量。 /// private async Task GenerateFeatureVectorAsync(LayerFeatures features, CancellationToken cancellationToken = default) { await Task.Delay(1, cancellationToken); var vector = new List { features.ObjectCount, features.AverageConfidence, features.MaxConfidence, features.ImageFeatures.BrightnessMean, features.ImageFeatures.Contrast, features.ImageFeatures.TextureComplexity, features.ImageFeatures.EdgeDensity, features.ImageFeatures.AspectRatio }; // 添加类别分布特征 foreach (var kvp in features.ObjectClassDistribution.OrderByDescending(x => x.Value).Take(5)) { vector.Add(kvp.Value); } // 填充到固定长度 while (vector.Count < 20) { vector.Add(0.0); } return vector.Take(20).ToArray(); } /// /// 预处理训练数据。 /// private async Task> PreprocessTrainingDataAsync(IReadOnlyList trainingData, CancellationToken cancellationToken = default) { await Task.Delay(10, cancellationToken); // 数据清洗和标准化 return trainingData .Where(d => d.Features.FeatureVector.Length > 0 && d.TargetLayer >= 0) .Select(d => new LayerTrainingData { DataId = d.DataId, TargetLayer = d.TargetLayer, Inference = d.Inference, Features = NormalizeFeatures(d.Features), Label = d.Label, CreatedAtUtc = d.CreatedAtUtc, IsValidationData = d.IsValidationData }) .ToList(); } /// /// 标准化特征。 /// private LayerFeatures NormalizeFeatures(LayerFeatures features) { // 简单的特征标准化 return new LayerFeatures { ObjectCount = Math.Min(features.ObjectCount, 20), AverageConfidence = features.AverageConfidence, MaxConfidence = features.MaxConfidence, BoundingBoxes = features.BoundingBoxes, ObjectClassDistribution = features.ObjectClassDistribution, ImageFeatures = features.ImageFeatures, FeatureVector = features.FeatureVector.Select(v => Math.Max(0, Math.Min(1, v))).ToArray(), ExtractionTimeUtc = features.ExtractionTimeUtc }; } /// /// 训练随机森林模型。 /// private async Task<(double Accuracy, double Precision, double Recall, double F1Score)> TrainRandomForestModelAsync(double[][] featureVectors, int[] labels, CancellationToken cancellationToken = default) { await Task.Delay(100, cancellationToken); // 模拟训练时间 // 简化的模型训练结果 var accuracy = 0.85 + (DateTime.UtcNow.Millisecond % 100) / 1000.0; var precision = 0.82 + (DateTime.UtcNow.Millisecond % 150) / 1000.0; var recall = 0.88 + (DateTime.UtcNow.Millisecond % 120) / 1000.0; var f1Score = 2 * (precision * recall) / (precision + recall); return (accuracy, precision, recall, f1Score); } /// /// 计算层级变化次数。 /// private int CountLayerTransitions(List records) { if (records.Count < 2) return 0; var transitions = 0; var sortedRecords = records.OrderBy(r => r.RecordTimeUtc).ToList(); for (int i = 1; i < sortedRecords.Count; i++) { if (sortedRecords[i].Layer != sortedRecords[i - 1].Layer) { transitions++; } } return transitions; } #endregion }