版本260406
This commit is contained in:
164
OrpaonVision.SiteApp/Runtime/Services/YoloInferenceAdapter.cs
Normal file
164
OrpaonVision.SiteApp/Runtime/Services/YoloInferenceAdapter.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
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推理适配器时发生异常");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user