diff --git a/Wpf_AiSportsMicrospace/Common/SportOperate.cs b/Wpf_AiSportsMicrospace/Common/SportOperate.cs
index 936e7df..13afba2 100644
--- a/Wpf_AiSportsMicrospace/Common/SportOperate.cs
+++ b/Wpf_AiSportsMicrospace/Common/SportOperate.cs
@@ -27,7 +27,11 @@ namespace Wpf_AiSportsMicrospace.Common
IPointTracker _rightTracker;
IPointTracker _leftElbow;
IPointTracker _rightElbow;
- WebcamClient _webcamClient;
+ WebcamClient _webcamClient;
+ private Point? _lastWrist = null; // 上一帧的手腕位置
+ private DateTime _lastActionTime = DateTime.MinValue; // 上次动作时间
+ private readonly TimeSpan _cooldown = TimeSpan.FromMilliseconds(800); // 动作冷却,避免误触发
+
public SportOperate()
{
@@ -41,6 +45,7 @@ namespace Wpf_AiSportsMicrospace.Common
_leftElbow.Amplitude = 0.05f;
_rightElbow.Amplitude = 0.05f;
}
+
public WebcamClient CreateRTSP()
{
_webcamClient = WebcamClient.CreateRTSP("192.168.3.64", "admin", "yd708090", 554u);
@@ -59,13 +64,18 @@ namespace Wpf_AiSportsMicrospace.Common
var rightElbowResult = _rightElbow.Tracking(human);
// 节流:每 300ms 最多更新一次 UI
- if ((DateTime.Now - _lastSlideTime).TotalMilliseconds < 500) return 0;
- _lastSlideTime = DateTime.Now;
+ //if ((DateTime.Now - _lastSlideTime).TotalMilliseconds < 500) return 0;
+ //_lastSlideTime = DateTime.Now;
// 根据手势结果选择滑动方向
if (leftResult != 0 && leftElbowResult != 0) return 1;
- if (rightResult != 0 & rightElbowResult != 0) return 2;
-
+ if (rightResult != 0 & rightElbowResult != 0)
+ {
+ var wrist = human.Keypoints.Where(x => x.Name == "right_wrist").FirstOrDefault();
+ var elbow = human.Keypoints.Where(x => x.Name == "right_elbow").FirstOrDefault();
+ if (wrist == null || elbow == null) return 0;
+ return RecognizeRightHandGesture(new Point(wrist.X, wrist.Y), new Point(elbow.X, elbow.Y));
+ }
return 0;
}
@@ -84,5 +94,46 @@ namespace Wpf_AiSportsMicrospace.Common
return 0;
}
+
+ public int RecognizeRightHandGesture(Point wrist, Point elbow)
+ {
+ // 判断举手:手腕在肘部之上,且垂直距离超过一定阈值
+ if (wrist.Y + 40 < elbow.Y) // 手腕比肘高 40 像素以上
+ {
+ if (CheckCooldown())
+ return 3; // 举手
+ }
+
+ // 需要至少两帧来判断水平移动方向
+ 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)
+ {
+ if (CheckCooldown())
+ {
+ if (dx > 0)
+ return 2; // 右挥手
+ else
+ return 1; // 左挥手
+ }
+ }
+ }
+
+ _lastWrist = wrist;
+ return 0;
+ }
+ private bool CheckCooldown()
+ {
+ if (DateTime.Now - _lastActionTime > _cooldown)
+ {
+ _lastActionTime = DateTime.Now;
+ return true;
+ }
+ return false;
+ }
}
}
diff --git a/Wpf_AiSportsMicrospace/Home.xaml.cs b/Wpf_AiSportsMicrospace/Home.xaml.cs
index 25e5f12..e1afa20 100644
--- a/Wpf_AiSportsMicrospace/Home.xaml.cs
+++ b/Wpf_AiSportsMicrospace/Home.xaml.cs
@@ -15,6 +15,7 @@ using System.Windows.Media;
using System.Windows.Media.Animation;
using Wpf_AiSportsMicrospace.Common;
using Wpf_AiSportsMicrospace.MyUserControl;
+using Wpf_AiSportsMicrospace.Views;
using Yunzhi.Database;
using Yztob.AiSports.Inferences.Abstractions;
using Yztob.AiSports.Postures;
@@ -96,14 +97,32 @@ namespace Wpf_AiSportsMicrospace
if (item.ImageUri.ToString().EndsWith("1.jpg"))
{
// 跳转到页面1
+ Dispatcher.BeginInvoke(new Action(() =>
+ {
+ GroupJumpRope groupJumpRope = new GroupJumpRope();
+ groupJumpRope.Owner = Application.Current.MainWindow;
+ groupJumpRope.Show();
+ }));
}
else if (item.ImageUri.ToString().EndsWith("2.jpg"))
{
// 跳转到页面2
+ Dispatcher.BeginInvoke(new Action(() =>
+ {
+ GroupJumpRope groupJumpRope = new GroupJumpRope();
+ groupJumpRope.Owner = Application.Current.MainWindow;
+ groupJumpRope.Show();
+ }));
}
else if (item.ImageUri.ToString().EndsWith("3.jpg"))
{
// 跳转到页面3
+ Dispatcher.BeginInvoke(new Action(() =>
+ {
+ GroupJumpRope groupJumpRope = new GroupJumpRope();
+ groupJumpRope.Owner = Application.Current.MainWindow;
+ groupJumpRope.Show();
+ }));
}
}
@@ -148,33 +167,33 @@ namespace Wpf_AiSportsMicrospace
if (human == null) return;
+ //检测挥手动作
+ var wavingaction = _sportOperate.VerifyWavingAction(human);
- // 启动进度条动画;
- //SlideCoverFlow(coverFlow.StartSelectedProgress);
-
- ////检测挥手动作
- //var wavingAction = _sportOperate.VerifyWavingAction(human);
- //// 根据手势结果选择滑动方向
- //if (wavingAction == 1)
- //{
- // SlideCoverFlow(coverFlow.SlideRight);
- // return;
- //}
- //if (wavingAction == 2)
- //{
- // SlideCoverFlow(coverFlow.SlideLeft);
- // return;
- //}
-
- //检测举手动作
- var liftHandAction = _sportOperate.VerifyLiftHandAction(human);
-
- // 根据手势结果
- if (liftHandAction == 1)
+ switch (wavingaction)
{
- // 启动进度条动画;
- Dispatcher.BeginInvoke(() => coverFlow.StartSelectedProgress());
+ case 1:
+ Dispatcher.BeginInvoke(() => coverFlow.SlideLeft());
+ break;
+ case 2:
+ Dispatcher.BeginInvoke(() => coverFlow.SlideRight());
+ break;
+ case 3:
+ Dispatcher.BeginInvoke(() => coverFlow.StartSelectedProgress());
+ break;
+ default:
+ break;
}
+
+ ////检测举手动作
+ //var liftHandAction = _sportOperate.VerifyLiftHandAction(human);
+
+ //// 根据手势结果
+ //if (liftHandAction == 1)
+ //{
+ // // 启动进度条动画;
+ // Dispatcher.BeginInvoke(() => coverFlow.StartSelectedProgress());
+ //}
}
catch (Exception ex)
{
diff --git a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml
new file mode 100644
index 0000000..26ba7e6
--- /dev/null
+++ b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs
new file mode 100644
index 0000000..e26ef5a
--- /dev/null
+++ b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace Wpf_AiSportsMicrospace.Views
+{
+ ///
+ /// GroupJumpRope.xaml 的交互逻辑
+ ///
+ public partial class GroupJumpRope : Window
+ {
+ public GroupJumpRope()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml b/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml
new file mode 100644
index 0000000..32f139b
--- /dev/null
+++ b/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml.cs b/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml.cs
new file mode 100644
index 0000000..3235a2d
--- /dev/null
+++ b/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace Wpf_AiSportsMicrospace.Views
+{
+ ///
+ /// MusicJumpRope.xaml 的交互逻辑
+ ///
+ public partial class MusicJumpRope : Window
+ {
+ public MusicJumpRope()
+ {
+ InitializeComponent();
+ }
+ }
+}