📝 plus d'explications

bodyStream
Nicolas FRANCO 1 year ago
parent 22bdfb72ff
commit d26575451e

@ -101,11 +101,12 @@ namespace KinectConnection
public BodyImageStream() : base() public BodyImageStream() : base()
{ {
this.coordinateMapper = this.KinectSensor.CoordinateMapper; this.coordinateMapper = this.KinectSensor.CoordinateMapper;
frameDescription = this.KinectSensor.DepthFrameSource.FrameDescription; frameDescription = this.KinectSensor.DepthFrameSource.FrameDescription;
displayHeight = frameDescription.Height; displayHeight = frameDescription.Height;
displayWidth = frameDescription.Width; displayWidth = frameDescription.Width;
// Torso // Torse
this.bones.Add(new Tuple<JointType, JointType>(JointType.Head, JointType.Neck)); this.bones.Add(new Tuple<JointType, JointType>(JointType.Head, JointType.Neck));
this.bones.Add(new Tuple<JointType, JointType>(JointType.Neck, JointType.SpineShoulder)); this.bones.Add(new Tuple<JointType, JointType>(JointType.Neck, JointType.SpineShoulder));
this.bones.Add(new Tuple<JointType, JointType>(JointType.SpineShoulder, JointType.SpineMid)); this.bones.Add(new Tuple<JointType, JointType>(JointType.SpineShoulder, JointType.SpineMid));
@ -115,30 +116,31 @@ namespace KinectConnection
this.bones.Add(new Tuple<JointType, JointType>(JointType.SpineBase, JointType.HipRight)); this.bones.Add(new Tuple<JointType, JointType>(JointType.SpineBase, JointType.HipRight));
this.bones.Add(new Tuple<JointType, JointType>(JointType.SpineBase, JointType.HipLeft)); this.bones.Add(new Tuple<JointType, JointType>(JointType.SpineBase, JointType.HipLeft));
// Right Arm // Bras droit
this.bones.Add(new Tuple<JointType, JointType>(JointType.ShoulderRight, JointType.ElbowRight)); this.bones.Add(new Tuple<JointType, JointType>(JointType.ShoulderRight, JointType.ElbowRight));
this.bones.Add(new Tuple<JointType, JointType>(JointType.ElbowRight, JointType.WristRight)); this.bones.Add(new Tuple<JointType, JointType>(JointType.ElbowRight, JointType.WristRight));
this.bones.Add(new Tuple<JointType, JointType>(JointType.WristRight, JointType.HandRight)); this.bones.Add(new Tuple<JointType, JointType>(JointType.WristRight, JointType.HandRight));
this.bones.Add(new Tuple<JointType, JointType>(JointType.HandRight, JointType.HandTipRight)); this.bones.Add(new Tuple<JointType, JointType>(JointType.HandRight, JointType.HandTipRight));
this.bones.Add(new Tuple<JointType, JointType>(JointType.WristRight, JointType.ThumbRight)); this.bones.Add(new Tuple<JointType, JointType>(JointType.WristRight, JointType.ThumbRight));
// Left Arm // Bras gauche
this.bones.Add(new Tuple<JointType, JointType>(JointType.ShoulderLeft, JointType.ElbowLeft)); this.bones.Add(new Tuple<JointType, JointType>(JointType.ShoulderLeft, JointType.ElbowLeft));
this.bones.Add(new Tuple<JointType, JointType>(JointType.ElbowLeft, JointType.WristLeft)); this.bones.Add(new Tuple<JointType, JointType>(JointType.ElbowLeft, JointType.WristLeft));
this.bones.Add(new Tuple<JointType, JointType>(JointType.WristLeft, JointType.HandLeft)); this.bones.Add(new Tuple<JointType, JointType>(JointType.WristLeft, JointType.HandLeft));
this.bones.Add(new Tuple<JointType, JointType>(JointType.HandLeft, JointType.HandTipLeft)); this.bones.Add(new Tuple<JointType, JointType>(JointType.HandLeft, JointType.HandTipLeft));
this.bones.Add(new Tuple<JointType, JointType>(JointType.WristLeft, JointType.ThumbLeft)); this.bones.Add(new Tuple<JointType, JointType>(JointType.WristLeft, JointType.ThumbLeft));
// Right Leg // Jambe droite
this.bones.Add(new Tuple<JointType, JointType>(JointType.HipRight, JointType.KneeRight)); this.bones.Add(new Tuple<JointType, JointType>(JointType.HipRight, JointType.KneeRight));
this.bones.Add(new Tuple<JointType, JointType>(JointType.KneeRight, JointType.AnkleRight)); this.bones.Add(new Tuple<JointType, JointType>(JointType.KneeRight, JointType.AnkleRight));
this.bones.Add(new Tuple<JointType, JointType>(JointType.AnkleRight, JointType.FootRight)); this.bones.Add(new Tuple<JointType, JointType>(JointType.AnkleRight, JointType.FootRight));
// Left Leg // Jambe gauche
this.bones.Add(new Tuple<JointType, JointType>(JointType.HipLeft, JointType.KneeLeft)); this.bones.Add(new Tuple<JointType, JointType>(JointType.HipLeft, JointType.KneeLeft));
this.bones.Add(new Tuple<JointType, JointType>(JointType.KneeLeft, JointType.AnkleLeft)); this.bones.Add(new Tuple<JointType, JointType>(JointType.KneeLeft, JointType.AnkleLeft));
this.bones.Add(new Tuple<JointType, JointType>(JointType.AnkleLeft, JointType.FootLeft)); this.bones.Add(new Tuple<JointType, JointType>(JointType.AnkleLeft, JointType.FootLeft));
// Couleurs
this.bodyColors.Add(new Pen(Brushes.Red, 6)); this.bodyColors.Add(new Pen(Brushes.Red, 6));
this.bodyColors.Add(new Pen(Brushes.Orange, 6)); this.bodyColors.Add(new Pen(Brushes.Orange, 6));
this.bodyColors.Add(new Pen(Brushes.Green, 6)); this.bodyColors.Add(new Pen(Brushes.Green, 6));
@ -188,6 +190,7 @@ namespace KinectConnection
/// <param name="e">event arguments</param> /// <param name="e">event arguments</param>
private void Reader_BodyFrameArrived(object sender, BodyFrameArrivedEventArgs e) private void Reader_BodyFrameArrived(object sender, BodyFrameArrivedEventArgs e)
{ {
// flag pour savoir si la donnée est reçu ou pas
bool dataReceived = false; bool dataReceived = false;
using (BodyFrame bodyFrame = e.FrameReference.AcquireFrame()) using (BodyFrame bodyFrame = e.FrameReference.AcquireFrame())
@ -196,27 +199,32 @@ namespace KinectConnection
{ {
if (this.bodies == null) if (this.bodies == null)
{ {
// ajouter des corps en fonction du bodyCount
this.bodies = new Body[bodyFrame.BodyCount]; this.bodies = new Body[bodyFrame.BodyCount];
} }
// The first time GetAndRefreshBodyData is called, Kinect will allocate each Body in the array. // Une fois que GetAndRefreshBodyData est appele le Kinect va allouer chaque body dans le tableau
// As long as those body objects are not disposed and not set to null in the array, // Tant que le body est toujours dans le cadre il ne sera pas supprimé donc les body deja alloues
// those body objects will be re-used. // seront réutilisé
bodyFrame.GetAndRefreshBodyData(this.bodies); bodyFrame.GetAndRefreshBodyData(this.bodies);
// flag
dataReceived = true; dataReceived = true;
} }
} }
// Si on reçoit de la donnée, alors dessiner le body
if (dataReceived) if (dataReceived)
{ {
using (DrawingContext dc = this.drawingGroup.Open()) using (DrawingContext dc = this.drawingGroup.Open())
{ {
// Draw a transparent background to set the render size // Fond transparent
dc.DrawRectangle(Brushes.Black, null, new Rect(0.0, 0.0, displayWidth, displayHeight)); dc.DrawRectangle(Brushes.Black, null, new Rect(0.0, 0.0, displayWidth, displayHeight));
int penIndex = 0; int penIndex = 0;
foreach (Body body in this.bodies) foreach (Body body in this.bodies)
{ {
// pour avoir des couleurs differentes pour chaque body
Pen drawPen = this.bodyColors[penIndex++]; Pen drawPen = this.bodyColors[penIndex++];
if (body.IsTracked) if (body.IsTracked)
@ -230,8 +238,8 @@ namespace KinectConnection
foreach (JointType jointType in joints.Keys) foreach (JointType jointType in joints.Keys)
{ {
// sometimes the depth(Z) of an inferred joint may show as negative // parfois la profondeur Z peut venir negatif
// clamp down to 0.1f to prevent coordinatemapper from returning (-Infinity, -Infinity) // avec 0.1 on evite les coordonées negatives du coordinateMapper
CameraSpacePoint position = joints[jointType].Position; CameraSpacePoint position = joints[jointType].Position;
if (position.Z < 0) if (position.Z < 0)
{ {
@ -242,14 +250,16 @@ namespace KinectConnection
jointPoints[jointType] = new Point(depthSpacePoint.X, depthSpacePoint.Y); jointPoints[jointType] = new Point(depthSpacePoint.X, depthSpacePoint.Y);
} }
// dessiner les joints
this.DrawBody(joints, jointPoints, dc, drawPen); this.DrawBody(joints, jointPoints, dc, drawPen);
// dessiner les mains
this.DrawHand(body.HandLeftState, jointPoints[JointType.HandLeft], dc); this.DrawHand(body.HandLeftState, jointPoints[JointType.HandLeft], dc);
this.DrawHand(body.HandRightState, jointPoints[JointType.HandRight], dc); this.DrawHand(body.HandRightState, jointPoints[JointType.HandRight], dc);
} }
} }
// prevent drawing outside of our render area // empeche de dessiner hors du cadre
this.drawingGroup.ClipGeometry = new RectangleGeometry(new Rect(0.0, 0.0, displayWidth, displayHeight)); this.drawingGroup.ClipGeometry = new RectangleGeometry(new Rect(0.0, 0.0, displayWidth, displayHeight));
} }
} }
@ -260,13 +270,13 @@ namespace KinectConnection
/// </summary> /// </summary>
private void DrawBody(IReadOnlyDictionary<JointType, Joint> joints, IDictionary<JointType, Point> jointPoints, DrawingContext drawingContext, Pen drawingPen) private void DrawBody(IReadOnlyDictionary<JointType, Joint> joints, IDictionary<JointType, Point> jointPoints, DrawingContext drawingContext, Pen drawingPen)
{ {
// Draw the bones // Dessiner les os (lignes entre les joints)
foreach (var bone in this.bones) foreach (var bone in this.bones)
{ {
this.DrawBone(joints, jointPoints, bone.Item1, bone.Item2, drawingContext, drawingPen); this.DrawBone(joints, jointPoints, bone.Item1, bone.Item2, drawingContext, drawingPen);
} }
// Draw the joints // Dessiner les joints
foreach (JointType jointType in joints.Keys) foreach (JointType jointType in joints.Keys)
{ {
Brush drawBrush = null; Brush drawBrush = null;
@ -318,14 +328,13 @@ namespace KinectConnection
Joint joint0 = joints[jointType0]; Joint joint0 = joints[jointType0];
Joint joint1 = joints[jointType1]; Joint joint1 = joints[jointType1];
// If we can't find either of these joints, exit // Si ces joints n'existent pas, return (pas besoin de dessiner)
if (joint0.TrackingState == TrackingState.NotTracked || if (joint0.TrackingState == TrackingState.NotTracked ||
joint1.TrackingState == TrackingState.NotTracked) joint1.TrackingState == TrackingState.NotTracked)
{ {
return; return;
} }
// We assume all drawn bones are inferred unless BOTH joints are tracked
Pen drawPen = this.inferredBonePen; Pen drawPen = this.inferredBonePen;
if ((joint0.TrackingState == TrackingState.Tracked) && (joint1.TrackingState == TrackingState.Tracked)) if ((joint0.TrackingState == TrackingState.Tracked) && (joint1.TrackingState == TrackingState.Tracked))
{ {

@ -21,27 +21,22 @@ namespace KinectConnection
private const int MapDepthToByte = 8000 / 256; private const int MapDepthToByte = 8000 / 256;
/// <summary> /// <summary>
/// Active Kinect sensor /// Reader pour les données
/// </summary>
private KinectSensor kinectSensor = null;
/// <summary>
/// Reader for depth frames
/// </summary> /// </summary>
private DepthFrameReader depthFrameReader = null; private DepthFrameReader depthFrameReader = null;
/// <summary> /// <summary>
/// Description of the data contained in the depth frame /// Description du cadre (hauteur/largeur)
/// </summary> /// </summary>
private FrameDescription depthFrameDescription = null; private FrameDescription depthFrameDescription = null;
/// <summary> /// <summary>
/// Bitmap to display /// Le bitmap permettant d'afficher l'image
/// </summary> /// </summary>
private WriteableBitmap depthBitmap = null; private WriteableBitmap depthBitmap = null;
/// <summary> /// <summary>
/// Intermediate storage for frame data converted to color /// Stockage intermediare des données avant de convertir en couleurs
/// </summary> /// </summary>
private byte[] depthPixels = null; private byte[] depthPixels = null;
@ -155,17 +150,17 @@ namespace KinectConnection
/// <param name="maxDepth">La plus fiable valeur maximale pour la frame</param> /// <param name="maxDepth">La plus fiable valeur maximale pour la frame</param>
private unsafe void ProcessDepthFrameData(IntPtr depthFrameData, uint depthFrameDataSize, ushort minDepth, ushort maxDepth) private unsafe void ProcessDepthFrameData(IntPtr depthFrameData, uint depthFrameDataSize, ushort minDepth, ushort maxDepth)
{ {
// depth frame data is a 16 bit value // la donnée du dephtFrame est une valeur de 16 bits
ushort* frameData = (ushort*)depthFrameData; ushort* frameData = (ushort*)depthFrameData;
// convert depth to a visual representation // traduit la profondeur en une representation visuelle
for (int i = 0; i < (int)(depthFrameDataSize / this.depthFrameDescription.BytesPerPixel); ++i) for (int i = 0; i < (int)(depthFrameDataSize / this.depthFrameDescription.BytesPerPixel); ++i)
{ {
// Get the depth for this pixel // obtenir la profondeur d'un pixel
ushort depth = frameData[i]; ushort depth = frameData[i];
// To convert to a byte, we're mapping the depth value to the byte range. // Pour convertir en bytes on doit traduire la profondeur en bytes
// Values outside the reliable depth range are mapped to 0 (black). // Des valeurs qui n'est pas dans la portée valide on met 0
this.depthPixels[i] = (byte)(depth >= minDepth && depth <= maxDepth ? (depth / MapDepthToByte) : 0); this.depthPixels[i] = (byte)(depth >= minDepth && depth <= maxDepth ? (depth / MapDepthToByte) : 0);
} }
} }

@ -16,47 +16,47 @@ namespace KinectConnection
public class InfraredImageStream : KinectStream public class InfraredImageStream : KinectStream
{ {
/// <summary> /// <summary>
/// Maximum value (as a float) that can be returned by the InfraredFrame /// Valeur maximale (en tant que float) que peut renvoyer InfraredFrame.
/// </summary> /// </summary>
private const float InfraredSourceValueMaximum = (float)ushort.MaxValue; private const float InfraredSourceValueMaximum = (float)ushort.MaxValue;
/// <summary> /// <summary>
/// The value by which the infrared source data will be scaled /// La valeur par laquelle les données de la source infrarouge seront ajustées.
/// </summary> /// </summary>
private const float InfraredSourceScale = 0.75f; private const float InfraredSourceScale = 0.75f;
/// <summary> /// <summary>
/// Smallest value to display when the infrared data is normalized /// Plus petite valeur à afficher lorsque les données infrarouges sont normalisées.
/// </summary> /// </summary>
private const float InfraredOutputValueMinimum = 0.01f; private const float InfraredOutputValueMinimum = 0.01f;
/// <summary> /// <summary>
/// Largest value to display when the infrared data is normalized /// Plus grande valeur à afficher lorsque les données infrarouges sont normalisées.
/// </summary> /// </summary>
private const float InfraredOutputValueMaximum = 1.0f; private const float InfraredOutputValueMaximum = 1.0f;
/// <summary> /// <summary>
/// Active Kinect sensor /// Capteur Kinect actif.
/// </summary> /// </summary>
private KinectSensor kinectSensor = null; private KinectSensor kinectSensor = null;
/// <summary> /// <summary>
/// Reader for infrared frames /// Lecteur pour les images infrarouges.
/// </summary> /// </summary>
private InfraredFrameReader infraredFrameReader = null; private InfraredFrameReader infraredFrameReader = null;
/// <summary> /// <summary>
/// Description (width, height, etc) of the infrared frame data /// Description (largeur, hauteur, etc.) des données du cadre infrarouge.
/// </summary> /// </summary>
private FrameDescription infraredFrameDescription = null; private FrameDescription infraredFrameDescription = null;
/// <summary> /// <summary>
/// Bitmap to display /// Bitmap à afficher.
/// </summary> /// </summary>
private WriteableBitmap infraredBitmap = null; private WriteableBitmap infraredBitmap = null;
/// <summary> /// <summary>
/// Current status text to display /// Texte d'état actuel à afficher.
/// </summary> /// </summary>
private string statusText = null; private string statusText = null;
@ -76,10 +76,10 @@ namespace KinectConnection
/// </summary> /// </summary>
public InfraredImageStream() public InfraredImageStream()
{ {
// get FrameDescription from InfraredFrameSource // Obtient la description du cadre infrarouge à partir de InfraredFrameSource
this.infraredFrameDescription = this.KinectSensor.InfraredFrameSource.FrameDescription; this.infraredFrameDescription = this.KinectSensor.InfraredFrameSource.FrameDescription;
// create the bitmap to display // Crée la bitmap à afficher
this.infraredBitmap = new WriteableBitmap(this.infraredFrameDescription.Width, this.infraredFrameDescription.Height, 96.0, 96.0, PixelFormats.Gray32Float, null); this.infraredBitmap = new WriteableBitmap(this.infraredFrameDescription.Width, this.infraredFrameDescription.Height, 96.0, 96.0, PixelFormats.Gray32Float, null);
} }
@ -90,12 +90,12 @@ namespace KinectConnection
{ {
if (this.KinectSensor != null) if (this.KinectSensor != null)
{ {
// open the reader for the depth frames // Ouvre le lecteur pour les trames infrarouges
this.infraredFrameReader = this.KinectSensor.InfraredFrameSource.OpenReader(); this.infraredFrameReader = this.KinectSensor.InfraredFrameSource.OpenReader();
if (this.infraredFrameReader != null) if (this.infraredFrameReader != null)
{ {
// wire handler for frame arrival // Lie le gestionnaire pour l'arrivée de la trame
this.infraredFrameReader.FrameArrived += this.Reader_InfraredFrameArrived; this.infraredFrameReader.FrameArrived += this.Reader_InfraredFrameArrived;
} }
} }
@ -110,30 +110,30 @@ namespace KinectConnection
{ {
this.infraredFrameReader.FrameArrived -= this.Reader_InfraredFrameArrived; this.infraredFrameReader.FrameArrived -= this.Reader_InfraredFrameArrived;
// Dispose the reader to free resources. // Libère le lecteur pour libérer des ressources.
// If we don't dispose manualy, the gc will do it for us, but we don't know when. // Si nous ne le faisons pas manuellement, le GC le fera pour nous, mais nous ne savons pas quand.
this.infraredFrameReader.Dispose(); this.infraredFrameReader.Dispose();
this.infraredFrameReader = null; this.infraredFrameReader = null;
} }
} }
/// <summary> /// <summary>
/// Méthode appelée lors de l'arrivée d'un nouveau frame infrarouge. /// Méthode appelée lors de l'arrivée d'un nouveau cadre infrarouge.
/// </summary> /// </summary>
/// <param name="sender">object sending the event</param> /// <param name="sender">objet envoyant l'événement</param>
/// <param name="e">event arguments</param> /// <param name="e">arguments de l'événement</param>
private void Reader_InfraredFrameArrived(object sender, InfraredFrameArrivedEventArgs e) private void Reader_InfraredFrameArrived(object sender, InfraredFrameArrivedEventArgs e)
{ {
// InfraredFrame is IDisposable // InfraredFrame est IDisposable
using (InfraredFrame infraredFrame = e.FrameReference.AcquireFrame()) using (InfraredFrame infraredFrame = e.FrameReference.AcquireFrame())
{ {
if (infraredFrame != null) if (infraredFrame != null)
{ {
// the fastest way to process the infrared frame data is to directly access // La manière la plus rapide de traiter les données du cadre infrarouge est d'accéder directement
// the underlying buffer // au tampon sous-jacent
using (Microsoft.Kinect.KinectBuffer infraredBuffer = infraredFrame.LockImageBuffer()) using (Microsoft.Kinect.KinectBuffer infraredBuffer = infraredFrame.LockImageBuffer())
{ {
// verify data and write the new infrared frame data to the display bitmap // Vérifie les données et écrit les nouvelles données du cadre infrarouge sur la bitmap d'affichage
if (((this.infraredFrameDescription.Width * this.infraredFrameDescription.Height) == (infraredBuffer.Size / this.infraredFrameDescription.BytesPerPixel)) && if (((this.infraredFrameDescription.Width * this.infraredFrameDescription.Height) == (infraredBuffer.Size / this.infraredFrameDescription.BytesPerPixel)) &&
(this.infraredFrameDescription.Width == this.infraredBitmap.PixelWidth) && (this.infraredFrameDescription.Height == this.infraredBitmap.PixelHeight)) (this.infraredFrameDescription.Width == this.infraredBitmap.PixelWidth) && (this.infraredFrameDescription.Height == this.infraredBitmap.PixelHeight))
{ {
@ -150,31 +150,31 @@ namespace KinectConnection
/// Cette fonction nécessite l'option /unsafe du compilateur car nous utilisons un accès direct /// Cette fonction nécessite l'option /unsafe du compilateur car nous utilisons un accès direct
/// à la mémoire native pointée par le pointeur infraredFrameData. /// à la mémoire native pointée par le pointeur infraredFrameData.
/// </summary> /// </summary>
/// <param name="infraredFrameData">Pointeur vers les données d'image InfraredFrame</param> /// <param name="infraredFrameData">Pointeur vers les données du cadre infrarouge</param>
/// <param name="infraredFrameDataSize">Taille des données d'image InfraredFrame</param> /// <param name="infraredFrameDataSize">Taille des données du cadre infrarouge</param>
private unsafe void ProcessInfraredFrameData(IntPtr infraredFrameData, uint infraredFrameDataSize) private unsafe void ProcessInfraredFrameData(IntPtr infraredFrameData, uint infraredFrameDataSize)
{ {
// infrared frame data is a 16 bit value // Les données du cadre infrarouge sont une valeur de 16 bits
ushort* frameData = (ushort*)infraredFrameData; ushort* frameData = (ushort*)infraredFrameData;
// lock the target bitmap // Verrouille la bitmap cible
this.infraredBitmap.Lock(); this.infraredBitmap.Lock();
// get the pointer to the bitmap's back buffer // Obtient le pointeur vers le tampon arrière de la bitmap
float* backBuffer = (float*)this.infraredBitmap.BackBuffer; float* backBuffer = (float*)this.infraredBitmap.BackBuffer;
// process the infrared data // Traite les données infrarouges
for (int i = 0; i < (int)(infraredFrameDataSize / this.infraredFrameDescription.BytesPerPixel); ++i) for (int i = 0; i < (int)(infraredFrameDataSize / this.infraredFrameDescription.BytesPerPixel); ++i)
{ {
// since we are displaying the image as a normalized grey scale image, we need to convert from // Comme nous affichons l'image en niveaux de gris normalisés, nous devons convertir de
// the ushort data (as provided by the InfraredFrame) to a value from [InfraredOutputValueMinimum, InfraredOutputValueMaximum] // la donnée ushort (fournie par InfraredFrame) à une valeur de [InfraredOutputValueMinimum, InfraredOutputValueMaximum]
backBuffer[i] = Math.Min(InfraredOutputValueMaximum, (((float)frameData[i] / InfraredSourceValueMaximum * InfraredSourceScale) * (1.0f - InfraredOutputValueMinimum)) + InfraredOutputValueMinimum); backBuffer[i] = Math.Min(InfraredOutputValueMaximum, (((float)frameData[i] / InfraredSourceValueMaximum * InfraredSourceScale) * (1.0f - InfraredOutputValueMinimum)) + InfraredOutputValueMinimum);
} }
// mark the entire bitmap as needing to be drawn // Marque toute la bitmap comme nécessitant un redessin
this.infraredBitmap.AddDirtyRect(new Int32Rect(0, 0, this.infraredBitmap.PixelWidth, this.infraredBitmap.PixelHeight)); this.infraredBitmap.AddDirtyRect(new Int32Rect(0, 0, this.infraredBitmap.PixelWidth, this.infraredBitmap.PixelHeight));
// unlock the bitmap // Déverrouille la bitmap
this.infraredBitmap.Unlock(); this.infraredBitmap.Unlock();
} }
} }

Loading…
Cancel
Save