Middleware :
No proximity bugs anymore.
The skeleton disappear if a tracked person is too close or not tracked anymore.
Processing :
There are no laggs anymore when an user stay too long moving his hands and drawing
tons of ellipses. (TUIO Cursors are not taken by their vectors, only the last position
of the cursors are caught to be drawn).
/*
* Projet : TraKERS
* Module : MIDDLEWARE
* Sous-Module : Tracking/Gestures
* Classe : GestureDetector
*
* Auteur : alexandre.bastien@iri.centrepompidou.fr
*
* Fonctionnalités : Reçoit les positions des noeuds envoyés par la classe de manipulation de la Kinect
* et les stocke dans un historique.
* Contient également des variables propres à toute gesture : distance de référence, point de départ,
* durée de la gesture, FPS et nombre de frames à traiter.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Kinect;
using System.Drawing;
namespace Trakers.Tracking.Gestures
{
public class GestureDetector
{
//Historique des positions du squelette.
protected static List<List<Joint>> history = new List<List<Joint>>();
//protected JointCollection previousSkeleton;
//Voici les ID des noeuds d'un squelette : variables magiques en attente de factorisation.
/*protected int hipCenterID = 0, spineID = 1, shoulderCenterID = 2, headID = 3;
protected int shoulderLeftID = 4, elbowLeftID = 5, wristLeftID = 6, handLeftID = 7;
protected int shoulderRightID = 8, elbowRightID = 9, wristRightID = 10, handRightID = 11;
protected int hipLeftID = 12, kneeLeftID = 13, ankleLeftID = 14, footLeftID = 15;
protected int hipRightID = 16, kneeRightID = 17, ankleRightID = 18, footRightID = 19;*/
//Elements nécessaires à la reconnaissance du geste :
//Distance du parcours du geste (va dépendre de la distance de l'utilisateur).
protected float refDistance;
//Position de départ pour le geste.
protected SkeletonPoint startPoint;
//Estimation du temps que prend la gesture (en s).
protected float gesturePeriod = 1;
//Estimation du nombre d'indexes par seconde (framerate).
protected int indexesPerSecond = 30;
//Estimation du nombre de positions du squelette à vérifier dans l'historique.
protected int indexesToCheck;// = gesturePeriod * indexesPerSecond;
public GestureDetector()
{
}
//Setters.
public void setRefDistance(float _refDistance)
{
refDistance = _refDistance;
}
public void setStartPoint(SkeletonPoint _startPoint)
{
startPoint = _startPoint;
}
public void setGesturePeriod(float _gesturePeriod)
{
gesturePeriod = _gesturePeriod;
}
public void setIndexesPerSecond(int _indexesPerSecond)
{
indexesPerSecond = _indexesPerSecond;
}
public void setIndexesToCheck(int _indexesToCheck)
{
indexesToCheck = _indexesToCheck;
}
//Getters.
public float getRefDistance()
{
return refDistance;
}
public SkeletonPoint getStartPoint()
{
return startPoint;
}
public float getGesturePeriod()
{
return gesturePeriod;
}
public int getIndexesPerSecond()
{
return indexesPerSecond;
}
public int getIndexesToCheck()
{
return indexesToCheck;
}
//Stocke les gestes du skelette pour ~3 seconds (si on prend en compte que le framerate de la Kinect
//est de ~30 fps.
public static void UpdateSkeletonHistory(List<Joint> latestSkeleton)
{
history.Add(latestSkeleton);
if (history.Count > 90)
{
history.RemoveAt(0);
}
}
/*public bool CheckForHandWave()
{
//Crée un historique de squelette local, puisque l'historique est mis à jour toutes les ~1/30 s.
List<Skeleton> history = new List<Skeleton>(history);
//Si il n'y a pas assez de positions dans l'historique local pour vérifier le geste.
if (history.Count < indexesToCheck)
return false;
float refDistance = Math.Abs(history[0].Joints.ElementAt(spineID).Position.Y - history[0].Joints.ElementAt(hipCenterID).Position.Y);
float startPos = history[history.Count - indexesToCheck].Joints.ElementAt(handRightID).Position.X;
bool movedRight = false;
for (int i = history.Count - indexesToCheck + 1; i < history.Count; i++)
{
// Throughout the gesture period, right hand should be above theelbow, below the head and hand should be higher than the wrist
if (!(history[i].Joints[JointID.HandRight].Position.Y > history[i].Joints[JointID.ElbowRight].Position.Y + refDistance &&
history[i].Joints[JointID.HandRight].Position.Y < history[i].Joints[JointID.Head].Position.Y &&
history[i].Joints[JointID.HandRight].Position.Y > history[i].Joints[JointID.WristRight].Position.Y + refDistance / 4))
{
return false;
}
// If the previous condition was met, check if the hand has moved to the right
if (history[i].Joints[JointID.HandRight].Position.X >= startPos + refDistance / 2 && !movedRight)
{
movedRight = true;
}
// If the hand did move to the right, check if it returned near the original position
if (movedRight && history[i].Joints[JointID.HandRight].Position.X <= startPos + refDistance / 5)
{
skeletonHistory.Clear();
return true;
}
}
return false;
}*/
}
}