From e32b820538d095139359687c7e2a9fce65c69eda Mon Sep 17 00:00:00 2001 From: "johan.lachenal" Date: Thu, 25 Jan 2024 17:48:29 +0100 Subject: [PATCH 1/3] Create(kinectStreams): Add StatusText to binding, every streams works but the change of stream doesn't yet --- Sources/Lib/ColorAndBodyImageStream.cs | 96 +++++++++ Sources/Lib/ColorImageStream.cs | 12 +- Sources/Lib/DepthImageStream.cs | 91 ++++++++ Sources/Lib/InfraredImageStream.cs | 125 +++++++++++ Sources/Lib/KinectManager.cs | 68 ++++-- Sources/Lib/KinectStream.cs | 8 +- Sources/Lib/KinectStreams.cs | 16 ++ Sources/Lib/KinectStreamsFactory.cs | 42 +++- Sources/Lib/Lib.csproj | 5 + Sources/WpfApp/MainWindow.xaml | 10 +- Sources/WpfApp/MainWindow.xaml.cs | 279 ++++--------------------- 11 files changed, 476 insertions(+), 276 deletions(-) create mode 100644 Sources/Lib/ColorAndBodyImageStream.cs create mode 100644 Sources/Lib/DepthImageStream.cs create mode 100644 Sources/Lib/InfraredImageStream.cs create mode 100644 Sources/Lib/KinectStreams.cs diff --git a/Sources/Lib/ColorAndBodyImageStream.cs b/Sources/Lib/ColorAndBodyImageStream.cs new file mode 100644 index 0000000..1526442 --- /dev/null +++ b/Sources/Lib/ColorAndBodyImageStream.cs @@ -0,0 +1,96 @@ +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; + +//namespace Lib +//{ +// class ColorAndBodyImageStream : 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 ColorAndBodyImageStream() : base() +// { +// var frameDescription = KinectManager.Sensor.ColorFrameSource.CreateFrameDescription(ColorImageFormat.Bgra); +// this.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]; +// } + +// private void DrawSkeleton(Body body) +// { +// foreach (JointType jointType in body.Joints.Keys) +// { +// Joint joint = body.Joints[jointType]; +// if (joint.TrackingState == TrackingState.Tracked) +// { +// // Convertir les coordonnées du joint en coordonnées de l'écran +// Point point = new Point(); +// ColorSpacePoint colorPoint = KinectManager.Sensor.CoordinateMapper.MapCameraPointToColorSpace(joint.Position); +// point.X = float.IsInfinity(colorPoint.X) ? 0 : colorPoint.X; +// point.Y = float.IsInfinity(colorPoint.Y) ? 0 : colorPoint.Y; + +// // Dessiner le joint +// DrawJoint(point); +// } +// } + +// // Dessinez les os ici si nécessaire +// } + +// 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); + +// skeletonCanvas.Children.Add(ellipse); +// } +// private void Reader_BodyFrameArrived(object sender, BodyFrameArrivedEventArgs e) +// { +// using (var bodyFrame = e.FrameReference.AcquireFrame()) +// { +// if (bodyFrame != null) +// { +// bodyFrame.GetAndRefreshBodyData(this.bodies); + +// skeletonCanvas.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/ColorImageStream.cs b/Sources/Lib/ColorImageStream.cs index 8bdd2a2..4de3e46 100644 --- a/Sources/Lib/ColorImageStream.cs +++ b/Sources/Lib/ColorImageStream.cs @@ -18,7 +18,7 @@ namespace Lib reader = value; } } - public ColorImageStream() : base() + public ColorImageStream(KinectManager kinectManager) : base(kinectManager) { var frameDescription = KinectManager.Sensor.ColorFrameSource.CreateFrameDescription(ColorImageFormat.Bgra); this.Bitmap = new WriteableBitmap(frameDescription.Width, frameDescription.Height, 96.0, 96.0, PixelFormats.Bgr32, null); @@ -26,6 +26,16 @@ namespace Lib reader.FrameArrived += Reader_FrameArrived; } + public override void Stop() + { + if (reader != null) + { + reader.Dispose(); + reader = null; + } + base.Stop(); + } + private void Reader_FrameArrived(object sender, ColorFrameArrivedEventArgs e) { using (var colorFrame = e.FrameReference.AcquireFrame()) diff --git a/Sources/Lib/DepthImageStream.cs b/Sources/Lib/DepthImageStream.cs new file mode 100644 index 0000000..fde4b21 --- /dev/null +++ b/Sources/Lib/DepthImageStream.cs @@ -0,0 +1,91 @@ +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; + +namespace Lib +{ + class DepthImageStream : KinectStream + { + private DepthFrameReader reader; + public DepthFrameReader Reader + { + get + { + return reader; + } + set + { + reader = value; + } + } + private byte[] depthPixels; + public byte[] DepthPixels { + get { + return depthPixels; + } + set + { + depthPixels = value; + } + } + public DepthImageStream(KinectManager kinectManager) : base(kinectManager) + { + var frameDescription = KinectManager.Sensor.DepthFrameSource.FrameDescription; + this.Bitmap = new WriteableBitmap(frameDescription.Width, frameDescription.Height, 96.0, 96.0, PixelFormats.Gray8, null); + reader = KinectManager.Sensor.DepthFrameSource.OpenReader(); + reader.FrameArrived += Reader_DepthFrameArrived; + DepthPixels = new byte[frameDescription.Width * frameDescription.Height]; + } + private void Reader_DepthFrameArrived(object sender, DepthFrameArrivedEventArgs e) + { + using (DepthFrame depthFrame = e.FrameReference.AcquireFrame()) + { + if (depthFrame != null) + { + FrameDescription depthFrameDescription = depthFrame.FrameDescription; + + // Créez un tableau pour stocker les données de profondeur + ushort[] depthData = new ushort[depthFrameDescription.LengthInPixels]; + depthFrame.CopyFrameDataToArray(depthData); + + // Traitez les données de profondeur + ProcessDepthFrameData(depthData, depthFrameDescription.LengthInPixels, depthFrame.DepthMinReliableDistance, depthFrame.DepthMaxReliableDistance); + + // Mettez à jour le bitmap de profondeur + this.Bitmap.WritePixels( + new Int32Rect(0, 0, depthFrameDescription.Width, depthFrameDescription.Height), + this.depthPixels, + depthFrameDescription.Width, + 0); + } + } + } + + public override void Stop() + { + if (reader != null) + { + reader.Dispose(); + reader = null; + } + base.Stop(); + } + + private void ProcessDepthFrameData(ushort[] depthData, uint depthFrameDataSize, ushort minDepth, ushort maxDepth) + { + // Convertir les données de profondeur en niveaux de gris + for (int i = 0; i < depthFrameDataSize; ++i) + { + ushort depth = depthData[i]; + DepthPixels[i] = (byte)(depth >= minDepth && depth <= maxDepth ? (depth % 256) : 0); + } + } + + } +} diff --git a/Sources/Lib/InfraredImageStream.cs b/Sources/Lib/InfraredImageStream.cs new file mode 100644 index 0000000..51af0eb --- /dev/null +++ b/Sources/Lib/InfraredImageStream.cs @@ -0,0 +1,125 @@ +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; + +namespace Lib +{ + class InfraredImageStream : KinectStream + { + private InfraredFrameReader reader; + private byte[] infraredPixels; + public byte[] InfraredPixels + { + get + { + return infraredPixels; + } + private set + { + infraredPixels = value; + } + } + public InfraredFrameReader Reader + { + get + { + return reader; + } + private set + { + reader = value; + } + } + public InfraredImageStream(KinectManager kinectManager) : base(kinectManager) + { + var frameDescription = KinectManager.Sensor.InfraredFrameSource.FrameDescription; + this.Bitmap = new WriteableBitmap(frameDescription.Width, frameDescription.Height, 96.0, 96.0, PixelFormats.Gray8, null); + reader = KinectManager.Sensor.InfraredFrameSource.OpenReader(); + reader.FrameArrived += Reader_InfraredFrameArrived; + infraredPixels = new byte[frameDescription.Width * frameDescription.Height]; + } + + public override void Stop() + { + if (reader != null) + { + reader.Dispose(); + reader = null; + } + base.Stop(); + } + + private void Reader_FrameArrived(object sender, ColorFrameArrivedEventArgs e) + { + using (var colorFrame = e.FrameReference.AcquireFrame()) + { + if (colorFrame != null) + { + // ... Logique existante pour traiter la frame + //Debug.WriteLine("Traitement de la frame de couleur."); + FrameDescription infraredFrameDescription = colorFrame.FrameDescription; + + using (KinectBuffer colorBuffer = colorFrame.LockRawImageBuffer()) + { + this.Bitmap.Lock(); + + // Vérifier si la taille de l'image a changé + if ((infraredFrameDescription.Width == this.Bitmap.PixelWidth) && (infraredFrameDescription.Height == this.Bitmap.PixelHeight)) + { + colorFrame.CopyConvertedFrameDataToIntPtr( + this.Bitmap.BackBuffer, + (uint)(infraredFrameDescription.Width * infraredFrameDescription.Height * 4), + ColorImageFormat.Bgra); + + this.Bitmap.AddDirtyRect(new Int32Rect(0, 0, this.Bitmap.PixelWidth, this.Bitmap.PixelHeight)); + } + + this.Bitmap.Unlock(); + } + //Debug.WriteLine("Frame de couleur traitée."); + } + } + } + private void ProcessInfraredFrameData(ushort[] frameData, uint frameDataSize) + { + // Convertir les données infrarouges en niveaux de gris + for (int i = 0; i < frameDataSize; ++i) + { + // Convertir la valeur infrarouge en une intensité lumineuse + byte intensity = (byte)(frameData[i] >> 8); + InfraredPixels[i] = intensity; + } + } + + private void Reader_InfraredFrameArrived(object sender, InfraredFrameArrivedEventArgs e) + { + using (InfraredFrame infraredFrame = e.FrameReference.AcquireFrame()) + { + if (infraredFrame != null) + { + FrameDescription infraredFrameDescription = infraredFrame.FrameDescription; + + // Créez un tableau pour stocker les données infrarouges + ushort[] infraredData = new ushort[infraredFrameDescription.LengthInPixels]; + infraredFrame.CopyFrameDataToArray(infraredData); + + // Traitez les données infrarouges + ProcessInfraredFrameData(infraredData, infraredFrameDescription.LengthInPixels); + + // Mettez à jour le bitmap infrarouge + this.Bitmap.WritePixels( + new Int32Rect(0, 0, infraredFrameDescription.Width, infraredFrameDescription.Height), + this.infraredPixels, + infraredFrameDescription.Width, + 0); + } + } + } + } +} diff --git a/Sources/Lib/KinectManager.cs b/Sources/Lib/KinectManager.cs index bf9ce2b..3486974 100644 --- a/Sources/Lib/KinectManager.cs +++ b/Sources/Lib/KinectManager.cs @@ -27,49 +27,77 @@ namespace Lib public KinectManager() { sensor = KinectSensor.GetDefault(); + if (Sensor == null) + { + StatusText = "Kinect n'est pas connecté"; + } + else if (!Sensor.IsOpen) + { + StatusText = "Kinect n'est pas ouvert"; + } + else if (Sensor.IsAvailable) + { + StatusText = "Kinect est disponible"; + } + else + { + StatusText = "Kinect n'est pas disponible"; + } } public void StartSensor() { if (sensor != null) { sensor.Open(); } + else { + sensor = KinectSensor.GetDefault(); + sensor.Open(); + } } public void StopSensor() { if (sensor != null) { sensor.Close(); + sensor = null; } } public bool Status { get { return Sensor != null && Sensor.IsAvailable; } } + private string _statusText; public string StatusText { - get - { - if (Sensor == null) + get { return _statusText; } + set { + _statusText = value; + if(this.PropertyChanged != null) { - return "Kinect n'est pas connecté"; - } - else if (!Sensor.IsOpen) - { - return "Kinect n'est pas ouvert"; - } - else if (Sensor.IsAvailable) - { - return "Kinect est disponible"; - } - else - { - return "Kinect n'est pas disponible"; + this.PropertyChanged(this, new PropertyChangedEventArgs("StatusText")); } } } + private void KinectSensor_IsAvailableChanged(object sender, IsAvailableChangedEventArgs args) - { - // Vous pouvez ajouter ici une logique supplémentaire si nécessaire + { + if (Sensor == null) + { + StatusText = "Kinect n'est pas connecté"; + } + else if (!Sensor.IsOpen) + { + StatusText = "Kinect n'est pas ouvert"; + } + else if (Sensor.IsAvailable) + { + StatusText = "Kinect est disponible"; + } + else + { + StatusText = "Kinect n'est pas disponible"; + } + + } + } } - } -} diff --git a/Sources/Lib/KinectStream.cs b/Sources/Lib/KinectStream.cs index 61d2fdf..0240c81 100644 --- a/Sources/Lib/KinectStream.cs +++ b/Sources/Lib/KinectStream.cs @@ -33,9 +33,13 @@ namespace Lib PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } - public KinectStream() + public KinectStream(KinectManager kinectManager) { - KinectManager = new KinectManager(); + KinectManager = kinectManager; + if (kinectManager.Sensor == null) + { + KinectManager.StartSensor(); + } } public virtual void Start() diff --git a/Sources/Lib/KinectStreams.cs b/Sources/Lib/KinectStreams.cs new file mode 100644 index 0000000..43c3b97 --- /dev/null +++ b/Sources/Lib/KinectStreams.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Lib +{ + public enum KinectStreams + { + None, + Color, + Depth, + IR + } +} diff --git a/Sources/Lib/KinectStreamsFactory.cs b/Sources/Lib/KinectStreamsFactory.cs index 63c55d7..7ac4345 100644 --- a/Sources/Lib/KinectStreamsFactory.cs +++ b/Sources/Lib/KinectStreamsFactory.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; @@ -9,9 +8,44 @@ namespace Lib { public class KinectStreamsFactory { - private Dictionary> streamFactory; - public KinectStreamsFactory() { - + private KinectManager _kinectManager; + public KinectManager KinectManager { + get { return _kinectManager; } + private set { _kinectManager = value; } + } + + private Dictionary> _streamFactory; + public Dictionary> StreamFactory + { + get { return _streamFactory; } + private set { _streamFactory = value; } + } + + public KinectStreamsFactory(KinectManager kinect) + { + _kinectManager = kinect; + // Initialisation de la fabrique avec les fonctions de création pour chaque type de flux. + StreamFactory = new Dictionary> + { + { KinectStreams.Color, () => new ColorImageStream(KinectManager) }, + { KinectStreams.Depth, () => new DepthImageStream(KinectManager) }, + { KinectStreams.IR, () => new InfraredImageStream(KinectManager) } + }; + } + + public KinectStream this[KinectStreams stream] + { + get + { + if (StreamFactory.ContainsKey(stream)) + { + return StreamFactory[stream](); + } + else + { + throw new ArgumentException("Invalid stream type."); + } + } } } } diff --git a/Sources/Lib/Lib.csproj b/Sources/Lib/Lib.csproj index dd258d7..5be8933 100644 --- a/Sources/Lib/Lib.csproj +++ b/Sources/Lib/Lib.csproj @@ -46,9 +46,14 @@ + + + + + diff --git a/Sources/WpfApp/MainWindow.xaml b/Sources/WpfApp/MainWindow.xaml index d2f7fdc..df5ebf5 100644 --- a/Sources/WpfApp/MainWindow.xaml +++ b/Sources/WpfApp/MainWindow.xaml @@ -15,18 +15,18 @@ - + -