Well, I'm trying to program in C #, I'm a newbie and using the Microsoft bodybasics code, with the latest version of Kinect and visual studio 2013. I'm trying to save all the coordinates in an array of the 25 joints that the Kinect camera, but I can not think of how to do it since they are 3 xyz coordinates. The idea is that they are constantly stored so that they can then see how they change and interpret that a movement has been made. Anyone have any ideas or could you give me a cable please.
This is my code:
public partial class MainWindow : Window, INotifyPropertyChanged
{
/// <summary>
/// Radius of drawn hand circles: Radio de círculos de mano dibujados
/// </summary>
private const double HandSize = 30;
/// <summary>
/// Thickness of drawn joint lines: Espesor de las líneas de tracción
/// </summary>
private const double JointThickness = 4;
/// <summary>
/// Thickness of clip edge rectangles:Espesor de los rectángulos del borde del clip
/// </summary>
private const double ClipBoundsThickness = 10;
/// <summary>
/// Constant for clamping Z values of camera space points from being negative:Constante para fijar los valores Z de los puntos de espacio de cámara de ser negativo
/// </summary>
private const float InferredZPositionClamp = 0.1f;
/// <summary>
/// Brush used for drawing hands that are currently tracked as closed: Pincel utilizado para dibujar manos que actualmente se siguen como cerradas
/// </summary>
private readonly Brush handClosedBrush = new SolidColorBrush(Color.FromArgb(128, 255, 0, 0));
/// <summary>
/// Brush used for drawing hands that are currently tracked as opened: Pincel utilizado para dibujar manos que actualmente se siguen como abiertas
/// </summary>
private readonly Brush handOpenBrush = new SolidColorBrush(Color.FromArgb(128, 0, 255, 0));
/// <summary>
/// Brush used for drawing hands that are currently tracked as in lasso (pointer) position:Pincel utilizado para dibujar las manos que se rastrean actualmente como en la posición del lazo (puntero)
/// </summary>
private readonly Brush handLassoBrush = new SolidColorBrush(Color.FromArgb(128, 0, 0, 255));
/// <summary>
/// Brush used for drawing joints that are currently tracked: Cepillo utilizado para el dibujo de las articulaciones que se siguen actualmente
/// </summary>
private readonly Brush trackedJointBrush = new SolidColorBrush(Color.FromArgb(255, 68, 192, 68));
/// <summary>
/// Brush used for drawing joints that are currently inferred:Pincel utilizado para el dibujo de las articulaciones que actualmente se infiere
/// </summary>
private readonly Brush inferredJointBrush = Brushes.Yellow;
/// <summary>
/// Pen used for drawing bones that are currently inferred
/// </summary>
private readonly Pen inferredBonePen = new Pen(Brushes.Gray, 1);
/// <summary>
/// Drawing group for body rendering output: Grupo de dibujo para la salida de la representación corporal
/// </summary>
private DrawingGroup drawingGroup;
/// <summary>
/// Drawing image that we will display
/// </summary>
private DrawingImage imageSource;
/// <summary>
/// Active Kinect sensor
/// </summary>
private KinectSensor kinectSensor = null;
/// <summary>
/// Coordinate mapper to map one type of point to another: Mapeador de coordenadas para asignar un tipo de punto a otro
/// </summary>
private CoordinateMapper coordinateMapper = null;
/// <summary>
/// Reader for body frames
/// </summary>
private BodyFrameReader bodyFrameReader = null;
/// <summary>
/// Array for the bodies: Array para los cuerpos
/// </summary>
private Body[] bodies = null;
/// <summary>
/// definition of bones
/// </summary>
private List<Tuple<JointType, JointType>> bones;
//Dani
// public List<>
//Declaracion de una matriz bidimensional
public float [,] MatrizCoordBodyGlobales= new float[2,2];
//float[][,][,] ArraydeMatrices;
//Array rectangular dentro de otro array
public float[][,] ArraydeMatrices = new float[10][,];
public int i =0;
public int j = 0;
// Me da error este tipo de arrays, MIRAR ESTA PARTE, TENEMOS QUE CONSEGUIR METER LA MATRIZ EN UN HUECO DE UN ARRAY
/// <summary>
/// Width of display (depth space)
/// </summary>
private int displayWidth;
/// <summary>
/// Height of display (depth space)
/// </summary>
private int displayHeight;
/// <summary>
/// List of colors for each body tracked
/// </summary>
private List<Pen> bodyColors;
/// <summary>
/// Current status text to display
/// </summary>
private string statusText = null;
//Hecho por Dani
//private WriteableBitmap colorBitmap = null;
// private ColorFrameReader colorFrameReader = null;
/// <summary>
/// Initializes a new instance of the MainWindow class.
/// </summary>
public MainWindow()
{
// one sensor is currently supported
this.kinectSensor = KinectSensor.GetDefault();
// get the coordinate mapper
this.coordinateMapper = this.kinectSensor.CoordinateMapper;
// get the depth (display) extents
//Dani
FrameDescription frameDescription = this.kinectSensor.DepthFrameSource.FrameDescription;
// get size of joint space : Obtener el tamaño del espacio de articulación
this.displayWidth = frameDescription.Width;
this.displayHeight = frameDescription.Height;
// open the reader for the body frames : Abra el lector para los marcos del cuerpo
this.bodyFrameReader = this.kinectSensor.BodyFrameSource.OpenReader();
// a bone defined as a line between two joints: Un hueso definido como una línea entre dos
this.bones = new List<Tuple<JointType, JointType>>();
// Torso : Añade las distintas lineas de union entre dos partes de una zona concreta del cuerpo, se trata de dibujar el Esqueleto del cuerpo
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.SpineShoulder, JointType.SpineMid));
this.bones.Add(new Tuple<JointType, JointType>(JointType.SpineMid, JointType.SpineBase));
this.bones.Add(new Tuple<JointType, JointType>(JointType.SpineShoulder, JointType.ShoulderRight));
this.bones.Add(new Tuple<JointType, JointType>(JointType.SpineShoulder, JointType.ShoulderLeft));
this.bones.Add(new Tuple<JointType, JointType>(JointType.SpineBase, JointType.HipRight));
this.bones.Add(new Tuple<JointType, JointType>(JointType.SpineBase, JointType.HipLeft));
// Right Arm
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.WristRight, JointType.HandRight));
this.bones.Add(new Tuple<JointType, JointType>(JointType.HandRight, JointType.HandTipRight));
this.bones.Add(new Tuple<JointType, JointType>(JointType.WristRight, JointType.ThumbRight));
// Left Arm
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.WristLeft, JointType.HandLeft));
this.bones.Add(new Tuple<JointType, JointType>(JointType.HandLeft, JointType.HandTipLeft));
this.bones.Add(new Tuple<JointType, JointType>(JointType.WristLeft, JointType.ThumbLeft));
// Right Leg
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.AnkleRight, JointType.FootRight));
// Left Leg
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.AnkleLeft, JointType.FootLeft));
// populate body colors, one for each BodyIndex
this.bodyColors = new List<Pen>();
this.bodyColors.Add(new Pen(Brushes.Red, 6));
this.bodyColors.Add(new Pen(Brushes.Orange, 6));
this.bodyColors.Add(new Pen(Brushes.Green, 6));
this.bodyColors.Add(new Pen(Brushes.Blue, 6));
this.bodyColors.Add(new Pen(Brushes.Indigo, 6));
this.bodyColors.Add(new Pen(Brushes.Violet, 6));
// set IsAvailableChanged event notifier: En caso de algun cambio, refrescar los datos de marco
this.kinectSensor.IsAvailableChanged += this.Sensor_IsAvailableChanged;
// open the sensor
this.kinectSensor.Open();
// set the status text
this.StatusText = this.kinectSensor.IsAvailable ? Properties.Resources.RunningStatusText
: Properties.Resources.NoSensorStatusText;
// Create the drawing group we'll use for drawing : Crear un grupo de dibujo
this.drawingGroup = new DrawingGroup();
// Create an image source that we can use in our image control :Crear una fuente de imagen que podamos usar en nuestro control de imagen
this.imageSource = new DrawingImage(this.drawingGroup);
// use the window object as the view model in this simple example
this.DataContext = this;
// initialize the components (controls) of the window
this.InitializeComponent();
}
/// <summary>
/// INotifyPropertyChangedPropertyChanged event to allow window controls to bind to changeable data: Evento para permitir que los controles de ventana se enlacen a datos cambiables
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Gets the bitmap to display
/// </summary>
public ImageSource ImageSource
{
get
{
return this.imageSource;
}
}
/// <summary>
/// Gets or sets the current status text to display
/// </summary>
public string StatusText
{
get
{
return this.statusText;
}
set
{
if (this.statusText != value)
{
this.statusText = value;
// notify any bound elements that the text has changed
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs("StatusText"));
}
}
}
}
/// <summary>
/// Execute start up tasks :Ejecutar tareas de inicio
/// </summary>
/// <param name="sender">object sending the event</param>
/// <param name="e">event arguments</param>
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
if (this.bodyFrameReader != null)
{
this.bodyFrameReader.FrameArrived += this.Reader_FrameArrived;
}
}
/// <summary>
/// Execute shutdown tasks
/// </summary>
/// <param name="sender">object sending the event</param>
/// <param name="e">event arguments</param>
private void MainWindow_Closing(object sender, CancelEventArgs e)
{
if (this.bodyFrameReader != null)
{
// BodyFrameReader is IDisposable
this.bodyFrameReader.Dispose();
this.bodyFrameReader = null;
}
if (this.kinectSensor != null)
{
this.kinectSensor.Close();
this.kinectSensor = null;
}
}
/// <summary>
/// Handles the body frame data arriving from the sensor
/// </summary>
/// <param name="sender">object sending the event</param>
/// <param name="e">event arguments</param>
private void Reader_FrameArrived(object sender, BodyFrameArrivedEventArgs e)
{
bool dataReceived = false;
using (BodyFrame bodyFrame = e.FrameReference.AcquireFrame())
{
if (bodyFrame != null)
{
if (this.bodies == null)
{
this.bodies = new Body[bodyFrame.BodyCount];
}
// The first time GetAndRefreshBodyData is called, Kinect will allocate each Body in the array.
// As long as those body objects are not disposed and not set to null in the array,
// those body objects will be re-used.
bodyFrame.GetAndRefreshBodyData(this.bodies);
dataReceived = true;
}
}
if (dataReceived)
{
using (DrawingContext dc = this.drawingGroup.Open())
{
// Draw a transparent background to set the render size: Se trata de realizar un fondo , en este caso negro
dc.DrawRectangle(Brushes.Black, null, new Rect(0.0, 0.0, this.displayWidth, this.displayHeight));
int penIndex = 0;
foreach (Body body in this.bodies)
{
Pen drawPen = this.bodyColors[penIndex++];
// Dani ICloneable
if (body.IsTracked)
{
this.DrawClippedEdges(body, dc);
IReadOnlyDictionary<JointType, Joint> joints = body.Joints;
// Console.WriteLine("HandRight" + JointType.HandRight);
// convert the joint points to depth (display) space
Dictionary<JointType, Point> jointPoints = new Dictionary<JointType, Point>();
foreach (JointType jointType in joints.Keys)
{
// sometimes the depth(Z) of an inferred joint may show as negative
// clamp down to 0.1f to prevent coordinatemapper from returning (-Infinity, -Infinity)
CameraSpacePoint position = joints[jointType].Position;
if (position.Z < 0)
{
position.Z = InferredZPositionClamp;
}
DepthSpacePoint depthSpacePoint = this.coordinateMapper.MapCameraPointToDepthSpace(position);
jointPoints[jointType] = new Point(depthSpacePoint.X, depthSpacePoint.Y);
}
this.DrawBody(joints, jointPoints, dc, drawPen);
this.DrawHand(body.HandLeftState, jointPoints[JointType.HandLeft], dc);
this.DrawHand(body.HandRightState, jointPoints[JointType.HandRight], dc);
//SE TRATA DE SACAR LOS PUNTOS X E Y DE LA MANO DERECHA
// Distancias sacadas en metros
//Mano Derecha
VariablesGlobales.HandRightX = body.Joints[JointType.HandRight].Position.X;
VariablesGlobales.HandRightY = body.Joints[JointType.HandRight].Position.Y;
VariablesGlobales.HandRightZ = body.Joints[JointType.HandRight].Position.Z;
//ManoIzquierda
VariablesGlobales.HandLeftX = body.Joints[JointType.HandLeft].Position.X;
VariablesGlobales.HandLeftY = body.Joints[JointType.HandLeft].Position.Y;
VariablesGlobales.HandLeftZ = body.Joints[JointType.HandLeft].Position.Z;
//Matriz Rectangular multidimensional
// float[,] MatrizCoordBodyGlobales = { { body.Joints[JointType.HandLeft].Position.X, body.Joints[JointType.HandLeft].Position.Y },
// { body.Joints[JointType.HandRight].Position.X, body.Joints[JointType.HandRight].Position.Y },
//{ body.Joints[JointType.Head].Position.X, body.Joints[JointType.Head].Position.Y },
//{ body.Joints[JointType.SpineMid].Position.X, body.Joints[JointType.SpineMid].Position.Y }};
MatrizCoordBodyGlobales[0, 0] = VariablesGlobales.HandRightX;
MatrizCoordBodyGlobales[0, 1] = VariablesGlobales.HandRightY;
MatrizCoordBodyGlobales[1, 0] = VariablesGlobales.HandLeftX;
MatrizCoordBodyGlobales[1, 1] = VariablesGlobales.HandLeftY;
// ArraydeMatrices[0] = MatrizCoordBodyGlobales;
for (j = 0; j <= 200;j++)
{
if(j== 200 )
{
ArraydeMatrices[i] = MatrizCoordBodyGlobales;
j = 0;
i++;
}
}
// Probar sacar ese punto de coordenada y almacenarlo en una variable.
// Se depura , metiendo ventanas-resultados, aqui se pone el punto de parada para depurar
// mirar tambien como guardar essos parametros en archivos
}
}
// prevent drawing outside of our render area: Evitar el dibujo fuera de nuestro área de de devolucion
this.drawingGroup.ClipGeometry = new RectangleGeometry(new Rect(0.0, 0.0, this.displayWidth, this.displayHeight));
}
}
}
/// <summary>
/// Draws a body
/// </summary>
/// <param name="joints">joints to draw</param>
/// <param name="jointPoints">translated positions of joints to draw</param>
/// <param name="drawingContext">drawing context to draw to</param>
/// <param name="drawingPen">specifies color to draw a specific body</param>
private void DrawBody(IReadOnlyDictionary<JointType, Joint> joints, IDictionary<JointType, Point> jointPoints, DrawingContext drawingContext, Pen drawingPen)
{
// Draw the bones
foreach (var bone in this.bones)
{
this.DrawBone(joints, jointPoints, bone.Item1, bone.Item2, drawingContext, drawingPen);
}
// Draw the joints: Dibujar las articulaciones
foreach (JointType jointType in joints.Keys)
{
Brush drawBrush = null;
TrackingState trackingState = joints[jointType].TrackingState;
if (trackingState == TrackingState.Tracked)
{
drawBrush = this.trackedJointBrush;
}
else if (trackingState == TrackingState.Inferred)
{
drawBrush = this.inferredJointBrush;
}
if (drawBrush != null)
{
drawingContext.DrawEllipse(drawBrush, null, jointPoints[jointType], JointThickness, JointThickness);
}
}
}
/// <summary>
/// Draws one bone of a body (joint to joint)
/// </summary>
/// <param name="joints">joints to draw</param>
/// <param name="jointPoints">translated positions of joints to draw</param>
/// <param name="jointType0">first joint of bone to draw</param>
/// <param name="jointType1">second joint of bone to draw</param>
/// <param name="drawingContext">drawing context to draw to</param>
/// /// <param name="drawingPen">specifies color to draw a specific bone</param>
private void DrawBone(IReadOnlyDictionary<JointType, Joint> joints, IDictionary<JointType, Point> jointPoints, JointType jointType0, JointType jointType1, DrawingContext drawingContext, Pen drawingPen)
{
Joint joint0 = joints[jointType0];
Joint joint1 = joints[jointType1];
// If we can't find either of these joints, exit
if (joint0.TrackingState == TrackingState.NotTracked || joint1.TrackingState == TrackingState.NotTracked)
{
return;
}
// We assume all drawn bones are inferred unless BOTH joints are tracked
Pen drawPen = this.inferredBonePen;
if ((joint0.TrackingState == TrackingState.Tracked) && (joint1.TrackingState == TrackingState.Tracked))
{
drawPen = drawingPen;
}
drawingContext.DrawLine(drawPen, jointPoints[jointType0], jointPoints[jointType1]);
}
/// <summary>
/// Draws a hand symbol if the hand is tracked: red circle = closed, green circle = opened; blue circle = lasso ( lazo)
/// </summary>
/// <param name="handState">state of the hand</param>
/// <param name="handPosition">position of the hand</param>
/// <param name="drawingContext">drawing context to draw to</param>
private void DrawHand(HandState handState, Point handPosition, DrawingContext drawingContext)
{
switch (handState)
{
case HandState.Closed:
drawingContext.DrawEllipse(this.handClosedBrush, null, handPosition, HandSize, HandSize);
break;
case HandState.Open:
drawingContext.DrawEllipse(this.handOpenBrush, null, handPosition, HandSize, HandSize);
break;
case HandState.Lasso:
drawingContext.DrawEllipse(this.handLassoBrush, null, handPosition, HandSize, HandSize);
break;
}
}
/// <summary>
/// Draws indicators to show which edges are clipping body data
/// Dibuja indicadores para mostrar qué bordes están recortando los datos del cuerpo
/// </summary>
/// <param name="body">body to draw clipping information for</param>
/// <param name="drawingContext">drawing context to draw to</param>
private void DrawClippedEdges(Body body, DrawingContext drawingContext)
{
FrameEdges clippedEdges = body.ClippedEdges;
if (clippedEdges.HasFlag(FrameEdges.Bottom))
{
drawingContext.DrawRectangle(Brushes.Red, null, new Rect(0, this.displayHeight - ClipBoundsThickness, this.displayWidth, ClipBoundsThickness));
}
if (clippedEdges.HasFlag(FrameEdges.Top))
{
drawingContext.DrawRectangle(Brushes.Red, null, new Rect(0, 0, this.displayWidth, ClipBoundsThickness));
}
if (clippedEdges.HasFlag(FrameEdges.Left))
{
drawingContext.DrawRectangle(Brushes.Red, null, new Rect(0, 0, ClipBoundsThickness, this.displayHeight));
}
if (clippedEdges.HasFlag(FrameEdges.Right))
{
drawingContext.DrawRectangle(Brushes.Red, null, new Rect(this.displayWidth - ClipBoundsThickness, 0, ClipBoundsThickness, this.displayHeight));
}
}
/// <summary>
/// Handles the event which the sensor becomes unavailable (E.g. paused, closed, unplugged).
/// </summary>
/// <param name="sender">object sending the event</param>
/// <param name="e">event arguments</param>
private void Sensor_IsAvailableChanged(object sender, IsAvailableChangedEventArgs e)
{
// on failure, set the status text
this.StatusText = this.kinectSensor.IsAvailable ? Properties.Resources.RunningStatusText
: Properties.Resources.SensorNotAvailableStatusText;
}
}
}