using Microsoft.Extensions.Logging; using OrpaonVision.SiteApp.Controls; using OrpaonVision.SiteApp.Runtime.Contracts; using OrpaonVision.SiteApp.Runtime.Services; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Windows.Media; using System.Windows.Media.Imaging; namespace OrpaonVision.SiteApp.ViewModels; /// /// 优化的运行端主窗口 ViewModel。 /// public sealed class OptimizedMainWindowViewModel : INotifyPropertyChanged { private readonly ICameraService _cameraService; private readonly IInferenceService _inferenceService; private readonly IRuleEngineService _ruleEngineService; private readonly IRuntimeStateMachineService _runtimeStateMachineService; private readonly IImageProcessingService _imageProcessingService; private readonly ILogger _logger; private string _statusText = "准备就绪。"; private Brush _statusBrush = Brushes.DarkGreen; private string _layerText = "1/1"; private string _inferenceText = "-"; private string _decisionText = "-"; private BitmapSource? _currentImage; private List _detectionBoxes = new(); private ImageDisplayMode _displayMode = ImageDisplayMode.Fit; private bool _showDetectionBoxes = true; private bool _isAutoRunning = false; private int _frameRate = 1; private int _totalFrames = 0; private int _successFrames = 0; private int _failedFrames = 0; private DateTime _lastFrameTime = DateTime.MinValue; private double _actualFrameRate = 0; /// /// 构造函数。 /// public OptimizedMainWindowViewModel( ICameraService cameraService, IInferenceService inferenceService, IRuleEngineService ruleEngineService, IRuntimeStateMachineService runtimeStateMachineService, IImageProcessingService imageProcessingService, ILogger logger) { _cameraService = cameraService; _inferenceService = inferenceService; _ruleEngineService = ruleEngineService; _runtimeStateMachineService = runtimeStateMachineService; _imageProcessingService = imageProcessingService; _logger = logger; // 初始化占位图像 _currentImage = _imageProcessingService.CreatePlaceholderImage(640, 480, "等待图像..."); RefreshSnapshot(); } /// /// 状态文本。 /// public string StatusText { get => _statusText; private set => SetProperty(ref _statusText, value); } /// /// 状态颜色。 /// public Brush StatusBrush { get => _statusBrush; private set => SetProperty(ref _statusBrush, value); } /// /// 当前层显示文本。 /// public string LayerText { get => _layerText; private set => SetProperty(ref _layerText, value); } /// /// 最近一次推理结果。 /// public string InferenceText { get => _inferenceText; private set => SetProperty(ref _inferenceText, value); } /// /// 最近一次规则判定结果。 /// public string DecisionText { get => _decisionText; private set => SetProperty(ref _decisionText, value); } /// /// 当前图像。 /// public BitmapSource? CurrentImage { get => _currentImage; private set => SetProperty(ref _currentImage, value); } /// /// 检测框列表。 /// public List DetectionBoxes { get => _detectionBoxes; private set => SetProperty(ref _detectionBoxes, value); } /// /// 图像显示模式。 /// public ImageDisplayMode DisplayMode { get => _displayMode; set => SetProperty(ref _displayMode, value); } /// /// 是否显示检测框。 /// public bool ShowDetectionBoxes { get => _showDetectionBoxes; set => SetProperty(ref _showDetectionBoxes, value); } /// /// 是否自动运行。 /// public bool IsAutoRunning { get => _isAutoRunning; private set => SetProperty(ref _isAutoRunning, value); } /// /// 帧率设置。 /// public int FrameRate { get => _frameRate; set => SetProperty(ref _frameRate, value); } /// /// 总帧数。 /// public int TotalFrames { get => _totalFrames; private set => SetProperty(ref _totalFrames, value); } /// /// 成功帧数。 /// public int SuccessFrames { get => _successFrames; private set => SetProperty(ref _successFrames, value); } /// /// 失败帧数。 /// public int FailedFrames { get => _failedFrames; private set => SetProperty(ref _failedFrames, value); } /// /// 实际帧率。 /// public double ActualFrameRate { get => _actualFrameRate; private set => SetProperty(ref _actualFrameRate, value); } /// /// 成功率。 /// public double SuccessRate { get => TotalFrames > 0 ? (double)SuccessFrames / TotalFrames * 100 : 0; } /// public event PropertyChangedEventHandler? PropertyChanged; /// /// 执行一轮采集-推理-规则判定。 /// public void RunOneCycle() { try { var snapshot = _runtimeStateMachineService.GetSnapshot(); // 采集图像 var captureResult = _cameraService.CaptureFrame(); if (!captureResult.Succeeded || captureResult.Data is null) { SetError("相机采图失败。", captureResult.Message); _failedFrames++; UpdateStatistics(); return; } // 转换图像 var imageResult = _imageProcessingService.ConvertFrameToBitmapSource(captureResult.Data); if (!imageResult.Succeeded || imageResult.Data is null) { SetError("图像转换失败。", imageResult.Message); _failedFrames++; UpdateStatistics(); return; } CurrentImage = imageResult.Data; // 推理 var predictResult = _inferenceService.Predict(captureResult.Data); if (!predictResult.Succeeded || predictResult.Data is null) { SetError("模型推理失败。", predictResult.Message); _failedFrames++; UpdateStatistics(); return; } var inference = predictResult.Data; InferenceText = $"{inference.Label} (置信度: {inference.Confidence:P0})"; // 转换检测结果 var detectionResult = _imageProcessingService.ConvertInferenceToDetectionBoxes(inference); if (detectionResult.Succeeded) { DetectionBoxes = detectionResult.Data ?? new List(); } // 规则判定 var decisionResult = _ruleEngineService.Evaluate(snapshot.CurrentLayer, inference); if (!decisionResult.Succeeded || decisionResult.Data is null) { SetError("规则判定失败。", decisionResult.Message); _failedFrames++; UpdateStatistics(); return; } var decision = decisionResult.Data; DecisionText = $"{decision.Code} - {decision.Message}"; StatusBrush = decision.IsPass ? Brushes.DarkGreen : Brushes.OrangeRed; StatusText = decision.IsPass ? "当前层判定通过。" : "当前层判定 NG,请人工复核。"; _successFrames++; UpdateStatistics(); } catch (Exception ex) { _logger.LogError(ex, "执行一轮检测失败"); SetError("执行检测失败。", ex.Message); _failedFrames++; UpdateStatistics(); } } /// /// 推进到下一层。 /// public void MoveToNextLayer() { try { var moveResult = _runtimeStateMachineService.MoveToNextLayer(); if (!moveResult.Succeeded) { SetError("状态机切层失败。", moveResult.Message); return; } RefreshSnapshot(); StatusBrush = Brushes.DarkGreen; StatusText = moveResult.Message; } catch (Exception ex) { _logger.LogError(ex, "推进到下一层失败"); SetError("推进下一层失败。", ex.Message); } } /// /// 重置运行状态。 /// public void ResetRuntime() { try { _runtimeStateMachineService.Reset(); InferenceText = "-"; DecisionText = "-"; DetectionBoxes = new List(); CurrentImage = _imageProcessingService.CreatePlaceholderImage(640, 480, "等待图像..."); RefreshSnapshot(); // 重置统计 _totalFrames = 0; _successFrames = 0; _failedFrames = 0; _actualFrameRate = 0; UpdateStatistics(); StatusBrush = Brushes.DarkGreen; StatusText = "运行状态已重置。"; } catch (Exception ex) { _logger.LogError(ex, "重置运行状态失败"); SetError("重置状态失败。", ex.Message); } } /// /// 切换自动运行。 /// public void ToggleAutoRun() { IsAutoRunning = !IsAutoRunning; if (IsAutoRunning) { StatusBrush = Brushes.Blue; StatusText = "自动运行已启动。"; _logger.LogInformation("自动运行已启动,帧率: {FrameRate}", FrameRate); } else { StatusBrush = Brushes.DarkGreen; StatusText = "自动运行已停止。"; _logger.LogInformation("自动运行已停止"); } } /// /// 更新图像显示模式。 /// public void UpdateDisplayMode(ImageDisplayMode mode) { DisplayMode = mode; _logger.LogInformation("图像显示模式已更新: {Mode}", mode); } /// /// 切换检测框显示。 /// public void ToggleDetectionBoxes() { ShowDetectionBoxes = !ShowDetectionBoxes; _logger.LogInformation("检测框显示已切换: {Show}", ShowDetectionBoxes); } /// /// 应用图像滤镜。 /// public void ApplyImageFilter(ImageFilter filter) { if (CurrentImage == null) { StatusText = "没有可应用滤镜的图像。"; return; } try { var filterResult = _imageProcessingService.ApplyFilter(CurrentImage, filter); if (filterResult.Succeeded && filterResult.Data != null) { CurrentImage = filterResult.Data; StatusText = $"已应用滤镜: {filter}"; } else { SetError("应用滤镜失败。", filterResult.Message); } } catch (Exception ex) { _logger.LogError(ex, "应用图像滤镜失败"); SetError("应用滤镜失败。", ex.Message); } } /// /// 保存当前图像。 /// public void SaveCurrentImage() { if (CurrentImage == null) { StatusText = "没有可保存的图像。"; return; } try { // 这里可以实现图像保存功能 StatusText = "图像保存功能待实现。"; } catch (Exception ex) { _logger.LogError(ex, "保存图像失败"); SetError("保存图像失败。", ex.Message); } } /// /// 更新统计信息。 /// private void UpdateStatistics() { TotalFrames = _totalFrames; SuccessFrames = _successFrames; FailedFrames = _failedFrames; // 计算实际帧率 if (_lastFrameTime != DateTime.MinValue) { var elapsed = DateTime.Now - _lastFrameTime; if (elapsed.TotalSeconds > 0) { _actualFrameRate = 1.0 / elapsed.TotalSeconds; } } _lastFrameTime = DateTime.Now; ActualFrameRate = Math.Round(_actualFrameRate, 2); } private void RefreshSnapshot() { var snapshot = _runtimeStateMachineService.GetSnapshot(); LayerText = $"{snapshot.CurrentLayer}/{snapshot.TotalLayers}"; } private void SetError(string title, string message) { StatusBrush = Brushes.OrangeRed; StatusText = $"{title} {message}"; } private void SetProperty(ref T field, T value, [CallerMemberName] string? propertyName = null) { if (EqualityComparer.Default.Equals(field, value)) { return; } field = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }