using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using OrpaonVision.Core.Results; using OrpaonVision.SiteApp.Runtime.Contracts; using OrpaonVision.SiteApp.Runtime.Options; using OrpaonVision.SiteApp.Runtime.Services; namespace OrpaonVision.SiteApp.Runtime.Services; /// /// YOLO推理服务适配器,将IYoloInferenceService适配到IInferenceService接口。 /// public sealed class YoloInferenceAdapter : IInferenceService { private readonly ILogger _logger; private readonly IYoloInferenceService _yoloInferenceService; private readonly RuntimeOptions _options; /// /// 构造函数。 /// public YoloInferenceAdapter( ILogger logger, IYoloInferenceService yoloInferenceService, IOptions options) { _logger = logger; _yoloInferenceService = yoloInferenceService; _options = options.Value; } /// public Result Predict(CameraFrameDto frame) { try { // 确保YOLO模型已初始化 if (!_yoloInferenceService.IsInitialized) { var initResult = _yoloInferenceService.Initialize(); if (!initResult.Succeeded) { return Result.Fail(initResult.Code, initResult.Message, initResult.Errors.ToArray()); } } // 执行YOLO推理 var predictResult = _yoloInferenceService.Predict( frame.ImageData, frame.Width, frame.Height, frame.PixelFormat); if (!predictResult.Succeeded) { return Result.Fail(predictResult.Code, predictResult.Message, predictResult.Errors.ToArray()); } var detections = predictResult.Data; // 转换为InferenceResultDto格式 var inferenceResult = new InferenceResultDto { FrameId = frame.FrameId, InferenceId = Guid.NewGuid(), InferredAtUtc = DateTime.UtcNow, ModelName = _yoloInferenceService.GetModelInfo().ModelName, ModelVersion = _yoloInferenceService.GetModelInfo().ModelVersion, InferenceTimeMs = _yoloInferenceService.GetModelInfo().InferenceTimeMs, Detections = detections.Select(d => new DetectionDto { ClassId = d.ClassId, ClassName = d.ClassName, Confidence = d.Confidence, X = d.X, Y = d.Y, Width = d.Width, Height = d.Height, CenterX = d.CenterX, CenterY = d.CenterY, Area = d.Area }).ToList() }; // 应用NG阈值 var hasHighConfidenceDetection = detections.Any(d => d.Confidence >= (float)_options.NgConfidenceThreshold); inferenceResult.IsNg = hasHighConfidenceDetection; _logger.LogDebug("YOLO推理完成,检测到 {Count} 个目标,NG判定: {IsNg}", detections.Count, inferenceResult.IsNg); return Result.Success(inferenceResult, message: "YOLO推理成功。"); } catch (Exception ex) { var traceId = Guid.NewGuid().ToString("N"); _logger.LogError(ex, "YOLO推理适配失败。TraceId: {TraceId}", traceId); var result = Result.FromException(ex, "YOLO_ADAPTER_PREDICT_FAILED", "YOLO推理适配失败。", traceId); return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray()); } } /// /// 初始化推理服务。 /// public Result Initialize() { try { _logger.LogInformation("正在初始化YOLO推理适配器..."); var initResult = _yoloInferenceService.Initialize(); if (!initResult.Succeeded) { return initResult; } var modelInfo = _yoloInferenceService.GetModelInfo(); _logger.LogInformation("YOLO推理适配器初始化成功,模型: {ModelName},类别数: {ClassCount}", modelInfo.ModelName, modelInfo.ClassCount); return Result.Success(message: "YOLO推理适配器初始化成功。"); } catch (Exception ex) { var traceId = Guid.NewGuid().ToString("N"); _logger.LogError(ex, "初始化YOLO推理适配器失败。TraceId: {TraceId}", traceId); var result = Result.FromException(ex, "YOLO_ADAPTER_INIT_FAILED", "初始化YOLO推理适配器失败。", traceId); return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray()); } } /// /// 获取模型信息。 /// public YoloModelInfo GetModelInfo() { return _yoloInferenceService.GetModelInfo(); } /// /// 获取支持的类别。 /// public IReadOnlyList GetSupportedClasses() { return _yoloInferenceService.GetSupportedClasses(); } /// /// 清理资源。 /// public void Cleanup() { try { _yoloInferenceService.Dispose(); _logger.LogInformation("YOLO推理适配器清理完成"); } catch (Exception ex) { _logger.LogError(ex, "清理YOLO推理适配器时发生异常"); } } }