using AiSportsMicrospaceDB.DBContext; using Common; using HandyControl.Controls; using Microsoft.EntityFrameworkCore.Storage.Json; using Microsoft.Extensions.DependencyInjection; using SportExpand; 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 { /// /// 运动检测操作类 /// public class SportOperate { IPointTracker _leftTracker; IPointTracker _rightTracker; private readonly ICalculator _calculator; private readonly CalcBaseRule _raiseRightHandRule; private readonly CalcBaseRule _raiseLeftHandRule; private int _leftWaveCount = 0; private int _rightWaveCount = 0; private const int WaveThreshold = 3; WebcamClient _webcamClient; private DateTime? _wristStartTime = null; private bool _firstHandTriggered = false; public SportOperate() { _leftTracker = PostureCalculate.CreatePointTracker("left_wrist", 0); _rightTracker = PostureCalculate.CreatePointTracker("right_wrist", 0); _calculator = PostureCalculate.CreateCalculator(); _raiseRightHandRule = RaiseHand.RaiseRightHand(); _raiseLeftHandRule = RaiseHand.RaiseLeftHand(); _leftTracker.Amplitude = 0.3f; _rightTracker.Amplitude = 0.3f; } public WebcamClient CreateRTSP() { try { using var scope = App.AppHost.Services.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); var baseData = db.BasicConfig.FirstOrDefault(x => x.Code == AppSettings.Code); if (baseData == null) { HandyControl.Controls.MessageBox.Show("请先配置摄像头网络!"); return null; } _webcamClient = WebcamClient.CreateRTSP(baseData.Host, baseData.UserName, baseData.Password); } catch (Exception) { HandyControl.Controls.MessageBox.Show("摄像头网络异常,请重新连接!"); return null; } return _webcamClient; } /// /// 验证右手动作(右手举手优先,然后左右挥手) /// public int VerifyRightWavingAction(List humans) { if (humans == null || humans.Count == 0) return (int)WavingAction.None; // 先找到控制点区域的人 Human target = null; double cx = AppSettings.ControlPoint.X; double cy = AppSettings.ControlPoint.Y; double halfW = AppSettings.AreaSize.X; double halfH = AppSettings.AreaSize.Y; for (int i = 0; i < humans.Count; i++) { var h = humans[i]; foreach (var k in h.Keypoints) { if (k.Name == "right_ankle") { double x = k.X; double y = k.Y; if (x >= cx - halfW && x <= cx + halfW && y >= cy - halfH && y <= cy + halfH) { target = h; break; } } } if (target != null) break; } if (target == null) return (int)WavingAction.None; // ---- 右手举手优先 ---- int rightHandAction = DetectRightHandRaise(target); if (rightHandAction != (int)WavingAction.None) { ResetWaveCounts(); return rightHandAction; } if (IsRightHandRaiseIntent(target)) { ResetWaveCounts(); return (int)WavingAction.None; } // ---- 左右挥手累加 ---- int leftValue = _leftTracker.Tracking(target); int rightValue = _rightTracker.Tracking(target); if (leftValue == 1 || leftValue == 2) _leftWaveCount++; if (rightValue == 1 || rightValue == 2) _rightWaveCount++; if (_leftWaveCount >= WaveThreshold) { ResetWaveCounts(); return (int)WavingAction.LeftWave; } if (_rightWaveCount >= WaveThreshold) { ResetWaveCounts(); return (int)WavingAction.RightWave; } return (int)WavingAction.None; } private void ResetWaveCounts() { _leftWaveCount = 0; _rightWaveCount = 0; } private static bool IsRightHandRaiseIntent(Human human) { var wrist = human.Keypoints.FirstOrDefault(k => k.Name == "right_wrist"); var elbow = human.Keypoints.FirstOrDefault(k => k.Name == "right_elbow"); var shoulder = human.Keypoints.FirstOrDefault(k => k.Name == "right_shoulder"); if (wrist == null) return false; if (shoulder != null && wrist.Y <= shoulder.Y + 40) return true; if (elbow != null && wrist.Y <= elbow.Y - 20) return true; return false; } /// /// 优化后的右手举手检测 /// public int DetectRightHandRaise(Human human) { bool pass = _calculator.Calculating(human, _raiseRightHandRule); if (!pass) { _wristStartTime = null; _firstHandTriggered = false; return (int)WavingAction.None; } var now = DateTime.Now; _wristStartTime ??= now; double wristElapsed = (now - _wristStartTime.Value).TotalSeconds; // 第一步:触发倒计时 / 举手开始 if (!_firstHandTriggered && wristElapsed >= 0) { _firstHandTriggered = true; return (int)WavingAction.FirstHand; } // 第二步:举手完成 if (wristElapsed >= 3) { _wristStartTime = null; _firstHandTriggered = false; return (int)WavingAction.RaiseHand; } // 举手中 return (int)WavingAction.Raising; } /// /// 验证左手动作(目前只有举手) /// public int VerifyLeftWavingAction(List humans) { if (humans == null || humans.Count == 0) return (int)WavingAction.None; // 先找到控制点区域的人 Human target = null; double cx = AppSettings.ControlPoint.X; double cy = AppSettings.ControlPoint.Y; double halfW = AppSettings.AreaSize.X; double halfH = AppSettings.AreaSize.Y; for (int i = 0; i < humans.Count; i++) { var h = humans[i]; if (IsAnyFootInCircle(h, cx, cy, halfW, halfH)) { target = h; break; } } if (target == null) return (int)WavingAction.None; // ---- 右手举手优先 ---- int rightHandAction = DetectLeftHandRaise(target); return rightHandAction; } public int DetectLeftHandRaise(Human human) { bool pass = _calculator.Calculating(human, _raiseLeftHandRule); return pass ? (int)WavingAction.RaiseHand : (int)WavingAction.None; } public bool IsAnyFootInCircle(Human h, double cx, double cy, double halfW, double halfH) { foreach (var k in h.Keypoints) { if (k.Name != "right_ankle" && k.Name != "left_ankle") continue; double x = 1920 - k.X; double y = k.Y; if (Math.Abs(x - cx) <= halfW && Math.Abs(y - cy) <= halfH) { return true; } } return false; } } }