From 9c631565512526d16fc2170754e5fb317416415c Mon Sep 17 00:00:00 2001 From: tanglong <842690096@qq.com> Date: Sun, 28 Sep 2025 14:08:36 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=8B=E5=8A=BF=E8=AF=86=E5=88=AB=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Wpf_AiSportsMicrospace/Common/SportOperate.cs | 155 ++++++++---------- Wpf_AiSportsMicrospace/Home.xaml.cs | 8 +- .../MyUserControl/CoverFlowControl.xaml.cs | 1 + 3 files changed, 74 insertions(+), 90 deletions(-) diff --git a/Wpf_AiSportsMicrospace/Common/SportOperate.cs b/Wpf_AiSportsMicrospace/Common/SportOperate.cs index 1e2e3b8..d94d67f 100644 --- a/Wpf_AiSportsMicrospace/Common/SportOperate.cs +++ b/Wpf_AiSportsMicrospace/Common/SportOperate.cs @@ -34,6 +34,9 @@ namespace Wpf_AiSportsMicrospace.Common private Point? _lastRightWrist = null; private DateTime? _raiseStartTime = null; private DateTime? _wristStartTime = null; + private double _leftWristDeltaX = 0; + private double _rightWristDeltaX = 0; + private bool _firstHandTriggered = false; public SportOperate() @@ -62,126 +65,106 @@ namespace Wpf_AiSportsMicrospace.Common 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) { - var result = RecognizeLeftHandGesture( + int leftResult = DetectHorizontalWave( new Point(leftWrist.X, leftWrist.Y), - new Point(leftElbow.X, leftElbow.Y)); - if (result != 0) return result; + new Point(leftElbow.X, leftElbow.Y), + ref _lastLeftWrist, + ref _leftWristDeltaX, + true); + if (leftResult != (int)WavingAction.None) return leftResult; } - // 右手逻辑 + // --- 右手挥手或举手 --- if (rightWrist != null && rightElbow != null) { - var result = RecognizeRightHandGesture( + int rightWaveResult = DetectHorizontalWave( new Point(rightWrist.X, rightWrist.Y), - new Point(rightElbow.X, rightElbow.Y)); - if (result != 0) return result; + new Point(rightElbow.X, rightElbow.Y), + ref _lastRightWrist, + ref _rightWristDeltaX, + false); + if (rightWaveResult != (int)WavingAction.None) return rightWaveResult; + + // --- 举手逻辑 --- + double verticalRise = rightElbow.Y - rightWrist.Y; // 手腕在肘上方 → 正值 + if (verticalRise >= 60) // 举手阈值 + { + // 初始化计时 + if (_raiseStartTime == null) + _raiseStartTime = DateTime.Now; + + if (_wristStartTime == null) + _wristStartTime = DateTime.Now; + + var wristDuration = DateTime.Now - _wristStartTime.Value; + + // 保持 >1 秒才触发一次 FirstHand + if (!_firstHandTriggered && wristDuration.TotalSeconds >= 1) + { + _firstHandTriggered = true; + return (int)WavingAction.FirstHand; // 举手开始,只触发一次 + } + + // 判断是否完成3秒举手 + var duration = DateTime.Now - _raiseStartTime.Value; + if (duration.TotalSeconds >= 3) + { + _raiseStartTime = null; + _wristStartTime = null; + _firstHandTriggered = false; // 重置状态 + return (int)WavingAction.RaiseHand; // 举手完成 + } + else + { + return (int)WavingAction.Raising; // 举手中 + } + } + else + { + // 手放下,重置计时和状态 + _raiseStartTime = null; + _wristStartTime = null; + _firstHandTriggered = false; + } } - return 0; + return (int)WavingAction.None; } /// /// 统一的水平挥手检测 /// - private int DetectHorizontalWave(Point wrist, Point elbow, Point? lastWrist, bool isLeft) + private int DetectHorizontalWave(Point wrist, Point elbow, ref Point? lastWrist, ref double deltaX, bool isLeft) { if (lastWrist != null) { double dx = wrist.X - lastWrist.Value.X; double dy = Math.Abs(wrist.Y - lastWrist.Value.Y); - // 挥手:水平位移明显,垂直位移小,且接近肘部水平 - if (Math.Abs(dx) > 30 && dy < 40 && Math.Abs(wrist.Y - elbow.Y) < 150) + // 累计水平位移 + deltaX += dx; + + if (Math.Abs(deltaX) > 40 && dy < 60 && Math.Abs(wrist.Y - elbow.Y) < 60) { + deltaX = 0; // 重置 if (CheckCooldown()) { - if (isLeft && dx > 0) - return (int)WavingAction.LeftWave; // 左手往右挥 - if (!isLeft && dx < 0) - return (int)WavingAction.RightWave; // 右手往左挥 + return isLeft ? (int)WavingAction.LeftWave : (int)WavingAction.RightWave; } } } - return (int)WavingAction.None; - } - - /// - /// 识别左手动作 - /// - public int RecognizeLeftHandGesture(Point wrist, Point elbow) - { - int result = DetectHorizontalWave(wrist, elbow, _lastLeftWrist, true); - _lastLeftWrist = wrist; // 更新记录 - return result; - } - private bool _firstHandTriggered = false; - - /// - /// 识别右手动作 - /// - /// - /// - /// - public int RecognizeRightHandGesture(Point wrist, Point elbow) - { - // --- 先判断水平挥手 --- - int waveResult = DetectHorizontalWave(wrist, elbow, _lastRightWrist, false); - _lastRightWrist = wrist; // 更新记录 - if (waveResult != (int)WavingAction.None) - return waveResult; - - // --- 举手逻辑 --- - double verticalRise = elbow.Y - wrist.Y; // 手腕在肘上方 → 正值 - if (verticalRise > 60) // 举手阈值 - { - // 初始化计时 - if (_raiseStartTime == null) - _raiseStartTime = DateTime.Now; - - if (_wristStartTime == null) - _wristStartTime = DateTime.Now; - - var wristDuration = DateTime.Now - _wristStartTime.Value; - - // 保持 >1 秒才触发一次 FirstHand - if (!_firstHandTriggered && wristDuration.TotalSeconds >= 1) - { - _firstHandTriggered = true; - return (int)WavingAction.FirstHand; // 举手开始,只触发一次 - } - - // 判断是否完成3秒举手 - var duration = DateTime.Now - _raiseStartTime.Value; - if (duration.TotalSeconds >= 3) - { - _raiseStartTime = null; - _wristStartTime = null; - _firstHandTriggered = false; // 重置状态 - return (int)WavingAction.RaiseHand; // 举手完成 - } - else - { - return (int)WavingAction.Raising; // 举手中 - } - } - else - { - // 手放下,重置计时和状态 - _raiseStartTime = null; - _wristStartTime = null; - _firstHandTriggered = false; - } + lastWrist = wrist; return (int)WavingAction.None; } /// /// 冷却防抖(避免重复触发) /// - private bool CheckCooldown(int cooldownMs = 800) + private bool CheckCooldown(int cooldownMs = 1000) { if ((DateTime.Now - _lastActionTime).TotalMilliseconds < cooldownMs) return false; diff --git a/Wpf_AiSportsMicrospace/Home.xaml.cs b/Wpf_AiSportsMicrospace/Home.xaml.cs index f605763..220d7ee 100644 --- a/Wpf_AiSportsMicrospace/Home.xaml.cs +++ b/Wpf_AiSportsMicrospace/Home.xaml.cs @@ -173,10 +173,10 @@ namespace Wpf_AiSportsMicrospace var wavingaction = _sportOperate.VerifyWavingAction(human); // 把低 8 位作为动作类型,高 8 位作为进度 - int actionType = wavingaction & 0xFF; - int progress = (wavingaction >> 8) & 0xFF; + //int actionType = wavingaction & 0xFF; + //int progress = (wavingaction >> 8) & 0xFF; - switch (actionType) + switch (wavingaction) { case (int)WavingAction.LeftWave: // 左手挥动 Dispatcher.BeginInvoke(() => coverFlow.SlideRight()); @@ -194,8 +194,8 @@ namespace Wpf_AiSportsMicrospace break; case (int)WavingAction.RaiseHand: // 举手完成 + _cts.Cancel(); coverFlow.ProgressCompleted += CoverFlow_ProgressCompleted; - // _cts.Cancel(); break; default: // 没有动作 → 取消进度 diff --git a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml.cs b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml.cs index 366d67b..e79269c 100644 --- a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml.cs +++ b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml.cs @@ -136,6 +136,7 @@ namespace Wpf_AiSportsMicrospace.MyUserControl } private void StopProgress() + { if (_renderHandler != null) {