Files
OrpaonVision/OrpaonVision.SiteApp/Runtime/Services/YoloInferenceAdapter.cs
2026-04-06 22:04:05 +08:00

165 lines
5.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
/// <summary>
/// YOLO推理服务适配器将IYoloInferenceService适配到IInferenceService接口。
/// </summary>
public sealed class YoloInferenceAdapter : IInferenceService
{
private readonly ILogger<YoloInferenceAdapter> _logger;
private readonly IYoloInferenceService _yoloInferenceService;
private readonly RuntimeOptions _options;
/// <summary>
/// 构造函数。
/// </summary>
public YoloInferenceAdapter(
ILogger<YoloInferenceAdapter> logger,
IYoloInferenceService yoloInferenceService,
IOptions<RuntimeOptions> options)
{
_logger = logger;
_yoloInferenceService = yoloInferenceService;
_options = options.Value;
}
/// <inheritdoc />
public Result<InferenceResultDto> Predict(CameraFrameDto frame)
{
try
{
// 确保YOLO模型已初始化
if (!_yoloInferenceService.IsInitialized)
{
var initResult = _yoloInferenceService.Initialize();
if (!initResult.Succeeded)
{
return Result<InferenceResultDto>.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<InferenceResultDto>.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<InferenceResultDto>.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<InferenceResultDto>.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
}
}
/// <summary>
/// 初始化推理服务。
/// </summary>
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());
}
}
/// <summary>
/// 获取模型信息。
/// </summary>
public YoloModelInfo GetModelInfo()
{
return _yoloInferenceService.GetModelInfo();
}
/// <summary>
/// 获取支持的类别。
/// </summary>
public IReadOnlyList<string> GetSupportedClasses()
{
return _yoloInferenceService.GetSupportedClasses();
}
/// <summary>
/// 清理资源。
/// </summary>
public void Cleanup()
{
try
{
_yoloInferenceService.Dispose();
_logger.LogInformation("YOLO推理适配器清理完成");
}
catch (Exception ex)
{
_logger.LogError(ex, "清理YOLO推理适配器时发生异常");
}
}
}