diff --git a/Wpf_AiSportsMicrospace/Home.xaml b/Wpf_AiSportsMicrospace/Home.xaml index 246ea15..a152e2e 100644 --- a/Wpf_AiSportsMicrospace/Home.xaml +++ b/Wpf_AiSportsMicrospace/Home.xaml @@ -4,6 +4,6 @@ xmlns:local="clr-namespace:Wpf_AiSportsMicrospace.MyUserControl" Title="Home" Height="600" Width="800" Loaded="Window_Loaded"> - + diff --git a/Wpf_AiSportsMicrospace/Home.xaml.cs b/Wpf_AiSportsMicrospace/Home.xaml.cs index d530382..f93599f 100644 --- a/Wpf_AiSportsMicrospace/Home.xaml.cs +++ b/Wpf_AiSportsMicrospace/Home.xaml.cs @@ -43,23 +43,30 @@ namespace Wpf_AiSportsMicrospace public Home() { InitializeComponent(); - _humanPredictor = HumanPredictorFactory.Create(HumanPredictorType.SingleHigh); - _objectDetector = ObjectDetectorFactory.CreateSportGoodsDetector(); - _humanGraphicsRenderer = new HumanGraphicsRenderer(); - _humanGraphicsRenderer.DrawLabel = false; + //_humanPredictor = HumanPredictorFactory.Create(HumanPredictorType.SingleHigh); + //_objectDetector = ObjectDetectorFactory.CreateSportGoodsDetector(); + //_humanGraphicsRenderer = new HumanGraphicsRenderer(); + //_humanGraphicsRenderer.DrawLabel = false; - _sports = SportBase.GetSports(); - _detectQueue = new SportDetectionQueue(); + //_sports = SportBase.GetSports(); + //_detectQueue = new SportDetectionQueue(); string projectRoot = Path.Combine(AppContext.BaseDirectory, @"..\..\.."); string albumPath = Path.Combine(projectRoot, "Resources", "Img", "Album"); // 转换为 Uri - coverFlow.Images.Add(new Uri(Path.Combine(albumPath, "1.jpg"))); - coverFlow.Images.Add(new Uri(Path.Combine(albumPath, "2.jpg"))); - coverFlow.Images.Add(new Uri(Path.Combine(albumPath, "3.jpg"))); - coverFlow.Images.Add(new Uri(Path.Combine(albumPath, "4.jpg"))); - coverFlow.Images.Add(new Uri(Path.Combine(albumPath, "5.jpg"))); + //coverFlow.Images.Add(new Uri(Path.Combine(albumPath, "1.jpg"))); + //coverFlow.Images.Add(new Uri(Path.Combine(albumPath, "2.jpg"))); + //coverFlow.Images.Add(new Uri(Path.Combine(albumPath, "3.jpg"))); + //coverFlow.Images.Add(new Uri(Path.Combine(albumPath, "4.jpg"))); + //coverFlow.Images.Add(new Uri(Path.Combine(albumPath, "5.jpg"))); + + + coverFlow.Images.Add(new CoverFlowItem { ImageUri = new Uri(Path.Combine(albumPath, "1.jpg")) }); + coverFlow.Images.Add(new CoverFlowItem { ImageUri = new Uri(Path.Combine(albumPath, "2.jpg")) }); + coverFlow.Images.Add(new CoverFlowItem { ImageUri = new Uri(Path.Combine(albumPath, "3.jpg")) }); + coverFlow.Images.Add(new CoverFlowItem { ImageUri = new Uri(Path.Combine(albumPath, "4.jpg")) }); + coverFlow.Images.Add(new CoverFlowItem { ImageUri = new Uri(Path.Combine(albumPath, "5.jpg")) }); // 默认选中第3张 coverFlow.SelectedIndex = 2; @@ -67,18 +74,18 @@ namespace Wpf_AiSportsMicrospace private void Window_Loaded(object sender, RoutedEventArgs e) { - _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 = 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.05f; - _rightTracker.Amplitude = 0.05f; + //_leftTracker.Amplitude = 0.05f; + //_rightTracker.Amplitude = 0.05f; - _leftElbow.Amplitude = 0.05f; - _rightElbow.Amplitude = 0.05f; + //_leftElbow.Amplitude = 0.05f; + //_rightElbow.Amplitude = 0.05f; - LoadRTSP(); + //LoadRTSP(); } private void LoadRTSP() diff --git a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl1.xaml b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl1.xaml index 0c9b038..e5371f0 100644 --- a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl1.xaml +++ b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl1.xaml @@ -4,46 +4,43 @@ xmlns:_3DTools="clr-namespace:_3DTools;assembly=3DTools" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:local="clr-namespace:Wpf_AiSportsMicrospace.MyUserControl" - mc:Ignorable="d" Background="Black" x:Name="Root"> - - - - - + xmlns:local="clr-namespace:Wpf_AiSportsMicrospace.MyUserControl" + Height="300" Width="600"> + + + + - - <_3DTools:Interactive3DDecorator> - - - - + + + + + + + - - - - - - - + + + + + + + + + - - - + + - - - - - - + + + + + + + diff --git a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl1.xaml.cs b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl1.xaml.cs index d169a80..964be4c 100644 --- a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl1.xaml.cs +++ b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl1.xaml.cs @@ -1,6 +1,7 @@ using _3DTools; using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Text; @@ -16,344 +17,151 @@ using System.Windows.Media.Imaging; using System.Windows.Media.Media3D; using System.Windows.Navigation; using System.Windows.Shapes; +using System.Windows.Threading; namespace Wpf_AiSportsMicrospace.MyUserControl { /// /// CoverFlowControl1.xaml 的交互逻辑 /// + public partial class CoverFlowControl1 : UserControl { + public ObservableCollection Images { get; set; } = new ObservableCollection(); + private int _selectedIndex = 0; + + public int SelectedIndex + { + get => _selectedIndex; + set + { + if (Images.Count == 0) return; + if (value < 0) _selectedIndex = Images.Count - 1; + else if (value >= Images.Count) _selectedIndex = 0; + else _selectedIndex = value; + + for (int i = 0; i < Images.Count; i++) + { + Images[i].IsSelected = (i == _selectedIndex); + if (i == _selectedIndex) Images[i].Progress = 0; + } + + UpdateLayoutWithAnimation(); + } + } + public CoverFlowControl1() { InitializeComponent(); - InitControl(); - } + DataContext = this; + Loaded += (s, e) => UpdateLayoutWithAnimation(true); - #region 依赖属性注册 - public static readonly DependencyProperty CurrentMidIndexProperty = - DependencyProperty.Register( - "CurrentMidIndex", typeof(double), typeof(CoverFlowControl), - new FrameworkPropertyMetadata(new PropertyChangedCallback(CurrentMidIndexPropertyChangedCallback))); - - private static void CurrentMidIndexPropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs arg) - { - var ctrl = sender as CoverFlowControl1; - ctrl?.ReLayoutInteractiveVisual3D(); - } - - public double CurrentMidIndex - { - get => (double)GetValue(CurrentMidIndexProperty); - set => SetValue(CurrentMidIndexProperty, value); - } - - public static readonly DependencyProperty ModelAngleProperty = - DependencyProperty.Register( - "ModelAngle", typeof(double), typeof(CoverFlowControl), - new FrameworkPropertyMetadata(70.0, new PropertyChangedCallback(ModelAnglePropertyChangedCallback))); - - private static void ModelAnglePropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs arg) - { - var ctrl = sender as CoverFlowControl1; - ctrl?.ReLayoutInteractiveVisual3D(); - } - - public double ModelAngle - { - get => (double)GetValue(ModelAngleProperty); - set => SetValue(ModelAngleProperty, value); - } - - public static readonly DependencyProperty XDistanceBetweenModelsProperty = - DependencyProperty.Register( - "XDistanceBetweenModels", typeof(double), typeof(CoverFlowControl), - new FrameworkPropertyMetadata(0.5, XDistanceBetweenModelsPropertyChangedCallback)); - - private static void XDistanceBetweenModelsPropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs arg) - { - var ctrl = sender as CoverFlowControl1; - ctrl?.ReLayoutInteractiveVisual3D(); - } - - public double XDistanceBetweenModels - { - get => (double)GetValue(XDistanceBetweenModelsProperty); - set => SetValue(XDistanceBetweenModelsProperty, value); - } - - public static readonly DependencyProperty ZDistanceBetweenModelsProperty = - DependencyProperty.Register( - "ZDistanceBetweenModels", typeof(double), typeof(CoverFlowControl), - new FrameworkPropertyMetadata(0.5, ZDistanceBetweenModelsPropertyChangedCallback)); - - private static void ZDistanceBetweenModelsPropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs arg) - { - var ctrl = sender as CoverFlowControl1; - ctrl?.ReLayoutInteractiveVisual3D(); - } - - public double ZDistanceBetweenModels - { - get => (double)GetValue(ZDistanceBetweenModelsProperty); - set => SetValue(ZDistanceBetweenModelsProperty, value); - } - - public static readonly DependencyProperty MidModelDistanceProperty = - DependencyProperty.Register( - "MidModelDistance", typeof(double), typeof(CoverFlowControl), - new FrameworkPropertyMetadata(1.5, MidModelDistancePropertyChangedCallback)); - - private static void MidModelDistancePropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs arg) - { - var ctrl = sender as CoverFlowControl1; - ctrl?.ReLayoutInteractiveVisual3D(); - } - - public double MidModelDistance - { - get => (double)GetValue(MidModelDistanceProperty); - set => SetValue(MidModelDistanceProperty, value); - } - #endregion - private void InitControl() - { - this.LoadImageToViewport3D(this.GetUserImages()); - - // 鼠标事件改为控件自身 - this.MouseDown += (s, e) => + var timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(30) }; + timer.Tick += (s, e) => { - if (e.LeftButton == MouseButtonState.Pressed) - this.CurrentMidIndex++; + if (Images.Count == 0) return; + var current = Images[_selectedIndex]; + if (current.Progress < 1) + current.Progress += 0.01; // 调整速度 + }; + timer.Start(); + } + + private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + if (sender is Border border) + { + var container = ItemsHost.ItemContainerGenerator.ContainerFromItem(border.DataContext) as ContentPresenter; + if (container != null) + { + int index = ItemsHost.ItemContainerGenerator.IndexFromContainer(container); + SelectedIndex = index; + } + } + } + + private void UpdateLayoutWithAnimation(bool instant = false) + { + double centerX = ActualWidth / 2; + double spacing = 180; + double sideScale = 0.8; + double centerScale = 1.2; + + for (int i = 0; i < ItemsHost.Items.Count; i++) + { + var container = ItemsHost.ItemContainerGenerator.ContainerFromIndex(i) as ContentPresenter; + if (container == null) continue; + + var border = FindVisualChild(container); + if (border == null) continue; + + var transformGroup = border.RenderTransform as TransformGroup; + var scale = transformGroup.Children[0] as ScaleTransform; + var translate = transformGroup.Children[1] as TranslateTransform; + + double targetX; + double targetScale; + double targetOpacity; + + if (i == SelectedIndex) + { + targetX = centerX - 75; + targetScale = centerScale; + targetOpacity = 1.0; + } + else if (i == SelectedIndex - 1 || (SelectedIndex == 0 && i == Images.Count - 1)) + { + targetX = centerX - spacing - 75; + targetScale = sideScale; + targetOpacity = 1.0; + } + else if (i == SelectedIndex + 1 || (SelectedIndex == Images.Count - 1 && i == 0)) + { + targetX = centerX + spacing - 75; + targetScale = sideScale; + targetOpacity = 1.0; + } else - this.CurrentMidIndex--; - }; - } - - /// - /// 获取当前用户的图片文件夹中的图片(不包含子文件夹) - /// - /// 返回图片路径列表 - private List GetUserImages() - { - List images = new List(); - - string path = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures); - DirectoryInfo dir = new DirectoryInfo(path); - FileInfo[] files = dir.GetFiles("*.jpg", SearchOption.AllDirectories); - if (files != null) - { - foreach (FileInfo file in files) { - images.Add(file.FullName); + targetX = centerX - 75; + targetScale = sideScale; + targetOpacity = 0.0; } - } - return images; - } - - /// - /// 添加图片到视口 - /// - /// - private void LoadImageToViewport3D(List images) - { - if (images == null) - { - return; - } - - for (int i = 0; i < images.Count; i++) - { - string imageFile = images[i]; - - InteractiveVisual3D iv3d = this.CreateInteractiveVisual3D(imageFile, i); - - this.viewport3D.Children.Add(iv3d); - } - - this.ReLayoutInteractiveVisual3D(); - } - private InteractiveVisual3D CreateInteractiveVisual3D(string imageFile, int index) - { - InteractiveVisual3D iv3d = new InteractiveVisual3D(); - iv3d.Visual = this.CreateVisual(imageFile, index); - iv3d.Geometry = this.CreateGeometry3D(); - iv3d.Transform = this.CreateEmptyTransform3DGroup(); - - return iv3d; - } - /// - /// 创建一个空的Transform3DGroup - /// - /// - private Transform3DGroup CreateEmptyTransform3DGroup() - { - Transform3DGroup group = new Transform3DGroup(); - group.Children.Add(new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 1, 0), 0))); - group.Children.Add(new TranslateTransform3D(new Vector3D())); - group.Children.Add(new ScaleTransform3D()); - - return group; - } - - /// - /// 创建3D图形 - /// - /// 创建的3D图形 - private Geometry3D CreateGeometry3D() - { - MeshGeometry3D geometry = new MeshGeometry3D(); - - geometry.Positions = new Point3DCollection(); - geometry.Positions.Add(new Point3D(-1, 1, 0)); - geometry.Positions.Add(new Point3D(-1, -1, 0)); - geometry.Positions.Add(new Point3D(1, -1, 0)); - geometry.Positions.Add(new Point3D(1, 1, 0)); - - geometry.TriangleIndices = new Int32Collection(); - geometry.TriangleIndices.Add(0); - geometry.TriangleIndices.Add(1); - geometry.TriangleIndices.Add(2); - geometry.TriangleIndices.Add(0); - geometry.TriangleIndices.Add(2); - geometry.TriangleIndices.Add(3); - - geometry.TextureCoordinates = new PointCollection(); - geometry.TextureCoordinates.Add(new Point(0, 0)); - geometry.TextureCoordinates.Add(new Point(0, 1)); - geometry.TextureCoordinates.Add(new Point(1, 1)); - geometry.TextureCoordinates.Add(new Point(1, 0)); - - return geometry; - } - - - /// - /// 由指定的图片路径创建一个可视对象 - /// - /// 图片路径 - /// 创建的可视对象 - private Visual CreateVisual(string imageFile, int index) - { - BitmapImage bmp = null; - - try - { - bmp = new BitmapImage(new Uri(imageFile)); - } - catch - { - } - - Image img = new Image(); - img.Width = 50; - img.Source = bmp; - - Border outBordre = new Border(); - outBordre.BorderBrush = Brushes.White; - outBordre.BorderThickness = new Thickness(0.5); - outBordre.Child = img; - - outBordre.MouseDown += delegate (object sender, MouseButtonEventArgs e) - { - this.CurrentMidIndex = index; - e.Handled = true; - }; - - return outBordre; - - } - - /// - /// 重新布局3D内容 - /// - private void ReLayoutInteractiveVisual3D() - { - int j = 0; - for (int i = 0; i < this.viewport3D.Children.Count; i++) - { - InteractiveVisual3D iv3d = this.viewport3D.Children[i] as InteractiveVisual3D; - if (iv3d != null) + if (instant) { - double angle = 0; - double offsetX = 0; - double offsetZ = 0; - this.GetTransformOfInteractiveVisual3D(j++, this.CurrentMidIndex, out angle, out offsetX, out offsetZ); - - - NameScope.SetNameScope(this, new NameScope()); - this.RegisterName("iv3d", iv3d); - Duration time = new Duration(TimeSpan.FromSeconds(0.3)); - - DoubleAnimation angleAnimation = new DoubleAnimation(angle, time); - DoubleAnimation xAnimation = new DoubleAnimation(offsetX, time); - DoubleAnimation zAnimation = new DoubleAnimation(offsetZ, time); - - Storyboard story = new Storyboard(); - story.Children.Add(angleAnimation); - story.Children.Add(xAnimation); - story.Children.Add(zAnimation); - - Storyboard.SetTargetName(angleAnimation, "iv3d"); - Storyboard.SetTargetName(xAnimation, "iv3d"); - Storyboard.SetTargetName(zAnimation, "iv3d"); - - Storyboard.SetTargetProperty( - angleAnimation, - new PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[0].(RotateTransform3D.Rotation).(AxisAngleRotation3D.Angle)")); - - Storyboard.SetTargetProperty( - xAnimation, - new PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[1].(TranslateTransform3D.OffsetX)")); - Storyboard.SetTargetProperty( - zAnimation, - new PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[1].(TranslateTransform3D.OffsetZ)")); - - story.Begin(this); - + translate.X = targetX; + scale.ScaleX = scale.ScaleY = targetScale; + border.Opacity = targetOpacity; + } + else + { + translate.BeginAnimation(TranslateTransform.XProperty, + new DoubleAnimation(targetX, TimeSpan.FromMilliseconds(400)) { EasingFunction = new QuadraticEase() }); + scale.BeginAnimation(ScaleTransform.ScaleXProperty, + new DoubleAnimation(targetScale, TimeSpan.FromMilliseconds(400)) { EasingFunction = new QuadraticEase() }); + scale.BeginAnimation(ScaleTransform.ScaleYProperty, + new DoubleAnimation(targetScale, TimeSpan.FromMilliseconds(400)) { EasingFunction = new QuadraticEase() }); + border.BeginAnimation(Border.OpacityProperty, + new DoubleAnimation(targetOpacity, TimeSpan.FromMilliseconds(400))); } } } - /// - /// 依照InteractiveVisual3D在列表中的序号来变换其位置等 - /// - /// 在列表中的序号 - /// 列表中被作为中间项的序号 - private void GetTransformOfInteractiveVisual3D(int index, double midIndex, out double angle, out double offsetX, out double offsetZ) + private static T FindVisualChild(DependencyObject obj) where T : DependencyObject { - double disToMidIndex = index - midIndex; - - - //旋转,两翼的图片各旋转一定的度数 - angle = 0; - if (disToMidIndex < 0) + for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) { - angle = this.ModelAngle;//左边的旋转N度 + var child = VisualTreeHelper.GetChild(obj, i); + if (child is T target) return target; + var result = FindVisualChild(child); + if (result != null) return result; } - else if (disToMidIndex > 0) - { - angle = (-this.ModelAngle);//右边的旋转-N度 - } - - - - //平移,两翼的图片逐渐向X轴负和正两个方向展开 - offsetX = 0;//中间的不平移 - if (Math.Abs(disToMidIndex) <= 1) - { - offsetX = disToMidIndex * this.MidModelDistance; - } - else if (disToMidIndex != 0) - { - offsetX = disToMidIndex * this.XDistanceBetweenModels + (disToMidIndex > 0 ? this.MidModelDistance : -this.MidModelDistance); - } - - - //两翼的图片逐渐向Z轴负方向移动一点,造成中间突出(离观众较近的效果) - offsetZ = Math.Abs(disToMidIndex) * -this.ZDistanceBetweenModels; - + return null; } + + public void SlideLeft() => SelectedIndex++; + public void SlideRight() => SelectedIndex--; } + } diff --git a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowItem.cs b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowItem.cs index 2668220..34cfac5 100644 --- a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowItem.cs +++ b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowItem.cs @@ -8,17 +8,27 @@ using System.Windows; namespace Wpf_AiSportsMicrospace.MyUserControl { - public class CoverFlowItem : DependencyObject + public class CoverFlowItem : INotifyPropertyChanged { + private bool _isSelected; + private double _progress; // 0~1 + public Uri ImageUri { get; set; } + public bool IsSelected + { + get => _isSelected; + set { _isSelected = value; OnPropertyChanged(nameof(IsSelected)); } + } + public double Progress { - get => (double)GetValue(ProgressProperty); - set => SetValue(ProgressProperty, value); + get => _progress; + set { _progress = value; OnPropertyChanged(nameof(Progress)); } } - public static readonly DependencyProperty ProgressProperty = - DependencyProperty.Register(nameof(Progress), typeof(double), typeof(CoverFlowItem), new PropertyMetadata(0.0)); + public event PropertyChangedEventHandler PropertyChanged; + protected void OnPropertyChanged(string name) => + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); } }