259 lines
8.0 KiB
C#
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;
|
|
}
|
|
|
|
}
|
|
}
|