From 6834f1394299c29d45e3a649a3c46aa5d4dd4180 Mon Sep 17 00:00:00 2001 From: "johan.lachenal" Date: Fri, 2 Feb 2024 18:27:02 +0100 Subject: [PATCH] UPDATE(dev): body captor works with the architecture but the body is not disposed where you are --- Sources/Lib/BodyImageStream.cs | 171 +++++++++++++++++++++++ Sources/Lib/ColorAndBodyImageStream.cs | 156 ++++++++++----------- Sources/Lib/KinectStream.cs | 12 ++ Sources/Lib/KinectStreamsFactory.cs | 20 +-- Sources/Lib/Lib.csproj | 1 + Sources/WpfApp/Bone.cs | 55 ++++++++ Sources/WpfApp/Bones.cs | 17 +++ Sources/WpfApp/MainWindow.xaml.cs | 4 +- Sources/WpfApp/StreamTemplateSelector.cs | 2 +- Sources/WpfApp/WpfApp.csproj | 2 + 10 files changed, 347 insertions(+), 93 deletions(-) create mode 100644 Sources/Lib/BodyImageStream.cs create mode 100644 Sources/WpfApp/Bone.cs create mode 100644 Sources/WpfApp/Bones.cs diff --git a/Sources/Lib/BodyImageStream.cs b/Sources/Lib/BodyImageStream.cs new file mode 100644 index 0000000..bcebacb --- /dev/null +++ b/Sources/Lib/BodyImageStream.cs @@ -0,0 +1,171 @@ +using Microsoft.Kinect; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media.Imaging; +using System.Windows.Media; +using System.Windows; +using System.Windows.Shapes; +using Lib; +using System.Windows.Controls; + +namespace Lib +{ + public class BodyImageStream : KinectStream + { + private BodyFrameReader reader; + public BodyFrameReader Reader + { + get { return reader; } + set { reader = value; } + } + + private Body[] bodies; + public Body[] Bodies + { + get { return bodies; } + private set { bodies = value; } + } + public override void Stop() + { + if (Reader != null) + { + Reader.Dispose(); + Reader = null; + } + + } + + public BodyImageStream(KinectManager kinectmanager, Canvas skeletonCanvas) : base(kinectmanager) + { + var framedescription = kinectmanager.Sensor.ColorFrameSource.CreateFrameDescription(ColorImageFormat.Bgra); + Bitmap = new WriteableBitmap(framedescription.Width, framedescription.Height, 96.0, 96.0, PixelFormats.Bgr32, null); + reader = kinectmanager.Sensor.BodyFrameSource.OpenReader(); + reader.FrameArrived += Reader_BodyFrameArrived; + // initialiser le tableau des corps + this.bodies = new Body[kinectmanager.Sensor.BodyFrameSource.BodyCount]; + Canvas = skeletonCanvas; + } + + private void drawbone(Body body, JointType JointType0, JointType JointType1) + { + Joint joint0 = body.Joints[JointType0]; + Joint joint1 = body.Joints[JointType1]; + + // ne dessinez que si les deux joints sont suivis + if (joint0.TrackingState == TrackingState.Tracked && joint1.TrackingState == TrackingState.Tracked) + { + Line bone = new Line + { + Stroke = new SolidColorBrush(Colors.LightBlue), + StrokeThickness = 4, + X1 = MapJointToScreen(joint0).X, + Y1 = MapJointToScreen(joint0).Y, + X2 = MapJointToScreen(joint1).X, + Y2 = MapJointToScreen(joint1).Y + }; + + Canvas.Children.Add(bone); + } + } + + private Point MapJointToScreen(Joint joint) + { + ColorSpacePoint colorPoint = this.KinectManager.Sensor.CoordinateMapper.MapCameraPointToColorSpace(joint.Position); + + // Gestion des coordonnées infinies + float x = float.IsInfinity(colorPoint.X) ? 0 : colorPoint.X; + float y = float.IsInfinity(colorPoint.Y) ? 0 : colorPoint.Y; + + return new Point(x, y); + } + + private void drawskeleton(Body body) + { + // tête et cou + drawbone(body, JointType.Head, JointType.Neck); + drawbone(body, JointType.Neck, JointType.SpineShoulder); + + // torse + drawbone(body, JointType.SpineShoulder, JointType.SpineMid); + drawbone(body, JointType.SpineMid, JointType.SpineBase); + drawbone(body, JointType.SpineShoulder, JointType.ShoulderRight); + drawbone(body, JointType.SpineShoulder, JointType.ShoulderLeft); + drawbone(body, JointType.SpineBase, JointType.HipRight); + drawbone(body, JointType.SpineBase, JointType.HipLeft); + + // bras droit + drawbone(body, JointType.ShoulderRight, JointType.ElbowRight); + drawbone(body, JointType.ElbowRight, JointType.WristRight); + drawbone(body, JointType.WristRight, JointType.HandRight); + drawbone(body, JointType.HandRight, JointType.HandTipRight); + drawbone(body, JointType.WristRight, JointType.ThumbRight); + + // bras gauche + drawbone(body, JointType.ShoulderLeft, JointType.ElbowLeft); + drawbone(body, JointType.ElbowLeft, JointType.WristLeft); + drawbone(body, JointType.WristLeft, JointType.HandLeft); + drawbone(body, JointType.HandLeft, JointType.HandTipLeft); + drawbone(body, JointType.WristLeft, JointType.ThumbLeft); + + // jambe droite + drawbone(body, JointType.HipRight, JointType.KneeRight); + drawbone(body, JointType.KneeRight, JointType.AnkleRight); + drawbone(body, JointType.AnkleRight, JointType.FootRight); + + // jambe gauche + drawbone(body, JointType.HipLeft, JointType.KneeLeft); + drawbone(body, JointType.KneeLeft, JointType.AnkleLeft); + drawbone(body, JointType.AnkleLeft, JointType.FootLeft); + + // dessinez les joints + foreach (JointType JointType in body.Joints.Keys) + { + Joint joint = body.Joints[JointType]; + if (joint.TrackingState == TrackingState.Tracked) + { + DrawJoint(MapJointToScreen(joint)); + } + } + } + + private void DrawJoint(Point point) + { + Ellipse ellipse = new Ellipse + { + Width = 10, + Height = 10, + Fill = new SolidColorBrush(Colors.Red) + }; + + Canvas.SetLeft(ellipse, point.X - ellipse.Width / 2); + Canvas.SetTop(ellipse, point.Y - ellipse.Height / 2); + + Canvas.Children.Add(ellipse); + } + private void Reader_BodyFrameArrived(object sender, BodyFrameArrivedEventArgs e) + { + using (var bodyframe = e.FrameReference.AcquireFrame()) + { + if (bodyframe != null) + { + bodyframe.GetAndRefreshBodyData(this.bodies); + + Canvas.Children.Clear(); // nettoyer le Canvas avant de dessiner + + foreach (var body in this.bodies) + { + if (body.IsTracked) + { + // dessiner le squelette + drawskeleton(body); + } + } + } + } + } + } +} + diff --git a/Sources/Lib/ColorAndBodyImageStream.cs b/Sources/Lib/ColorAndBodyImageStream.cs index f52390b..9ea035f 100644 --- a/Sources/Lib/ColorAndBodyImageStream.cs +++ b/Sources/Lib/ColorAndBodyImageStream.cs @@ -4,12 +4,11 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows.Controls; using System.Windows.Media.Imaging; using System.Windows.Media; -using System.Windows; using System.Windows.Shapes; -using Lib; -using System.Windows.Controls; +using System.Windows; namespace Lib { @@ -22,6 +21,8 @@ namespace Lib set { reader = value; } } + //private ColorFrameReader colorReader; + private Body[] bodies; public Body[] Bodies { @@ -30,16 +31,12 @@ namespace Lib } public override void Stop() { - if (reader != null) + if (Reader != null) { - reader.Dispose(); - reader = null; + Reader.Dispose(); + Reader = null; } - } - private Canvas skeletonCanvas; - public Canvas SkeletonCanvas { - get { return skeletonCanvas; } - private set { skeletonCanvas = value; } + } public ColorAndBodyImageStream(KinectManager kinectmanager, Canvas skeletonCanvas) : base(kinectmanager) @@ -50,7 +47,7 @@ namespace Lib reader.FrameArrived += Reader_BodyFrameArrived; // initialiser le tableau des corps this.bodies = new Body[kinectmanager.Sensor.BodyFrameSource.BodyCount]; - SkeletonCanvas = skeletonCanvas; + Canvas = skeletonCanvas; } private void drawbone(Body body, JointType JointType0, JointType JointType1) @@ -71,7 +68,7 @@ namespace Lib Y2 = MapJointToScreen(joint1).Y }; - skeletonCanvas.Children.Add(bone); + Canvas.Children.Add(bone); } } @@ -87,89 +84,88 @@ namespace Lib } private void drawskeleton(Body body) + { + // tête et cou + drawbone(body, JointType.Head, JointType.Neck); + drawbone(body, JointType.Neck, JointType.SpineShoulder); + + // torse + drawbone(body, JointType.SpineShoulder, JointType.SpineMid); + drawbone(body, JointType.SpineMid, JointType.SpineBase); + drawbone(body, JointType.SpineShoulder, JointType.ShoulderRight); + drawbone(body, JointType.SpineShoulder, JointType.ShoulderLeft); + drawbone(body, JointType.SpineBase, JointType.HipRight); + drawbone(body, JointType.SpineBase, JointType.HipLeft); + + // bras droit + drawbone(body, JointType.ShoulderRight, JointType.ElbowRight); + drawbone(body, JointType.ElbowRight, JointType.WristRight); + drawbone(body, JointType.WristRight, JointType.HandRight); + drawbone(body, JointType.HandRight, JointType.HandTipRight); + drawbone(body, JointType.WristRight, JointType.ThumbRight); + + // bras gauche + drawbone(body, JointType.ShoulderLeft, JointType.ElbowLeft); + drawbone(body, JointType.ElbowLeft, JointType.WristLeft); + drawbone(body, JointType.WristLeft, JointType.HandLeft); + drawbone(body, JointType.HandLeft, JointType.HandTipLeft); + drawbone(body, JointType.WristLeft, JointType.ThumbLeft); + + // jambe droite + drawbone(body, JointType.HipRight, JointType.KneeRight); + drawbone(body, JointType.KneeRight, JointType.AnkleRight); + drawbone(body, JointType.AnkleRight, JointType.FootRight); + + // jambe gauche + drawbone(body, JointType.HipLeft, JointType.KneeLeft); + drawbone(body, JointType.KneeLeft, JointType.AnkleLeft); + drawbone(body, JointType.AnkleLeft, JointType.FootLeft); + + // dessinez les joints + foreach (JointType JointType in body.Joints.Keys) { - // tête et cou - drawbone(body, JointType.Head, JointType.Neck); - drawbone(body, JointType.Neck, JointType.SpineShoulder); - - // torse - drawbone(body, JointType.SpineShoulder, JointType.SpineMid); - drawbone(body, JointType.SpineMid, JointType.SpineBase); - drawbone(body, JointType.SpineShoulder, JointType.ShoulderRight); - drawbone(body, JointType.SpineShoulder, JointType.ShoulderLeft); - drawbone(body, JointType.SpineBase, JointType.HipRight); - drawbone(body, JointType.SpineBase, JointType.HipLeft); - - // bras droit - drawbone(body, JointType.ShoulderRight, JointType.ElbowRight); - drawbone(body, JointType.ElbowRight, JointType.WristRight); - drawbone(body, JointType.WristRight, JointType.HandRight); - drawbone(body, JointType.HandRight, JointType.HandTipRight); - drawbone(body, JointType.WristRight, JointType.ThumbRight); - - // bras gauche - drawbone(body, JointType.ShoulderLeft, JointType.ElbowLeft); - drawbone(body, JointType.ElbowLeft, JointType.WristLeft); - drawbone(body, JointType.WristLeft, JointType.HandLeft); - drawbone(body, JointType.HandLeft, JointType.HandTipLeft); - drawbone(body, JointType.WristLeft, JointType.ThumbLeft); - - // jambe droite - drawbone(body, JointType.HipRight, JointType.KneeRight); - drawbone(body, JointType.KneeRight, JointType.AnkleRight); - drawbone(body, JointType.AnkleRight, JointType.FootRight); - - // jambe gauche - drawbone(body, JointType.HipLeft, JointType.KneeLeft); - drawbone(body, JointType.KneeLeft, JointType.AnkleLeft); - drawbone(body, JointType.AnkleLeft, JointType.FootLeft); - - // dessinez les joints - foreach (JointType JointType in body.Joints.Keys) + Joint joint = body.Joints[JointType]; + if (joint.TrackingState == TrackingState.Tracked) { - Joint joint = body.Joints[JointType]; - if (joint.TrackingState == TrackingState.Tracked) - { - DrawJoint(MapJointToScreen(joint)); - } + DrawJoint(MapJointToScreen(joint)); } } + } - private void DrawJoint(Point point) + private void DrawJoint(Point point) + { + Ellipse ellipse = new Ellipse { - Ellipse ellipse = new Ellipse - { - Width = 10, - Height = 10, - Fill = new SolidColorBrush(Colors.Red) - }; + Width = 10, + Height = 10, + Fill = new SolidColorBrush(Colors.Red) + }; - Canvas.SetLeft(ellipse, point.X - ellipse.Width / 2); - Canvas.SetTop(ellipse, point.Y - ellipse.Height / 2); + Canvas.SetLeft(ellipse, point.X - ellipse.Width / 2); + Canvas.SetTop(ellipse, point.Y - ellipse.Height / 2); - skeletonCanvas.Children.Add(ellipse); - } - private void Reader_BodyFrameArrived(object sender, BodyFrameArrivedEventArgs e) + Canvas.Children.Add(ellipse); + } + private void Reader_BodyFrameArrived(object sender, BodyFrameArrivedEventArgs e) + { + using (var bodyframe = e.FrameReference.AcquireFrame()) { - using (var bodyframe = e.FrameReference.AcquireFrame()) + if (bodyframe != null) { - if (bodyframe != null) - { - bodyframe.GetAndRefreshBodyData(this.bodies); + bodyframe.GetAndRefreshBodyData(this.bodies); - SkeletonCanvas.Children.Clear(); // nettoyer le Canvas avant de dessiner + Canvas.Children.Clear(); // nettoyer le Canvas avant de dessiner - foreach (var body in this.bodies) + foreach (var body in this.bodies) + { + if (body.IsTracked) { - if (body.IsTracked) - { - // dessiner le squelette - drawskeleton(body); - } + // dessiner le squelette + drawskeleton(body); } } } } } + } } - diff --git a/Sources/Lib/KinectStream.cs b/Sources/Lib/KinectStream.cs index 29e5f66..0be4e5a 100644 --- a/Sources/Lib/KinectStream.cs +++ b/Sources/Lib/KinectStream.cs @@ -5,6 +5,7 @@ using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Imaging; @@ -26,6 +27,16 @@ namespace Lib } } } + private Canvas _canvas; + public Canvas Canvas + { + get { return _canvas; } + protected set + { + _canvas = value; + OnPropertyChanged(nameof(Canvas)); + } + } public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string propertyName) @@ -36,6 +47,7 @@ namespace Lib public KinectStream(KinectManager kinectManager) { KinectManager = kinectManager; + Canvas = null; if (kinectManager.Sensor == null) { KinectManager.StartSensor(); diff --git a/Sources/Lib/KinectStreamsFactory.cs b/Sources/Lib/KinectStreamsFactory.cs index f119338..ce211e9 100644 --- a/Sources/Lib/KinectStreamsFactory.cs +++ b/Sources/Lib/KinectStreamsFactory.cs @@ -15,33 +15,33 @@ namespace Lib private set { _kinectManager = value; } } - private Dictionary> _streamFactory; - public Dictionary> StreamFactory + private Dictionary> _streamFactory; + public Dictionary> StreamFactory { get { return _streamFactory; } private set { _streamFactory = value; } } - public KinectStreamsFactory(KinectManager kinect, Canvas skeletonCanvas = null) + public KinectStreamsFactory(KinectManager kinect,Canvas SkeletonCanvas) { _kinectManager = kinect; // Initialisation de la fabrique avec les fonctions de création pour chaque type de flux. - StreamFactory = new Dictionary> + StreamFactory = new Dictionary> { - { KinectStreams.Color, (canvas) => new ColorImageStream(KinectManager) }, - { KinectStreams.Depth, (canvas) => new DepthImageStream(KinectManager) }, - { KinectStreams.IR, (canvas) => new InfraredImageStream(KinectManager) }, - { KinectStreams.ColorAndBody, (canvas) => new ColorAndBodyImageStream(KinectManager,skeletonCanvas) } + { KinectStreams.Color, () => new ColorImageStream(KinectManager) }, + { KinectStreams.Depth, () => new DepthImageStream(KinectManager) }, + { KinectStreams.IR, () => new InfraredImageStream(KinectManager) }, + { KinectStreams.ColorAndBody, () => new BodyImageStream(KinectManager,SkeletonCanvas) } }; } - public KinectStream this[KinectStreams stream, Canvas skeletonCanvas = null] + public KinectStream this[KinectStreams stream] { get { if (StreamFactory.ContainsKey(stream)) { - return StreamFactory[stream](skeletonCanvas); + return StreamFactory[stream](); } else { diff --git a/Sources/Lib/Lib.csproj b/Sources/Lib/Lib.csproj index e7870f9..1898143 100644 --- a/Sources/Lib/Lib.csproj +++ b/Sources/Lib/Lib.csproj @@ -47,6 +47,7 @@ + diff --git a/Sources/WpfApp/Bone.cs b/Sources/WpfApp/Bone.cs new file mode 100644 index 0000000..4b9bf97 --- /dev/null +++ b/Sources/WpfApp/Bone.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media; + +namespace WpfApp +{ + public class Bone : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + private void OnPropertyChanged(string propName) + { + if(PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs(propName)); + } + } + + private double _top; + public double Top + { + get { return _top; } + set { + _top = value; + OnPropertyChanged(nameof(Top)); + } + } + public double Left + { + get; + set; + } + + public double Diameter + { + get + { + return _diameter; + } + set + { + _diameter = value; + OnPropertyChanged(nameof(Diameter)); + } + } + private double _diameter; + public SolidColorBrush ColorBrush { + get; + set; + } + } +} diff --git a/Sources/WpfApp/Bones.cs b/Sources/WpfApp/Bones.cs new file mode 100644 index 0000000..e56fc98 --- /dev/null +++ b/Sources/WpfApp/Bones.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WpfApp +{ + class Bones : Collection + { + public Bones() { + Add(new Bone { }); + } + + } +} diff --git a/Sources/WpfApp/MainWindow.xaml.cs b/Sources/WpfApp/MainWindow.xaml.cs index c736bb4..181a008 100644 --- a/Sources/WpfApp/MainWindow.xaml.cs +++ b/Sources/WpfApp/MainWindow.xaml.cs @@ -58,7 +58,7 @@ namespace WpfApp InitializeComponent(); this.DataContext = this; KinectManager = new KinectManager(); - Factory = new KinectStreamsFactory(KinectManager); + Factory = new KinectStreamsFactory(KinectManager, skeletonCanvas); CurrentKinectStream = Factory[KinectStreams.Color]; Debug.WriteLine(CurrentKinectStream.KinectManager.StatusText); CurrentKinectStream.Start(); @@ -100,7 +100,7 @@ namespace WpfApp private void ToColorAndBodyImageStream(object sender, RoutedEventArgs e) { CurrentKinectStream.Stop(); - CurrentKinectStream = Factory[KinectStreams.ColorAndBody,skeletonCanvas]; + CurrentKinectStream = Factory[KinectStreams.ColorAndBody]; Debug.WriteLine(CurrentKinectStream.GetType().Name); CurrentKinectStream.Start(); } diff --git a/Sources/WpfApp/StreamTemplateSelector.cs b/Sources/WpfApp/StreamTemplateSelector.cs index 1547213..c22b909 100644 --- a/Sources/WpfApp/StreamTemplateSelector.cs +++ b/Sources/WpfApp/StreamTemplateSelector.cs @@ -16,7 +16,7 @@ namespace WpfApp public override DataTemplate SelectTemplate(object item, DependencyObject container) { - if (item is ColorAndBodyImageStream) return ColorAndBodyImageStreamTemplate; + if (item is BodyImageStream) return ColorAndBodyImageStreamTemplate; else return OtherStreamTemplate; } } diff --git a/Sources/WpfApp/WpfApp.csproj b/Sources/WpfApp/WpfApp.csproj index 4400a9d..53ec170 100644 --- a/Sources/WpfApp/WpfApp.csproj +++ b/Sources/WpfApp/WpfApp.csproj @@ -58,6 +58,8 @@ MSBuild:Compile Designer + + MSBuild:Compile