举手
This commit is contained in:
parent
027cffa506
commit
29360dcb96
@ -65,57 +65,65 @@ namespace Wpf_AiSportsMicrospace.Common
|
|||||||
|
|
||||||
return _webcamClient;
|
return _webcamClient;
|
||||||
}
|
}
|
||||||
public int VerifyWavingAction(Human human)
|
public int VerifyWavingAction(List<Human> humans)
|
||||||
{
|
{
|
||||||
var nose = human.Keypoints.FirstOrDefault(k => k.Name == "right_ankle");
|
if (humans == null || humans.Count == 0)
|
||||||
if (nose == null)
|
|
||||||
return (int)WavingAction.None;
|
return (int)WavingAction.None;
|
||||||
|
|
||||||
double xNorm = nose.X / 1920;
|
foreach (var human in humans)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
int leftResult = DetectHorizontalWave(
|
var rightAnkle = human.Keypoints.FirstOrDefault(k => k.Name == "right_ankle");
|
||||||
new Point(leftWrist.X, leftWrist.Y),
|
if (rightAnkle == null)
|
||||||
new Point(leftElbow.X, leftElbow.Y),
|
continue;
|
||||||
ref _lastLeftWrist,
|
|
||||||
ref _leftWristDeltaX,
|
|
||||||
true);
|
|
||||||
if (leftResult != (int)WavingAction.None)
|
|
||||||
return leftResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- 右手举手优先判断 ---
|
double xNorm = rightAnkle.X / 1920;
|
||||||
int rightHandAction = DetectRightHandRaise(human);
|
double yNorm = rightAnkle.Y / 1080;
|
||||||
if (rightHandAction != (int)WavingAction.None)
|
|
||||||
return rightHandAction;
|
|
||||||
|
|
||||||
// --- 右手挥手,仅当未举手时判断 ---
|
// 仅检测中心区域内的人
|
||||||
if (rightWrist != null && rightElbow != null)
|
if (!(xNorm >= 0.44 && xNorm <= 0.57 && yNorm >= 0.81))
|
||||||
{
|
continue;
|
||||||
int rightWaveResult = DetectHorizontalWave(
|
|
||||||
new Point(rightWrist.X, rightWrist.Y),
|
var leftWrist = human.Keypoints.FirstOrDefault(x => x.Name == "left_wrist");
|
||||||
new Point(rightElbow.X, rightElbow.Y),
|
var leftElbow = human.Keypoints.FirstOrDefault(x => x.Name == "left_elbow");
|
||||||
ref _lastRightWrist,
|
var rightWrist = human.Keypoints.FirstOrDefault(x => x.Name == "right_wrist");
|
||||||
ref _rightWristDeltaX,
|
var rightElbow = human.Keypoints.FirstOrDefault(x => x.Name == "right_elbow");
|
||||||
false);
|
|
||||||
if (rightWaveResult != (int)WavingAction.None)
|
// --- 右手举手优先 ---
|
||||||
return rightWaveResult;
|
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;
|
return (int)WavingAction.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 检测右手举手状态
|
/// 检测右手举手状态
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -87,7 +87,7 @@ namespace Wpf_AiSportsMicrospace.Views
|
|||||||
if (human == null) return;
|
if (human == null) return;
|
||||||
|
|
||||||
//检测挥手动作
|
//检测挥手动作
|
||||||
var wavingaction = sportOperate.VerifyWavingAction(human);
|
var wavingaction = sportOperate.VerifyWavingAction(humans);
|
||||||
|
|
||||||
switch (wavingaction)
|
switch (wavingaction)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -71,7 +71,7 @@ namespace Wpf_AiSportsMicrospace
|
|||||||
if (human == null) return;
|
if (human == null) return;
|
||||||
|
|
||||||
//检测挥手动作
|
//检测挥手动作
|
||||||
var wavingaction = _mainWin.SportOperate.VerifyWavingAction(human);
|
var wavingaction = _mainWin.SportOperate.VerifyWavingAction(humans);
|
||||||
|
|
||||||
switch (wavingaction)
|
switch (wavingaction)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -158,38 +158,37 @@ namespace Wpf_AiSportsMicrospace.Views
|
|||||||
if (humans == null || humans.Count == 0) return;
|
if (humans == null || humans.Count == 0) return;
|
||||||
|
|
||||||
int wavingaction = 0;
|
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)
|
case (int)WavingAction.Raising:
|
||||||
continue;
|
// 持续倒计时中
|
||||||
|
UpdateCountdown();
|
||||||
|
break;
|
||||||
|
|
||||||
switch (wavingaction)
|
case (int)WavingAction.RaiseHand:
|
||||||
{
|
// 举手完成,倒计时结束
|
||||||
case (int)WavingAction.FirstHand:
|
FinishCountdown();
|
||||||
// 第一次举手,初始化倒计时
|
break;
|
||||||
StartCountdown(3);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case (int)WavingAction.Raising:
|
default:
|
||||||
// 持续倒计时中
|
// 没检测到动作,重置倒计时显示
|
||||||
UpdateCountdown();
|
Utils.StopBackgroundMusic();
|
||||||
break;
|
countdownText.Text = "3";
|
||||||
|
countdownGrid.Visibility = Visibility.Hidden;
|
||||||
case (int)WavingAction.RaiseHand:
|
break;
|
||||||
// 举手完成,倒计时结束
|
|
||||||
FinishCountdown();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// 没检测到动作,重置倒计时显示
|
|
||||||
Utils.StopBackgroundMusic();
|
|
||||||
countdownText.Text = "3";
|
|
||||||
countdownGrid.Visibility = Visibility.Hidden;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -273,66 +272,91 @@ namespace Wpf_AiSportsMicrospace.Views
|
|||||||
private bool _firstHandTriggered;
|
private bool _firstHandTriggered;
|
||||||
private int _lastCountdownSecond = 3;
|
private int _lastCountdownSecond = 3;
|
||||||
private DateTime? _countdownStartTime;
|
private DateTime? _countdownStartTime;
|
||||||
public int DetectRightHandRaise(Human human)
|
public int DetectRightHandRaise(List<Human> humans)
|
||||||
{
|
{
|
||||||
var rightWrist = human.Keypoints.FirstOrDefault(k => k.Name == "right_wrist");
|
if (humans == null || humans.Count == 0)
|
||||||
var rightElbow = human.Keypoints.FirstOrDefault(k => k.Name == "right_elbow");
|
return (int)WavingAction.None;
|
||||||
|
|
||||||
const double raiseThreshold = 60; // 举手阈值
|
foreach (var human in humans)
|
||||||
const double holdDuration = 1; // 持续 2 秒触发倒计时
|
|
||||||
const int countdownSeconds = 3; // 倒计时长度
|
|
||||||
|
|
||||||
bool handRaised = false;
|
|
||||||
|
|
||||||
if (rightWrist != null && rightElbow != null)
|
|
||||||
{
|
{
|
||||||
double verticalRise = rightElbow.Y - rightWrist.Y;
|
if (human?.Keypoints == null)
|
||||||
handRaised = verticalRise >= raiseThreshold;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
// ---------- 第一步:持续举手触发倒计时 ----------
|
// --- 筛选右脚踝坐标 ---
|
||||||
if (!_firstHandTriggered)
|
var rightAnkle = human.Keypoints.FirstOrDefault(k => k.Name == "right_ankle");
|
||||||
{
|
if (rightAnkle == null)
|
||||||
if (handRaised)
|
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;
|
double verticalRise = rightElbow.Y - rightWrist.Y;
|
||||||
var holdElapsed = (DateTime.Now - _raiseStartTime.Value).TotalSeconds;
|
handRaised = verticalRise >= raiseThreshold;
|
||||||
if (holdElapsed >= holdDuration)
|
}
|
||||||
|
|
||||||
|
// ---------- 第一步:持续举手触发倒计时 ----------
|
||||||
|
if (!_firstHandTriggered)
|
||||||
|
{
|
||||||
|
if (handRaised)
|
||||||
{
|
{
|
||||||
// 举手达到 2 秒,启动倒计时
|
_raiseStartTime ??= DateTime.Now;
|
||||||
_firstHandTriggered = true;
|
var holdElapsed = (DateTime.Now - _raiseStartTime.Value).TotalSeconds;
|
||||||
_countdownStartTime = DateTime.Now;
|
if (holdElapsed >= holdDuration)
|
||||||
_lastCountdownSecond = countdownSeconds;
|
{
|
||||||
return (int)WavingAction.FirstHand;
|
// 举手达到指定时间,启动倒计时
|
||||||
|
_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)
|
||||||
{
|
{
|
||||||
// 手放下,重置举手开始时间
|
_lastCountdownSecond = currentSecond;
|
||||||
_raiseStartTime = DateTime.Now;
|
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;
|
return (int)WavingAction.None;
|
||||||
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; // 倒计时中
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ResetRaiseState()
|
private void ResetRaiseState()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user