middleware/src/Tracking/Gestures/SwipeDetector.cs
changeset 3 92f19af39024
parent 0 6fefd4afe506
child 5 d40f84d77db4
equal deleted inserted replaced
2:11234537653b 3:92f19af39024
     1 using System;
     1 /*
       
     2  * Projet : TraKERS
       
     3  * Module : MIDDLEWARE
       
     4  * Sous-Module : Tracking/Gestures
       
     5  * Classe : SwipeDetector
       
     6  * 
       
     7  * Auteur : alexandre.bastien@iri.centrepompidou.fr
       
     8  * 
       
     9  * Fonctionnalités : Permet de détecter si l'utilisateur a effectué un Swipe, en se basant sur
       
    10  * des règles appliquées à la positions des noeuds dans le temps.
       
    11  */
       
    12 
       
    13 using System;
     2 using System.Collections.Generic;
    14 using System.Collections.Generic;
     3 using System.Linq;
    15 using System.Linq;
     4 using System.Text;
    16 using System.Text;
     5 using Microsoft.Kinect;
    17 using Microsoft.Kinect;
     6 
    18 
     8 {
    20 {
     9     public class SwipeDetector : GestureDetector
    21     public class SwipeDetector : GestureDetector
    10     {
    22     {
    11         public enum Direction {LEFT, RIGHT, TOP, DOWN};
    23         public enum Direction {LEFT, RIGHT, TOP, DOWN};
    12 
    24 
    13         public SwipeDetector() : base()
    25         Debug.DebugWindow debug;
       
    26 
       
    27         public SwipeDetector(Debug.DebugWindow _d) : base()
    14         {
    28         {
       
    29             debug = _d;
    15             gesturePeriod = (float)0.5;
    30             gesturePeriod = (float)0.5;
    16             indexesPerSecond = 30;
    31             indexesPerSecond = 30;
    17             indexesToCheck = (int)(gesturePeriod * indexesPerSecond);
    32             indexesToCheck = (int)(gesturePeriod * indexesPerSecond);
    18         }
    33         }
    19 
    34 
    26          * Le geste doit mesurer horizontalement une certaine distance.
    41          * Le geste doit mesurer horizontalement une certaine distance.
    27          */
    42          */
    28         public bool CheckForSwipeLeft()
    43         public bool CheckForSwipeLeft()
    29         {
    44         {
    30             //Crée un historique de squelette local, puisque l'historique est mis à jour toutes les ~1/30 s.
    45             //Crée un historique de squelette local, puisque l'historique est mis à jour toutes les ~1/30 s.
    31             //List<Skeleton> history = new List<Skeleton>(history);
    46             List<List<Joint>> localHistory = new List<List<Joint>>(history);
    32 
       
    33             /*for (int i = 0; i < history.Count; i++)
       
    34                 System.Console.Out.WriteLine(history[i].Joints.ElementAt(handRightID).Position.X);
       
    35             System.Console.Out.WriteLine("========================");*/
       
    36 
    47 
    37             //Si il n'y a pas assez de positions dans l'historique local pour vérifier le geste.
    48             //Si il n'y a pas assez de positions dans l'historique local pour vérifier le geste.
    38             if (history.Count < indexesToCheck+1)
    49             if (localHistory.Count < indexesToCheck+1)
    39                 return false;
    50                 return false;
    40             //Console.ReadLine();
    51             
    41 
       
    42             //La distance de référence est ici la distance entre le milieu du dos et le milieu des épaules.
    52             //La distance de référence est ici la distance entre le milieu du dos et le milieu des épaules.
    43             refDistance = Math.Abs(history[0][spineID].Position.Y - history[0][shoulderCenterID].Position.Y);
    53             refDistance = Math.Abs(localHistory[0][spineID].Position.Y - localHistory[0][shoulderCenterID].Position.Y);
    44             //On commence la position pour les indexesToCheck dernières postures (celle à l'index 0 étant la dernière).
    54             //On commence la position pour les indexesToCheck dernières postures (celle à l'index 0 étant la dernière).
    45             startPoint = history[history.Count - indexesToCheck][handRightID].Position;
    55             startPoint = localHistory[localHistory.Count - indexesToCheck][handRightID].Position;
    46 
    56 
    47             //De la position p1 à pn, on suit l'algorithme.
    57             //De la position p1 à pn, on suit l'algorithme.
    48             Console.Out.WriteLine("=================================");
    58             for (int i = localHistory.Count - indexesToCheck + 1; i < localHistory.Count; i++)
    49             for (int i = history.Count - indexesToCheck + 1; i < history.Count; i++)
       
    50             {
    59             {
    51                 System.Console.Out.WriteLine("hand:head " + history[i][handRightID].Position.Y + " <= " + history[i][headID].Position.Y + " && "
    60                 //Debug temporaire pour vérifier la validité de certaines contraintes durant la gesture.
    52                 + "hand:hip " + history[i][handRightID].Position.Y + " >= " + history[i][hipCenterID].Position.Y + " && "
    61                /*if (localHistory[i][handRightID].Position.Y > localHistory[i][headID].Position.Y)
    53                 + "handX:handX-1 " + history[i][handRightID].Position.X + " <= " + history[i - 1][handRightID].Position.X + " && "
    62                     debug.R1.Fill = System.Windows.Media.Brushes.Blue;
    54                 + "hand0:handN " + Math.Abs(history[i][handRightID].Position.Y - startPoint.Y) + " <= " + refDistance / 2);
    63                 else
       
    64                     debug.R1.Fill = System.Windows.Media.Brushes.DarkGray;
    55 
    65 
    56                 //Si la position Y de la main est supérieure à celle de l'épaule
    66                 if(localHistory[i][handRightID].Position.Y < localHistory[i][hipCenterID].Position.Y)
    57                 //OU si la position Y de la main est inférieure à celle de la hanche
    67                     debug.R2.Fill = System.Windows.Media.Brushes.Blue;
       
    68                 else
       
    69                     debug.R2.Fill = System.Windows.Media.Brushes.DarkGray;
       
    70 
       
    71                 if(localHistory[i][handRightID].Position.X < localHistory[i - 1][handRightID].Position.X)
       
    72                     debug.R3.Fill = System.Windows.Media.Brushes.Blue;
       
    73                 else
       
    74                     debug.R3.Fill = System.Windows.Media.Brushes.DarkGray;
       
    75 
       
    76                 if(Math.Abs(localHistory[i][handRightID].Position.Y - startPoint.Y) < refDistance/2)
       
    77                     debug.R4.Fill = System.Windows.Media.Brushes.Blue;
       
    78                 else
       
    79                     debug.R4.Fill = System.Windows.Media.Brushes.DarkGray;*/
       
    80 
       
    81                 //Si la position Y de la main est plus haute que la tête
       
    82                 //OU si la position Y de la main est plus basse que la hanche
    58                 //OU si la nouvelle position X de la main est à droite de la précédente
    83                 //OU si la nouvelle position X de la main est à droite de la précédente
    59                 //OU si la nouvelle position Y de la main est plus éloignée de la distance N par rapport à la première position Y
    84                 //OU si la nouvelle position Y de la main est plus éloignée de la distance N par rapport à la première position Y
    60                 //Alors on retourne faux.
    85                 //Alors on retourne faux.
    61                 if (history[i][handRightID].Position.Y > history[i][headID].Position.Y ||
    86                 if (localHistory[i][handRightID].Position.Y < localHistory[i][headID].Position.Y ||
    62                 history[i][handRightID].Position.Y < history[i][hipCenterID].Position.Y ||
    87                 localHistory[i][handRightID].Position.Y > localHistory[i][hipCenterID].Position.Y ||
    63                 history[i][handRightID].Position.X > history[i - 1][handRightID].Position.X ||
    88                 localHistory[i][handRightID].Position.X > localHistory[i - 1][handRightID].Position.X ||
    64                 Math.Abs(history[i][handRightID].Position.Y - startPoint.Y) > refDistance/2)
    89                 Math.Abs(localHistory[i][handRightID].Position.Y - startPoint.Y) > refDistance/2)
    65                     return false;
    90                     return false;
    66             }
    91             }
    67             Console.Out.WriteLine("=================================");
    92 
    68             Console.ReadLine();
       
    69             //Si la distance horizontale du geste a été plus courte que la distance N
    93             //Si la distance horizontale du geste a été plus courte que la distance N
    70             //Alors on retourne faux.
    94             //Alors on retourne faux.
    71             float dist = (history[history.Count - 1][handRightID].Position.X - history[history.Count - indexesToCheck][handRightID].Position.X);
    95             //float dist = (localHistory[localHistory.Count - 1][handRightID].Position.X - localHistory[localHistory.Count - indexesToCheck][handRightID].Position.X);
    72             
    96             
    73             //System.Console.Out.WriteLine(history[0].Joints.ElementAt(handRightID).Position.X + " " + history[1].Joints.ElementAt(handRightID).Position.X + " " + history[2].Joints.ElementAt(handRightID).Position.X);
    97             if (Math.Abs(localHistory[0][handRightID].Position.X - localHistory[localHistory.Count - indexesToCheck][handRightID].Position.X) < refDistance/2)
    74             //System.Console.Out.WriteLine(history[0].Joints.ElementAt(handRightID).Position.X + " " + history[1].Joints.ElementAt(handRightID).Position.X + " " + history[2].Joints.ElementAt(handRightID).Position.X);
       
    75             System.Console.Out.WriteLine(Math.Abs(history[0][handRightID].Position.X - history[history.Count - indexesToCheck][handRightID].Position.X) + " < " + refDistance*1.5);
       
    76             if (Math.Abs(history[0][handRightID].Position.X - history[history.Count - indexesToCheck][handRightID].Position.X) < refDistance*1.5)
       
    77                 return false;
    98                 return false;
    78 
    99 
    79             history.Clear();
   100             //Si la dernière position de la main droite est sur le côté droit du corps
    80             Console.Out.WriteLine("SWIPE LEF");
   101             //OU si la première position calculée de la main droite est sur le côté gauche du corps
    81             Console.ReadLine();
   102             //Alors on retourne faux.
       
   103             if(localHistory[localHistory.Count - 1][handRightID].Position.X > localHistory[localHistory.Count - 1][hipCenterID].Position.X ||
       
   104                localHistory[localHistory.Count - indexesToCheck][handRightID].Position.X < localHistory[localHistory.Count - 1][hipCenterID].Position.X)
       
   105                 return false;
       
   106 
       
   107             //System.Console.Out.WriteLine(Math.Abs(localHistory[0][handRightID].Position.X - localHistory[localHistory.Count - indexesToCheck][handRightID].Position.X) + " < " + refDistance/2);
       
   108             //On supprime l'historique local.
       
   109             localHistory.Clear();
       
   110             //Si on est arrivé jusqu'ici, toutes les conditions pour un swipe left ont été remplies.
       
   111             return true;
       
   112         }
       
   113 
       
   114         /*
       
   115          * Lit les noeuds de l'historique du squelette afin de détecter un Swipe right.
       
   116          * Règles :
       
   117          * Se fait avec la main gauche.
       
   118          * Chaque nouvelle position de la main doit être à la droite de la précédente.
       
   119          * Chaque nouvelle position de la main ne doit pas s'éloigner verticalement de plus d'une certaine distance.
       
   120          * Le geste doit mesurer horizontalement une certaine distance.
       
   121          */
       
   122         public bool CheckForSwipeRight()
       
   123         {
       
   124             //Crée un historique de squelette local, puisque l'historique est mis à jour toutes les ~1/30 s.
       
   125             List<List<Joint>> localHistory = new List<List<Joint>>(history);
       
   126 
       
   127             //Si il n'y a pas assez de positions dans l'historique local pour vérifier le geste.
       
   128             if (localHistory.Count < indexesToCheck + 1)
       
   129                 return false;
       
   130 
       
   131             //La distance de référence est ici la distance entre le milieu du dos et le milieu des épaules.
       
   132             refDistance = Math.Abs(localHistory[0][spineID].Position.Y - localHistory[0][shoulderCenterID].Position.Y);
       
   133             //On commence la position pour les indexesToCheck dernières postures (celle à l'index 0 étant la dernière).
       
   134             startPoint = localHistory[localHistory.Count - indexesToCheck][handLeftID].Position;
       
   135 
       
   136             //De la position p1 à pn, on suit l'algorithme.
       
   137             for (int i = localHistory.Count - indexesToCheck + 1; i < localHistory.Count; i++)
       
   138             {
       
   139                 //Debug temporaire pour vérifier la validité de certaines contraintes durant la gesture.
       
   140                 /*if (localHistory[i][handLeftID].Position.Y > localHistory[i][headID].Position.Y)
       
   141                     debug.R1.Fill = System.Windows.Media.Brushes.Cyan;
       
   142                 else
       
   143                     debug.R1.Fill = System.Windows.Media.Brushes.DarkGray;
       
   144 
       
   145                 if (localHistory[i][handLeftID].Position.Y < localHistory[i][hipCenterID].Position.Y)
       
   146                     debug.R2.Fill = System.Windows.Media.Brushes.Cyan;
       
   147                 else
       
   148                     debug.R2.Fill = System.Windows.Media.Brushes.DarkGray;
       
   149 
       
   150                 if (localHistory[i][handLeftID].Position.X > localHistory[i - 1][handLeftID].Position.X)
       
   151                     debug.R3.Fill = System.Windows.Media.Brushes.Cyan;
       
   152                 else
       
   153                     debug.R3.Fill = System.Windows.Media.Brushes.DarkGray;
       
   154 
       
   155                 if (Math.Abs(localHistory[i][handLeftID].Position.Y - startPoint.Y) < refDistance / 2)
       
   156                     debug.R4.Fill = System.Windows.Media.Brushes.Cyan;
       
   157                 else
       
   158                     debug.R4.Fill = System.Windows.Media.Brushes.DarkGray;*/
       
   159 
       
   160                 //Si la position Y de la main est plus haute que la tête
       
   161                 //OU si la position Y de la main est plus basse que la hanche
       
   162                 //OU si la nouvelle position X de la main est à gauche de la précédente
       
   163                 //OU si la nouvelle position Y de la main est plus éloignée de la distance N par rapport à la première position Y
       
   164                 //Alors on retourne faux.
       
   165                 if (localHistory[i][handLeftID].Position.Y < localHistory[i][headID].Position.Y ||
       
   166                 localHistory[i][handLeftID].Position.Y > localHistory[i][hipCenterID].Position.Y ||
       
   167                 localHistory[i][handLeftID].Position.X < localHistory[i - 1][handLeftID].Position.X ||
       
   168                 Math.Abs(localHistory[i][handLeftID].Position.Y - startPoint.Y) > refDistance / 2)
       
   169                     return false;
       
   170             }
       
   171 
       
   172             //Si la distance horizontale du geste a été plus courte que la distance N
       
   173             //Alors on retourne faux.
       
   174             //float dist = (localHistory[localHistory.Count - 1][handLeftID].Position.X - localHistory[localHistory.Count - indexesToCheck][handLeftID].Position.X);
       
   175 
       
   176             if (Math.Abs(localHistory[0][handLeftID].Position.X - localHistory[localHistory.Count - indexesToCheck][handLeftID].Position.X) < refDistance / 2)
       
   177                 return false;
       
   178 
       
   179             //Si la dernière position de la main droite est sur le côté gauche du corps
       
   180             //OU si la première position calculée de la main droite est sur le côté droit du corps
       
   181             //Alors on retourne faux.
       
   182             if (localHistory[localHistory.Count - 1][handLeftID].Position.X < localHistory[localHistory.Count - 1][hipCenterID].Position.X ||
       
   183                localHistory[localHistory.Count - indexesToCheck][handLeftID].Position.X > localHistory[localHistory.Count - 1][hipCenterID].Position.X)
       
   184                 return false;
       
   185 
       
   186             //System.Console.Out.WriteLine(Math.Abs(localHistory[0][handLeftID].Position.X - localHistory[localHistory.Count - indexesToCheck][handLeftID].Position.X) + " < " + refDistance / 2);
       
   187             //On supprime l'historique local.
       
   188             localHistory.Clear();
       
   189             //Si on est arrivé jusqu'ici, toutes les conditions pour un swipe right ont été remplies.
    82             return true;
   190             return true;
    83         }
   191         }
    84     }
   192     }
    85 }
   193 }