diff --git a/Wpf_AiSportsMicrospace/Common/SportOperate.cs b/Wpf_AiSportsMicrospace/Common/SportOperate.cs index cfce7d3..03f5253 100644 --- a/Wpf_AiSportsMicrospace/Common/SportOperate.cs +++ b/Wpf_AiSportsMicrospace/Common/SportOperate.cs @@ -65,57 +65,65 @@ namespace Wpf_AiSportsMicrospace.Common return _webcamClient; } - public int VerifyWavingAction(Human human) + public int VerifyWavingAction(List humans) { - var nose = human.Keypoints.FirstOrDefault(k => k.Name == "right_ankle"); - if (nose == null) + if (humans == null || humans.Count == 0) return (int)WavingAction.None; - double xNorm = nose.X / 1920; - double yNorm = nose.Y / 1080; - - if (!(xNorm >= 0.44 && xNorm <= 0.57 && yNorm >= 0.81)) - return (int)WavingAction.None; - - var leftWrist = human.Keypoints.FirstOrDefault(x => x.Name == "left_wrist"); - var leftElbow = human.Keypoints.FirstOrDefault(x => x.Name == "left_elbow"); - var rightWrist = human.Keypoints.FirstOrDefault(x => x.Name == "right_wrist"); - var rightElbow = human.Keypoints.FirstOrDefault(x => x.Name == "right_elbow"); - - // --- 左手挥手 --- - if (leftWrist != null && leftElbow != null) + foreach (var human in humans) { - int leftResult = DetectHorizontalWave( - new Point(leftWrist.X, leftWrist.Y), - new Point(leftElbow.X, leftElbow.Y), - ref _lastLeftWrist, - ref _leftWristDeltaX, - true); - if (leftResult != (int)WavingAction.None) - return leftResult; - } + var rightAnkle = human.Keypoints.FirstOrDefault(k => k.Name == "right_ankle"); + if (rightAnkle == null) + continue; - // --- 右手举手优先判断 --- - int rightHandAction = DetectRightHandRaise(human); - if (rightHandAction != (int)WavingAction.None) - return rightHandAction; + double xNorm = rightAnkle.X / 1920; + double yNorm = rightAnkle.Y / 1080; - // --- 右手挥手,仅当未举手时判断 --- - if (rightWrist != null && rightElbow != null) - { - int rightWaveResult = DetectHorizontalWave( - new Point(rightWrist.X, rightWrist.Y), - new Point(rightElbow.X, rightElbow.Y), - ref _lastRightWrist, - ref _rightWristDeltaX, - false); - if (rightWaveResult != (int)WavingAction.None) - return rightWaveResult; + // 仅检测中心区域内的人 + if (!(xNorm >= 0.44 && xNorm <= 0.57 && yNorm >= 0.81)) + continue; + + var leftWrist = human.Keypoints.FirstOrDefault(x => x.Name == "left_wrist"); + var leftElbow = human.Keypoints.FirstOrDefault(x => x.Name == "left_elbow"); + var rightWrist = human.Keypoints.FirstOrDefault(x => x.Name == "right_wrist"); + var rightElbow = human.Keypoints.FirstOrDefault(x => x.Name == "right_elbow"); + + // --- 右手举手优先 --- + int rightHandAction = DetectRightHandRaise(human); + if (rightHandAction != (int)WavingAction.None) + return rightHandAction; + + // --- 左手挥手 --- + if (leftWrist != null && leftElbow != null) + { + int leftResult = DetectHorizontalWave( + new Point(leftWrist.X, leftWrist.Y), + new Point(leftElbow.X, leftElbow.Y), + ref _lastLeftWrist, + ref _leftWristDeltaX, + true); + if (leftResult != (int)WavingAction.None) + return leftResult; + } + + // --- 右手挥手 --- + if (rightWrist != null && rightElbow != null) + { + int rightWaveResult = DetectHorizontalWave( + new Point(rightWrist.X, rightWrist.Y), + new Point(rightElbow.X, rightElbow.Y), + ref _lastRightWrist, + ref _rightWristDeltaX, + false); + if (rightWaveResult != (int)WavingAction.None) + return rightWaveResult; + } } return (int)WavingAction.None; } + /// /// 检测右手举手状态 /// diff --git a/Wpf_AiSportsMicrospace/Views/CenterHome.xaml.cs b/Wpf_AiSportsMicrospace/Views/CenterHome.xaml.cs index ec7a6f3..cfecfa3 100644 --- a/Wpf_AiSportsMicrospace/Views/CenterHome.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/CenterHome.xaml.cs @@ -87,7 +87,7 @@ namespace Wpf_AiSportsMicrospace.Views if (human == null) return; //检测挥手动作 - var wavingaction = sportOperate.VerifyWavingAction(human); + var wavingaction = sportOperate.VerifyWavingAction(humans); switch (wavingaction) { diff --git a/Wpf_AiSportsMicrospace/Views/Home.xaml.cs b/Wpf_AiSportsMicrospace/Views/Home.xaml.cs index 417e071..f573052 100644 --- a/Wpf_AiSportsMicrospace/Views/Home.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/Home.xaml.cs @@ -71,7 +71,7 @@ namespace Wpf_AiSportsMicrospace if (human == null) return; //检测挥手动作 - var wavingaction = _mainWin.SportOperate.VerifyWavingAction(human); + var wavingaction = _mainWin.SportOperate.VerifyWavingAction(humans); switch (wavingaction) { diff --git a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs index 707300b..20f00fc 100644 --- a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs @@ -158,38 +158,37 @@ namespace Wpf_AiSportsMicrospace.Views if (humans == null || humans.Count == 0) return; int wavingaction = 0; - foreach (var human in humans) + + wavingaction = DetectRightHandRaise(humans); + + if (wavingaction < 3) + return; + + switch (wavingaction) { - wavingaction = DetectRightHandRaise(human); + case (int)WavingAction.FirstHand: + // 第一次举手,初始化倒计时 + StartCountdown(3); + break; - if (wavingaction < 3) - continue; + case (int)WavingAction.Raising: + // 持续倒计时中 + UpdateCountdown(); + break; - switch (wavingaction) - { - case (int)WavingAction.FirstHand: - // 第一次举手,初始化倒计时 - StartCountdown(3); - break; + case (int)WavingAction.RaiseHand: + // 举手完成,倒计时结束 + FinishCountdown(); + break; - case (int)WavingAction.Raising: - // 持续倒计时中 - UpdateCountdown(); - break; - - case (int)WavingAction.RaiseHand: - // 举手完成,倒计时结束 - FinishCountdown(); - break; - - default: - // 没检测到动作,重置倒计时显示 - Utils.StopBackgroundMusic(); - countdownText.Text = "3"; - countdownGrid.Visibility = Visibility.Hidden; - break; - } + default: + // 没检测到动作,重置倒计时显示 + Utils.StopBackgroundMusic(); + countdownText.Text = "3"; + countdownGrid.Visibility = Visibility.Hidden; + break; } + } else { @@ -273,66 +272,91 @@ namespace Wpf_AiSportsMicrospace.Views private bool _firstHandTriggered; private int _lastCountdownSecond = 3; private DateTime? _countdownStartTime; - public int DetectRightHandRaise(Human human) + public int DetectRightHandRaise(List humans) { - var rightWrist = human.Keypoints.FirstOrDefault(k => k.Name == "right_wrist"); - var rightElbow = human.Keypoints.FirstOrDefault(k => k.Name == "right_elbow"); + if (humans == null || humans.Count == 0) + return (int)WavingAction.None; - const double raiseThreshold = 60; // 举手阈值 - const double holdDuration = 1; // 持续 2 秒触发倒计时 - const int countdownSeconds = 3; // 倒计时长度 - - bool handRaised = false; - - if (rightWrist != null && rightElbow != null) + foreach (var human in humans) { - double verticalRise = rightElbow.Y - rightWrist.Y; - handRaised = verticalRise >= raiseThreshold; - } + if (human?.Keypoints == null) + continue; - // ---------- 第一步:持续举手触发倒计时 ---------- - if (!_firstHandTriggered) - { - if (handRaised) + // --- 筛选右脚踝坐标 --- + 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) { - _raiseStartTime ??= DateTime.Now; - var holdElapsed = (DateTime.Now - _raiseStartTime.Value).TotalSeconds; - if (holdElapsed >= holdDuration) + double verticalRise = rightElbow.Y - rightWrist.Y; + handRaised = verticalRise >= raiseThreshold; + } + + // ---------- 第一步:持续举手触发倒计时 ---------- + if (!_firstHandTriggered) + { + if (handRaised) { - // 举手达到 2 秒,启动倒计时 - _firstHandTriggered = true; - _countdownStartTime = DateTime.Now; - _lastCountdownSecond = countdownSeconds; - return (int)WavingAction.FirstHand; + _raiseStartTime ??= DateTime.Now; + var holdElapsed = (DateTime.Now - _raiseStartTime.Value).TotalSeconds; + if (holdElapsed >= holdDuration) + { + // 举手达到指定时间,启动倒计时 + _firstHandTriggered = true; + _countdownStartTime = DateTime.Now; + _lastCountdownSecond = countdownSeconds; + return (int)WavingAction.FirstHand; + } } + else + { + // 手放下,重置举手开始时间 + _raiseStartTime = DateTime.Now; + } + + continue; // 本人未触发,检测下一个人 } - else + + // ---------- 第二步:倒计时逻辑 ---------- + var countdownElapsed = (DateTime.Now - _countdownStartTime.Value).TotalSeconds; + int currentSecond = countdownSeconds - (int)Math.Floor(countdownElapsed); + + if (currentSecond > 0 && currentSecond != _lastCountdownSecond) { - // 手放下,重置举手开始时间 - _raiseStartTime = DateTime.Now; + _lastCountdownSecond = currentSecond; + Console.WriteLine($"倒计时:{currentSecond}"); + return (int)WavingAction.Raising; // 倒计时中 } - return (int)WavingAction.None; // 倒计时未开始 + if (countdownElapsed >= countdownSeconds) + { + ResetRaiseState(); + return (int)WavingAction.RaiseHand; // 举手完成 + } + + return (int)WavingAction.Raising; } - // ---------- 第二步:倒计时逻辑(独立于手状态) ---------- - 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; // 倒计时中 + // 没有任何中心区域内的人举手 + return (int)WavingAction.None; } private void ResetRaiseState()