2026-03-11 13:16:02 +08:00

259 lines
8.0 KiB
C#

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
{
/// <summary>
/// 运动检测操作类
/// </summary>
public class SportOperate
{
IPointTracker _leftTracker;
IPointTracker _rightTracker;
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);
//_leftTracker.Amplitude = 0.3f;
//_rightTracker.Amplitude = 0.3f;
}
public WebcamClient CreateRTSP()
{
try
{
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;
}
_webcamClient = WebcamClient.CreateRTSP(baseData.Host, baseData.UserName, baseData.Password);
}
catch (Exception)
{
HandyControl.Controls.MessageBox.Show("摄像头网络异常,请重新连接!");
return null;
}
return _webcamClient;
}
/// <summary>
/// 验证右手动作(右手举手优先,然后左右挥手)
/// </summary>
public int
VerifyRightWavingAction(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];
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)
return rightHandAction;
// ---- 左右挥手累加 ----
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)
{
_leftWaveCount = 0;
return (int)WavingAction.LeftWave;
}
if (_rightWaveCount >= WaveThreshold)
{
_rightWaveCount = 0;
return (int)WavingAction.RightWave;
}
return (int)WavingAction.None;
}
/// <summary>
/// 优化后的右手举手检测
/// </summary>
public int DetectRightHandRaise(Human human)
{
var calculator = PostureCalculate.CreateCalculator();
var rule = RaiseHand.RaiseRightHand();
bool pass = calculator.Calculating(human, rule);
if (!pass)
{
_wristStartTime = null;
_firstHandTriggered = false;
return (int)WavingAction.None;
}
var now = DateTime.Now;
//_raiseStartTime ??= now;
_wristStartTime ??= now;
double wristElapsed = (now - _wristStartTime.Value).TotalSeconds;
//double raiseElapsed = (now - _raiseStartTime.Value).TotalSeconds;
// 第一步:触发倒计时 / 举手开始
if (!_firstHandTriggered && wristElapsed >= 0)
{
_firstHandTriggered = true;
return (int)WavingAction.FirstHand;
}
//if (wristElapsed <= 3)
//{
// return (int)WavingAction.Raising;
//}
//_wristStartTime = null;
//_firstHandTriggered = false;
//return (int)WavingAction.RaiseHand;
// 第二步:举手完成
if (wristElapsed >= 3)
{
_wristStartTime = null;
_firstHandTriggered = false;
return (int)WavingAction.RaiseHand;
}
// 举手中
return (int)WavingAction.Raising;
}
/// <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];
if (IsAnyFootInCircle(h, cx, cy, halfW, halfH))
{
target = h;
}
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);
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 = k.X;
double y = k.Y;
if (Math.Abs(x - cx) <= halfW &&
Math.Abs(y - cy) <= halfH)
{
return true;
}
}
return false;
}
}
}