diff --git a/Wpf_AiSportsMicrospace/Common/SportOperate.cs b/Wpf_AiSportsMicrospace/Common/SportOperate.cs index 3c95b08..49c7cb9 100644 --- a/Wpf_AiSportsMicrospace/Common/SportOperate.cs +++ b/Wpf_AiSportsMicrospace/Common/SportOperate.cs @@ -31,7 +31,7 @@ namespace Wpf_AiSportsMicrospace.Common IPointTracker _rightTracker; private int _leftWaveCount = 0; private int _rightWaveCount = 0; - private const int WaveThreshold = 3; + private const int WaveThreshold = 4; WebcamClient _webcamClient; private DateTime? _wristStartTime = null; @@ -43,8 +43,8 @@ namespace Wpf_AiSportsMicrospace.Common _leftTracker = PostureCalculate.CreatePointTracker("left_wrist", 0); _rightTracker = PostureCalculate.CreatePointTracker("right_wrist", 0); - //_leftTracker.Amplitude = 0.3f; - //_rightTracker.Amplitude = 0.3f; + _leftTracker.Amplitude = 0.3f; + _rightTracker.Amplitude = 0.3f; } public WebcamClient CreateRTSP() diff --git a/Wpf_AiSportsMicrospace/Common/Utils.cs b/Wpf_AiSportsMicrospace/Common/Utils.cs index cd614d2..014089b 100644 --- a/Wpf_AiSportsMicrospace/Common/Utils.cs +++ b/Wpf_AiSportsMicrospace/Common/Utils.cs @@ -1,4 +1,5 @@ -using Common; +using AiSportsMicrospaceDB.Entities; +using Common; using Dto; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Formats.Jpeg; @@ -87,7 +88,7 @@ namespace Wpf_AiSportsMicrospace.Common Application.Current.Dispatcher.Invoke(() => { if (_bgPlayer != null) - + currentTime = _bgPlayer.Position.TotalSeconds; }); return currentTime; @@ -353,5 +354,33 @@ namespace Wpf_AiSportsMicrospace.Common // 转成常用的 XX-XX-XX-XX-XX-XX 格式 return string.Join("-", macBytes.Select(b => b.ToString("X2"))); } + + public static List<(double XNorm, double YNorm)> GetPointsList(int pointCount, GroupPoints cfg) + { + List<(double XNorm, double YNorm)> pointlist = new List<(double XNorm, double YNorm)>(); + + if (cfg == null || pointCount <= 0) + return pointlist; + + // 所有可能的点 + var allPoints = new[] + { + cfg.Point1, cfg.Point2, cfg.Point3, + cfg.Point4, cfg.Point5, cfg.Point6, + cfg.Point7, cfg.Point8, cfg.Point9, cfg.Point10 + }; + + // 取前 pointCount 个点 + foreach (var point in allPoints.Take(pointCount)) + { + if (point != null) + { + pointlist.Add((point.X, point.Y)); + } + } + + return pointlist; + } + } } diff --git a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml index 7cfde0b..87c1732 100644 --- a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml +++ b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml @@ -13,7 +13,7 @@ - + diff --git a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml.cs b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml.cs index 518f93f..4d2df00 100644 --- a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml.cs +++ b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml.cs @@ -8,7 +8,6 @@ using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; -using System.Windows.Controls.Primitives; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; @@ -45,6 +44,10 @@ namespace Wpf_AiSportsMicrospace.MyUserControl Images[i].IsSelected = i == _selectedIndex; UpdateLayoutWithAnimation(); + + // 启动进度条动画 + //var current = Images[_selectedIndex]; + //StartProgress(current); } } @@ -54,6 +57,16 @@ namespace Wpf_AiSportsMicrospace.MyUserControl InitializeComponent(); DataContext = this; Loaded += (s, e) => UpdateLayoutWithAnimation(true); + + //var timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(5) }; + //timer.Tick += (s, e) => + //{ + // if (Images.Count == 0) return; + // var current = Images[_selectedIndex]; + // if (current.Progress < 1) + // current.Progress += 0.01; // 调整速度 + //}; + //timer.Start(); } private EventHandler _renderHandler; @@ -258,13 +271,12 @@ namespace Wpf_AiSportsMicrospace.MyUserControl } - public async void SlideLeft() + public void SlideLeft() { StopProgress(); SelectedIndex++; } - - public async void SlideRight() + public void SlideRight() { StopProgress(); SelectedIndex--; diff --git a/Wpf_AiSportsMicrospace/SportExpand/Optimizes.cs b/Wpf_AiSportsMicrospace/SportExpand/Optimizes.cs new file mode 100644 index 0000000..e2786ee --- /dev/null +++ b/Wpf_AiSportsMicrospace/SportExpand/Optimizes.cs @@ -0,0 +1,41 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; +using Yztob.AiSports.Postures.Sports; +using Yztob.AiSports.Postures.Things; + +namespace SportExpand +{ + public class Optimizes + { /// + /// 执行运动微调 + /// + /// 要微调的运动 + public static void Optimizeing(SportBase sport) + { + if (sport == null) + throw new ArgumentNullException(nameof(sport)); + + //获取运动的检测规则,如果使用的是规则检测时提供 + Console.WriteLine(JsonConvert.SerializeObject(sport.Rules)); + //获取运动的检测动作样本姿态,如果使用的是相似度时提供 + Console.WriteLine(JsonConvert.SerializeObject(sport.Samples)); + + switch (sport.Key) + { + case "squat": + var loggicRule = sport.Rules["squat"] as CalcLogicAndRule; + //删除手部姿态检查规则 + loggicRule.Rules.RemoveAt(2); + loggicRule.Rules.RemoveAt(1); + break; + + case "rope-skipping": + var newSport = sport as SportRopeSkipping; + newSport.ShakeRate = 0.02f; + break; + } + } + } +} diff --git a/Wpf_AiSportsMicrospace/Views/Home.xaml.cs b/Wpf_AiSportsMicrospace/Views/Home.xaml.cs index 68ec8d8..d3700fa 100644 --- a/Wpf_AiSportsMicrospace/Views/Home.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/Home.xaml.cs @@ -81,7 +81,7 @@ namespace Wpf_AiSportsMicrospace if (_mainWin.WebcamClient == null) { - //HandyControl.Controls.MessageBox.Show("摄像头网络异常,请重新连接!"); + HandyControl.Controls.MessageBox.Show("摄像头网络异常,请重新连接!"); return; } @@ -90,7 +90,7 @@ namespace Wpf_AiSportsMicrospace } private void Home_Unloaded(object sender, RoutedEventArgs e) { - //_mainWin.HumanFrameUpdated -= OnHumanFrameUpdated; + _mainWin.HumanFrameUpdated -= OnHumanFrameUpdated; } private bool IsGestureActive = true; // 标记手势识别是否有效 private void OnHumanFrameUpdated(object sender, List humans) @@ -120,9 +120,10 @@ namespace Wpf_AiSportsMicrospace break; case (int)WavingAction.RaiseHand: // 举手完成 - // 设置标记,停止后续手势识别 + // 设置标记,停止后续手势识别 + //coverFlow.ProgressCompleted += CoverFlow_ProgressCompleted; + RouterGoNew(); IsGestureActive = false; - coverFlow.ProgressCompleted += CoverFlow_ProgressCompleted; break; default: // 没有动作 → 取消进度 @@ -131,20 +132,6 @@ namespace Wpf_AiSportsMicrospace } } - private void CoverFlow_ProgressCompleted(CoverFlowItem item) - { - // 停止抽帧线程/释放资源 - try - { - _mainWin.HumanFrameUpdated -= OnHumanFrameUpdated; - _mainWin.WebcamClient.StopExtract(); - RouterGoNew(); - } - catch (Exception ex) - { - Debug.WriteLine($"停止抽帧异常: {ex.Message}"); - } - } //测试点击 private void GoNew(object sender, MouseButtonEventArgs e) { @@ -161,9 +148,6 @@ namespace Wpf_AiSportsMicrospace if (coverFlow.SelectedIndex == 0) { var newPage = new GroupJumpRope(); - //mainWin?.SwitchPageWithMaskAnimation(newPage, true); - - //var newPage = new BambooDragonfly(); mainWin?.SwitchPageWithMaskAnimation(newPage, true); } else if (coverFlow.SelectedIndex == 1) diff --git a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs index 7805ed6..5868a77 100644 --- a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs @@ -83,26 +83,27 @@ namespace Wpf_AiSportsMicrospace.Views var app = (App)Application.Current; using var scope = App.AppHost.Services.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); + + // 获取配置 + var pointCount = await db.BasicConfig + .Where(x => x.Code == AppSettings.Code) + .Select(x => x.HomeWidth) + .FirstOrDefaultAsync(); + var cfg = await db.GroupPoints.FirstOrDefaultAsync(x => x.Code == AppSettings.Code); - List<(double XNorm, double YNorm)> pointlist = new List<(double XNorm, double YNorm)>(); - var points = new[] { cfg.Point1, cfg.Point2, cfg.Point3, - cfg.Point4, cfg.Point5, cfg.Point6, - cfg.Point7, cfg.Point8, cfg.Point9, cfg.Point10 }; - - foreach (var point in points) + if (pointCount == 0 || cfg == null) { - if (point != null) - { - pointlist.Add((point.X, point.Y)); - } + HandyControl.Controls.MessageBox.Error("配置加载失败!", "提示"); + return; } - _groupJumpRopeContext.CirclePositions = pointlist; + + _groupJumpRopeContext.CirclePositions = Utils.GetPointsList(pointCount, cfg); _mainWin.HumanFrameUpdated += OnHumanFrameUpdated; _mainWin.WebcamClient.StartExtract(); - DrawCirclesWithText(); + DrawCirclesWithText(); // 播放音乐 PlayMusic("raisehand.mp3"); @@ -198,7 +199,7 @@ namespace Wpf_AiSportsMicrospace.Views private void OnHumanFrameUpdated(object sender, List humans) { if (humans == null || humans.Count == 0) return; - //var sportOperate = new SportOperate(); + switch (_currentGameState) { case GameState.NotStarted: // 未开始 @@ -208,9 +209,6 @@ namespace Wpf_AiSportsMicrospace.Views int leftWaving = sportOperate.VerifyLeftWavingAction(humans); if (leftWaving == 5) { - //_mainWin.HumanFrameUpdated -= OnHumanFrameUpdated; - //_mainWin.WebcamClient.StopExtract(); - // 举左手逻辑,例如结束动画或退出 var newPage = new Home(); _mainWin?.SwitchPageWithMaskAnimation(newPage, true); @@ -238,9 +236,6 @@ namespace Wpf_AiSportsMicrospace.Views } } - - private double _currentCountdown = 3600; - private DateTime _lastUpdateTime = DateTime.Now; private async void StartCountdown(int start = 3) { _mainWin.ShowCountDownAnimation(); @@ -281,25 +276,6 @@ namespace Wpf_AiSportsMicrospace.Views await Task.Delay(3000); FinishCountdown(); - //_currentGameState = GameState.Running; - } - - private void UpdateCountdown() - { - if ((DateTime.Now - _lastUpdateTime).TotalMilliseconds >= 600) - { - _lastUpdateTime = DateTime.Now; - _currentCountdown -= 600; - - if (_currentCountdown > 0) - { - countdownText.Text = _currentCountdown.ToString(); - } - else - { - FinishCountdown(); - } - } } private async void FinishCountdown() @@ -329,9 +305,6 @@ namespace Wpf_AiSportsMicrospace.Views x.ImageState = "1"; }); - _mainWin.HumanFrameUpdated -= OnHumanFrameUpdated; - _mainWin.WebcamClient.StopExtract(); - RankingItemList = _groupJumpRopeContext.UpdateRankList(); ShowRankingBoard(RankingItemList); Utils.StopBackgroundMusic(); @@ -339,8 +312,6 @@ namespace Wpf_AiSportsMicrospace.Views _currentGameState = GameState.NotStarted; _isCountdownStarted = false; - _mainWin.HumanFrameUpdated += OnHumanFrameUpdated; - _mainWin.WebcamClient.StartExtract(); } private void DrawCirclesWithText() @@ -360,7 +331,10 @@ namespace Wpf_AiSportsMicrospace.Views // 绘制发光圆 var userItem = AddUserItem(x, y, i); // 绑定运动对象 + var sport = SportBase.Create("rope-skipping"); + Optimizes.Optimizeing(sport); + int indexCopy = i; var currentItem = userItem; @@ -380,6 +354,55 @@ namespace Wpf_AiSportsMicrospace.Views _groupJumpRopeContext.Sports.Add(sport); } } + //private void UpdateCircleCounts(List humans) + //{ + // if (humans == null || humans.Count == 0) + // return; + + // double halfW = AppSettings.AreaSize.X; + // double halfH = AppSettings.AreaSize.Y; + + // var circles = _groupJumpRopeContext.CirclePositions; + // var sports = _groupJumpRopeContext.Sports; + + // int circleCount = circles.Count; + + // // 每个圈匹配到的人 + // Human[] circleHumans = new Human[circleCount]; + + // // 1️⃣ 批量匹配圈内的人(保留原验证逻辑) + // foreach (var h in humans) + // { + // for (int i = 0; i < circleCount; i++) + // { + // // 已经有人占用该圈 + // if (circleHumans[i] != null) + // continue; + + // var circle = circles[i]; + // double cx = circle.XNorm; + // double cy = circle.YNorm; + + // // ⭐ 保留你的原验证 + // if (sportOperate.IsAnyFootInCircle(h, cx, cy, halfW, halfH)) + // { + // circleHumans[i] = h; + // break; // 每个人只匹配一个圈 + // } + // } + // } + + // // 2️⃣ 推送跳绳计数 + // for (int i = 0; i < circleCount; i++) + // { + // var human = circleHumans[i]; + // if (human != null) + // { + // sports[i].Pushing(human); + // } + // } + //} + private void UpdateCircleCounts(List humans) { double halfW = AppSettings.AreaSize.X; @@ -407,18 +430,18 @@ namespace Wpf_AiSportsMicrospace.Views bool hasHuman = targetHuman != null; + // 3️⃣ 推送跳绳计数 + if (hasHuman) + { + _groupJumpRopeContext.Sports[i].Pushing(targetHuman); + } + // 2️⃣ 更新视觉状态 lock (_updateLock) { _groupJumpRopeContext.UserList[i].ImageState = GetJumpState(i, hasHuman); } - - // 3️⃣ 推送跳绳计数 - if (hasHuman) - { - _groupJumpRopeContext.Sports[i].Pushing(targetHuman); - } } } diff --git a/Wpf_AiSportsMicrospace/Views/SquatFu/WhackAMole.xaml.cs b/Wpf_AiSportsMicrospace/Views/SquatFu/WhackAMole.xaml.cs index e89f082..2dda50c 100644 --- a/Wpf_AiSportsMicrospace/Views/SquatFu/WhackAMole.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/SquatFu/WhackAMole.xaml.cs @@ -62,21 +62,22 @@ namespace Views.SquatFu var app = (App)Application.Current; using var scope = App.AppHost.Services.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); + // 获取配置 + var pointCount = await db.BasicConfig + .Where(x => x.Code == AppSettings.Code) + .Select(x => x.HomeWidth) + .FirstOrDefaultAsync(); + var cfg = await db.GroupPoints.FirstOrDefaultAsync(x => x.Code == AppSettings.Code); - List<(double XNorm, double YNorm)> pointlist = new List<(double XNorm, double YNorm)>(); - var points = new[] { cfg.Point1, cfg.Point2, cfg.Point3, - cfg.Point4, cfg.Point5, cfg.Point6, - cfg.Point7, cfg.Point8, cfg.Point9, cfg.Point10 }; - - foreach (var point in points) + if (pointCount == 0 || cfg == null) { - if (point != null) - { - pointlist.Add((point.X, point.Y)); - } + HandyControl.Controls.MessageBox.Error("配置加载失败!", "提示"); + return; } - _WhackAMoleContext.CirclePositions = pointlist; + + + _WhackAMoleContext.CirclePositions = Utils.GetPointsList(pointCount, cfg); DrawCirclesWithText(); // 播放音乐