手势识别优化

This commit is contained in:
tanglong 2025-09-28 14:08:36 +08:00
parent 2a24d26ce4
commit 9c63156551
3 changed files with 74 additions and 90 deletions

View File

@ -34,6 +34,9 @@ namespace Wpf_AiSportsMicrospace.Common
private Point? _lastRightWrist = null; private Point? _lastRightWrist = null;
private DateTime? _raiseStartTime = null; private DateTime? _raiseStartTime = null;
private DateTime? _wristStartTime = null; private DateTime? _wristStartTime = null;
private double _leftWristDeltaX = 0;
private double _rightWristDeltaX = 0;
private bool _firstHandTriggered = false;
public SportOperate() public SportOperate()
@ -62,80 +65,32 @@ namespace Wpf_AiSportsMicrospace.Common
var rightWrist = human.Keypoints.FirstOrDefault(x => x.Name == "right_wrist"); var rightWrist = human.Keypoints.FirstOrDefault(x => x.Name == "right_wrist");
var rightElbow = human.Keypoints.FirstOrDefault(x => x.Name == "right_elbow"); var rightElbow = human.Keypoints.FirstOrDefault(x => x.Name == "right_elbow");
// 左手逻辑 // --- 左手挥手 ---
if (leftWrist != null && leftElbow != null) if (leftWrist != null && leftElbow != null)
{ {
var result = RecognizeLeftHandGesture( int leftResult = DetectHorizontalWave(
new Point(leftWrist.X, leftWrist.Y), new Point(leftWrist.X, leftWrist.Y),
new Point(leftElbow.X, leftElbow.Y)); new Point(leftElbow.X, leftElbow.Y),
if (result != 0) return result; ref _lastLeftWrist,
ref _leftWristDeltaX,
true);
if (leftResult != (int)WavingAction.None) return leftResult;
} }
// 右手逻辑 // --- 右手挥手或举手 ---
if (rightWrist != null && rightElbow != null) if (rightWrist != null && rightElbow != null)
{ {
var result = RecognizeRightHandGesture( int rightWaveResult = DetectHorizontalWave(
new Point(rightWrist.X, rightWrist.Y), new Point(rightWrist.X, rightWrist.Y),
new Point(rightElbow.X, rightElbow.Y)); new Point(rightElbow.X, rightElbow.Y),
if (result != 0) return result; ref _lastRightWrist,
} ref _rightWristDeltaX,
false);
return 0; if (rightWaveResult != (int)WavingAction.None) return rightWaveResult;
}
/// <summary>
/// 统一的水平挥手检测
/// </summary>
private int DetectHorizontalWave(Point wrist, Point elbow, Point? lastWrist, 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)
{
if (CheckCooldown())
{
if (isLeft && dx > 0)
return (int)WavingAction.LeftWave; // 左手往右挥
if (!isLeft && dx < 0)
return (int)WavingAction.RightWave; // 右手往左挥
}
}
}
return (int)WavingAction.None;
}
/// <summary>
/// 识别左手动作
/// </summary>
public int RecognizeLeftHandGesture(Point wrist, Point elbow)
{
int result = DetectHorizontalWave(wrist, elbow, _lastLeftWrist, true);
_lastLeftWrist = wrist; // 更新记录
return result;
}
private bool _firstHandTriggered = false;
/// <summary>
/// 识别右手动作
/// </summary>
/// <param name="wrist"></param>
/// <param name="elbow"></param>
/// <returns></returns>
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; // 手腕在肘上方 → 正值 double verticalRise = rightElbow.Y - rightWrist.Y; // 手腕在肘上方 → 正值
if (verticalRise > 60) // 举手阈值 if (verticalRise >= 60) // 举手阈值
{ {
// 初始化计时 // 初始化计时
if (_raiseStartTime == null) if (_raiseStartTime == null)
@ -174,14 +129,42 @@ namespace Wpf_AiSportsMicrospace.Common
_wristStartTime = null; _wristStartTime = null;
_firstHandTriggered = false; _firstHandTriggered = false;
} }
}
return (int)WavingAction.None; return (int)WavingAction.None;
} }
/// <summary>
/// 统一的水平挥手检测
/// </summary>
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);
// 累计水平位移
deltaX += dx;
if (Math.Abs(deltaX) > 40 && dy < 60 && Math.Abs(wrist.Y - elbow.Y) < 60)
{
deltaX = 0; // 重置
if (CheckCooldown())
{
return isLeft ? (int)WavingAction.LeftWave : (int)WavingAction.RightWave;
}
}
}
lastWrist = wrist;
return (int)WavingAction.None;
}
/// <summary> /// <summary>
/// 冷却防抖(避免重复触发) /// 冷却防抖(避免重复触发)
/// </summary> /// </summary>
private bool CheckCooldown(int cooldownMs = 800) private bool CheckCooldown(int cooldownMs = 1000)
{ {
if ((DateTime.Now - _lastActionTime).TotalMilliseconds < cooldownMs) if ((DateTime.Now - _lastActionTime).TotalMilliseconds < cooldownMs)
return false; return false;

View File

@ -173,10 +173,10 @@ namespace Wpf_AiSportsMicrospace
var wavingaction = _sportOperate.VerifyWavingAction(human); var wavingaction = _sportOperate.VerifyWavingAction(human);
// 把低 8 位作为动作类型,高 8 位作为进度 // 把低 8 位作为动作类型,高 8 位作为进度
int actionType = wavingaction & 0xFF; //int actionType = wavingaction & 0xFF;
int progress = (wavingaction >> 8) & 0xFF; //int progress = (wavingaction >> 8) & 0xFF;
switch (actionType) switch (wavingaction)
{ {
case (int)WavingAction.LeftWave: // 左手挥动 case (int)WavingAction.LeftWave: // 左手挥动
Dispatcher.BeginInvoke(() => coverFlow.SlideRight()); Dispatcher.BeginInvoke(() => coverFlow.SlideRight());
@ -194,8 +194,8 @@ namespace Wpf_AiSportsMicrospace
break; break;
case (int)WavingAction.RaiseHand: // 举手完成 case (int)WavingAction.RaiseHand: // 举手完成
_cts.Cancel();
coverFlow.ProgressCompleted += CoverFlow_ProgressCompleted; coverFlow.ProgressCompleted += CoverFlow_ProgressCompleted;
// _cts.Cancel();
break; break;
default: // 没有动作 → 取消进度 default: // 没有动作 → 取消进度

View File

@ -136,6 +136,7 @@ namespace Wpf_AiSportsMicrospace.MyUserControl
} }
private void StopProgress() private void StopProgress()
{ {
if (_renderHandler != null) if (_renderHandler != null)
{ {