举手会首页
This commit is contained in:
parent
5ea60735e4
commit
6d248c8892
13
Wpf_AiSportsMicrospace/Enum/GameState.cs
Normal file
13
Wpf_AiSportsMicrospace/Enum/GameState.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Enum
|
||||||
|
{
|
||||||
|
public enum GameState
|
||||||
|
{
|
||||||
|
NotStarted, // 游戏未开始
|
||||||
|
Running, // 游戏进行中
|
||||||
|
Finished // 游戏完成
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -64,11 +64,12 @@ namespace Wpf_AiSportsMicrospace
|
|||||||
{
|
{
|
||||||
_mainWin.HumanFrameUpdated -= OnHumanFrameUpdated;
|
_mainWin.HumanFrameUpdated -= OnHumanFrameUpdated;
|
||||||
}
|
}
|
||||||
|
private bool IsGestureActive = true; // 标记手势识别是否有效
|
||||||
private void OnHumanFrameUpdated(object sender, List<Human> humans)
|
private void OnHumanFrameUpdated(object sender, List<Human> humans)
|
||||||
{
|
{
|
||||||
var human = humans.FirstOrDefault();
|
if (!IsGestureActive) return; // 手势识别已停止,直接返回
|
||||||
|
|
||||||
|
var human = humans.FirstOrDefault();
|
||||||
if (human == null) return;
|
if (human == null) return;
|
||||||
|
|
||||||
// 检测挥手动作
|
// 检测挥手动作
|
||||||
@ -93,6 +94,9 @@ namespace Wpf_AiSportsMicrospace
|
|||||||
|
|
||||||
case (int)WavingAction.RaiseHand: // 举手完成
|
case (int)WavingAction.RaiseHand: // 举手完成
|
||||||
coverFlow.ProgressCompleted += CoverFlow_ProgressCompleted;
|
coverFlow.ProgressCompleted += CoverFlow_ProgressCompleted;
|
||||||
|
|
||||||
|
// 设置标记,停止后续手势识别
|
||||||
|
IsGestureActive = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: // 没有动作 → 取消进度
|
default: // 没有动作 → 取消进度
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using Dto;
|
using Dto;
|
||||||
using Emgu.CV.Flann;
|
using Emgu.CV.Flann;
|
||||||
|
using Enum;
|
||||||
using HandyControl.Controls;
|
using HandyControl.Controls;
|
||||||
using SharpDX.Direct3D9;
|
using SharpDX.Direct3D9;
|
||||||
using System;
|
using System;
|
||||||
@ -49,18 +50,20 @@ namespace Wpf_AiSportsMicrospace.Views
|
|||||||
private MediaPlayer _mediaPlayer = new MediaPlayer();
|
private MediaPlayer _mediaPlayer = new MediaPlayer();
|
||||||
List<RankItem> RankingItemList = new();
|
List<RankItem> RankingItemList = new();
|
||||||
|
|
||||||
|
private readonly SportDetectionQueue _detectQueue;
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||||
{
|
{
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
}
|
}
|
||||||
private bool IsGameStarted = false;
|
private GameState _currentGameState = GameState.NotStarted;
|
||||||
private readonly object _updateLock = new object();
|
private readonly object _updateLock = new object();
|
||||||
private readonly Dictionary<int, (string lastNumber, DateTime lastChangeTime, string currentState)> _jumpStatus = new Dictionary<int, (string, DateTime, string)>();
|
private readonly Dictionary<int, (string lastNumber, DateTime lastChangeTime, string currentState)> _jumpStatus = new Dictionary<int, (string, DateTime, string)>();
|
||||||
private GroupJumpRopeContext _groupJumpRopeContext;
|
private GroupJumpRopeContext _groupJumpRopeContext;
|
||||||
public GroupJumpRope()
|
public GroupJumpRope()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
_detectQueue = new SportDetectionQueue();
|
||||||
Loaded += UserControl_Loaded;
|
Loaded += UserControl_Loaded;
|
||||||
Unloaded += UserControl_Unloaded;
|
Unloaded += UserControl_Unloaded;
|
||||||
_groupJumpRopeContext = new GroupJumpRopeContext();
|
_groupJumpRopeContext = new GroupJumpRopeContext();
|
||||||
@ -162,47 +165,46 @@ namespace Wpf_AiSportsMicrospace.Views
|
|||||||
private void OnHumanFrameUpdated(object sender, List<Human> humans)
|
private void OnHumanFrameUpdated(object sender, List<Human> humans)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
|
||||||
if (!IsGameStarted)
|
|
||||||
{
|
{
|
||||||
if (humans == null || humans.Count == 0) return;
|
if (humans == null || humans.Count == 0) return;
|
||||||
|
switch (_currentGameState)
|
||||||
int wavingaction = 0;
|
{
|
||||||
|
case GameState.NotStarted: // 未开始
|
||||||
wavingaction = DetectRightHandRaise(humans);
|
int rightWaving = DetectRightHandRaise(humans);
|
||||||
|
if (rightWaving >= 3)
|
||||||
if (wavingaction < 3)
|
{
|
||||||
return;
|
switch (rightWaving)
|
||||||
|
|
||||||
switch (wavingaction)
|
|
||||||
{
|
{
|
||||||
case (int)WavingAction.FirstHand:
|
case (int)WavingAction.FirstHand:
|
||||||
// 第一次举手,初始化倒计时
|
|
||||||
StartCountdown(3);
|
StartCountdown(3);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (int)WavingAction.Raising:
|
case (int)WavingAction.Raising:
|
||||||
// 持续倒计时中
|
|
||||||
UpdateCountdown();
|
UpdateCountdown();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (int)WavingAction.RaiseHand:
|
case (int)WavingAction.RaiseHand:
|
||||||
// 举手完成,倒计时结束
|
|
||||||
FinishCountdown();
|
FinishCountdown();
|
||||||
break;
|
_currentGameState = GameState.Running; // 倒计时完成 → 游戏开始
|
||||||
|
|
||||||
default:
|
|
||||||
// 没检测到动作,重置倒计时显示
|
|
||||||
Utils.StopBackgroundMusic();
|
|
||||||
countdownText.Text = "3";
|
|
||||||
countdownGrid.Visibility = Visibility.Hidden;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
break;
|
||||||
{
|
|
||||||
|
case GameState.Running: // 游戏进行中
|
||||||
UpdateCircleCounts(humans);
|
UpdateCircleCounts(humans);
|
||||||
|
|
||||||
|
// 可选:判断游戏结束条件,将状态切换到 Finished
|
||||||
|
// if (CheckGameFinished()) _currentGameState = GameState.Finished;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GameState.Finished: // 游戏完成
|
||||||
|
int leftWaving = DetectLeftHandRaise(humans);
|
||||||
|
if (leftWaving == 5)
|
||||||
|
{
|
||||||
|
// 举左手逻辑,例如结束动画或退出
|
||||||
|
var newPage = new Home();
|
||||||
|
_mainWin?.SwitchPageWithMaskAnimation(newPage, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -210,6 +212,7 @@ namespace Wpf_AiSportsMicrospace.Views
|
|||||||
Console.WriteLine("OnFrameExtracted error: " + ex.Message);
|
Console.WriteLine("OnFrameExtracted error: " + ex.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int _currentCountdown = 3;
|
private int _currentCountdown = 3;
|
||||||
private DateTime _lastUpdateTime = DateTime.Now;
|
private DateTime _lastUpdateTime = DateTime.Now;
|
||||||
private void StartCountdown(int start = 3)
|
private void StartCountdown(int start = 3)
|
||||||
@ -246,11 +249,9 @@ namespace Wpf_AiSportsMicrospace.Views
|
|||||||
{
|
{
|
||||||
countdownText.Text = "GO!";
|
countdownText.Text = "GO!";
|
||||||
countdownGrid.Visibility = Visibility.Hidden;
|
countdownGrid.Visibility = Visibility.Hidden;
|
||||||
IsGameStarted = true;
|
|
||||||
|
|
||||||
// 播放背景音乐(循环)
|
// 播放背景音乐(循环)
|
||||||
Utils.PlayBackgroundMusic("homeprojectselected1.mp3", true);
|
Utils.PlayBackgroundMusic("homeprojectselected1.mp3", true);
|
||||||
|
|
||||||
// 启动60秒倒计时(独立任务)
|
// 启动60秒倒计时(独立任务)
|
||||||
StartGameCountdown(60);
|
StartGameCountdown(60);
|
||||||
}
|
}
|
||||||
@ -273,8 +274,9 @@ namespace Wpf_AiSportsMicrospace.Views
|
|||||||
|
|
||||||
RankingItemList = _groupJumpRopeContext.UpdateRankList();
|
RankingItemList = _groupJumpRopeContext.UpdateRankList();
|
||||||
ShowRankingBoard(RankingItemList);
|
ShowRankingBoard(RankingItemList);
|
||||||
IsGameStarted = false;
|
|
||||||
Utils.StopBackgroundMusic();
|
Utils.StopBackgroundMusic();
|
||||||
|
|
||||||
|
_currentGameState = GameState.Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DateTime? _raiseStartTime;
|
private DateTime? _raiseStartTime;
|
||||||
@ -367,6 +369,46 @@ namespace Wpf_AiSportsMicrospace.Views
|
|||||||
// 没有任何中心区域内的人举手
|
// 没有任何中心区域内的人举手
|
||||||
return (int)WavingAction.None;
|
return (int)WavingAction.None;
|
||||||
}
|
}
|
||||||
|
public int DetectLeftHandRaise(List<Human> humans)
|
||||||
|
{
|
||||||
|
if (humans == null || humans.Count == 0)
|
||||||
|
return (int)WavingAction.None;
|
||||||
|
|
||||||
|
foreach (var human in humans)
|
||||||
|
{
|
||||||
|
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 = leftWrist.Y - leftElbow.Y;
|
||||||
|
if (verticalRise >= raiseThreshold)
|
||||||
|
{
|
||||||
|
return (int)WavingAction.RaiseHand; // 一旦检测到左手举起,立即返回
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)WavingAction.None; // 没有检测到举手
|
||||||
|
}
|
||||||
|
|
||||||
private void ResetRaiseState()
|
private void ResetRaiseState()
|
||||||
{
|
{
|
||||||
@ -529,7 +571,8 @@ namespace Wpf_AiSportsMicrospace.Views
|
|||||||
number3.Text = list[2].Number.ToString();
|
number3.Text = list[2].Number.ToString();
|
||||||
foreach (var item in list)
|
foreach (var item in list)
|
||||||
{
|
{
|
||||||
var grid = new Grid {
|
var grid = new Grid
|
||||||
|
{
|
||||||
Width = 1344,
|
Width = 1344,
|
||||||
Height = 71,
|
Height = 71,
|
||||||
HorizontalAlignment = HorizontalAlignment.Center,
|
HorizontalAlignment = HorizontalAlignment.Center,
|
||||||
|
|||||||
@ -30,6 +30,7 @@ namespace Wpf_AiSportsMicrospace.Views
|
|||||||
private HumanGraphicsRenderer _humanGraphicsRenderer;
|
private HumanGraphicsRenderer _humanGraphicsRenderer;
|
||||||
public SportOperate SportOperate { get; private set; }
|
public SportOperate SportOperate { get; private set; }
|
||||||
public WebcamClient WebcamClient { get; private set; }
|
public WebcamClient WebcamClient { get; private set; }
|
||||||
|
private readonly SportDetectionQueue _detectQueue;
|
||||||
private readonly ConcurrentQueue<VideoFrame> _frameQueue = new();
|
private readonly ConcurrentQueue<VideoFrame> _frameQueue = new();
|
||||||
private readonly CancellationTokenSource _cts = new();
|
private readonly CancellationTokenSource _cts = new();
|
||||||
private DateTime _lastFrameTime = DateTime.Now;
|
private DateTime _lastFrameTime = DateTime.Now;
|
||||||
@ -52,6 +53,7 @@ namespace Wpf_AiSportsMicrospace.Views
|
|||||||
_humanPredictor = HumanPredictorFactory.Create(HumanPredictorType.MultiMedium);
|
_humanPredictor = HumanPredictorFactory.Create(HumanPredictorType.MultiMedium);
|
||||||
_humanGraphicsRenderer = new HumanGraphicsRenderer();
|
_humanGraphicsRenderer = new HumanGraphicsRenderer();
|
||||||
_humanGraphicsRenderer.DrawLabel = false;
|
_humanGraphicsRenderer.DrawLabel = false;
|
||||||
|
_detectQueue = new SportDetectionQueue();
|
||||||
|
|
||||||
SportOperate = new SportOperate();
|
SportOperate = new SportOperate();
|
||||||
WebcamClient = SportOperate.CreateRTSP();
|
WebcamClient = SportOperate.CreateRTSP();
|
||||||
@ -108,6 +110,10 @@ namespace Wpf_AiSportsMicrospace.Views
|
|||||||
var humans = humanResult?.Humans?.ToList();
|
var humans = humanResult?.Humans?.ToList();
|
||||||
if (humans == null || humans.Count == 0)
|
if (humans == null || humans.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
foreach (var human in humans)
|
||||||
|
{
|
||||||
|
_detectQueue.Enqueue(frame.Number, human, null);
|
||||||
|
}
|
||||||
|
|
||||||
// 触发全局事件
|
// 触发全局事件
|
||||||
Application.Current.Dispatcher.BeginInvoke(() =>
|
Application.Current.Dispatcher.BeginInvoke(() =>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user