165 lines
5.8 KiB
C#
165 lines
5.8 KiB
C#
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推理适配器时发生异常");
|
||
}
|
||
}
|
||
}
|