middleware/Tracking/Gestures/SwipeDetector.cs
changeset 15 4b78f179e7ce
child 17 fda26bfcabef
equal deleted inserted replaced
14:10d5199d9874 15:4b78f179e7ce
       
     1 /*
       
     2 * This file is part of the TraKERS\Middleware package.
       
     3 *
       
     4 * (c) IRI <http://www.iri.centrepompidou.fr/>
       
     5 *
       
     6 * For the full copyright and license information, please view the LICENSE_MIDDLEWARE
       
     7 * file that was distributed with this source code.
       
     8 */
       
     9 
       
    10 /*
       
    11  * Projet : TraKERS
       
    12  * Module : MIDDLEWARE
       
    13  * Sous-Module : Tracking/Gestures
       
    14  * Classe : SwipeDetector
       
    15  * 
       
    16  * Auteur : alexandre.bastien@iri.centrepompidou.fr
       
    17  * 
       
    18  * Fonctionnalités : Permet de détecter si l'utilisateur a effectué un Swipe, en se basant sur
       
    19  * des règles appliquées à la positions des noeuds dans le temps.
       
    20  */
       
    21 
       
    22 using System;
       
    23 using System.Collections.Generic;
       
    24 using System.Linq;
       
    25 using System.Text;
       
    26 using Microsoft.Kinect;
       
    27 
       
    28 namespace Trakers.MainModule.Gestures
       
    29 {
       
    30     public class SwipeDetector : GestureDetector
       
    31     {
       
    32         public enum Direction {LEFT, RIGHT, TOP, DOWN};
       
    33 
       
    34         public SwipeDetector() : base()
       
    35         {
       
    36             gesturePeriod = (float)0.5;
       
    37             indexesPerSecond = 30;
       
    38             indexesToCheck = (int)(gesturePeriod * indexesPerSecond);
       
    39         }
       
    40 
       
    41         /*
       
    42          * Lit les noeuds de l'historique du squelette afin de détecter un Swipe left.
       
    43          * Règles :
       
    44          * Se fait avec la main droite.
       
    45          * Chaque nouvelle position de la main doit être à la gauche de la précédente.
       
    46          * Chaque nouvelle position de la main ne doit pas s'éloigner verticalement de plus d'une certaine distance.
       
    47          * Le geste doit mesurer horizontalement une certaine distance.
       
    48          */
       
    49         public bool CheckForSwipeLeft()
       
    50         {
       
    51             //Crée un historique de squelette local, puisque l'historique est mis à jour toutes les ~1/30 s.
       
    52             List<List<Joint>> localHistory = new List<List<Joint>>(history);
       
    53 
       
    54             //Si il n'y a pas assez de positions dans l'historique local pour vérifier le geste.
       
    55             if (localHistory.Count < indexesToCheck+1)
       
    56                 return false;
       
    57             
       
    58             //La distance de référence est ici la distance entre le milieu du dos et le milieu des épaules.
       
    59             refDistance = Math.Abs(localHistory[0][(int)JointType.Spine].Position.Y - localHistory[0][(int)JointType.ShoulderCenter].Position.Y);
       
    60             //On commence la position pour les indexesToCheck dernières postures (celle à l'index 0 étant la dernière).
       
    61             startPoint = localHistory[localHistory.Count - indexesToCheck][(int)JointType.HandRight].Position;
       
    62 
       
    63             //De la position p1 à pn, on suit l'algorithme.
       
    64             for (int i = localHistory.Count - indexesToCheck + 1; i < localHistory.Count; i++)
       
    65             {
       
    66                 //Si la position Y de la main est plus haute que la tête
       
    67                 //OU si la position Y de la main est plus basse que la hanche
       
    68                 //OU si la nouvelle position X de la main est à droite de la précédente
       
    69                 //OU si la nouvelle position Y de la main est plus éloignée de la distance N par rapport à la première position Y
       
    70                 //Alors on retourne faux.
       
    71                 if (localHistory[i][(int)JointType.HandRight].Position.Y < localHistory[i][(int)JointType.Head].Position.Y ||
       
    72                 localHistory[i][(int)JointType.HandRight].Position.Y > localHistory[i][(int)JointType.HipCenter].Position.Y ||
       
    73                 localHistory[i][(int)JointType.HandRight].Position.X > localHistory[i - 1][(int)JointType.HandRight].Position.X ||
       
    74                 Math.Abs(localHistory[i][(int)JointType.HandRight].Position.Y - startPoint.Y) > refDistance / 2)
       
    75                     return false;
       
    76             }
       
    77 
       
    78             //Si la distance horizontale du geste a été plus courte que la distance N
       
    79             //Alors on retourne faux.
       
    80             if (Math.Abs(localHistory[0][(int)JointType.HandRight].Position.X - localHistory[localHistory.Count - indexesToCheck][(int)JointType.HandRight].Position.X) < refDistance / 2)
       
    81                 return false;
       
    82 
       
    83             //Si la dernière position de la main droite est sur le côté droit du corps
       
    84             //OU si la première position calculée de la main droite est sur le côté gauche du corps
       
    85             //Alors on retourne faux.
       
    86             if (localHistory[localHistory.Count - 1][(int)JointType.HandRight].Position.X > localHistory[localHistory.Count - 1][(int)JointType.HipCenter].Position.X ||
       
    87                localHistory[localHistory.Count - indexesToCheck][(int)JointType.HandRight].Position.X < localHistory[localHistory.Count - 1][(int)JointType.HipCenter].Position.X)
       
    88                 return false;
       
    89 
       
    90             //On supprime l'historique local.
       
    91             localHistory.Clear();
       
    92             //Si on est arrivé jusqu'ici, toutes les conditions pour un swipe left ont été remplies.
       
    93             return true;
       
    94         }
       
    95 
       
    96         /*
       
    97          * Lit les noeuds de l'historique du squelette afin de détecter un Swipe right.
       
    98          * Règles :
       
    99          * Se fait avec la main gauche.
       
   100          * Chaque nouvelle position de la main doit être à la droite de la précédente.
       
   101          * Chaque nouvelle position de la main ne doit pas s'éloigner verticalement de plus d'une certaine distance.
       
   102          * Le geste doit mesurer horizontalement une certaine distance.
       
   103          */
       
   104         public bool CheckForSwipeRight()
       
   105         {
       
   106             //Crée un historique de squelette local, puisque l'historique est mis à jour toutes les ~1/30 s.
       
   107             List<List<Joint>> localHistory = new List<List<Joint>>(history);
       
   108 
       
   109             //Si il n'y a pas assez de positions dans l'historique local pour vérifier le geste.
       
   110             if (localHistory.Count < indexesToCheck + 1)
       
   111                 return false;
       
   112 
       
   113             //La distance de référence est ici la distance entre le milieu du dos et le milieu des épaules.
       
   114             refDistance = Math.Abs(localHistory[0][(int)JointType.Spine].Position.Y - localHistory[0][(int)JointType.ShoulderCenter].Position.Y);
       
   115             //On commence la position pour les indexesToCheck dernières postures (celle à l'index 0 étant la dernière).
       
   116             startPoint = localHistory[localHistory.Count - indexesToCheck][(int)JointType.HandLeft].Position;
       
   117 
       
   118             //De la position p1 à pn, on suit l'algorithme.
       
   119             for (int i = localHistory.Count - indexesToCheck + 1; i < localHistory.Count; i++)
       
   120             {
       
   121                 //Si la position Y de la main est plus haute que la tête
       
   122                 //OU si la position Y de la main est plus basse que la hanche
       
   123                 //OU si la nouvelle position X de la main est à gauche de la précédente
       
   124                 //OU si la nouvelle position Y de la main est plus éloignée de la distance N par rapport à la première position Y
       
   125                 //Alors on retourne faux.
       
   126                 if (localHistory[i][(int)JointType.HandLeft].Position.Y < localHistory[i][(int)JointType.Head].Position.Y ||
       
   127                 localHistory[i][(int)JointType.HandLeft].Position.Y > localHistory[i][(int)JointType.HipCenter].Position.Y ||
       
   128                 localHistory[i][(int)JointType.HandLeft].Position.X < localHistory[i - 1][(int)JointType.HandLeft].Position.X ||
       
   129                 Math.Abs(localHistory[i][(int)JointType.HandLeft].Position.Y - startPoint.Y) > refDistance / 2)
       
   130                     return false;
       
   131             }
       
   132 
       
   133             //Si la distance horizontale du geste a été plus courte que la distance N
       
   134             //Alors on retourne faux.
       
   135             if (Math.Abs(localHistory[0][(int)JointType.HandLeft].Position.X - localHistory[localHistory.Count - indexesToCheck][(int)JointType.HandLeft].Position.X) < refDistance / 2)
       
   136                 return false;
       
   137 
       
   138             //Si la dernière position de la main droite est sur le côté gauche du corps
       
   139             //OU si la première position calculée de la main droite est sur le côté droit du corps
       
   140             //Alors on retourne faux.
       
   141             if (localHistory[localHistory.Count - 1][(int)JointType.HandLeft].Position.X < localHistory[localHistory.Count - 1][(int)JointType.HipCenter].Position.X ||
       
   142                localHistory[localHistory.Count - indexesToCheck][(int)JointType.HandLeft].Position.X > localHistory[localHistory.Count - 1][(int)JointType.HipCenter].Position.X)
       
   143                 return false;
       
   144 
       
   145             //On supprime l'historique local.
       
   146             localHistory.Clear();
       
   147             //Si on est arrivé jusqu'ici, toutes les conditions pour un swipe right ont été remplies.
       
   148             return true;
       
   149         }
       
   150     }
       
   151 }