259 lines
8.0 KiB
C#
Raw Normal View History

2026-01-14 10:19:08 +08:00
using AiSportsMicrospaceDB.DBContext;
using Common;
using HandyControl.Controls;
2026-02-05 14:48:49 +08:00
using Microsoft.EntityFrameworkCore.Storage.Json;
2026-01-14 10:19:08 +08:00
using Microsoft.Extensions.DependencyInjection;
2025-12-30 11:32:35 +08:00
using SportExpand;
2025-09-26 16:46:22 +08:00
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;
2025-12-30 11:32:35 +08:00
private int _leftWaveCount = 0;
private int _rightWaveCount = 0;
2026-03-11 13:16:02 +08:00
private const int WaveThreshold = 3;
2025-09-26 16:46:22 +08:00
WebcamClient _webcamClient;
private DateTime? _wristStartTime = null;
2025-09-28 14:08:36 +08:00
private bool _firstHandTriggered = false;
2025-09-26 16:46:22 +08:00
public SportOperate()
{
_leftTracker = PostureCalculate.CreatePointTracker("left_wrist", 0);
_rightTracker = PostureCalculate.CreatePointTracker("right_wrist", 0);
2026-03-11 13:16:02 +08:00
//_leftTracker.Amplitude = 0.3f;
//_rightTracker.Amplitude = 0.3f;
2025-09-26 16:46:22 +08:00
}
public WebcamClient CreateRTSP()
{
2025-10-12 10:20:08 +08:00
try
{
2026-01-14 10:19:08 +08:00
using var scope = App.AppHost.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var baseData = db.BasicConfig.FirstOrDefault(x => x.Code == AppSettings.Code);
if (baseData == null)
{
HandyControl.Controls.MessageBox.Show("请先配置摄像头网络!");
return null;
}
2026-01-20 15:07:09 +08:00
_webcamClient = WebcamClient.CreateRTSP(baseData.Host, baseData.UserName, baseData.Password);
2025-10-12 10:20:08 +08:00
}
catch (Exception)
{
HandyControl.Controls.MessageBox.Show("摄像头网络异常,请重新连接!");
2026-01-14 10:19:08 +08:00
return null;
2025-10-12 10:20:08 +08:00
}
2025-09-26 16:46:22 +08:00
return _webcamClient;
}
2025-12-30 11:42:32 +08:00
2026-01-27 12:13:54 +08:00
/// <summary>
2026-02-03 12:01:37 +08:00
/// 验证右手动作(右手举手优先,然后左右挥手)
2026-01-27 12:13:54 +08:00
/// </summary>
2026-03-11 11:26:29 +08:00
public int
VerifyRightWavingAction(List<Human> humans)
2025-09-26 16:46:22 +08:00
{
2025-10-15 10:01:58 +08:00
if (humans == null || humans.Count == 0)
2025-10-12 10:20:08 +08:00
return (int)WavingAction.None;
2025-10-11 14:54:57 +08:00
2026-01-27 12:13:54 +08:00
// 先找到控制点区域的人
Human target = null;
2026-02-05 14:48:49 +08:00
double cx = AppSettings.ControlPoint.X;
double cy = AppSettings.ControlPoint.Y;
double halfW = AppSettings.AreaSize.X;
double halfH = AppSettings.AreaSize.Y;
2026-01-27 12:13:54 +08:00
for (int i = 0; i < humans.Count; i++)
2025-09-26 16:46:22 +08:00
{
2026-01-27 12:13:54 +08:00
var h = humans[i];
foreach (var k in h.Keypoints)
{
if (k.Name == "right_ankle")
{
2026-02-05 14:48:49 +08:00
double x = k.X;
2026-01-27 12:13:54 +08:00
double y = k.Y;
if (x >= cx - halfW && x <= cx + halfW &&
y >= cy - halfH && y <= cy + halfH)
{
target = h;
break;
}
}
}
if (target != null) break;
}
2025-10-15 10:01:58 +08:00
2026-01-27 12:13:54 +08:00
if (target == null)
return (int)WavingAction.None;
2025-10-15 10:01:58 +08:00
2026-01-27 12:13:54 +08:00
// ---- 右手举手优先 ----
int rightHandAction = DetectRightHandRaise(target);
if (rightHandAction != (int)WavingAction.None)
return rightHandAction;
2026-01-20 16:28:55 +08:00
2026-01-27 12:13:54 +08:00
// ---- 左右挥手累加 ----
int leftValue = _leftTracker.Tracking(target);
int rightValue = _rightTracker.Tracking(target);
2026-01-20 16:28:55 +08:00
2026-01-27 12:13:54 +08:00
if (leftValue == 1 || leftValue == 2) _leftWaveCount++;
if (rightValue == 1 || rightValue == 2) _rightWaveCount++;
2025-10-15 10:01:58 +08:00
2026-01-27 12:13:54 +08:00
if (_leftWaveCount >= WaveThreshold)
2026-01-14 16:03:44 +08:00
{
2026-01-27 12:13:54 +08:00
_leftWaveCount = 0;
return (int)WavingAction.LeftWave;
}
2025-12-30 11:32:35 +08:00
2026-01-27 12:13:54 +08:00
if (_rightWaveCount >= WaveThreshold)
{
_rightWaveCount = 0;
return (int)WavingAction.RightWave;
2025-10-12 16:13:44 +08:00
}
2026-01-27 12:13:54 +08:00
2025-10-12 16:13:44 +08:00
return (int)WavingAction.None;
}
/// <summary>
2026-01-27 12:13:54 +08:00
/// 优化后的右手举手检测
2025-10-12 16:13:44 +08:00
/// </summary>
public int DetectRightHandRaise(Human human)
{
2025-12-30 11:32:35 +08:00
var calculator = PostureCalculate.CreateCalculator();
var rule = RaiseHand.RaiseRightHand();
2026-01-27 12:13:54 +08:00
bool pass = calculator.Calculating(human, rule);
2025-09-28 14:08:36 +08:00
2026-01-27 12:13:54 +08:00
if (!pass)
2025-10-12 16:13:44 +08:00
{
2026-01-27 12:13:54 +08:00
_wristStartTime = null;
_firstHandTriggered = false;
return (int)WavingAction.None;
}
2025-10-12 16:13:44 +08:00
2026-01-27 12:13:54 +08:00
var now = DateTime.Now;
2025-12-24 12:37:08 +08:00
2026-03-11 11:26:29 +08:00
//_raiseStartTime ??= now;
2026-01-27 12:13:54 +08:00
_wristStartTime ??= now;
2025-10-12 16:13:44 +08:00
2026-01-27 12:13:54 +08:00
double wristElapsed = (now - _wristStartTime.Value).TotalSeconds;
2026-03-11 11:26:29 +08:00
//double raiseElapsed = (now - _raiseStartTime.Value).TotalSeconds;
2025-10-12 16:13:44 +08:00
2026-01-27 12:13:54 +08:00
// 第一步:触发倒计时 / 举手开始
2026-03-11 11:26:29 +08:00
if (!_firstHandTriggered && wristElapsed >= 0)
2026-01-27 12:13:54 +08:00
{
_firstHandTriggered = true;
return (int)WavingAction.FirstHand;
2025-09-26 16:46:22 +08:00
}
2026-01-27 12:13:54 +08:00
2026-03-11 11:26:29 +08:00
//if (wristElapsed <= 3)
//{
// return (int)WavingAction.Raising;
//}
//_wristStartTime = null;
//_firstHandTriggered = false;
//return (int)WavingAction.RaiseHand;
2026-01-27 12:13:54 +08:00
// 第二步:举手完成
2026-03-11 11:26:29 +08:00
if (wristElapsed >= 3)
2025-10-12 16:13:44 +08:00
{
_wristStartTime = null;
_firstHandTriggered = false;
2026-01-27 12:13:54 +08:00
return (int)WavingAction.RaiseHand;
2025-10-12 16:13:44 +08:00
}
2026-01-27 12:13:54 +08:00
// 举手中
return (int)WavingAction.Raising;
2025-09-26 16:46:22 +08:00
}
2026-02-03 12:01:37 +08:00
/// <summary>
/// 验证左手动作(目前只有举手)
/// </summary>
public int VerifyLeftWavingAction(List<Human> 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];
2026-02-05 14:48:49 +08:00
if (IsAnyFootInCircle(h, cx, cy, halfW, halfH))
2026-02-03 12:01:37 +08:00
{
2026-02-05 14:48:49 +08:00
target = h;
2026-02-03 12:01:37 +08:00
}
2026-02-05 14:48:49 +08:00
2026-02-03 12:01:37 +08:00
if (target != null) break;
}
if (target == null)
return (int)WavingAction.None;
// ---- 右手举手优先 ----
int rightHandAction = DetectLeftHandRaise(target);
return rightHandAction;
}
public int DetectLeftHandRaise(Human human)
{
var calculator = PostureCalculate.CreateCalculator();
var ruleLeft = RaiseHand.RaiseLeftHand();
bool pass = calculator.Calculating(human, ruleLeft);
2026-02-05 14:48:49 +08:00
return pass ? (int)WavingAction.RaiseHand : (int)WavingAction.None;
2026-02-03 12:01:37 +08:00
}
2026-02-05 14:48:49 +08:00
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;
}
2025-09-26 16:46:22 +08:00
}
}