179 lines
6.3 KiB
C#
Raw Normal View History

2025-09-26 16:46:22 +08:00
using HandyControl.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using Wpf_AiSportsMicrospace.Enum;
using Yztob.AiSports.Inferences.Abstractions;
using Yztob.AiSports.Inferences.Things;
using Yztob.AiSports.Postures;
using Yztob.AiSports.Postures.Abstractions;
using Yztob.AiSports.Postures.Sports;
using Yztob.AiSports.Postures.Things;
using Yztob.AiSports.Sensors.Abstractions;
using Yztob.AiSports.Sensors.Things;
namespace Wpf_AiSportsMicrospace.Common
{
/// <summary>
/// 运动检测操作类
/// </summary>
public class SportOperate
{
IPointTracker _leftTracker;
IPointTracker _rightTracker;
IPointTracker _leftElbow;
IPointTracker _rightElbow;
WebcamClient _webcamClient;
private DateTime _lastActionTime = DateTime.MinValue;
private Point? _lastLeftWrist = null;
private Point? _lastRightWrist = null;
private DateTime? _raiseStartTime = null;
private DateTime? _wristStartTime = null;
2025-09-28 14:08:36 +08:00
private double _leftWristDeltaX = 0;
private double _rightWristDeltaX = 0;
private bool _firstHandTriggered = false;
2025-09-26 16:46:22 +08:00
public SportOperate()
{
_leftTracker = PostureCalculate.CreatePointTracker("left_wrist", 0);
_rightTracker = PostureCalculate.CreatePointTracker("right_wrist", 0);
_leftElbow = PostureCalculate.CreatePointTracker("left_elbow", 0);
_rightElbow = PostureCalculate.CreatePointTracker("right_elbow", 0);
2025-09-28 09:17:44 +08:00
//_leftTracker.Amplitude = 0.03f;
//_rightTracker.Amplitude = 0.03f;
//_leftElbow.Amplitude = 0.03f;
//_rightElbow.Amplitude = 0.03f;
2025-09-26 16:46:22 +08:00
}
public WebcamClient CreateRTSP()
{
_webcamClient = WebcamClient.CreateRTSP("192.168.3.64", "admin", "yd708090", 554u);
return _webcamClient;
}
public int VerifyWavingAction(Human human)
{
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");
2025-09-28 14:08:36 +08:00
// --- 左手挥手 ---
2025-09-26 16:46:22 +08:00
if (leftWrist != null && leftElbow != null)
{
2025-09-28 14:08:36 +08:00
int leftResult = DetectHorizontalWave(
2025-09-26 16:46:22 +08:00
new Point(leftWrist.X, leftWrist.Y),
2025-09-28 14:08:36 +08:00
new Point(leftElbow.X, leftElbow.Y),
ref _lastLeftWrist,
ref _leftWristDeltaX,
true);
if (leftResult != (int)WavingAction.None) return leftResult;
2025-09-26 16:46:22 +08:00
}
2025-09-28 14:08:36 +08:00
// --- 右手挥手或举手 ---
2025-09-26 16:46:22 +08:00
if (rightWrist != null && rightElbow != null)
{
2025-09-28 14:08:36 +08:00
int rightWaveResult = DetectHorizontalWave(
2025-09-26 16:46:22 +08:00
new Point(rightWrist.X, rightWrist.Y),
2025-09-28 14:08:36 +08:00
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;
2025-09-26 16:46:22 +08:00
2025-09-28 14:08:36 +08:00
if (_wristStartTime == null)
_wristStartTime = DateTime.Now;
2025-09-26 16:46:22 +08:00
2025-09-28 14:08:36 +08:00
var wristDuration = DateTime.Now - _wristStartTime.Value;
2025-09-26 16:46:22 +08:00
2025-09-28 14:08:36 +08:00
// 保持 >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
2025-09-26 16:46:22 +08:00
{
2025-09-28 14:08:36 +08:00
return (int)WavingAction.Raising; // 举手中
2025-09-26 16:46:22 +08:00
}
}
2025-09-28 14:08:36 +08:00
else
{
// 手放下,重置计时和状态
_raiseStartTime = null;
_wristStartTime = null;
_firstHandTriggered = false;
}
2025-09-26 16:46:22 +08:00
}
2025-09-28 14:08:36 +08:00
return (int)WavingAction.None;
2025-09-26 16:46:22 +08:00
}
/// <summary>
2025-09-28 14:08:36 +08:00
/// 统一的水平挥手检测
2025-09-26 16:46:22 +08:00
/// </summary>
2025-09-28 14:08:36 +08:00
private int DetectHorizontalWave(Point wrist, Point elbow, ref Point? lastWrist, ref double deltaX, bool isLeft)
2025-09-26 16:46:22 +08:00
{
2025-09-28 14:08:36 +08:00
if (lastWrist != null)
2025-09-26 16:46:22 +08:00
{
2025-09-28 14:08:36 +08:00
double dx = wrist.X - lastWrist.Value.X;
double dy = Math.Abs(wrist.Y - lastWrist.Value.Y);
2025-09-26 16:46:22 +08:00
2025-09-28 14:08:36 +08:00
// 累计水平位移
deltaX += dx;
2025-09-26 16:46:22 +08:00
2025-09-28 14:08:36 +08:00
if (Math.Abs(deltaX) > 40 && dy < 60 && Math.Abs(wrist.Y - elbow.Y) < 60)
2025-09-26 16:46:22 +08:00
{
2025-09-28 14:08:36 +08:00
deltaX = 0; // 重置
if (CheckCooldown())
{
return isLeft ? (int)WavingAction.LeftWave : (int)WavingAction.RightWave;
}
2025-09-26 16:46:22 +08:00
}
}
2025-09-28 14:08:36 +08:00
lastWrist = wrist;
2025-09-26 16:46:22 +08:00
return (int)WavingAction.None;
}
/// <summary>
/// 冷却防抖(避免重复触发)
/// </summary>
2025-09-28 14:08:36 +08:00
private bool CheckCooldown(int cooldownMs = 1000)
2025-09-26 16:46:22 +08:00
{
if ((DateTime.Now - _lastActionTime).TotalMilliseconds < cooldownMs)
return false;
_lastActionTime = DateTime.Now;
return true;
}
2025-10-09 10:14:43 +08:00
2025-09-26 16:46:22 +08:00
}
}