From a3bdb136501d23027fda41678e366377059dd5c8 Mon Sep 17 00:00:00 2001
From: tanglong <842690096@qq.com>
Date: Tue, 24 Mar 2026 10:03:13 +0800
Subject: [PATCH] =?UTF-8?q?ai=20=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Common/SportDetectionQueue.cs | 30 ++++++++++---------
Wpf_AiSportsMicrospace/Common/SportOperate.cs | 6 ++--
.../Views/JumpLong/StandingLeap.xaml.cs | 6 +++-
Wpf_AiSportsMicrospace/Views/Main.xaml.cs | 16 ++++++++--
4 files changed, 36 insertions(+), 22 deletions(-)
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 49c7cb9..c8e78d0 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 890a006..91731d2 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;
@@ -146,6 +146,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);