update:setting

This commit is contained in:
ltx 2025-11-10 11:20:45 +08:00
parent 9f56229c59
commit 45a365e695
2 changed files with 367 additions and 0 deletions

View File

@ -0,0 +1,19 @@
<UserControl x:Class="Wpf_AiSportsMicrospace.Views.JumpSttting"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Wpf_AiSportsMicrospace.MyUserControl"
Loaded="Window_Loaded"
mc:Ignorable="d" Width="1920" Height="1080">
<Grid>
<!-- 右侧视频预览 -->
<Grid Background="Black">
<Button Width="200" Height="30" TextBlock.FontSize="16" MouseLeftButtonDown="Ellipse_MouseLeftButtonDown" MouseLeftButtonUp="Ellipse_MouseLeftButtonUp">
<TextBox Text="按钮"></TextBox>
</Button>
<Image x:Name="videoImage" Stretch="Uniform" />
<Canvas x:Name="overlayCanvas" IsHitTestVisible="False" />
</Grid>
</Grid>
</UserControl>

View File

@ -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<SportDescriptor> _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();
};
}
/// <summary>
/// 绘制可拖动的圆圈和位置文本
/// </summary>
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}");
}
}
/// <summary>
/// 创建可拖动的圆圈
/// </summary>
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;
}
/// <summary>
/// 创建位置显示文本
/// </summary>
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;
}
/// <summary>
/// 鼠标按下事件:开始拖动
/// </summary>
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;
}
/// <summary>
/// 查找圆圈对应的文本控件
/// </summary>
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;
}
/// <summary>
/// 鼠标移动事件:拖动过程中更新位置
/// </summary>
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})";
}
}
/// <summary>
/// 鼠标释放事件:结束拖动
/// </summary>
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;
}
}
}