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
}