diff --git a/Wpf_AiSportsMicrospace/Common/SportOperate.cs b/Wpf_AiSportsMicrospace/Common/SportOperate.cs index d3e8a4a..f48371c 100644 --- a/Wpf_AiSportsMicrospace/Common/SportOperate.cs +++ b/Wpf_AiSportsMicrospace/Common/SportOperate.cs @@ -1,6 +1,7 @@ using AiSportsMicrospaceDB.DBContext; using Common; using HandyControl.Controls; +using Microsoft.EntityFrameworkCore.Storage.Json; using Microsoft.Extensions.DependencyInjection; using SportExpand; using System; @@ -74,17 +75,17 @@ namespace Wpf_AiSportsMicrospace.Common /// /// 验证右手动作(右手举手优先,然后左右挥手) /// - public int VerifyRightWavingAction(List humans) + 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 ; + 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++) { @@ -93,7 +94,7 @@ namespace Wpf_AiSportsMicrospace.Common { if (k.Name == "right_ankle") { - double x = k.X; + double x = k.X; double y = k.Y; if (x >= cx - halfW && x <= cx + halfW && y >= cy - halfH && y <= cy + halfH) @@ -199,20 +200,12 @@ namespace Wpf_AiSportsMicrospace.Common for (int i = 0; i < humans.Count; i++) { var h = humans[i]; - foreach (var k in h.Keypoints) + + if (IsAnyFootInCircle(h, cx, cy, halfW, halfH)) { - 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; - } - } + target = h; } + if (target != null) break; } @@ -222,7 +215,6 @@ namespace Wpf_AiSportsMicrospace.Common // ---- 右手举手优先 ---- int rightHandAction = DetectLeftHandRaise(target); return rightHandAction; - } @@ -232,9 +224,28 @@ namespace Wpf_AiSportsMicrospace.Common var ruleLeft = RaiseHand.RaiseLeftHand(); bool pass = calculator.Calculating(human, ruleLeft); - - return pass ? (int)WavingAction.Raising : (int)WavingAction.None; + + return pass ? (int)WavingAction.Raising : (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 = k.X; + double y = k.Y; + + if (Math.Abs(x - cx) <= halfW && + Math.Abs(y - cy) <= halfH) + { + return true; + } + } + return false; + } + } } diff --git a/Wpf_AiSportsMicrospace/Dto/MusicJumpRopeContext.cs b/Wpf_AiSportsMicrospace/Dto/MusicJumpRopeContext.cs index 13317b0..bc1a575 100644 --- a/Wpf_AiSportsMicrospace/Dto/MusicJumpRopeContext.cs +++ b/Wpf_AiSportsMicrospace/Dto/MusicJumpRopeContext.cs @@ -55,10 +55,10 @@ namespace Dto public MusicJumpRopeContext() { CirclePositions = new List<(double XNorm, double YNorm)> - { - (0.50, 0.88), - (0.78, 0.88), - }; + { + (0.50, 0.88), + (0.78, 0.88), + }; MusicBeatsDic = MusicBeats["1"].GroupBy(b => (int)Math.Ceiling(b) - 1).ToDictionary(g => g.Key, g => g.ToList()); diff --git a/Wpf_AiSportsMicrospace/Views/Home.xaml.cs b/Wpf_AiSportsMicrospace/Views/Home.xaml.cs index c926cf0..7e03476 100644 --- a/Wpf_AiSportsMicrospace/Views/Home.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/Home.xaml.cs @@ -10,6 +10,7 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Threading; +using Views.JumpLong; using Views.JumpRope; using Views.SquatFu; using Wpf_AiSportsMicrospace.Common; @@ -173,7 +174,8 @@ namespace Wpf_AiSportsMicrospace } else { - var newPage = new TrainingRecords(); + //var newPage = new TrainingRecords(); + var newPage = new StandingLeap(); mainWin?.SwitchPageWithMaskAnimation(newPage, true); } } diff --git a/Wpf_AiSportsMicrospace/Views/JumpLong/StandingLeap.xaml.cs b/Wpf_AiSportsMicrospace/Views/JumpLong/StandingLeap.xaml.cs index 02f2167..bf0f642 100644 --- a/Wpf_AiSportsMicrospace/Views/JumpLong/StandingLeap.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/JumpLong/StandingLeap.xaml.cs @@ -1,4 +1,5 @@ using AiSportsMicrospaceDB.DBContext; +using AiSportsMicrospaceDB.Entities; using Common; using Dto; using Enum; @@ -49,6 +50,8 @@ namespace Views.JumpLong private MediaPlayer _mediaPlayer = new MediaPlayer(); private readonly SportDetectionQueue _detectQueue; + private JumpLongPoints _Points; + private int _sportType = 0; // 0:未开始 1:运动中 2:运动结束展示排行榜 #endregion @@ -66,7 +69,6 @@ namespace Views.JumpLong _sport = SportBase.Create("standing-long-jump"); _sport.OnTicked += this.OnSportTick; - _mainWin.HumanFrameUpdated += this.OnFrameUpdated; _measureApparatus = new ApparatusLongJumpDelineation(); _measureApparatus.MeasureLength = 300; var _isCalibrated = this.ReactangleCalibrating(1920, 1080); @@ -79,6 +81,14 @@ namespace Views.JumpLong { // 播放音乐 PlayMusic("raisehand.mp3"); + + var app = (App)Application.Current; + using var scope = App.AppHost.Services.CreateScope(); + var db = scope.ServiceProvider.GetRequiredService(); + + _Points = db.JumpLongPoints.FirstOrDefault(x => x.Code == AppSettings.Code); + + _mainWin.HumanFrameUpdated += OnFrameUpdated; } @@ -279,21 +289,6 @@ namespace Views.JumpLong // 关闭跳远抽帧线程 } - //关闭成绩展示 显示跳远页面 - private void closRope() - { - //关闭动画 - //var fadeInAnimation = new DoubleAnimation - //{ - // From = 1, - // To = 0, - // Duration = TimeSpan.FromSeconds(1) - //}; - // RankingGrid.BeginAnimation(UIElement.OpacityProperty, fadeInAnimation); - RankingGrid.Opacity = 0; - _sportType = 0; - PlayMusic("raisehand.mp3"); - } private bool ReactangleCalibrating(int frameWidth, int frameHeight) { @@ -429,23 +424,16 @@ namespace Views.JumpLong if (rightAnkle == null) continue; - //double xNorm = rightAnkle.X / 1920; - //double yNorm = rightAnkle.Y / 1080; - var app = (App)Application.Current; - using var scope = App.AppHost.Services.CreateScope(); - var db = scope.ServiceProvider.GetRequiredService(); - var points = db.JumpLongPoints.FirstOrDefault(x => x.Code == AppSettings.Code); - // 检测起跳区域的人 - var isinx = (rightAnkle.X < points.TopPoint3.X && rightAnkle.X > points.TopPoint2.X) || (rightAnkle.X < points.BottomPoint3.X && rightAnkle.X > points.BottomPoint2.X); - if (points.TopPoint3.X < points.TopPoint2.X) + var isinx = (rightAnkle.X < _Points.TopPoint3.X && rightAnkle.X > _Points.TopPoint2.X) || (rightAnkle.X < _Points.BottomPoint3.X && rightAnkle.X > _Points.BottomPoint2.X); + if (_Points.TopPoint3.X < _Points.TopPoint2.X) { - isinx = (rightAnkle.X > points.TopPoint3.X && rightAnkle.X < points.TopPoint2.X) || (rightAnkle.X > points.BottomPoint3.X && rightAnkle.X < points.BottomPoint2.X); + isinx = (rightAnkle.X > _Points.TopPoint3.X && rightAnkle.X < _Points.TopPoint2.X) || (rightAnkle.X > _Points.BottomPoint3.X && rightAnkle.X < _Points.BottomPoint2.X); } - var isiny = (rightAnkle.Y > points.TopPoint3.Y && rightAnkle.X < points.BottomPoint3.Y) || (rightAnkle.Y < points.TopPoint2.Y && rightAnkle.X > points.BottomPoint2.Y); + var isiny = (rightAnkle.Y > _Points.TopPoint3.Y && rightAnkle.X < _Points.BottomPoint3.Y) || (rightAnkle.Y < _Points.TopPoint2.Y && rightAnkle.X > _Points.BottomPoint2.Y); if (!isinx || !isiny) continue; diff --git a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs index cf9c04f..0509e06 100644 --- a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs @@ -84,8 +84,6 @@ namespace Wpf_AiSportsMicrospace.Views using var scope = App.AppHost.Services.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); var cfg = await db.GroupPoints.FirstOrDefaultAsync(x => x.Code == AppSettings.Code); - //var pointlist = JsonSerializer.Deserialize>(cfg!.PointsJson); - List<(double XNorm, double YNorm)> pointlist = new List<(double XNorm, double YNorm)>(); var points = new[] { cfg.Point1, cfg.Point2, cfg.Point3, @@ -101,6 +99,8 @@ namespace Wpf_AiSportsMicrospace.Views } _groupJumpRopeContext.CirclePositions = pointlist; + _mainWin.HumanFrameUpdated += OnHumanFrameUpdated; + DrawCirclesWithText(); // 播放音乐 @@ -350,90 +350,6 @@ namespace Wpf_AiSportsMicrospace.Views _mainWin.WebcamClient.StartExtract(); } - private DateTime? _raiseStartTime; - private bool _firstHandTriggered; - private int _lastCountdownSecond = 3; - private DateTime? _countdownStartTime; - public int DetectRightHandRaise(Human human) - { - - var calculator = PostureCalculate.CreateCalculator(); - var rule = RaiseHand.RaiseRightHand(); - var pass = calculator.Calculating(human, rule); - - const double holdDuration = 1; // 持续时间(秒) - const int countdownSeconds = 3; // 倒计时长度 - - // ---------- 第一步:持续举手触发倒计时 ---------- - if (!_firstHandTriggered) - { - if (pass) - { - _raiseStartTime ??= DateTime.Now; - var holdElapsed = (DateTime.Now - _raiseStartTime.Value).TotalSeconds; - if (holdElapsed >= holdDuration) - { - // 举手达到指定时间,启动倒计时 - _firstHandTriggered = true; - _countdownStartTime = DateTime.Now; - _lastCountdownSecond = countdownSeconds; - return (int)WavingAction.FirstHand; - } - } - else - { - // 手放下,重置举手开始时间 - _raiseStartTime = DateTime.Now; - } - - // 没有任何中心区域内的人举手 - return (int)WavingAction.None; - } - - // ---------- 第二步:倒计时逻辑 ---------- - var countdownElapsed = (DateTime.Now - _countdownStartTime.Value).TotalSeconds; - 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; - } - - - public int DetectLeftHandRaise(Human human) - { - var calculator = PostureCalculate.CreateCalculator(); - var rule = RaiseHand.RaiseLeftHand(); - var pass = calculator.Calculating(human, rule); - - if (pass) - { - // 一旦检测到左手举起,立即返回 - return (int)WavingAction.RaiseHand; - } - - // 没有检测到举手 - return (int)WavingAction.None; - } - - private void ResetRaiseState() - { - _raiseStartTime = null; - _countdownStartTime = null; - _firstHandTriggered = false; - _lastCountdownSecond = 3; - } private void DrawCirclesWithText() { userBox.Children.Clear(); @@ -445,8 +361,8 @@ namespace Wpf_AiSportsMicrospace.Views for (int i = 0; i < _groupJumpRopeContext.CirclePositions.Count; i++) { var pos = _groupJumpRopeContext.CirclePositions[i]; - double x = pos.XNorm ; - double y = pos.YNorm ; + double x = pos.XNorm; + double y = pos.YNorm; // 绘制发光圆 var userItem = AddUserItem(x, y, i); @@ -473,54 +389,46 @@ namespace Wpf_AiSportsMicrospace.Views } private void UpdateCircleCounts(List humans) { - double radiusNormX = 150; - double radiusNormY = 150; + double halfW = AppSettings.AreaSize.X; + double halfH = AppSettings.AreaSize.Y; - for (int i = 0; i < _groupJumpRopeContext.CirclePositions.Count; i++) + int circleCount = _groupJumpRopeContext.CirclePositions.Count; + + for (int i = 0; i < circleCount; i++) { - var circleX = _groupJumpRopeContext.CirclePositions[i].XNorm; - var circleY = _groupJumpRopeContext.CirclePositions[i].YNorm; + var circle = _groupJumpRopeContext.CirclePositions[i]; + double cx = circle.XNorm; + double cy = circle.YNorm; - Human humanInCircle = null; + Human targetHuman = null; - // 找圈内的人 - foreach (var hu in humans) + // 1️⃣ 找圈内的人(单脚命中即可) + foreach (var h in humans) { - var rightFoot = hu.Keypoints.FirstOrDefault(k => k.Name == "right_ankle"); - var leftFoot = hu.Keypoints.FirstOrDefault(k => k.Name == "left_ankle"); - if (rightFoot == null || leftFoot == null) - continue; - - double xRightNorm = rightFoot.X ; - double xLeftNorm = leftFoot.X ; - double yRightNorm = rightFoot.Y ; - double yLeftNorm = leftFoot.Y ; - - bool outOfCircle = - xRightNorm < (circleX - radiusNormX) || xRightNorm > (circleX + radiusNormX) || - xLeftNorm < (circleX - radiusNormX) || xLeftNorm > (circleX + radiusNormX) || - yRightNorm < (circleY - radiusNormY) || yRightNorm > (circleY + radiusNormY) || - yLeftNorm < (circleY - radiusNormY) || yLeftNorm > (circleY + radiusNormY); - - if (!outOfCircle) + if (sportOperate.IsAnyFootInCircle(h, cx, cy, halfW, halfH)) { - humanInCircle = hu; - break; // 每圈只处理一个人 + targetHuman = h; + break; // 每个圈只认一个人 } } - // 根据是否有人和跳绳数字判断状态 - bool hasHuman = humanInCircle != null; + bool hasHuman = targetHuman != null; + + // 2️⃣ 更新视觉状态 lock (_updateLock) { - _groupJumpRopeContext.UserList[i].ImageState = GetJumpState(i, hasHuman); + _groupJumpRopeContext.UserList[i].ImageState = + GetJumpState(i, hasHuman); } - // 推送计数 + // 3️⃣ 推送跳绳计数 if (hasHuman) - _groupJumpRopeContext.Sports[i].Pushing(humanInCircle); + { + _groupJumpRopeContext.Sports[i].Pushing(targetHuman); + } } } + private string GetJumpState(int circleIndex, bool humanInCircle) { if (!humanInCircle) @@ -567,7 +475,7 @@ namespace Wpf_AiSportsMicrospace.Views userItem.HorizontalAlignment = HorizontalAlignment.Left; userItem.ImageState = "1"; //userItem.Margin = new Thickness(centerX - (index == 0 ? 80 : index == 6 ? 190 : 135), centerY - 540, 0, 0); - userItem.Margin = new Thickness(centerX - 25 - 100, centerY - 490 , 0, 0); + userItem.Margin = new Thickness(centerX - 25 - 100, centerY - 490, 0, 0); userBox.Children.Add(userItem); _groupJumpRopeContext.UserList.Add(userItem); _groupJumpRopeContext.UserNumberList.Add("0"); @@ -645,21 +553,6 @@ namespace Wpf_AiSportsMicrospace.Views //rankingGrid.BeginAnimation(UIElement.OpacityProperty, fadeIn); } - /* - * 控制元素隐藏(渐隐动画 - * time: 动画持续时间(毫秒) - * name: 元素名称 - */ - public void HideElement(string name, int time) - { - var Element = FindName(name) as Grid; - if (Element == null) return; - - var fadeOut = new DoubleAnimation(1, 0, TimeSpan.FromMilliseconds(time)); - fadeOut.Completed += (s, e) => Element.Visibility = Visibility.Collapsed; - Element.BeginAnimation(UIElement.OpacityProperty, fadeOut); - } - /* * 控制元素限时(渐隐动画 * time: 动画持续时间(毫秒) diff --git a/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml.cs b/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml.cs index 90b1eff..1e251ee 100644 --- a/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml.cs @@ -23,7 +23,7 @@ using System.Windows.Media.Animation; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; -using System.Windows.Threading; +using System.Windows.Threading; using Wpf_AiSportsMicrospace.Common; using Wpf_AiSportsMicrospace.Dto; using Wpf_AiSportsMicrospace.Enum; @@ -75,26 +75,16 @@ namespace Wpf_AiSportsMicrospace.Views.JumpRope popSilder1.MusicBeats = _musicJumpRopeContext.MusicBeats["1"]; popSilder2.MusicBeats = _musicJumpRopeContext.MusicBeats["1"]; - //Random rnd = new Random(); - - //// 模拟 20 次随机更新 - //for (int i = 0; i < 200; i++) - //{ - // // 随机左右进度变化,保证总和=1 - // double left = rnd.NextDouble(); // 0~1 - // PkBar.LeftProgress = left; // RightProgress 自动 1-left - - // await Task.Delay(1000); // 200ms 间隔,不卡UI线程 - //} - var app = (App)Application.Current; using var scope = App.AppHost.Services.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); var cfg = await db.GroupPoints.FirstOrDefaultAsync(x => x.Code == AppSettings.Code); //var pointlist = JsonSerializer.Deserialize>(cfg!.PointsJson); - List<(double XNorm, double YNorm)> pointlist = [(cfg.Point3.X, cfg.Point3.Y), (cfg.Point5.X, cfg.Point5.Y)]; + List<(double XNorm, double YNorm)> pointlist = [(cfg.ControlPoint.X, cfg.ControlPoint.Y), (cfg.Point3.X, cfg.Point3.Y)]; _musicJumpRopeContext.UpdateCirclePositions(pointlist); + + _mainWin.HumanFrameUpdated += OnHumanFrameUpdated; } private void UserControl_Unloaded(object sender, RoutedEventArgs e) @@ -187,50 +177,49 @@ namespace Wpf_AiSportsMicrospace.Views.JumpRope { if (humans == null || humans.Count == 0) return; - - switch (_currentGameState) - { - case GameState.NotStarted: - if (!_isCountdownStarted) + switch (_currentGameState) + { + case GameState.NotStarted: + if (!_isCountdownStarted) + { + int leftWaving = sportOperate.VerifyLeftWavingAction(humans); + if (leftWaving == 5) { - int leftWaving = sportOperate.VerifyLeftWavingAction(humans); - if (leftWaving == 5) - { - _mainWin.HumanFrameUpdated -= OnHumanFrameUpdated; - _mainWin.WebcamClient.StopExtract(); + _mainWin.HumanFrameUpdated -= OnHumanFrameUpdated; + _mainWin.WebcamClient.StopExtract(); - // 举左手逻辑,例如结束动画或退出 - var newPage = new Home(); - _mainWin?.SwitchPageWithMaskAnimation(newPage, true); - return; // 提前退出 - } + // 举左手逻辑,例如结束动画或退出 + var newPage = new Home(); + _mainWin?.SwitchPageWithMaskAnimation(newPage, true); + return; // 提前退出 } + } - int rightWaving = sportOperate.VerifyRightWavingAction(humans); - if (rightWaving >= 3 && RankingGrid.Visibility != Visibility.Visible) + int rightWaving = sportOperate.VerifyRightWavingAction(humans); + if (rightWaving >= 3 && RankingGrid.Visibility != Visibility.Visible) + { + switch (rightWaving) { - switch (rightWaving) - { - case (int)WavingAction.FirstHand: - StartCountdown(3); - _isCountdownStarted = true; - break; - case (int)WavingAction.Raising: - UpdateCountdown(); - break; - case (int)WavingAction.RaiseHand: - FinishCountdown(); - _currentGameState = GameState.Running; - break; - } + case (int)WavingAction.FirstHand: + StartCountdown(3); + _isCountdownStarted = true; + break; + case (int)WavingAction.Raising: + UpdateCountdown(); + break; + case (int)WavingAction.RaiseHand: + FinishCountdown(); + _currentGameState = GameState.Running; + break; } - break; + } + break; + + case GameState.Running: + UpdateCircleCounts(humans); + break; + } - case GameState.Running: - UpdateCircleCounts(humans); - break; - } - } catch (Exception ex) { @@ -428,88 +417,6 @@ namespace Wpf_AiSportsMicrospace.Views.JumpRope Element.BeginAnimation(UIElement.OpacityProperty, fadeIn); } - private DateTime? _raiseStartTime; - private bool _firstHandTriggered; - private int _lastCountdownSecond = 3; - private DateTime? _countdownStartTime; - public int DetectRightHandRaise(Human human) - { - - var calculator = PostureCalculate.CreateCalculator(); - var rule = RaiseHand.RaiseRightHand(); - var pass = calculator.Calculating(human, rule); - - const double holdDuration = 1; // 持续时间(秒) - const int countdownSeconds = 3; // 倒计时长度 - - // ---------- 第一步:持续举手触发倒计时 ---------- - if (!_firstHandTriggered) - { - if (pass) - { - _raiseStartTime ??= DateTime.Now; - var holdElapsed = (DateTime.Now - _raiseStartTime.Value).TotalSeconds; - if (holdElapsed >= holdDuration) - { - // 举手达到指定时间,启动倒计时 - _firstHandTriggered = true; - _countdownStartTime = DateTime.Now; - _lastCountdownSecond = countdownSeconds; - return (int)WavingAction.FirstHand; - } - } - else - { - // 手放下,重置举手开始时间 - _raiseStartTime = DateTime.Now; - } - - // 没有任何中心区域内的人举手 - return (int)WavingAction.None; - } - - // ---------- 第二步:倒计时逻辑 ---------- - var countdownElapsed = (DateTime.Now - _countdownStartTime.Value).TotalSeconds; - 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; - } - public int DetectLeftHandRaise(Human human) - { - var calculator = PostureCalculate.CreateCalculator(); - var rule = RaiseHand.RaiseLeftHand(); - var pass = calculator.Calculating(human, rule); - - if (pass) - { - // 一旦检测到左手举起,立即返回 - return (int)WavingAction.RaiseHand; - } - - // 没有检测到举手 - return (int)WavingAction.None; - } - - private void ResetRaiseState() - { - _raiseStartTime = null; - _countdownStartTime = null; - _firstHandTriggered = false; - _lastCountdownSecond = 3; - } private void DrawCirclesWithText() { @@ -579,7 +486,6 @@ namespace Wpf_AiSportsMicrospace.Views.JumpRope //UpdateScore(right, score2); score1.Text = (right * 10).ToString(); } - } }; @@ -588,33 +494,6 @@ namespace Wpf_AiSportsMicrospace.Views.JumpRope } } - private void UpdateScore(double to, TextBlock score) - { - DoubleAnimation animation = new DoubleAnimation - { - From = double.Parse(score1.Text), - To = to, - Duration = TimeSpan.FromSeconds(0.2), - EasingFunction = new QuadraticEase { EasingMode = EasingMode.EaseOut }, - FillBehavior = FillBehavior.HoldEnd - }; - score.BeginAnimation(TextBlock.TextProperty, animation); - } - - //private void ChangeImgState(int index , string state) - //{ - // if(index== 0) - // { - // left1.Visibility = state == "1" ? Visibility.Visible : Visibility.Hidden; - // left2.Visibility = state == "2" ? Visibility.Visible : Visibility.Hidden; - // left3.Visibility = state == "3" ? Visibility.Visible : Visibility.Hidden; - // }else if (index == 1) - // { - // right1.Visibility = state == "1" ? Visibility.Visible : Visibility.Hidden; - // right2.Visibility = state == "1" ? Visibility.Visible : Visibility.Hidden; - // right3.Visibility = state == "1" ? Visibility.Visible : Visibility.Hidden; - // } - //} public void ShowMusicAnimation() { @@ -626,54 +505,40 @@ namespace Wpf_AiSportsMicrospace.Views.JumpRope private void UpdateCircleCounts(List humans) { - double radiusNormX = 0.07; - double radiusNormY = 0.14; + double halfW = AppSettings.AreaSize.X; + double halfH = AppSettings.AreaSize.Y; for (int i = 0; i < _musicJumpRopeContext.CirclePositions.Count; i++) { - var circleX = _musicJumpRopeContext.CirclePositions[i].XNorm; - var circleY = _musicJumpRopeContext.CirclePositions[i].YNorm; + var circle = _musicJumpRopeContext.CirclePositions[i]; + double cx = circle.XNorm; + double cy = circle.YNorm; Human humanInCircle = null; - // 找圈内的人 - foreach (var hu in humans) + // 1️⃣ 找圈内的人(单脚命中即可) + foreach (var h in humans) { - var rightFoot = hu.Keypoints.FirstOrDefault(k => k.Name == "right_ankle"); - var leftFoot = hu.Keypoints.FirstOrDefault(k => k.Name == "left_ankle"); - if (rightFoot == null || leftFoot == null) - continue; - - double xRightNorm = rightFoot.X / userBox.ActualWidth; - double xLeftNorm = leftFoot.X / userBox.ActualWidth; - double yRightNorm = rightFoot.Y / userBox.ActualHeight; - double yLeftNorm = leftFoot.Y / userBox.ActualHeight; - - bool outOfCircle = - xRightNorm < (circleX - radiusNormX) || xRightNorm > (circleX + radiusNormX) || - xLeftNorm < (circleX - radiusNormX) || xLeftNorm > (circleX + radiusNormX) || - yRightNorm < (circleY - radiusNormY) || yRightNorm > (circleY + radiusNormY) || - yLeftNorm < (circleY - radiusNormY) || yLeftNorm > (circleY + radiusNormY); - - if (!outOfCircle) + if (sportOperate.IsAnyFootInCircle(h, cx, cy, halfW, halfH)) { - humanInCircle = hu; - break; // 每圈只处理一个人 + humanInCircle = h; + break; // 每个圈只认一个人 } } + // 根据是否有人和跳绳数字判断状态 bool hasHuman = humanInCircle != null; lock (_updateLock) { _musicJumpRopeContext.UserList[i].ImageState = GetJumpState(i, hasHuman); - //var state = GetJumpState(i, hasHuman); - //ChangeImgState(i, state); } - // 推送计数 - //if (hasHuman) - _musicJumpRopeContext.Sports[i].Pushing(humanInCircle); + // 3️⃣ 推送计数 + if (hasHuman) + { + _musicJumpRopeContext.Sports[i].Pushing(humanInCircle); + } } } private string GetJumpState(int circleIndex, bool humanInCircle) diff --git a/Wpf_AiSportsMicrospace/Views/Setting/LongSetting.xaml.cs b/Wpf_AiSportsMicrospace/Views/Setting/LongSetting.xaml.cs index 1965960..b8391d3 100644 --- a/Wpf_AiSportsMicrospace/Views/Setting/LongSetting.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/Setting/LongSetting.xaml.cs @@ -63,7 +63,7 @@ namespace Wpf_AiSportsMicrospace.Views using var scope = App.AppHost.Services.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); var BaseData = await db.BasicConfig.FirstOrDefaultAsync(x => x.Code == AppSettings.Code); - if (BaseData==null) + if (BaseData == null) { this.ShowError("相机主机地址/IP不能为空。"); return; @@ -200,14 +200,19 @@ namespace Wpf_AiSportsMicrospace.Views { try { + string code = Utils.GetMacAddress(); var app = (App)Application.Current; using var scope = App.AppHost.Services.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); - var pointsData = db.JumpLongPoints.FirstOrDefault(x => x.Code == AppSettings.Code); + var pointsData = db.JumpLongPoints.FirstOrDefault(x => x.Code == code); if (pointsData == null) { pointsData = new JumpLongPoints(); + + pointsData.Code = code; + + // 保存所有点的位置 pointsData.TopPoint1 = new AiSportsMicrospaceDB.Entities.Point { @@ -247,7 +252,50 @@ namespace Wpf_AiSportsMicrospace.Views db.JumpLongPoints.Add(pointsData); } + else + { + // 保存所有点的位置 + pointsData.TopPoint1 = new AiSportsMicrospaceDB.Entities.Point + { + X = Canvas.GetLeft(TopPoint1) + 10, + Y = Canvas.GetTop(TopPoint1) + 10 + }; + + pointsData.TopPoint2 = new AiSportsMicrospaceDB.Entities.Point + { + X = Canvas.GetLeft(TopPoint2) + 10, + Y = Canvas.GetTop(TopPoint2) + 10 + }; + + pointsData.TopPoint3 = new AiSportsMicrospaceDB.Entities.Point + { + X = Canvas.GetLeft(TopPoint3) + 10, + Y = Canvas.GetTop(TopPoint3) + 10 + }; + + pointsData.BottomPoint1 = new AiSportsMicrospaceDB.Entities.Point + { + X = Canvas.GetLeft(BottomPoint1) + 10, + Y = Canvas.GetTop(BottomPoint1) + 10 + }; + + pointsData.BottomPoint2 = new AiSportsMicrospaceDB.Entities.Point + { + X = Canvas.GetLeft(BottomPoint2) + 10, + Y = Canvas.GetTop(BottomPoint2) + 10 + }; + + pointsData.BottomPoint3 = new AiSportsMicrospaceDB.Entities.Point + { + X = Canvas.GetLeft(BottomPoint3) + 10, + Y = Canvas.GetTop(BottomPoint3) + 10 + }; + + db.JumpLongPoints.Update(pointsData); + } + db.SaveChanges(); + UpdateStatus("点数据保存成功"); } catch (Exception ex)