603 lines
23 KiB
C#
603 lines
23 KiB
C#
using Microsoft.Extensions.Logging;
|
||
using Microsoft.Extensions.Options;
|
||
using OrpaonVision.Core.Results;
|
||
using OrpaonVision.SiteApp.Runtime.Contracts;
|
||
using OrpaonVision.SiteApp.Runtime.Services;
|
||
using System.IO;
|
||
|
||
namespace OrpaonVision.SiteApp.Runtime.Services;
|
||
|
||
/// <summary>
|
||
/// YOLO推理服务模拟实现。
|
||
/// </summary>
|
||
#if DISABLED_LEGACY_MOCK_YOLO_SERVICE
|
||
public sealed class MockYoloInferenceService : IYoloInferenceService, IDisposable
|
||
{
|
||
private readonly ILogger<MockYoloInferenceService> _logger;
|
||
private readonly YoloInferenceOptions _options;
|
||
private readonly object _lockObject = new();
|
||
private bool _isInitialized;
|
||
private readonly List<string> _classNames = new();
|
||
private readonly Random _random = new();
|
||
private YoloModelInfo _modelInfo = new();
|
||
|
||
/// <summary>
|
||
/// 构造函数。
|
||
/// </summary>
|
||
public MockYoloInferenceService(ILogger<MockYoloInferenceService> logger, IOptions<YoloInferenceOptions> options)
|
||
{
|
||
_logger = logger;
|
||
_options = options.Value;
|
||
_logger.LogInformation("YOLO推理服务已初始化(模拟模式)");
|
||
}
|
||
|
||
#endif
|
||
|
||
/// <summary>
|
||
/// YOLO推理服务模拟实现(最小可编译版本)。
|
||
/// </summary>
|
||
public sealed class MockYoloInferenceService : IYoloInferenceService, IDisposable
|
||
{
|
||
private readonly ILogger<MockYoloInferenceService> _logger;
|
||
private readonly YoloInferenceOptions _options;
|
||
private bool _initialized;
|
||
private readonly IReadOnlyList<string> _classNames = Array.Empty<string>();
|
||
|
||
public MockYoloInferenceService(ILogger<MockYoloInferenceService> logger, IOptions<YoloInferenceOptions> options)
|
||
{
|
||
_logger = logger;
|
||
_options = options.Value;
|
||
}
|
||
|
||
public bool IsInitialized => _initialized;
|
||
|
||
public Result Initialize()
|
||
{
|
||
_initialized = true;
|
||
return Result.Success(message: "YOLO模型初始化成功(模拟)。");
|
||
}
|
||
|
||
public Result<IReadOnlyList<YoloDetectionResult>> Predict(byte[] imageData, int width, int height, string pixelFormat = "BGR8Packed")
|
||
{
|
||
IReadOnlyList<YoloDetectionResult> detections = Array.Empty<YoloDetectionResult>();
|
||
return Result<IReadOnlyList<YoloDetectionResult>>.Success(detections);
|
||
}
|
||
|
||
public Result<IReadOnlyList<IReadOnlyList<YoloDetectionResult>>> PredictBatch(IReadOnlyList<byte[]> imageBatch, IReadOnlyList<(int width, int height)> dimensions, string pixelFormat = "BGR8Packed")
|
||
{
|
||
var batchResults = new List<IReadOnlyList<YoloDetectionResult>>(imageBatch.Count);
|
||
for (var i = 0; i < imageBatch.Count; i++)
|
||
{
|
||
batchResults.Add(Array.Empty<YoloDetectionResult>());
|
||
}
|
||
|
||
return Result<IReadOnlyList<IReadOnlyList<YoloDetectionResult>>>.Success(batchResults);
|
||
}
|
||
|
||
public IReadOnlyList<string> GetSupportedClasses()
|
||
{
|
||
return _classNames;
|
||
}
|
||
|
||
public YoloModelInfo GetModelInfo()
|
||
{
|
||
return new YoloModelInfo
|
||
{
|
||
ModelName = Path.GetFileNameWithoutExtension(_options.ModelPath),
|
||
ModelVersion = _options.ModelVersion,
|
||
InputSize = (_options.InputWidth, _options.InputHeight),
|
||
ClassCount = _classNames.Count,
|
||
ClassNames = _classNames,
|
||
UseGpu = false,
|
||
InferenceTimeMs = 0,
|
||
ModelFileSize = 0,
|
||
LoadTimeMs = 0
|
||
};
|
||
}
|
||
|
||
public Result Warmup(int warmupCount = 3)
|
||
{
|
||
_logger.LogDebug("执行YOLO模型预热(模拟),次数={WarmupCount}", warmupCount);
|
||
return Result.Success(message: "YOLO模型预热完成(模拟)。");
|
||
}
|
||
|
||
public void Dispose()
|
||
{
|
||
_initialized = false;
|
||
}
|
||
}
|
||
|
||
#if DISABLED_LEGACY_MOCK_YOLO_SERVICE_REMAINDER
|
||
|
||
/// <inheritdoc />
|
||
public Result Initialize()
|
||
{
|
||
lock (_lockObject)
|
||
{
|
||
try
|
||
{
|
||
if (_isInitialized)
|
||
{
|
||
return Result.Success(message: "YOLO模型已初始化(模拟)。");
|
||
}
|
||
|
||
_logger.LogInformation("正在初始化YOLO模型(模拟): {ModelPath}", _options.ModelPath);
|
||
|
||
// 模拟初始化过程
|
||
Thread.Sleep(200); // 模拟加载时间
|
||
|
||
// 初始化模拟类别名称
|
||
_classNames.AddRange(new[]
|
||
{
|
||
"person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck",
|
||
"boat", "traffic light", "fire hydrant", "stop sign", "parking meter", "bench",
|
||
"bird", "cat", "dog", "horse", "sheep", "cow", "elephant", "bear", "zebra",
|
||
"giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee",
|
||
"skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove",
|
||
"skateboard", "surfboard", "tennis racket", "bottle", "wine glass", "cup",
|
||
"fork", "knife", "spoon", "bowl", "banana", "apple", "sandwich", "orange",
|
||
"broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
|
||
"potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse",
|
||
"remote", "keyboard", "cell phone", "microwave", "oven", "toaster", "sink",
|
||
"refrigerator", "book", "clock", "vase", "scissors", "teddy bear", "hair drier",
|
||
"toothbrush"
|
||
});
|
||
|
||
// 设置模拟模型信息
|
||
_modelInfo = new YoloModelInfo
|
||
{
|
||
ModelPath = _options.ModelPath,
|
||
ModelType = "Mock",
|
||
InputWidth = _options.InputWidth,
|
||
InputHeight = _options.InputHeight,
|
||
ClassCount = _classNames.Count,
|
||
Version = "mock-v1.0",
|
||
IsInitialized = true
|
||
};
|
||
|
||
_isInitialized = true;
|
||
_logger.LogInformation("YOLO推理服务初始化成功(模拟),类别数量: {ClassCount}", _classNames.Count);
|
||
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_INIT_FAILED", "初始化YOLO推理服务失败。", traceId);
|
||
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result<InferenceResultDto> Inference(byte[] imageData, int width, int height, string pixelFormat = "BGR8Packed")
|
||
{
|
||
try
|
||
{
|
||
if (!_isInitialized)
|
||
{
|
||
return Result<InferenceResultDto>.Fail("YOLO_NOT_INITIALIZED", "YOLO推理服务未初始化。");
|
||
}
|
||
|
||
_logger.LogDebug("开始YOLO推理(模拟),图像尺寸: {Width}x{Height}, 像素格式: {PixelFormat}", width, height, pixelFormat);
|
||
|
||
// 模拟推理过程
|
||
Thread.Sleep(_random.Next(50, 150)); // 模拟推理时间
|
||
|
||
// 生成模拟检测结果
|
||
var detections = new List<DetectionDto>();
|
||
var detectionCount = _random.Next(0, 5); // 随机生成0-4个检测结果
|
||
|
||
for (int i = 0; i < detectionCount; i++)
|
||
{
|
||
var classId = _random.Next(0, _classNames.Count);
|
||
var confidence = (float)(_random.NextDouble() * 0.4 + 0.6); // 0.6-1.0之间的置信度
|
||
|
||
// 过滤低于置信度阈值的检测结果
|
||
if (confidence < _options.ConfidenceThreshold)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
var detection = new DetectionDto
|
||
{
|
||
ClassId = classId,
|
||
ClassName = _classNames[classId],
|
||
Confidence = confidence,
|
||
X = (int)(_random.NextDouble() * width * 0.8),
|
||
Y = (int)(_random.NextDouble() * height * 0.8),
|
||
Width = (int)(_random.NextDouble() * width * 0.3 + 20),
|
||
Height = (int)(_random.NextDouble() * height * 0.3 + 20)
|
||
};
|
||
|
||
detections.Add(detection);
|
||
}
|
||
|
||
// 应用NMS(非极大值抑制)的简单模拟
|
||
detections = ApplyMockNms(detections);
|
||
|
||
var result = new InferenceResultDto
|
||
{
|
||
Timestamp = DateTime.UtcNow,
|
||
ImageWidth = width,
|
||
ImageHeight = height,
|
||
Detections = detections,
|
||
InferenceTimeMs = _random.Next(50, 200), // 50-200ms推理时间
|
||
ModelVersion = _modelInfo.Version,
|
||
Success = true
|
||
};
|
||
|
||
_logger.LogDebug("YOLO推理完成(模拟),检测到 {Count} 个目标", detections.Count);
|
||
return Result<InferenceResultDto>.Success(result, message: "YOLO推理完成(模拟)。");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var traceId = Guid.NewGuid().ToString("N");
|
||
_logger.LogError(ex, "YOLO推理失败。TraceId: {TraceId}", traceId);
|
||
var result = Result.FromException(ex, "YOLO_INFERENCE_FAILED", "YOLO推理失败。", traceId);
|
||
return Result<InferenceResultDto>.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result<InferenceResultDto> InferenceWithImage(byte[] imageData, int width, int height, string pixelFormat = "BGR8Packed")
|
||
{
|
||
var inferenceResult = Inference(imageData, width, height, pixelFormat);
|
||
if (!inferenceResult.Succeeded)
|
||
{
|
||
return inferenceResult;
|
||
}
|
||
|
||
// 在模拟模式中,可以添加一些可视化的模拟数据
|
||
// 实际实现中,这里应该生成带有检测框的图像
|
||
return inferenceResult;
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result<List<string>> GetClassNames()
|
||
{
|
||
try
|
||
{
|
||
if (!_isInitialized)
|
||
{
|
||
return Result<List<string>>.Fail("YOLO_NOT_INITIALIZED", "YOLO推理服务未初始化。");
|
||
}
|
||
|
||
return Result<List<string>>.Success(_classNames.ToList(), message: "获取类别名称成功(模拟)。");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var traceId = Guid.NewGuid().ToString("N");
|
||
_logger.LogError(ex, "获取YOLO类别名称失败。TraceId: {TraceId}", traceId);
|
||
var result = Result.FromException(ex, "YOLO_GET_CLASSES_FAILED", "获取YOLO类别名称失败。", traceId);
|
||
return Result<List<string>>.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result<YoloModelInfo> GetModelInfo()
|
||
{
|
||
try
|
||
{
|
||
if (!_isInitialized)
|
||
{
|
||
return Result<YoloModelInfo>.Fail("YOLO_NOT_INITIALIZED", "YOLO推理服务未初始化。");
|
||
}
|
||
|
||
return Result<YoloModelInfo>.Success(_modelInfo, message: "获取模型信息成功(模拟)。");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var traceId = Guid.NewGuid().ToString("N");
|
||
_logger.LogError(ex, "获取YOLO模型信息失败。TraceId: {TraceId}", traceId);
|
||
var result = Result.FromException(ex, "YOLO_GET_MODEL_INFO_FAILED", "获取YOLO模型信息失败。", traceId);
|
||
return Result<YoloModelInfo>.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result SetConfidenceThreshold(float threshold)
|
||
{
|
||
try
|
||
{
|
||
if (threshold < 0 || threshold > 1)
|
||
{
|
||
return Result.Fail("INVALID_THRESHOLD", "置信度阈值必须在0-1之间。");
|
||
}
|
||
|
||
_options.ConfidenceThreshold = threshold;
|
||
_logger.LogInformation("YOLO置信度阈值已更新为: {Threshold}(模拟)", threshold);
|
||
|
||
return Result.Success(message: "置信度阈值更新成功(模拟)。");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var traceId = Guid.NewGuid().ToString("N");
|
||
_logger.LogError(ex, "设置YOLO置信度阈值失败。TraceId: {TraceId}", traceId);
|
||
var result = Result.FromException(ex, "YOLO_SET_THRESHOLD_FAILED", "设置置信度阈值失败。", traceId);
|
||
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result SetNmsThreshold(float threshold)
|
||
{
|
||
try
|
||
{
|
||
if (threshold < 0 || threshold > 1)
|
||
{
|
||
return Result.Fail("INVALID_THRESHOLD", "NMS阈值必须在0-1之间。");
|
||
}
|
||
|
||
_options.NmsThreshold = threshold;
|
||
_logger.LogInformation("YOLO NMS阈值已更新为: {Threshold}(模拟)", threshold);
|
||
|
||
return Result.Success(message: "NMS阈值更新成功(模拟)。");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var traceId = Guid.NewGuid().ToString("N");
|
||
_logger.LogError(ex, "设置YOLO NMS阈值失败。TraceId: {TraceId}", traceId);
|
||
var result = Result.FromException(ex, "YOLO_SET_NMS_FAILED", "设置NMS阈值失败。", traceId);
|
||
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 应用模拟的NMS(非极大值抑制)。
|
||
/// </summary>
|
||
private List<DetectionDto> ApplyMockNms(List<DetectionDto> detections)
|
||
{
|
||
if (detections.Count <= 1)
|
||
{
|
||
return detections;
|
||
}
|
||
|
||
var filteredDetections = new List<DetectionDto>();
|
||
|
||
// 按置信度降序排序
|
||
var sortedDetections = detections.OrderByDescending(d => d.Confidence).ToList();
|
||
|
||
foreach (var detection in sortedDetections)
|
||
{
|
||
bool shouldKeep = true;
|
||
|
||
// 检查与已保留检测的重叠度
|
||
foreach (var kept in filteredDetections)
|
||
{
|
||
var iou = CalculateMockIoU(detection, kept);
|
||
if (iou > _options.NmsThreshold)
|
||
{
|
||
shouldKeep = false;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (shouldKeep)
|
||
{
|
||
filteredDetections.Add(detection);
|
||
}
|
||
}
|
||
|
||
return filteredDetections;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算模拟的IoU(交并比)。
|
||
/// </summary>
|
||
private float CalculateMockIoU(DetectionDto box1, DetectionDto box2)
|
||
{
|
||
// 计算交集区域
|
||
var x1 = Math.Max(box1.X, box2.X);
|
||
var y1 = Math.Max(box1.Y, box2.Y);
|
||
var x2 = Math.Min(box1.X + box1.Width, box2.X + box2.Width);
|
||
var y2 = Math.Min(box1.Y + box1.Height, box2.Y + box2.Height);
|
||
|
||
if (x2 <= x1 || y2 <= y1)
|
||
{
|
||
return 0f;
|
||
}
|
||
|
||
var intersection = (x2 - x1) * (y2 - y1);
|
||
|
||
// 计算并集区域
|
||
var area1 = box1.Width * box1.Height;
|
||
var area2 = box2.Width * box2.Height;
|
||
var union = area1 + area2 - intersection;
|
||
|
||
return (float)(intersection / union);
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result<YoloModelInfo> GetModelInfo()
|
||
{
|
||
if (!_isInitialized)
|
||
{
|
||
return Result.Fail<YoloModelInfo>("YOLO_NOT_INITIALIZED", "YOLO模型未初始化。");
|
||
}
|
||
|
||
try
|
||
{
|
||
var modelInfo = new YoloModelInfo
|
||
{
|
||
ModelName = Path.GetFileNameWithoutExtension(_options.ModelPath),
|
||
ModelVersion = _options.ModelVersion,
|
||
ClassNames = _classNames.ToArray(),
|
||
InputSize = new Size(_options.InputWidth, _options.InputHeight),
|
||
LoadTimeMs = 200 // 模拟加载时间
|
||
};
|
||
|
||
_logger.LogDebug("获取YOLO模型信息(模拟): {ModelName}", modelInfo.ModelName);
|
||
return Result.Success(modelInfo);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var traceId = Guid.NewGuid().ToString("N");
|
||
_logger.LogError(ex, "获取YOLO模型信息失败(模拟)。TraceId: {TraceId}", traceId);
|
||
var result = Result.FromException(ex, "YOLO_MODEL_INFO_FAILED", "获取YOLO模型信息失败。", traceId);
|
||
return Result.FailWithTrace<YoloModelInfo>(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result<IReadOnlyList<YoloDetectionResult>> Predict(byte[] imageData, int width, int height, string pixelFormat = "BGR8Packed")
|
||
{
|
||
try
|
||
{
|
||
if (!_isInitialized)
|
||
{
|
||
return Result.Fail<IReadOnlyList<YoloDetectionResult>>("YOLO_NOT_INITIALIZED", "YOLO模型未初始化。");
|
||
}
|
||
|
||
var inferenceResult = Inference(imageData, width, height, pixelFormat);
|
||
if (!inferenceResult.Succeeded)
|
||
{
|
||
return Result.Fail<IReadOnlyList<YoloDetectionResult>>(inferenceResult.Code, inferenceResult.Message, inferenceResult.Errors.ToArray());
|
||
}
|
||
|
||
// 转换为YoloDetectionResult格式
|
||
var results = new List<YoloDetectionResult>();
|
||
foreach (var detection in inferenceResult.Data.Detections)
|
||
{
|
||
var result = new YoloDetectionResult
|
||
{
|
||
ClassId = detection.ClassId,
|
||
ClassName = detection.ClassName ?? $"Class_{detection.ClassId}",
|
||
Confidence = detection.Confidence,
|
||
X = detection.X,
|
||
Y = detection.Y,
|
||
Width = detection.Width,
|
||
Height = detection.Height
|
||
};
|
||
results.Add(result);
|
||
}
|
||
|
||
return Result.Success<IReadOnlyList<YoloDetectionResult>>(results);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var traceId = Guid.NewGuid().ToString("N");
|
||
_logger.LogError(ex, "YOLO推理失败(模拟)。TraceId: {TraceId}", traceId);
|
||
var result = Result.FromException(ex, "YOLO_PREDICT_FAILED", "YOLO推理失败。", traceId);
|
||
return Result.FailWithTrace<IReadOnlyList<YoloDetectionResult>>(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result<IReadOnlyList<YoloDetectionResult[]>> PredictBatch(IReadOnlyList<byte[]> imageDataList, IReadOnlyList<(int width, int height)> dimensions, string pixelFormat = "BGR8Packed")
|
||
{
|
||
try
|
||
{
|
||
if (!_isInitialized)
|
||
{
|
||
return Result.Fail<IReadOnlyList<YoloDetectionResult[]>>("YOLO_NOT_INITIALIZED", "YOLO模型未初始化。");
|
||
}
|
||
|
||
var batchResults = new List<YoloDetectionResult[]>();
|
||
|
||
for (int i = 0; i < imageDataList.Count; i++)
|
||
{
|
||
var imageData = imageDataList[i];
|
||
var (width, height) = dimensions[i];
|
||
|
||
var singleResult = Predict(imageData, width, height, pixelFormat);
|
||
if (singleResult.Succeeded)
|
||
{
|
||
batchResults.Add(singleResult.Data.ToArray());
|
||
}
|
||
else
|
||
{
|
||
batchResults.Add(Array.Empty<YoloDetectionResult>());
|
||
}
|
||
}
|
||
|
||
return Result.Success<IReadOnlyList<YoloDetectionResult[]>>(batchResults);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var traceId = Guid.NewGuid().ToString("N");
|
||
_logger.LogError(ex, "YOLO批量推理失败(模拟)。TraceId: {TraceId}", traceId);
|
||
var result = Result.FromException(ex, "YOLO_BATCH_PREDICT_FAILED", "YOLO批量推理失败。", traceId);
|
||
return Result.FailWithTrace<IReadOnlyList<YoloDetectionResult[]>>(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Result<IReadOnlyList<string>> GetSupportedClasses()
|
||
{
|
||
try
|
||
{
|
||
if (!_isInitialized)
|
||
{
|
||
return Result.Fail<IReadOnlyList<string>>("YOLO_NOT_INITIALIZED", "YOLO模型未初始化。");
|
||
}
|
||
|
||
return Result.Success<IReadOnlyList<string>>(_classNames.ToList());
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
var traceId = Guid.NewGuid().ToString("N");
|
||
_logger.LogError(ex, "获取YOLO支持类别失败(模拟)。TraceId: {TraceId}", traceId);
|
||
var result = Result.FromException(ex, "YOLO_GET_CLASSES_FAILED", "获取YOLO支持类别失败。", traceId);
|
||
return Result.FailWithTrace<IReadOnlyList<string>>(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public bool IsInitialized => _isInitialized;
|
||
|
||
/// <inheritdoc />
|
||
public Result Warmup(int iterations = 10)
|
||
{
|
||
try
|
||
{
|
||
if (!_isInitialized)
|
||
{
|
||
return Result.Fail("YOLO_NOT_INITIALIZED", "YOLO模型未初始化。");
|
||
}
|
||
|
||
_logger.LogInformation("正在执行YOLO模型预热(模拟),迭代次数: {Iterations}", iterations);
|
||
|
||
// 创建一个小的测试图像进行预热
|
||
var testImageData = new byte[640 * 640 * 3]; // 640x640 BGR图像
|
||
|
||
for (int i = 0; i < iterations; i++)
|
||
{
|
||
var warmupResult = Predict(testImageData, 640, 640);
|
||
if (!warmupResult.Succeeded)
|
||
{
|
||
_logger.LogWarning("YOLO预热第{Iteration}次迭代失败(模拟): {Error}", i + 1, warmupResult.Message);
|
||
}
|
||
}
|
||
|
||
_logger.LogInformation("YOLO模型预热完成(模拟)");
|
||
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_WARMUP_FAILED", "YOLO模型预热失败。", traceId);
|
||
return Result.FailWithTrace(result.Code, result.Message, result.TraceId ?? traceId, result.Errors.ToArray());
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 释放资源。
|
||
/// </summary>
|
||
public void Dispose()
|
||
{
|
||
try
|
||
{
|
||
_isInitialized = false;
|
||
_classNames.Clear();
|
||
_logger.LogInformation("YOLO推理服务资源已释放(模拟)");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "释放YOLO推理服务资源时发生异常");
|
||
}
|
||
}
|
||
}
|
||
#endif
|