using CSScripting; using OpenCvSharp; using OpenCvSharp.Extensions; using OpenCvSharp.WpfExtensions; using OxyPlot; using OxyPlot.Axes; using OxyPlot.Series; using Prism.Commands; using Prism.Mvvm; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using TeamAAS_VP.Core; using TeamAAS_VP.Enums; using TeamAAS_VP.Models; namespace TeamAAS_VP.Controls { public partial class FocusAnalyzerControl : UserControl { private FocusAnalyzerViewModel ViewModel; // 鼠标状态 private bool _isMouseDown = false; private System.Windows.Point _mouseDownPoint; public FocusAnalyzerControl() { InitializeComponent(); Loaded += OnLoaded; } private void OnLoaded(object sender, RoutedEventArgs e) { // 初始化ViewModel if (DataContext == null) DataContext = new FocusAnalyzerViewModel(); ViewModel=DataContext as FocusAnalyzerViewModel; } #region 鼠标事件处理 private void ImageDisplay_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { if (ViewModel == null) return; _isMouseDown = true; _mouseDownPoint = e.GetPosition(ImageDisplay); // 处理ROI操作 if (ViewModel.CurrentRoi != null) { // 检查是否点击了ROI if (ViewModel.StartRoiDrag(_mouseDownPoint)) { CaptureMouse(); return; } } // 开始绘制新ROI if (ViewModel.RoiMode == RoiOperationMode.Draw) { ViewModel.StartRoiDrawing(_mouseDownPoint); CaptureMouse(); } } private void ImageDisplay_MouseMove(object sender, MouseEventArgs e) { if (ViewModel == null || !_isMouseDown) return; var currentPoint = e.GetPosition(ImageDisplay); // 处理ROI拖动 if (ViewModel.RoiMode != RoiOperationMode.Draw && ViewModel.CurrentRoi != null) { ViewModel.UpdateRoiDrag(currentPoint); UpdateRoiVisual(); } // 处理ROI绘制 else if (ViewModel.RoiMode == RoiOperationMode.Draw) { ViewModel.UpdateRoiDrawing(currentPoint); UpdateRoiVisual(); } } private void ImageDisplay_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if (ViewModel == null || !_isMouseDown) return; _isMouseDown = false; ReleaseMouseCapture(); if (ViewModel.RoiMode == RoiOperationMode.Draw) { ViewModel.FinishRoiDrawing(); } else { ViewModel.FinishRoiDrag(); } } #endregion #region ROI可视化更新 private void UpdateRoiVisual() { if (ViewModel?.CurrentRoi == null) return; // 更新ROI矩形位置和大小 Canvas.SetLeft(RoiRectangle, ViewModel.CurrentRoi.X); Canvas.SetTop(RoiRectangle, ViewModel.CurrentRoi.Y); RoiRectangle.Width = ViewModel.CurrentRoi.Width; RoiRectangle.Height = ViewModel.CurrentRoi.Height; // 更新控制点位置 UpdateRoiHandles(); } private void UpdateRoiHandles() { if (ViewModel?.CurrentRoi == null) return; var roi = ViewModel.CurrentRoi; // 更新角点 UpdateHandlePosition(TopLeftHandle, roi.X, roi.Y); UpdateHandlePosition(TopRightHandle, roi.X + roi.Width, roi.Y); UpdateHandlePosition(BottomLeftHandle, roi.X, roi.Y + roi.Height); UpdateHandlePosition(BottomRightHandle, roi.X + roi.Width, roi.Y + roi.Height); // 更新边中点 UpdateHandlePosition(TopHandle, roi.X + roi.Width / 2, roi.Y); UpdateHandlePosition(RightHandle, roi.X + roi.Width, roi.Y + roi.Height / 2); UpdateHandlePosition(BottomHandle, roi.X + roi.Width / 2, roi.Y + roi.Height); UpdateHandlePosition(LeftHandle, roi.X, roi.Y + roi.Height / 2); // 更新旋转控制点 UpdateRotateHandlePosition(roi); } private void UpdateHandlePosition(FrameworkElement handle, double x, double y) { if (handle == null) return; Canvas.SetLeft(handle, x - handle.Width / 2); Canvas.SetTop(handle, y - handle.Height / 2); } private void UpdateRotateHandlePosition(RotatedRect roi) { if (RotateHandle == null) return; // 旋转控制点在矩形顶部中心上方 double centerX = roi.X + roi.Width / 2; double centerY = roi.Y + roi.Height / 2; // 计算旋转后的位置 double angleRad = roi.Angle * Math.PI / 180; double radius = Math.Max(roi.Width, roi.Height) / 2 + 20; // 距离中心20像素 double x = centerX + radius * Math.Sin(angleRad); double y = centerY - radius * Math.Cos(angleRad); // 设置位置 RotateHandle.RenderTransform = new RotateTransform(roi.Angle); Canvas.SetLeft(RotateHandle, x - 5); // 5是三角形宽度的一半 Canvas.SetTop(RotateHandle, y - 5); // 5是三角形高度的一半 } #endregion #region 依赖属性 // CurrentImage依赖属性 public static readonly DependencyProperty CurrentImageProperty = DependencyProperty.Register("CurrentImage", typeof(ImageSource), typeof(FocusAnalyzerControl), new PropertyMetadata(null, OnCurrentImageChanged)); public ImageSource CurrentImage { get => (ImageSource)GetValue(CurrentImageProperty); set => SetValue(CurrentImageProperty, value); } private static void OnCurrentImageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = d as FocusAnalyzerControl; if (control.ViewModel != null) control.ViewModel.CurrentImage = e.NewValue as ImageSource; } // Parameters依赖属性 public static readonly DependencyProperty ParametersProperty = DependencyProperty.Register("Parameters", typeof(AnalysisParameters), typeof(FocusAnalyzerControl), new PropertyMetadata(new AnalysisParameters(), OnParametersChanged)); public AnalysisParameters Parameters { get => (AnalysisParameters)GetValue(ParametersProperty); set => SetValue(ParametersProperty, value); } private static void OnParametersChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = d as FocusAnalyzerControl; if (control.ViewModel != null) control.ViewModel.Parameters = e.NewValue as AnalysisParameters; } // CurrentResult依赖属性 public static readonly DependencyProperty CurrentResultProperty = DependencyProperty.Register("CurrentResult", typeof(AnalysisResult), typeof(FocusAnalyzerControl), new PropertyMetadata(new AnalysisResult(), OnCurrentResultChanged)); public AnalysisResult CurrentResult { get => (AnalysisResult)GetValue(CurrentResultProperty); set => SetValue(CurrentResultProperty, value); } private static void OnCurrentResultChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = d as FocusAnalyzerControl; if (control.ViewModel != null) control.ViewModel.CurrentResult = e.NewValue as AnalysisResult; } // StartAnalysisCommand依赖属性 public static readonly DependencyProperty StartAnalysisCommandProperty = DependencyProperty.Register("StartAnalysisCommand", typeof(ICommand), typeof(FocusAnalyzerControl), new PropertyMetadata(null, OnStartAnalysisCommandChanged)); public ICommand StartAnalysisCommand { get => (ICommand)GetValue(StartAnalysisCommandProperty); set => SetValue(StartAnalysisCommandProperty, value); } private static void OnStartAnalysisCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = d as FocusAnalyzerControl; if (control.ViewModel != null) control.ViewModel.StartAnalysisCommand = e.NewValue as ICommand; } // 其他命令和属性的依赖属性... #endregion #region 公共方法 /// /// 处理图像帧 /// public async Task ProcessImageFrameAsync(OpenCvSharp.Mat frame) { if (ViewModel != null) await ViewModel.ProcessImageFrameAsync(frame); } /// /// 执行单次分析 /// public void PerformAnalysis(OpenCvSharp.Mat frame) { ViewModel?.PerformAnalysis(frame); } /// /// 获取当前ROI区域 /// public OpenCvSharp.Rect? GetCurrentRoiRect() { if (ViewModel?.CurrentRoi == null) return null; return new OpenCvSharp.Rect( (int)ViewModel.CurrentRoi.X, (int)ViewModel.CurrentRoi.Y, (int)ViewModel.CurrentRoi.Width, (int)ViewModel.CurrentRoi.Height); } /// /// 获取旋转ROI /// public OpenCvSharp.RotatedRect? GetCurrentRotatedRoi() { if (ViewModel?.CurrentRoi == null) return null; return ViewModel.CurrentRoi.ToCvRotatedRect(); } #endregion } }