diff --git a/Wpf_AiSportsMicrospace/Common/SportDetectionQueue.cs b/Wpf_AiSportsMicrospace/Common/SportDetectionQueue.cs index 18b08ee..c3f816d 100644 --- a/Wpf_AiSportsMicrospace/Common/SportDetectionQueue.cs +++ b/Wpf_AiSportsMicrospace/Common/SportDetectionQueue.cs @@ -1,8 +1,7 @@ -using System; +using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; -using System.Security.Cryptography; -using System.Text; using System.Threading.Tasks; using Yztob.AiSports.Inferences.Things; using Yztob.AiSports.Postures.Sports; @@ -10,7 +9,7 @@ using Yztob.AiSports.Postures.Sports; namespace Wpf_AiSportsMicrospace.Common { /// - /// 运动检后台线程顺序检测队列 + /// 运动检后台线程顺序检测队列(线程安全) /// internal class SportDetectionQueue { @@ -36,8 +35,8 @@ namespace Wpf_AiSportsMicrospace.Common #endregion #region 私有成员 - private readonly Queue _queues; - private int _signral = 0; //0-停止 1-执行中 2-停止信号 + private readonly ConcurrentQueue _queues; + private volatile int _signral = 0; //0-停止 1-执行中 2-停止信号 #endregion #region 构造方法 @@ -46,7 +45,7 @@ namespace Wpf_AiSportsMicrospace.Common /// public SportDetectionQueue() { - _queues = new Queue(); + _queues = new ConcurrentQueue(); } #endregion @@ -73,14 +72,12 @@ namespace Wpf_AiSportsMicrospace.Common _signral = 1; while (_signral == 1) { - //无队列 - if (!_queues.Any()) + if (!_queues.TryDequeue(out var item)) { - Thread.Sleep(5); + Thread.Sleep(1); continue; } - var item = _queues.Dequeue(); if (item == null) continue; @@ -129,7 +126,7 @@ namespace Wpf_AiSportsMicrospace.Common return; _signral = 1; - _queues.Clear();//队列清空 + DrainQueue(); var thread = new Thread(Detecting); thread.IsBackground = true; thread.Start(); @@ -145,7 +142,7 @@ namespace Wpf_AiSportsMicrospace.Common _signral = 2; - _queues.Clear(); + DrainQueue(); } /// @@ -153,7 +150,12 @@ namespace Wpf_AiSportsMicrospace.Common /// public void Clear() { - _queues.Clear(); + DrainQueue(); + } + + private void DrainQueue() + { + while (_queues.TryDequeue(out _)) { } } #endregion } diff --git a/Wpf_AiSportsMicrospace/Common/SportOperate.cs b/Wpf_AiSportsMicrospace/Common/SportOperate.cs index ccd8b65..b03c187 100644 --- a/Wpf_AiSportsMicrospace/Common/SportOperate.cs +++ b/Wpf_AiSportsMicrospace/Common/SportOperate.cs @@ -1,4 +1,4 @@ -using AiSportsMicrospaceDB.DBContext; +using AiSportsMicrospaceDB.DBContext; using Common; using HandyControl.Controls; using Microsoft.EntityFrameworkCore.Storage.Json; @@ -196,13 +196,11 @@ namespace Wpf_AiSportsMicrospace.Common 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) break; } if (target == null) diff --git a/Wpf_AiSportsMicrospace/Views/JumpLong/StandingLeap.xaml.cs b/Wpf_AiSportsMicrospace/Views/JumpLong/StandingLeap.xaml.cs index 000ed65..33cfc77 100644 --- a/Wpf_AiSportsMicrospace/Views/JumpLong/StandingLeap.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/JumpLong/StandingLeap.xaml.cs @@ -1,4 +1,4 @@ -using AiSportsMicrospaceDB.DBContext; +using AiSportsMicrospaceDB.DBContext; using AiSportsMicrospaceDB.Entities; using Common; using Dto; @@ -147,6 +147,10 @@ namespace Views.JumpLong { try { + // 仅在运动中进行跳远检测,避免等待举手时的重复推理 + if (_sportType != 1) + return; + var buffer = frame.GetImageBuffer(ImageFormat.Jpeg).ToArray(); var humanResult = await Task.Run(() => _humanPredictor.Predicting(buffer, frame.Number)); var objects = _sport.Equipment ? await Task.Run>(() => _objectDetector.Detecting(buffer)) : new List(); diff --git a/Wpf_AiSportsMicrospace/Views/Main.xaml.cs b/Wpf_AiSportsMicrospace/Views/Main.xaml.cs index db72059..d02b9f7 100644 --- a/Wpf_AiSportsMicrospace/Views/Main.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/Main.xaml.cs @@ -1,4 +1,4 @@ - + using SharpDX.Direct3D9; using System.Collections.Concurrent; using System.Drawing; @@ -32,6 +32,8 @@ namespace Wpf_AiSportsMicrospace.Views private readonly ConcurrentQueue _frameQueue = new(); private readonly CancellationTokenSource _cts = new(); private readonly object _reconnectLock = new(); + private int _lastEnqueuedFrame = -1; + private const int MaxFrameQueueSize = 8; // 队列上限,防止内存堆积 public event EventHandler> HumanFrameUpdated; @@ -75,6 +77,14 @@ namespace Wpf_AiSportsMicrospace.Views WebcamClient.OnExtractFrame += frame => { + // 跳帧:降低识别负载,保持约 15fps,与其他预览逻辑一致 + if (_lastEnqueuedFrame >= 0 && frame.Number - _lastEnqueuedFrame < 2) + return; + _lastEnqueuedFrame = (int)frame.Number; + + // 队列满时丢弃新帧,避免内存堆积和延迟 + if (_frameQueue.Count >= MaxFrameQueueSize) + return; _frameQueue.Enqueue(frame); }; @@ -90,8 +100,8 @@ namespace Wpf_AiSportsMicrospace.Views } else { - // 避免 CPU 占满 - Thread.Sleep(5); + // 队列空时短暂休眠,1ms 比 5ms 响应更快 + Thread.Sleep(1); } } }, _cts.Token);