diff --git a/Wpf_AiSportsMicrospace/Views/Setting/JumpSetting.xaml b/Wpf_AiSportsMicrospace/Views/Setting/JumpSetting.xaml
new file mode 100644
index 0000000..213adb8
--- /dev/null
+++ b/Wpf_AiSportsMicrospace/Views/Setting/JumpSetting.xaml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/Wpf_AiSportsMicrospace/Views/Setting/JumpSetting.xaml.cs b/Wpf_AiSportsMicrospace/Views/Setting/JumpSetting.xaml.cs
new file mode 100644
index 0000000..6d5cedf
--- /dev/null
+++ b/Wpf_AiSportsMicrospace/Views/Setting/JumpSetting.xaml.cs
@@ -0,0 +1,348 @@
+using AiSportsMicrospaceDB.DBContext;
+using Emgu.CV.Reg;
+using Microsoft.EntityFrameworkCore;
+using SharpDX.Direct3D9;
+using SkiaSharp;
+using System.Diagnostics;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Net.NetworkInformation;
+using System.Runtime.InteropServices;
+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 System.Windows.Shapes;
+using System.Windows.Threading;
+using Wpf_AiSportsMicrospace.Common;
+using Wpf_AiSportsMicrospace.Dto;
+using Yztob.AiSports.Inferences.Abstractions;
+using Yztob.AiSports.Inferences.Things;
+using Yztob.AiSports.Postures.Sports;
+using Yztob.AiSports.Postures.Things;
+using Yztob.AiSports.Sensors.Abstractions;
+using Yztob.AiSports.Sensors.Things;
+
+namespace Wpf_AiSportsMicrospace.Views
+{
+ public partial class JumpSttting : UserControl
+ {
+ #region 私有成员
+ private IHumanPredictor _humanPredictor;
+ private IObjectDetector _objectDetector;
+ private HumanGraphicsRenderer _humanGraphicsRenderer;
+ private readonly List _sports;
+ private SportBase _sport;
+ private readonly SportDetectionQueue _detectQueue;
+
+ private WriteableBitmap _videoBitmap;
+ private int _lastFrameNumber = -1;
+
+ // 拖拽相关成员变量
+ private bool _isDragging = false;
+ private Ellipse? _draggingEllipse;
+ private TextBlock? _draggingTextBlock;
+ private Point _dragStartMousePos;
+ private double _dragStartLeft;
+ private double _dragStartTop;
+ #endregion
+
+ public JumpSttting()
+ {
+ InitializeComponent();
+
+ _humanPredictor = HumanPredictorFactory.Create(HumanPredictorType.SingleHigh);
+ _objectDetector = ObjectDetectorFactory.CreateSportGoodsDetector();
+ _humanGraphicsRenderer = new HumanGraphicsRenderer();
+ _humanGraphicsRenderer.DrawLabel = false;
+
+ _sports = SportBase.GetSports();
+
+ _detectQueue = new SportDetectionQueue();
+
+ // 确保在加载完成后绘制圆圈
+ this.Loaded += (s, e) => DrawCirclesWithText();
+ }
+
+ private void Window_Loaded(object sender, RoutedEventArgs e)
+ {
+ Application.Current.Dispatcher.InvokeAsync(() =>
+ {
+ DrawCirclesWithText();
+ }, DispatcherPriority.Loaded);
+
+ videoImage.SizeChanged += (s, ev) =>
+ {
+ DrawCirclesWithText();
+ };
+ }
+
+ ///
+ /// 绘制可拖动的圆圈和位置文本
+ ///
+ private void DrawCirclesWithText()
+ {
+ if (overlayCanvas == null)
+ {
+ Debug.WriteLine("overlayCanvas 为空,无法绘制");
+ return;
+ }
+
+ try
+ {
+ overlayCanvas.Children.Clear();
+ Debug.WriteLine($"Canvas 尺寸: {overlayCanvas.ActualWidth} x {overlayCanvas.ActualHeight}");
+
+ double imgWidth = overlayCanvas.ActualWidth;
+ double imgHeight = overlayCanvas.ActualHeight;
+
+ // 如果实际尺寸为0,使用控件大小
+ if (imgWidth <= 0 || imgHeight <= 0)
+ {
+ imgWidth = this.videoImage?.ActualWidth ?? 800;
+ imgHeight = this.videoImage?.ActualHeight ?? 600;
+ Debug.WriteLine($"使用备用尺寸: {imgWidth} x {imgHeight}");
+ }
+
+ if (imgWidth <= 0 || imgHeight <= 0)
+ {
+ Debug.WriteLine("尺寸无效,跳过绘制");
+ return;
+ }
+
+ double radius = 50;
+ int circleIndex = 1;
+
+ // 每个圆的位置:X 和 Y 都归一化 0~1
+ var circlePositions = new List<(double XNorm, double YNorm)>
+ {
+ (0.1, 0.6),
+ (0.3, 0.8),
+ (0.5, 0.6),
+ (0.7, 0.8),
+ (0.9, 0.6)
+ };
+
+ foreach (var pos in circlePositions)
+ {
+ double x = pos.XNorm * imgWidth;
+ double y = pos.YNorm * imgHeight;
+
+ Debug.WriteLine($"创建第{circleIndex}个圆: 原始坐标 ({x:F0}, {y:F0})");
+
+ // 创建圆圈
+ var ellipse = CreateDraggableEllipse(x, y, radius);
+
+ // 创建文本控件
+ var textBlock = CreatePositionText(x, y, radius, circleIndex);
+
+ overlayCanvas.Children.Add(ellipse);
+ overlayCanvas.Children.Add(textBlock);
+
+ circleIndex++;
+ }
+
+ Debug.WriteLine($"成功绘制 {circleIndex - 1} 个可拖动圆圈");
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"绘制圆圈时出错: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 创建可拖动的圆圈
+ ///
+ private Ellipse CreateDraggableEllipse(double centerX, double centerY, double radius)
+ {
+ var ellipse = new Ellipse
+ {
+ Width = radius * 2,
+ Height = radius * 2,
+ Opacity = 0.7,
+ Fill = new SolidColorBrush(Colors.Blue),
+ Stroke = new SolidColorBrush(Colors.Yellow),
+ StrokeThickness = 3,
+ Cursor = Cursors.Hand,
+ Tag = "draggable_circle" // 添加标记便于识别
+ };
+
+ Canvas.SetLeft(ellipse, centerX - radius);
+ Canvas.SetTop(ellipse, centerY - radius);
+
+ // 添加鼠标事件处理程序
+ ellipse.MouseLeftButtonDown += Ellipse_MouseLeftButtonDown;
+ ellipse.MouseMove += Ellipse_MouseMove;
+ ellipse.MouseLeftButtonUp += Ellipse_MouseLeftButtonUp;
+ ellipse.MouseEnter += (s, e) => ellipse.Opacity = 0.9;
+ ellipse.MouseLeave += (s, e) => ellipse.Opacity = _isDragging ? 1.0 : 0.7;
+
+ return ellipse;
+ }
+
+ ///
+ /// 创建位置显示文本
+ ///
+ private TextBlock CreatePositionText(double centerX, double centerY, double radius, int circleIndex)
+ {
+ var textBlock = new TextBlock
+ {
+ Text = $"圆{circleIndex}: ({centerX:F0}, {centerY:F0})",
+ Foreground = Brushes.Red,
+ FontWeight = FontWeights.Bold,
+ FontSize = 14,
+ TextAlignment = TextAlignment.Center,
+ Width = 150,
+ Height = 25,
+ Background = new SolidColorBrush(Color.FromArgb(180, 255, 255, 255)),
+ Tag = $"text_for_circle_{circleIndex}"
+ };
+
+ Canvas.SetLeft(textBlock, centerX - 75);
+ Canvas.SetTop(textBlock, centerY - radius - 30);
+
+ return textBlock;
+ }
+
+ ///
+ /// 鼠标按下事件:开始拖动
+ ///
+ private void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+ {
+ if (sender is not Ellipse ellipse || overlayCanvas == null) return;
+
+ Debug.WriteLine("开始拖动圆圈");
+
+ _draggingEllipse = ellipse;
+ _isDragging = true;
+ _dragStartMousePos = e.GetPosition(overlayCanvas);
+ _dragStartLeft = Canvas.GetLeft(ellipse);
+ _dragStartTop = Canvas.GetTop(ellipse);
+
+ // 查找对应的文本控件
+ _draggingTextBlock = FindCorrespondingTextBlock(ellipse);
+
+ ellipse.CaptureMouse();
+ ellipse.Opacity = 1.0;
+ e.Handled = true;
+ }
+
+ ///
+ /// 查找圆圈对应的文本控件
+ ///
+ private TextBlock? FindCorrespondingTextBlock(Ellipse ellipse)
+ {
+ double centerX = Canvas.GetLeft(ellipse) + ellipse.Width / 2;
+ double centerY = Canvas.GetTop(ellipse) + ellipse.Height / 2;
+
+ // 查找距离圆圈中心最近的文本控件
+ TextBlock? closestTextBlock = null;
+ double minDistance = double.MaxValue;
+
+ foreach (var child in overlayCanvas.Children)
+ {
+ if (child is TextBlock textBlock)
+ {
+ double textX = Canvas.GetLeft(textBlock) + textBlock.Width / 2;
+ double textY = Canvas.GetTop(textBlock) + textBlock.Height / 2;
+
+ double distance = Math.Sqrt(Math.Pow(textX - centerX, 2) + Math.Pow(textY - centerY, 2));
+
+ if (distance < minDistance)
+ {
+ minDistance = distance;
+ closestTextBlock = textBlock;
+ }
+ }
+ }
+
+ return closestTextBlock;
+ }
+
+ ///
+ /// 鼠标移动事件:拖动过程中更新位置
+ ///
+ private void Ellipse_MouseMove(object sender, MouseEventArgs e)
+ {
+ if (!_isDragging || _draggingEllipse == null || overlayCanvas == null) return;
+
+ var currentPos = e.GetPosition(overlayCanvas);
+ double dx = currentPos.X - _dragStartMousePos.X;
+ double dy = currentPos.Y - _dragStartMousePos.Y;
+
+ double newLeft = _dragStartLeft + dx;
+ double newTop = _dragStartTop + dy;
+
+ // 限制边界
+ double maxLeft = overlayCanvas.ActualWidth - _draggingEllipse.Width;
+ double maxTop = overlayCanvas.ActualHeight - _draggingEllipse.Height;
+ newLeft = Math.Max(0, Math.Min(newLeft, maxLeft));
+ newTop = Math.Max(0, Math.Min(newTop, maxTop));
+
+ // 更新圆圈位置
+ Canvas.SetLeft(_draggingEllipse, newLeft);
+ Canvas.SetTop(_draggingEllipse, newTop);
+
+ // 更新对应文本
+ if (_draggingTextBlock != null)
+ {
+ double centerX = newLeft + _draggingEllipse.Width / 2;
+ double centerY = newTop + _draggingEllipse.Height / 2;
+ double radius = _draggingEllipse.Width / 2;
+
+ Canvas.SetLeft(_draggingTextBlock, centerX - 75);
+ Canvas.SetTop(_draggingTextBlock, centerY - radius - 30);
+
+ // 更新文本内容
+ _draggingTextBlock.Text = $"({centerX:F0}, {centerY:F0})";
+ }
+ }
+
+ ///
+ /// 鼠标释放事件:结束拖动
+ ///
+ private void Ellipse_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
+ {
+ if (_draggingEllipse == null || overlayCanvas == null) return;
+
+ if (_isDragging)
+ {
+ _isDragging = false;
+ _draggingEllipse.ReleaseMouseCapture();
+
+ double left = Canvas.GetLeft(_draggingEllipse);
+ double top = Canvas.GetTop(_draggingEllipse);
+ double centerX = left + _draggingEllipse.Width / 2;
+ double centerY = top + _draggingEllipse.Height / 2;
+
+ Debug.WriteLine($"圆圈移动到坐标: X={centerX:F0}, Y={centerY:F0}");
+
+ // 显示完成标记
+ if (_draggingTextBlock != null)
+ {
+ _draggingTextBlock.Text = $"({centerX:F0}, {centerY:F0}) ✓";
+
+ Task.Delay(2000).ContinueWith(t =>
+ {
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ if (_draggingTextBlock != null)
+ {
+ _draggingTextBlock.Text = $"({centerX:F0}, {centerY:F0})";
+ }
+ });
+ });
+ }
+
+ Debug.WriteLine("结束拖动圆圈");
+ }
+
+ _draggingEllipse.Opacity = 0.7;
+ _draggingEllipse = null;
+ _draggingTextBlock = null;
+ e.Handled = true;
+ }
+ }
+}
\ No newline at end of file