diff --git a/Wpf_AiSportsMicrospace/Common/SportOperate.cs b/Wpf_AiSportsMicrospace/Common/SportOperate.cs index 7cb99ce..f68e49c 100644 --- a/Wpf_AiSportsMicrospace/Common/SportOperate.cs +++ b/Wpf_AiSportsMicrospace/Common/SportOperate.cs @@ -76,19 +76,21 @@ namespace Wpf_AiSportsMicrospace.Common if (humans == null || humans.Count == 0) return (int)WavingAction.None; - foreach (var human in humans) + var human = humans.FirstOrDefault(h => { - var rightAnkle = human.Keypoints.FirstOrDefault(k => k.Name == "right_ankle"); + var rightAnkle = h.Keypoints.FirstOrDefault(k => k.Name == "right_ankle"); if (rightAnkle == null) - continue; + return false; - double xNorm = rightAnkle.X / 1920; - double yNorm = rightAnkle.Y / 1080; + double xNorm = rightAnkle.X / 1920.0; + double yNorm = rightAnkle.Y / 1080.0; - // 仅检测中心区域内的人 - if (!(xNorm >= 0.44 && xNorm <= 0.57 && yNorm >= 0.81)) - continue; + return xNorm >= 0.44 && xNorm <= 0.57 && yNorm >= 0.81; + }); + if (human != null) + { + // 找到了符合条件的人 // --- 右手举手优先 --- int rightHandAction = DetectRightHandRaise(human); if (rightHandAction != (int)WavingAction.None) @@ -122,7 +124,6 @@ namespace Wpf_AiSportsMicrospace.Common return (int)WavingAction.RightWave; } } - return (int)WavingAction.None; } diff --git a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs index db882b3..02994e0 100644 --- a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs @@ -7,6 +7,7 @@ using HandyControl.Controls; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using SharpDX.Direct3D9; +using SportExpand; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -38,6 +39,7 @@ using Yztob.AiSports.Common; using Yztob.AiSports.Common.Implement; using Yztob.AiSports.Inferences.Abstractions; using Yztob.AiSports.Inferences.Things; +using Yztob.AiSports.Postures; using Yztob.AiSports.Postures.Sports; using Yztob.AiSports.Sensors.Abstractions; using Yztob.AiSports.Sensors.Things; @@ -80,11 +82,11 @@ namespace Wpf_AiSportsMicrospace.Views var app = (App)Application.Current; using var scope = App.AppHost.Services.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); - var cfg = await db.SixGroupPoints.FirstOrDefaultAsync(x=>x.Code==AppSettings.Code); + var cfg = await db.SixGroupPoints.FirstOrDefaultAsync(x => x.Code == AppSettings.Code); //var pointlist = JsonSerializer.Deserialize>(cfg!.PointsJson); - List<(double XNorm, double YNorm)> pointlist = - [(cfg.Point1.X, cfg.Point1.Y),(cfg.Point2.X, cfg.Point2.Y), + List<(double XNorm, double YNorm)> pointlist = + [(cfg.Point1.X, cfg.Point1.Y),(cfg.Point2.X, cfg.Point2.Y), (cfg.Point3.X, cfg.Point3.Y), (cfg.Point4.X, cfg.Point4.Y), (cfg.Point5.X, cfg.Point5.Y),(cfg.Point6.X, cfg.Point6.Y)]; _groupJumpRopeContext.CirclePositions = pointlist; @@ -130,7 +132,7 @@ namespace Wpf_AiSportsMicrospace.Views HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, Opacity = 0, - Margin = new Thickness(0, -100, 0, 0), + Margin = new Thickness(0, -100, 0, 0), }; // 增加图片的大小,调整比例 @@ -188,47 +190,63 @@ namespace Wpf_AiSportsMicrospace.Views { if (humans == null || humans.Count == 0) return; - switch (_currentGameState) + + var human = humans.FirstOrDefault(h => { - case GameState.NotStarted: // 未开始 - if (!_isCountdownStarted) // 只有倒计时未开始才检测左手 - { - int leftWaving = DetectLeftHandRaise(humans); - if (leftWaving == 5) + var rightAnkle = h.Keypoints.FirstOrDefault(k => k.Name == "right_ankle"); + if (rightAnkle == null) + return false; + + double xNorm = rightAnkle.X / 1920.0; + double yNorm = rightAnkle.Y / 1080.0; + + return xNorm >= 0.44 && xNorm <= 0.57 && yNorm >= 0.81; + }); + + if (human != null) + { + switch (_currentGameState) + { + case GameState.NotStarted: + if (!_isCountdownStarted) { - _mainWin.HumanFrameUpdated -= OnHumanFrameUpdated; - _mainWin.WebcamClient.StopExtract(); + int leftWaving = DetectLeftHandRaise(human); + if (leftWaving == 5) + { + _mainWin.HumanFrameUpdated -= OnHumanFrameUpdated; + _mainWin.WebcamClient.StopExtract(); - // 举左手逻辑,例如结束动画或退出 - var newPage = new Home(); - _mainWin?.SwitchPageWithMaskAnimation(newPage, true); - return; // 提前退出 + // 举左手逻辑,例如结束动画或退出 + var newPage = new Home(); + _mainWin?.SwitchPageWithMaskAnimation(newPage, true); + return; // 提前退出 + } } - } - int rightWaving = DetectRightHandRaise(humans); - if (rightWaving >= 3 && RankingGrid.Visibility != Visibility.Visible) - { - switch (rightWaving) + int rightWaving = DetectRightHandRaise(human); + if (rightWaving >= 3 && RankingGrid.Visibility != Visibility.Visible) { - case (int)WavingAction.FirstHand: - StartCountdown(3); - _isCountdownStarted = true; // 倒计时开始,停止左手检测 - break; - case (int)WavingAction.Raising: - UpdateCountdown(); - break; - case (int)WavingAction.RaiseHand: - FinishCountdown(); - _currentGameState = GameState.Running; // 倒计时完成 → 游戏开始 - break; + switch (rightWaving) + { + case (int)WavingAction.FirstHand: + StartCountdown(3); + _isCountdownStarted = true; + break; + case (int)WavingAction.Raising: + UpdateCountdown(); + break; + case (int)WavingAction.RaiseHand: + FinishCountdown(); + _currentGameState = GameState.Running; + break; + } } - } - break; + break; - case GameState.Running: // 游戏进行中 - UpdateCircleCounts(humans); - break; + case GameState.Running: + UpdateCircleCounts(humans); + break; + } } } catch (Exception ex) @@ -347,131 +365,77 @@ namespace Wpf_AiSportsMicrospace.Views private bool _firstHandTriggered; private int _lastCountdownSecond = 3; private DateTime? _countdownStartTime; - public int DetectRightHandRaise(List humans) + public int DetectRightHandRaise(Human human) { - if (humans == null || humans.Count == 0) - return (int)WavingAction.None; - foreach (var human in humans) + var calculator = PostureCalculate.CreateCalculator(); + var rule = RaiseHand.RaiseRightHand(); + var pass = calculator.Calculating(human, rule); + + const double holdDuration = 1; // 持续时间(秒) + const int countdownSeconds = 3; // 倒计时长度 + + // ---------- 第一步:持续举手触发倒计时 ---------- + if (!_firstHandTriggered) { - if (human?.Keypoints == null) - continue; - - // --- 筛选右脚踝坐标 --- - var rightAnkle = human.Keypoints.FirstOrDefault(k => k.Name == "right_ankle"); - if (rightAnkle == null) - continue; - - double xNorm = rightAnkle.X / 1920; - double yNorm = rightAnkle.Y / 1080; - - // 仅检测中心区域内的人 - if (!(xNorm >= 0.44 && xNorm <= 0.57 && yNorm >= 0.81)) - continue; - - // --- 获取右臂关键点 --- - var rightWrist = human.Keypoints.FirstOrDefault(k => k.Name == "right_wrist"); - var rightElbow = human.Keypoints.FirstOrDefault(k => k.Name == "right_elbow"); - - const double raiseThreshold = 60; // 举手阈值 - const double holdDuration = 1; // 持续时间(秒) - const int countdownSeconds = 3; // 倒计时长度 - - bool handRaised = false; - - if (rightWrist != null && rightElbow != null) + if (pass) { - double verticalRise = rightElbow.Y - rightWrist.Y; - handRaised = verticalRise >= raiseThreshold; - } - - // ---------- 第一步:持续举手触发倒计时 ---------- - if (!_firstHandTriggered) - { - if (handRaised) + _raiseStartTime ??= DateTime.Now; + var holdElapsed = (DateTime.Now - _raiseStartTime.Value).TotalSeconds; + if (holdElapsed >= holdDuration) { - _raiseStartTime ??= DateTime.Now; - var holdElapsed = (DateTime.Now - _raiseStartTime.Value).TotalSeconds; - if (holdElapsed >= holdDuration) - { - // 举手达到指定时间,启动倒计时 - _firstHandTriggered = true; - _countdownStartTime = DateTime.Now; - _lastCountdownSecond = countdownSeconds; - return (int)WavingAction.FirstHand; - } + // 举手达到指定时间,启动倒计时 + _firstHandTriggered = true; + _countdownStartTime = DateTime.Now; + _lastCountdownSecond = countdownSeconds; + return (int)WavingAction.FirstHand; } - else - { - // 手放下,重置举手开始时间 - _raiseStartTime = DateTime.Now; - } - - continue; // 本人未触发,检测下一个人 } - - // ---------- 第二步:倒计时逻辑 ---------- - var countdownElapsed = (DateTime.Now - _countdownStartTime.Value).TotalSeconds; - int currentSecond = countdownSeconds - (int)Math.Floor(countdownElapsed); - - if (currentSecond > 0 && currentSecond != _lastCountdownSecond) + else { - _lastCountdownSecond = currentSecond; - Console.WriteLine($"倒计时:{currentSecond}"); - return (int)WavingAction.Raising; // 倒计时中 + // 手放下,重置举手开始时间 + _raiseStartTime = DateTime.Now; } - if (countdownElapsed >= countdownSeconds) - { - ResetRaiseState(); - return (int)WavingAction.RaiseHand; // 举手完成 - } - - return (int)WavingAction.Raising; + // 没有任何中心区域内的人举手 + return (int)WavingAction.None; } - // 没有任何中心区域内的人举手 - return (int)WavingAction.None; + // ---------- 第二步:倒计时逻辑 ---------- + var countdownElapsed = (DateTime.Now - _countdownStartTime.Value).TotalSeconds; + int currentSecond = countdownSeconds - (int)Math.Floor(countdownElapsed); + + if (currentSecond > 0 && currentSecond != _lastCountdownSecond) + { + _lastCountdownSecond = currentSecond; + Console.WriteLine($"倒计时:{currentSecond}"); + return (int)WavingAction.Raising; // 倒计时中 + } + + if (countdownElapsed >= countdownSeconds) + { + ResetRaiseState(); + return (int)WavingAction.RaiseHand; // 举手完成 + } + + return (int)WavingAction.Raising; } - public int DetectLeftHandRaise(List humans) + + + public int DetectLeftHandRaise(Human human) { - if (humans == null || humans.Count == 0) - return (int)WavingAction.None; + var calculator = PostureCalculate.CreateCalculator(); + var rule = RaiseHand.RaiseLeftHand(); + var pass = calculator.Calculating(human, rule); - - foreach (var human in humans) + if (pass) { - if (human?.Keypoints == null) - continue; - - // --- 筛选右脚踝坐标 --- - var rightAnkle = human.Keypoints.FirstOrDefault(k => k.Name == "right_ankle"); - if (rightAnkle == null) - continue; - double xNorm = rightAnkle.X / 1920; - double yNorm = rightAnkle.Y / 1080; - // 仅检测中心区域内的人 - if (!(xNorm >= 0.44 && xNorm <= 0.57 && yNorm >= 0.81)) - continue; - - // 获取左手关键点 - var leftWrist = human.Keypoints.FirstOrDefault(k => k.Name == "left_wrist"); - var leftElbow = human.Keypoints.FirstOrDefault(k => k.Name == "left_elbow"); - - if (leftWrist == null || leftElbow == null) - continue; - - const double raiseThreshold = 60; // 举手阈值 - - // 判断左手是否举起 - double verticalRise = leftElbow.Y - leftWrist.Y; - if (verticalRise >= raiseThreshold) - { - return (int)WavingAction.RaiseHand; // 一旦检测到左手举起,立即返回 - } + // 一旦检测到左手举起,立即返回 + return (int)WavingAction.RaiseHand; } - return (int)WavingAction.None; // 没有检测到举手 + // 没有检测到举手 + return (int)WavingAction.None; } private void ResetRaiseState() diff --git a/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml.cs b/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml.cs index 927145c..0a575ae 100644 --- a/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml.cs @@ -187,6 +187,7 @@ namespace Wpf_AiSportsMicrospace.Views.JumpRope switch (_currentGameState) { case GameState.NotStarted: // 未开始 + if (!_isCountdownStarted) // 只有倒计时未开始才检测左手 { int leftWaving = DetectLeftHandRaise(humans);