2025-10-18 10:44:56 +08:00

220 lines
7.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
private double _leftWristDeltaX = 0;
private double _rightWristDeltaX = 0;
private bool _firstHandTriggered = false;
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);
//_leftTracker.Amplitude = 0.03f;
//_rightTracker.Amplitude = 0.03f;
//_leftElbow.Amplitude = 0.03f;
//_rightElbow.Amplitude = 0.03f;
}
public WebcamClient CreateRTSP()
{
try
{
_webcamClient = WebcamClient.CreateRTSP("172.17.30.64", "admin", "yd708090", 554u);
}
catch (Exception)
{
HandyControl.Controls.MessageBox.Show("摄像头网络异常,请重新连接!");
}
return _webcamClient;
}
public int VerifyWavingAction(List<Human> humans)
{
if (humans == null || humans.Count == 0)
return (int)WavingAction.None;
foreach (var human in humans)
{
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(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");
// --- 右手举手优先 ---
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;
}
/// <summary>
/// 检测右手举手状态
/// </summary>
/// <param name="human">人体关键点信息</param>
/// <returns>返回 WavingActionFirstHand / Raising / RaiseHand / None</returns>
public int DetectRightHandRaise(Human human)
{
var rightWrist = human.Keypoints.FirstOrDefault(k => k.Name == "right_wrist");
var rightElbow = human.Keypoints.FirstOrDefault(k => k.Name == "right_elbow");
if (rightWrist == null || rightElbow == null)
return (int)WavingAction.None;
double verticalRise = rightElbow.Y - rightWrist.Y; // 手腕在肘上方 → 正值
const double raiseThreshold = 60; // 举手阈值,可根据实际调整
if (verticalRise >= raiseThreshold)
{
// 初始化计时
if (_raiseStartTime == null) _raiseStartTime = DateTime.Now;
if (_wristStartTime == null) _wristStartTime = DateTime.Now;
var wristDuration = DateTime.Now - _wristStartTime.Value;
if (!_firstHandTriggered && wristDuration.TotalSeconds >= 1)
{
_firstHandTriggered = true;
return (int)WavingAction.FirstHand; // 举手开始
}
var duration = DateTime.Now - _raiseStartTime.Value;
if (duration.TotalSeconds >= 1)
{
_raiseStartTime = null;
_wristStartTime = null;
_firstHandTriggered = false; // 重置状态
return (int)WavingAction.RaiseHand; // 举手完成
}
else
{
return (int)WavingAction.Raising; // 举手中
}
}
else
{
// 手放下,重置状态
_raiseStartTime = null;
_wristStartTime = null;
_firstHandTriggered = false;
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>
private bool CheckCooldown(int cooldownMs = 1000)
{
if ((DateTime.Now - _lastActionTime).TotalMilliseconds < cooldownMs)
return false;
_lastActionTime = DateTime.Now;
return true;
}
}
}