Merge branch 'dev' of http://8.153.108.90:3000/YD/Wpf_AiSportsMicrospace into dev
This commit is contained in:
commit
f3fd48a651
@ -1,4 +1,5 @@
|
||||
using HandyControl.Controls;
|
||||
using SportExpand;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -24,18 +25,13 @@ namespace Wpf_AiSportsMicrospace.Common
|
||||
{
|
||||
IPointTracker _leftTracker;
|
||||
IPointTracker _rightTracker;
|
||||
IPointTracker _leftElbow;
|
||||
IPointTracker _rightElbow;
|
||||
private int _leftWaveCount = 0;
|
||||
private int _rightWaveCount = 0;
|
||||
private const int WaveThreshold = 4;
|
||||
WebcamClient _webcamClient;
|
||||
|
||||
private DateTime _lastActionTime = DateTime.MinValue;
|
||||
|
||||
private Point? _lastLeftWrist = null;
|
||||
private Point? _lastRightWrist = null;
|
||||
private DateTime? _raiseStartTime = null;
|
||||
private DateTime? _wristStartTime = null;
|
||||
private double _leftWristDeltaX = 0;
|
||||
private double _rightWristDeltaX = 0;
|
||||
private bool _firstHandTriggered = false;
|
||||
|
||||
|
||||
@ -43,13 +39,9 @@ namespace Wpf_AiSportsMicrospace.Common
|
||||
{
|
||||
_leftTracker = PostureCalculate.CreatePointTracker("left_wrist", 0);
|
||||
_rightTracker = PostureCalculate.CreatePointTracker("right_wrist", 0);
|
||||
_leftElbow = PostureCalculate.CreatePointTracker("left_elbow", 0);
|
||||
_rightElbow = PostureCalculate.CreatePointTracker("right_elbow", 0);
|
||||
|
||||
//_leftTracker.Amplitude = 0.03f;
|
||||
//_rightTracker.Amplitude = 0.03f;
|
||||
//_leftElbow.Amplitude = 0.03f;
|
||||
//_rightElbow.Amplitude = 0.03f;
|
||||
_leftTracker.Amplitude = 0.3f;
|
||||
_rightTracker.Amplitude = 0.3f;
|
||||
}
|
||||
|
||||
public WebcamClient CreateRTSP()
|
||||
@ -65,6 +57,7 @@ namespace Wpf_AiSportsMicrospace.Common
|
||||
|
||||
return _webcamClient;
|
||||
}
|
||||
|
||||
public int VerifyWavingAction(List<Human> humans)
|
||||
{
|
||||
if (humans == null || humans.Count == 0)
|
||||
@ -83,47 +76,43 @@ namespace Wpf_AiSportsMicrospace.Common
|
||||
if (!(xNorm >= 0.44 && xNorm <= 0.57 && yNorm >= 0.81))
|
||||
continue;
|
||||
|
||||
var leftWrist = human.Keypoints.FirstOrDefault(x => x.Name == "left_wrist");
|
||||
var leftElbow = human.Keypoints.FirstOrDefault(x => x.Name == "left_elbow");
|
||||
var rightWrist = human.Keypoints.FirstOrDefault(x => x.Name == "right_wrist");
|
||||
var rightElbow = human.Keypoints.FirstOrDefault(x => x.Name == "right_elbow");
|
||||
|
||||
// --- 右手举手优先 ---
|
||||
int rightHandAction = DetectRightHandRaise(human);
|
||||
if (rightHandAction != (int)WavingAction.None)
|
||||
return rightHandAction;
|
||||
|
||||
// --- 左手挥手 ---
|
||||
if (leftWrist != null && leftElbow != null)
|
||||
var leftValue = _leftTracker.Tracking(human);
|
||||
var rightValue = _rightTracker.Tracking(human);
|
||||
|
||||
// ===== 左挥手判定 =====
|
||||
if (leftValue == 1 || leftValue == 2)
|
||||
_leftWaveCount++;
|
||||
//else
|
||||
// _leftWaveCount = 0;
|
||||
|
||||
// ===== 右挥手判定 =====
|
||||
if (rightValue == 1 || rightValue == 2)
|
||||
_rightWaveCount++;
|
||||
//else
|
||||
// _rightWaveCount = 0;
|
||||
|
||||
// ===== 触发判断 =====
|
||||
if (_leftWaveCount >= WaveThreshold)
|
||||
{
|
||||
int leftResult = DetectHorizontalWave(
|
||||
new Point(leftWrist.X, leftWrist.Y),
|
||||
new Point(leftElbow.X, leftElbow.Y),
|
||||
ref _lastLeftWrist,
|
||||
ref _leftWristDeltaX,
|
||||
true);
|
||||
if (leftResult != (int)WavingAction.None)
|
||||
return leftResult;
|
||||
_leftWaveCount = 0; // 只重置左手
|
||||
return (int)WavingAction.LeftWave;
|
||||
}
|
||||
|
||||
// --- 右手挥手 ---
|
||||
//if (rightWrist != null && rightElbow != null)
|
||||
//{
|
||||
// int rightWaveResult = DetectHorizontalWave(
|
||||
// new Point(rightWrist.X, rightWrist.Y),
|
||||
// new Point(rightElbow.X, rightElbow.Y),
|
||||
// ref _lastRightWrist,
|
||||
// ref _rightWristDeltaX,
|
||||
// false);
|
||||
// if (rightWaveResult != (int)WavingAction.None)
|
||||
// return rightWaveResult;
|
||||
//}
|
||||
if (_rightWaveCount >= WaveThreshold)
|
||||
{
|
||||
_rightWaveCount = 0; // 只重置右手
|
||||
return (int)WavingAction.RightWave;
|
||||
}
|
||||
}
|
||||
|
||||
return (int)WavingAction.None;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 检测右手举手状态
|
||||
/// </summary>
|
||||
@ -131,16 +120,11 @@ namespace Wpf_AiSportsMicrospace.Common
|
||||
/// <returns>返回 WavingAction:FirstHand / Raising / RaiseHand / None</returns>
|
||||
public int DetectRightHandRaise(Human human)
|
||||
{
|
||||
var rightWrist = human.Keypoints.FirstOrDefault(k => k.Name == "right_wrist");
|
||||
var rightElbow = human.Keypoints.FirstOrDefault(k => k.Name == "right_elbow");
|
||||
var calculator = PostureCalculate.CreateCalculator();
|
||||
var rule = RaiseHand.RaiseRightHand();
|
||||
var pass = calculator.Calculating(human, rule);
|
||||
|
||||
if (rightWrist == null || rightElbow == null)
|
||||
return (int)WavingAction.None;
|
||||
|
||||
double verticalRise = rightElbow.Y - rightWrist.Y; // 手腕在肘上方 → 正值
|
||||
const double raiseThreshold = 60; // 举手阈值,可根据实际调整
|
||||
|
||||
if (verticalRise >= raiseThreshold)
|
||||
if (pass)
|
||||
{
|
||||
// 初始化计时
|
||||
if (_raiseStartTime == null) _raiseStartTime = DateTime.Now;
|
||||
@ -177,44 +161,5 @@ namespace Wpf_AiSportsMicrospace.Common
|
||||
return (int)WavingAction.None;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 统一的水平挥手检测
|
||||
/// </summary>
|
||||
private int DetectHorizontalWave(Point wrist, Point elbow, ref Point? lastWrist, ref double deltaX, bool isLeft)
|
||||
{
|
||||
if (lastWrist != null)
|
||||
{
|
||||
double dx = wrist.X - lastWrist.Value.X;
|
||||
double dy = Math.Abs(wrist.Y - lastWrist.Value.Y);
|
||||
|
||||
// 累计水平位移
|
||||
deltaX += dx;
|
||||
|
||||
if (Math.Abs(deltaX) > 40 && dy < 60 && Math.Abs(wrist.Y - elbow.Y) < 60)
|
||||
{
|
||||
deltaX = 0; // 重置
|
||||
if (CheckCooldown())
|
||||
{
|
||||
return isLeft ? (int)WavingAction.LeftWave : (int)WavingAction.RightWave;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastWrist = wrist;
|
||||
return (int)WavingAction.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 冷却防抖(避免重复触发)
|
||||
/// </summary>
|
||||
private bool CheckCooldown(int cooldownMs = 1000)
|
||||
{
|
||||
if ((DateTime.Now - _lastActionTime).TotalMilliseconds < cooldownMs)
|
||||
return false;
|
||||
|
||||
_lastActionTime = DateTime.Now;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
45
Wpf_AiSportsMicrospace/SportExpand/RaiseHand.cs
Normal file
45
Wpf_AiSportsMicrospace/SportExpand/RaiseHand.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Yztob.AiSports.Postures.Things;
|
||||
|
||||
namespace SportExpand
|
||||
{
|
||||
/// <summary>
|
||||
/// 举右手
|
||||
/// </summary>
|
||||
public class RaiseHand
|
||||
{
|
||||
/// <summary>
|
||||
/// 举右手
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static CalcBaseRule RaiseRightHand()
|
||||
{
|
||||
return new CalcPositionRule()
|
||||
{
|
||||
Name = "右手是否举过头顶",
|
||||
PositionKey = "right_wrist",
|
||||
ReferenceKey = "right_eye",
|
||||
Position = "top",
|
||||
Relaxed = true
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 举左手
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static CalcBaseRule RaiseLeftHand()
|
||||
{
|
||||
return new CalcPositionRule
|
||||
{
|
||||
Name = "左手是否举过头顶",
|
||||
PositionKey = "left_wrist",
|
||||
ReferenceKey = "left_eye",
|
||||
Position = "top",
|
||||
Relaxed = true
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,568 +0,0 @@
|
||||
//using AiSportsMicrospaceDB.DBContext;
|
||||
//using Dto;
|
||||
//using Enum;
|
||||
//using Microsoft.Extensions.DependencyInjection;
|
||||
//using System;
|
||||
//using System.Collections.Concurrent;
|
||||
//using System.Collections.Generic;
|
||||
//using System.IO;
|
||||
//using System.Text;
|
||||
//using System.Windows;
|
||||
//using System.Windows.Controls;
|
||||
//using System.Windows.Data;
|
||||
//using System.Windows.Documents;
|
||||
//using System.Windows.Input;
|
||||
//using System.Windows.Media;
|
||||
//using System.Windows.Media.Animation;
|
||||
//using System.Windows.Media.Imaging;
|
||||
//using System.Windows.Navigation;
|
||||
//using System.Windows.Shapes;
|
||||
//using Wpf_AiSportsMicrospace;
|
||||
//using Wpf_AiSportsMicrospace.Common;
|
||||
//using Wpf_AiSportsMicrospace.Enum;
|
||||
//using Wpf_AiSportsMicrospace.MyUserControl;
|
||||
//using Wpf_AiSportsMicrospace.Views;
|
||||
//using Yztob.AiSports.Inferences.Abstractions;
|
||||
//using Yztob.AiSports.Inferences.Implement;
|
||||
//using Yztob.AiSports.Inferences.Things;
|
||||
//using Yztob.AiSports.Postures.Sports;
|
||||
//using Yztob.AiSports.Postures.Things;
|
||||
//using Yztob.AiSports.Sensors.Abstractions;
|
||||
//using Yztob.AiSports.Sensors.Things;
|
||||
|
||||
//namespace Views.JumpLong
|
||||
//{
|
||||
// /// <summary>
|
||||
// /// StandingLeap.xaml 的交互逻辑
|
||||
// /// </summary>
|
||||
// public partial class StandingLeap : UserControl
|
||||
// {
|
||||
// #region 私有成员
|
||||
// private Main _mainWin => Application.Current.MainWindow as Main;
|
||||
// private IHumanPredictor _humanPredictor;
|
||||
// private IObjectDetector _objectDetector;
|
||||
// private HumanGraphicsRenderer _humanGraphicsRenderer;
|
||||
// private SportBase _sport;
|
||||
// private ApparatusLongJumpDelineation _measureApparatus;
|
||||
// private MediaPlayer _mediaPlayer = new MediaPlayer();
|
||||
// private readonly SportDetectionQueue _detectQueue;
|
||||
|
||||
// private int _sportType = 0; // 0:未开始 1:运动中 2:运动结束展示排行榜
|
||||
|
||||
// #endregion
|
||||
|
||||
// public StandingLeap()
|
||||
// {
|
||||
// InitializeComponent();
|
||||
// Loaded += UserControl_Loaded;
|
||||
// Unloaded += UserControl_Unloaded;
|
||||
|
||||
// _humanPredictor = HumanPredictorFactory.Create(HumanPredictorType.SingleHigh);
|
||||
// _humanGraphicsRenderer = new HumanGraphicsRenderer();
|
||||
// _humanGraphicsRenderer.DrawLabel = false;
|
||||
// _objectDetector = ObjectDetectorFactory.CreateSportGoodsDetector();
|
||||
// _detectQueue = new SportDetectionQueue();
|
||||
|
||||
// _sport = SportBase.Create("standing-long-jump");
|
||||
// _sport.OnTicked += this.OnSportTick;
|
||||
// _mainWin.HumanFrameUpdated += OnHumanFrameUpdated;
|
||||
|
||||
// }
|
||||
|
||||
// private async void UserControl_Loaded(object sender, RoutedEventArgs e)
|
||||
// {
|
||||
// // 播放音乐
|
||||
// PlayMusic("raisehand.mp3");
|
||||
// }
|
||||
|
||||
|
||||
// //举手检测
|
||||
// private void OnHumanFrameUpdated(object sender, List<Human> humans)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// if (humans == null || humans.Count == 0) return;
|
||||
|
||||
// //举手检测 未开始 :退出& 开始 运动中:不检测 2.结束:继续测试 & 退出
|
||||
// if (_sportType != 1)
|
||||
// {
|
||||
// //左手返回
|
||||
// int leftWaving = DetectLeftHandRaise(humans);
|
||||
// if (leftWaving == 5)
|
||||
// {
|
||||
// _mainWin.HumanFrameUpdated -= OnHumanFrameUpdated;
|
||||
// _mainWin.WebcamClient.StopExtract();
|
||||
|
||||
// // 举左手逻辑,例如结束动画或退出
|
||||
// var newPage = new Home();
|
||||
// _mainWin?.SwitchPageWithMaskAnimation(newPage, true);
|
||||
// return; // 提前退出
|
||||
// }
|
||||
|
||||
// //右手判断
|
||||
// int rightWaving = DetectRightHandRaise(humans);
|
||||
// if (rightWaving >= 3 && _sportType == 0) //举手完成 开始跳远检测
|
||||
// {
|
||||
// Utils.PlayBackgroundMusic("countdown_3.mp3", false);
|
||||
// _sportType = 1;
|
||||
// StartSport();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// Console.WriteLine("OnFrameExtracted error: " + ex.Message);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// private void UserControl_Unloaded(object sender, RoutedEventArgs e)
|
||||
// {
|
||||
// _sport.Stop();
|
||||
// _humanPredictor?.Dispose();
|
||||
// _objectDetector?.Dispose();
|
||||
// }
|
||||
|
||||
// private async void HumanPredicting(VideoFrame frame)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// var buffer = frame.GetImageBuffer(ImageFormat.Jpeg).ToArray();
|
||||
// var humanResult = await Task.Run<HumanInferenceResult>(() => _humanPredictor.Predicting(buffer, frame.Number));
|
||||
// var objects = _sport.Equipment ? await Task.Run<List<BoundingBox>>(() => _objectDetector.Detecting(buffer)) : new List<BoundingBox>();
|
||||
// if (_sport.MeasureApparatus != null)
|
||||
// objects.AddRange(_sport.MeasureApparatus.Apparatuses);
|
||||
|
||||
// //运动需要保证时序
|
||||
// var human = humanResult?.Humans?.FirstOrDefault();
|
||||
// _detectQueue.Enqueue(frame.Number, human, objects);
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// Console.WriteLine("ProcessFrame error: " + ex.Message);
|
||||
// }
|
||||
// }
|
||||
|
||||
// //播放音乐
|
||||
// private void PlayMusic(string musicFileName)
|
||||
// {
|
||||
// // 获取项目根目录
|
||||
// string projectRoot = System.IO.Path.Combine(AppContext.BaseDirectory, @"..\..\..");
|
||||
// string musicPath = System.IO.Path.Combine(projectRoot, "Resources", "Music", musicFileName);
|
||||
|
||||
// if (!File.Exists(musicPath))
|
||||
// {
|
||||
// Console.WriteLine($"音乐文件不存在: {musicPath}");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// _mediaPlayer.Open(new Uri(musicPath, UriKind.Absolute));
|
||||
|
||||
// ShowCenterTip(TimeSpan.FromSeconds(3));
|
||||
|
||||
// // 监听播放完成事件
|
||||
// _mediaPlayer.MediaEnded += MediaPlayer_MediaEnded;
|
||||
// //_mainWin.WebcamClient.StartExtract();
|
||||
// _mediaPlayer.Play();
|
||||
// }
|
||||
// private void ShowCenterTip(TimeSpan duration)
|
||||
// {
|
||||
// // 渐变出现动画
|
||||
// var fadeInAnimation = new DoubleAnimation
|
||||
// {
|
||||
// From = 0,
|
||||
// To = 1,
|
||||
// Duration = TimeSpan.FromSeconds(1.5)
|
||||
// };
|
||||
// TipBox.BeginAnimation(UIElement.OpacityProperty, fadeInAnimation);
|
||||
|
||||
// // 定时移除,并且渐变消失
|
||||
// Task.Delay(duration).ContinueWith(_ =>
|
||||
// {
|
||||
// Dispatcher.Invoke(() =>
|
||||
// {
|
||||
// // 渐变消失动画
|
||||
// var fadeOutAnimation = new DoubleAnimation
|
||||
// {
|
||||
// From = 1,
|
||||
// To = 0,
|
||||
// Duration = TimeSpan.FromSeconds(1.5)
|
||||
// };
|
||||
// TipBox.BeginAnimation(UIElement.OpacityProperty, fadeOutAnimation);
|
||||
|
||||
// });
|
||||
// });
|
||||
|
||||
// }
|
||||
// private void MediaPlayer_MediaEnded(object sender, EventArgs e)
|
||||
// {
|
||||
// // 音乐播放完成后的逻辑
|
||||
// Console.WriteLine("音乐播放完成!");
|
||||
// }
|
||||
|
||||
// private void OnSportTick(int counts, int times)
|
||||
// {
|
||||
// var ts = TimeSpan.FromSeconds(times);
|
||||
// _ = Dispatcher.BeginInvoke(() =>
|
||||
// {
|
||||
// //sportCounts.Content = _sport.GetFormatCounts(); //counts.ToString();
|
||||
// //sportTimes.Content = _sport.GetFormatTimes();//ts.ToString(@"mm\'ss\""");
|
||||
// var counts = _sport.GetFormatCounts();
|
||||
// if (double.Parse(counts[..^1]) > 0 && _sportType == 1) //正向跳远时候&&处于测试阶段时候触发更新
|
||||
// {
|
||||
// _sport.Stop();//关闭运动
|
||||
|
||||
// count.Text = counts;
|
||||
// time.Text = _sport.GetFormatTimes();
|
||||
// ShowRope();
|
||||
// if (!_sport.IsCounting)
|
||||
// {
|
||||
// _sport.Stop();
|
||||
// _sport.Start();
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
// //展示成绩
|
||||
// private async void ShowRope()
|
||||
// {
|
||||
// // 渐变出现动画
|
||||
// var fadeInAnimation = new DoubleAnimation
|
||||
// {
|
||||
// From = 0,
|
||||
// To = 1,
|
||||
// Duration = TimeSpan.FromSeconds(1.5)
|
||||
// };
|
||||
// var fadeInAnimation1 = new DoubleAnimation
|
||||
// {
|
||||
// From = 1,
|
||||
// To = 0,
|
||||
// Duration = TimeSpan.FromSeconds(1.5)
|
||||
// };
|
||||
// //videoImage.Opacity = 0;
|
||||
// //centerImg1.Opacity = 1;
|
||||
// //centerImg2.Opacity = 1;
|
||||
// //centerImg3.Opacity = 1;
|
||||
// _sportType = 2;
|
||||
// RankingGrid.BeginAnimation(UIElement.OpacityProperty, fadeInAnimation);
|
||||
// //_mainWin.WebcamClient.OnExtractFrame -= this.OnFrameExtracted;
|
||||
// for (int i = 12; i >= 0; i--)
|
||||
// {
|
||||
// countDown.Text = i.ToString() + "s";
|
||||
// if(i == 1)
|
||||
// {
|
||||
// RankingGrid.BeginAnimation(UIElement.OpacityProperty, fadeInAnimation1);
|
||||
// _sportType = 0;
|
||||
// PlayMusic("raisehand.mp3");
|
||||
// }
|
||||
// await Task.Delay(1000);
|
||||
// }
|
||||
// // 关闭跳远抽帧线程
|
||||
// }
|
||||
|
||||
// //关闭成绩展示 显示跳远页面
|
||||
// private void closRope()
|
||||
// {
|
||||
// //关闭动画
|
||||
// //var fadeInAnimation = new DoubleAnimation
|
||||
// //{
|
||||
// // From = 1,
|
||||
// // To = 0,
|
||||
// // Duration = TimeSpan.FromSeconds(1)
|
||||
// //};
|
||||
// // RankingGrid.BeginAnimation(UIElement.OpacityProperty, fadeInAnimation);
|
||||
// RankingGrid.Opacity = 0;
|
||||
// _sportType = 0;
|
||||
// PlayMusic("raisehand.mp3");
|
||||
// }
|
||||
// private bool ReactangleCalibrating(int frameWidth, int frameHeight)
|
||||
// {
|
||||
|
||||
// var mainWin = Application.Current.MainWindow as Main;
|
||||
// var app = (App)Application.Current;
|
||||
// using var scope = App.AppHost.Services.CreateScope();
|
||||
// var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
// var points = db.JumpLongPoints.FirstOrDefault();
|
||||
// var boxes = new List<BoundingBox>()
|
||||
// {
|
||||
// new BoundingBox(){
|
||||
// ImageWidth = frameWidth,
|
||||
// ImageHeight = frameHeight,
|
||||
// Label = new PredictionLabel(){
|
||||
// Key = "begin"
|
||||
// },
|
||||
// MaskLayer = new MaskLayer(){
|
||||
// Contours = [
|
||||
// new ((float)points.BottomPoint3.X, (float)points.BottomPoint3.Y),
|
||||
// new ((float)points.TopPoint3.X, (float)points.TopPoint3.Y),
|
||||
// ]
|
||||
// }
|
||||
// },
|
||||
// new BoundingBox(){
|
||||
// ImageWidth = frameWidth,
|
||||
// ImageHeight = frameHeight,
|
||||
// Label = new PredictionLabel{
|
||||
// Key = "end"
|
||||
// },
|
||||
// MaskLayer = new MaskLayer(){
|
||||
// Contours = [
|
||||
// new((float)points.BottomPoint2.X, (float)points.BottomPoint2.Y),
|
||||
// new((float)points.TopPoint2.X, (float)points.TopPoint2.Y),
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
// boxes[1].Label.Key = "take-off";
|
||||
// boxes.Add(new BoundingBox()
|
||||
// {
|
||||
// ImageWidth = frameWidth,
|
||||
// ImageHeight = frameHeight,
|
||||
// Label = new PredictionLabel
|
||||
// {
|
||||
// Key = "end"
|
||||
// },
|
||||
// MaskLayer = new MaskLayer()
|
||||
// {
|
||||
// Contours = [
|
||||
// new ((float)points.BottomPoint1.X, (float)points.BottomPoint1.Y),
|
||||
// new ((float)points.TopPoint1.X, (float)points.TopPoint1.Y),
|
||||
// ]
|
||||
// }
|
||||
// });
|
||||
|
||||
// return _measureApparatus.Calibrating(boxes);
|
||||
// }
|
||||
|
||||
|
||||
// public int DetectLeftHandRaise(List<Human> humans)
|
||||
// {
|
||||
// if (humans == null || humans.Count == 0)
|
||||
// return (int)WavingAction.None;
|
||||
|
||||
|
||||
// foreach (var human in humans)
|
||||
// {
|
||||
// if (human?.Keypoints == null)
|
||||
// continue;
|
||||
|
||||
// // --- 筛选右脚踝坐标 ---
|
||||
// var rightAnkle = human.Keypoints.FirstOrDefault(k => k.Name == "right_ankle");
|
||||
// if (rightAnkle == null)
|
||||
// continue;
|
||||
// double xNorm = rightAnkle.X / 1920;
|
||||
// double yNorm = rightAnkle.Y / 1080;
|
||||
// // 仅检测中心区域内的人
|
||||
// if (!(xNorm >= 0.44 && xNorm <= 0.57 && yNorm >= 0.81))
|
||||
// continue;
|
||||
|
||||
// // 获取左手关键点
|
||||
// var leftWrist = human.Keypoints.FirstOrDefault(k => k.Name == "left_wrist");
|
||||
// var leftElbow = human.Keypoints.FirstOrDefault(k => k.Name == "left_elbow");
|
||||
|
||||
// if (leftWrist == null || leftElbow == null)
|
||||
// continue;
|
||||
|
||||
// const double raiseThreshold = 60; // 举手阈值
|
||||
|
||||
// // 判断左手是否举起
|
||||
// double verticalRise = leftElbow.Y - leftWrist.Y;
|
||||
// if (verticalRise >= raiseThreshold)
|
||||
// {
|
||||
// return (int)WavingAction.RaiseHand; // 一旦检测到左手举起,立即返回
|
||||
// }
|
||||
// }
|
||||
|
||||
// return (int)WavingAction.None; // 没有检测到举手
|
||||
// }
|
||||
|
||||
// private DateTime? _raiseStartTime;
|
||||
// private bool _firstHandTriggered;
|
||||
// private int _lastCountdownSecond = 3;
|
||||
// private DateTime? _countdownStartTime;
|
||||
// public int DetectRightHandRaise(List<Human> humans)
|
||||
// {
|
||||
// if (humans == null || humans.Count == 0)
|
||||
// return (int)WavingAction.None;
|
||||
|
||||
// foreach (var human in humans)
|
||||
// {
|
||||
// if (human?.Keypoints == null)
|
||||
// continue;
|
||||
|
||||
// // --- 筛选右脚踝坐标 ---
|
||||
// var rightAnkle = human.Keypoints.FirstOrDefault(k => k.Name == "right_ankle");
|
||||
// if (rightAnkle == null)
|
||||
// continue;
|
||||
|
||||
// //double xNorm = rightAnkle.X / 1920;
|
||||
// //double yNorm = rightAnkle.Y / 1080;
|
||||
|
||||
|
||||
// var app = (App)Application.Current;
|
||||
// using var scope = App.AppHost.Services.CreateScope();
|
||||
// var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
// var points = db.JumpLongPoints.FirstOrDefault();
|
||||
|
||||
// // 检测起跳区域的人
|
||||
|
||||
// var isinx = (rightAnkle.X < points.TopPoint3.X && rightAnkle.X > points.TopPoint2.X) || (rightAnkle.X < points.BottomPoint3.X && rightAnkle.X > points.BottomPoint2.X) ;
|
||||
// if(points.TopPoint3.X < points.TopPoint2.X)
|
||||
// {
|
||||
// isinx = (rightAnkle.X > points.TopPoint3.X && rightAnkle.X < points.TopPoint2.X) || (rightAnkle.X > points.BottomPoint3.X && rightAnkle.X < points.BottomPoint2.X);
|
||||
// }
|
||||
// var isiny = (rightAnkle.Y > points.TopPoint3.Y && rightAnkle.X < points.BottomPoint3.Y) || (rightAnkle.Y < points.TopPoint2.Y && rightAnkle.X > points.BottomPoint2.Y) ;
|
||||
// if (!isinx || !isiny) continue;
|
||||
|
||||
|
||||
// var rightWrist = human.Keypoints.FirstOrDefault(k => k.Name == "right_wrist");
|
||||
// var rightElbow = human.Keypoints.FirstOrDefault(k => k.Name == "right_elbow");
|
||||
|
||||
// const double raiseThreshold = 60; // 举手阈值
|
||||
// const double holdDuration = 1; // 持续时间(秒)
|
||||
// const int countdownSeconds = 3; // 倒计时长度
|
||||
|
||||
// bool handRaised = false;
|
||||
|
||||
// if (rightWrist != null && rightElbow != null)
|
||||
// {
|
||||
// double verticalRise = rightElbow.Y - rightWrist.Y;
|
||||
// handRaised = verticalRise >= raiseThreshold;
|
||||
// }
|
||||
|
||||
// // ---------- 第一步:持续举手触发倒计时 ----------
|
||||
// if (!_firstHandTriggered)
|
||||
// {
|
||||
|
||||
// if (handRaised)
|
||||
// {
|
||||
// _raiseStartTime ??= DateTime.Now;
|
||||
// var holdElapsed = (DateTime.Now - _raiseStartTime.Value).TotalSeconds;
|
||||
// if (holdElapsed >= holdDuration)
|
||||
// {
|
||||
// // 举手达到指定时间,启动倒计时
|
||||
// _firstHandTriggered = true;
|
||||
// return (int)WavingAction.FirstHand;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // 手放下,重置举手开始时间
|
||||
// _raiseStartTime = DateTime.Now;
|
||||
// }
|
||||
|
||||
// continue; // 本人未触发,检测下一个人
|
||||
// }
|
||||
|
||||
// // ---------- 第二步:倒计时逻辑 ----------
|
||||
// var countdownElapsed = (DateTime.Now - _countdownStartTime.Value).TotalSeconds;
|
||||
// int currentSecond = countdownSeconds - (int)Math.Floor(countdownElapsed);
|
||||
|
||||
// if (currentSecond > 0 && currentSecond != _lastCountdownSecond)
|
||||
// {
|
||||
// _lastCountdownSecond = currentSecond;
|
||||
// Console.WriteLine($"倒计时:{currentSecond}");
|
||||
// return (int)WavingAction.Raising; // 倒计时中
|
||||
// }
|
||||
|
||||
// if (countdownElapsed >= countdownSeconds)
|
||||
// {
|
||||
// ResetRaiseState();
|
||||
// return (int)WavingAction.RaiseHand; // 举手完成
|
||||
// }
|
||||
|
||||
// return (int)WavingAction.Raising;
|
||||
// }
|
||||
|
||||
// // 没有任何中心区域内的人举手
|
||||
// return (int)WavingAction.None;
|
||||
// }
|
||||
|
||||
// private void ResetRaiseState()
|
||||
// {
|
||||
// _raiseStartTime = null;
|
||||
// _countdownStartTime = null;
|
||||
// _firstHandTriggered = false;
|
||||
// _lastCountdownSecond = 3;
|
||||
// }
|
||||
|
||||
// private void StartSport()
|
||||
// {
|
||||
|
||||
|
||||
// //if (_sport?.IsCounting == true)
|
||||
// //_mainWin.WebcamClient.OnExtractFrame += this.OnFrameExtracted;
|
||||
// _sport.Start();
|
||||
|
||||
// _measureApparatus = new ApparatusLongJumpDelineation();
|
||||
// _measureApparatus.MeasureLength = 300;
|
||||
// var _isCalibrated = this.ReactangleCalibrating(1920, 1080);
|
||||
// _sport.MeasureApparatus = _measureApparatus;
|
||||
// _detectQueue.Sport = _sport;
|
||||
// _detectQueue.Start();
|
||||
|
||||
// // 开始跳远抽帧线程
|
||||
// _mainWin.FacialRecognitionEvent += HumanPredicting;
|
||||
// }
|
||||
|
||||
// private WriteableBitmap _videoBitmap;
|
||||
// private int _lastFrameNumber = -1;
|
||||
// private async void OnFrameExtracted(VideoFrame frame)
|
||||
// {
|
||||
// if (frame == null) return;
|
||||
|
||||
// // 跳帧:每秒只渲染 10~15 帧,降低 CPU 占用
|
||||
|
||||
// if (frame.Number %2 != 0) return;
|
||||
|
||||
// if (_lastFrameNumber != -1 && frame.Number - _lastFrameNumber < 2) return;
|
||||
// _lastFrameNumber = (int)frame.Number;
|
||||
|
||||
// //获得帧二进制流,保存图像、人体识别竺
|
||||
// var buffer = frame.GetImageBuffer(Yztob.AiSports.Sensors.Things.ImageFormat.Jpeg).ToArray();
|
||||
// //await File.WriteAllBytesAsync($"./temps/{frame.Number}.jpg", buffer);
|
||||
|
||||
// // === 显示到 WPF ===
|
||||
// BitmapImage bitmap = null;
|
||||
// await Task.Run(() =>
|
||||
// {
|
||||
// using var ms = new MemoryStream(buffer);
|
||||
// bitmap = new BitmapImage();
|
||||
// bitmap.BeginInit();
|
||||
// bitmap.CacheOption = BitmapCacheOption.OnLoad;
|
||||
// bitmap.StreamSource = ms;
|
||||
// bitmap.EndInit();
|
||||
// bitmap.Freeze(); // 跨线程安全
|
||||
// });
|
||||
|
||||
// // UI 线程显示
|
||||
// Application.Current.Dispatcher.Invoke(() =>
|
||||
// {
|
||||
// if (videoImage == null) return;
|
||||
|
||||
// if (_videoBitmap == null ||
|
||||
// _videoBitmap.PixelWidth != bitmap.PixelWidth ||
|
||||
// _videoBitmap.PixelHeight != bitmap.PixelHeight)
|
||||
// {
|
||||
// _videoBitmap = new WriteableBitmap(bitmap.PixelWidth, bitmap.PixelHeight,
|
||||
// 96, 96, PixelFormats.Bgra32, null);
|
||||
// videoImage.Source = _videoBitmap;
|
||||
// }
|
||||
|
||||
// _videoBitmap.Lock();
|
||||
// bitmap.CopyPixels(new Int32Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight),
|
||||
// _videoBitmap.BackBuffer,
|
||||
// _videoBitmap.BackBufferStride * bitmap.PixelHeight,
|
||||
// _videoBitmap.BackBufferStride);
|
||||
// _videoBitmap.AddDirtyRect(new Int32Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight));
|
||||
// _videoBitmap.Unlock();
|
||||
|
||||
// videoImage.Opacity = 1;
|
||||
// centerImg1.Opacity = 0;
|
||||
// centerImg2.Opacity = 0;
|
||||
// centerImg3.Opacity = 0;
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
Loading…
x
Reference in New Issue
Block a user