Posture Tutorial
<< Back to the TouchID Toolkit page
In this tutorial you learn how to use postures in an application.
Therefore, we will implement a posture training application together. A label in the center of the screen will show the name of a posture that is randomly picked from the posture repository (My Documents/GroupLab/TouchID Toolkit/Postures). The user has to perform this posture to get a point and move on to the next random posture.
Prerequisite 1: At least one glove configuration has been created
Glove configurations can be conveniently created with the GloveConfigurator which stores the glove configuration files also directly in the glove repository (My Documents/GroupLab/TouchID Toolkit/Gloves) right away. If you have glove configuration files in a different folder and want them to work with this example, copy them into the glove repository.
Prerequisite 2: A set of postures has been created
Postures can be conveniently created with the PostureConfigurator which stores them also in the posture repository (My Documents/GroupLab/TouchID Toolkit/Postures) right away. If you have posture configuration files in a different folder and want them to work with this example, copy them into the posture repository.
Step 1: Creating a new TouchID Application
For detailed information, please read: How to start a new TouchID Application
The TouchID Application template creates the following code skeleton for you:
public Window1(){
InitializeComponent();
//Creates a glove for every glove model in the glove repository
this.LoadHands();
//Alternatively you can also instantiate glove by glove;
//Hand hand = new Hand(this, "Hand1");
//Creates posture recognizer and loads all postures from the posture repository into the recognition engine
this.PostureRecognizer = new PostureRecognizer(this);
this.PostureRecognizer.LoadPostures(PostureRepository);
//Creates gesture recognizer and loads all gesture from the gesture repository into the recognition engine
this.GestureRecognizer = new GestureRecognizer();
this.GestureRecognizer.LoadGestures(GestureRepository);
this.HandpartDown += new EventHandler<GloveTouchEventArgs>(Window1_HandpartDown);
}
void Window1_HandpartDown(object sender, GloveTouchEventArgs e){
Console.WriteLine(e.Glove.Hand + " " + e.Handpart.Identifier);
}
}
Step 2: Deleting unnecessary parts of the template code
Since we do not use hand parts or gestures in this example, we delete the code for the gesture recognizer, the HandpartDown event and the corresponding callback method Window1_HandpartDown.
Step 3: Adding a label for displaying the name of the randomly picked posture
private Label postureNameLabel;
public partial class Window1 : TouchIDWindow{
public Window1(){
InitializeComponent();
this.LoadHands();
this.PostureRecognizer = new PostureRecognizer(this);
this.PostureRecognizer.LoadPostures(PostureRepository);
this.postureNameLabel = new Label();
this.postureNameLabel.Width = 200.0;
this.postureNameLabel.Height = 50.0;
this.postureNameLabel.FontSize = 25.0;
// Position label in screen center
double centerX = (this.Width - this.postureNameLabel.Width)/2.0;
double centerY = (this.Height - this.postureNameLabel.Height)/2.0
this.postureNameLabel.RenderTransform = new TranslateTransform(centerX, centerY);
this.Container.Children.Add(postureNameLabel);
}
}
Step 4: Adding a instance variable that stores the currently picked posture
Step 5: Creating a method that sets a new random posture and displays the name in the center label.
Random random = new Random(DateTime.Now.Millisecond);
this.WantedPosture = this.PostureRecognizer.Postures.ElementAt(random.Next(0, this.PostureRecognizer.Postures.Count));
this.postureNameLabel.Content = this.WantedPosture.Identifier;
}
Step 6: Calling the SetRandomPosture() method in the constructor
This way, a first random posture is picked for the start of the training. Make sure to call this method after the PostureRecognizer has loaded the postures!
private Label postureNameLabel;
public partial class Window1 : TouchIDWindow {
public Window1(){
InitializeComponent();
this.LoadHands();
this.PostureRecognizer = new PostureRecognizer(this);
this.PostureRecognizer.LoadPostures(PostureRepository);
this.postureNameLabel = new Label();
this.postureNameLabel.Width = 200.0;
this.postureNameLabel.Height = 50.0;
this.postureNameLabel.FontSize = 25.0;
// Position label in screen center
double centerX = (this.Width - this.postureNameLabel.Width)/2.0;
double centerY = (this.Height - this.postureNameLabel.Height)/2.0
this.postureNameLabel.RenderTransform = new TranslateTransform(centerX, centerY);
this.Container.Children.Add(postureNameLabel);
// Set first random posture
this.SetRandomPosture();
}
}
So far we have an application that shows a randomly picked posture in the center of the screen. What we need now is a mechanism that changes the label text to another randomly picked posture name when the currently wanted posture is performed correctly.
Step 7: Subscribing to the PostureDown event
Therefor we subscribe to the PostureDown event. This event is raised whenever a posture is placed down on the surface.
private Label postureNameLabel;
public partial class Window1 : TouchIDWindow{
public Window1(){
InitializeComponent();
this.LoadHands();
this.PostureRecognizer = new PostureRecognizer(this);
this.PostureRecognizer.LoadPostures(PostureRepository);
this.postureNameLabel = new Label();
this.postureNameLabel.Width = 200.0;
this.postureNameLabel.Height = 50.0;
this.postureNameLabel.FontSize = 25.0;
// Position label in screen center
double centerX = (this.Width - this.postureNameLabel.Width)/2.0;
double centerY = (this.Height - this.postureNameLabel.Height)/2.0
this.postureNameLabel.RenderTransform = new TranslateTransform(centerX, centerY);
this.Container.Children.Add(postureNameLabel);
// Set first random posture
this.SetRandomPosture();
this.PostureDown += new EventArgs<HandPostureEventArgs>(Window1_PostureDown);
}
}
Step 8: Adjusting the callback method of the PostureDown event
If the callback method wasn't automatically created, do this manually. Then we adjust it, so it checks whether the recognized posture matches the wanted posture or not. If so, the SetRandomPosture() method is called and the application switches to the next randomly picked posture.
if(e.RecognizedPosture.Identifier.Equals(this.WantedPosture.Identifier)){
this.SetRandomPosture();
} else {
Console.WriteLine(e.RecognizedPosture.Identifier + " is not " + this.WantedPosture.Identifier +".");
}
}
The HandPostureEventArgs contain also a list of all postures that were recognized (e.RecognizedPostures). This way you can also access postures that have been recognized with a lower confidence as the best result that is exposed as separate value (e.RecognizedPosture). The recognized postures provide not only their identifiers, but also the recognition confidence, as well as the posture position and orientation on the screen.
This is where the posture tutorial ends. You've learned how to set up an application that uses posture recognition and how to subscribe to posture events.
Optional Step: Adding a label at the posture position that displays the recognition confidence
For those of you who want to learn a little bit more about postures and how they can be used, we will extend the example above with the following addition: Each time the wanted posture was successfully performed, a label will be added at the position of the posture. The label will show the recognition confidence with which the wanted posture was recreated.
if(e.RecognizedPosture.Identifier.Equals(this.WantedPosture.Identifier)){
this.SetRandomPosture();
// Add label at posture position that displays recognition confidence
Label confidenceLabel = new Label();
// Math.Round cuts the decimals
double confidenceInPercent = Math.Round(e.RecognizedPosture.Confidence*100.0,0);
confidenceLabel.Content = confidenceInPercent + " %";
confidenceLabel.Width=200.0;
confidenceLabel.Height=50.0;
confidenceLabel.FontSize = 25.0;
confidenceLabel.VerticalContentAlignment = VerticalAlignment.Center;
confidenceLabel.HorizontalContentAlignment = HorizonalAlignment.Center;
// Moves the center of label to the position of the posture
double centerX = e.RecognizedPosture.Position.X - confidenceLabel.Width/2.0;
double centerY = e.RecognizedPosture.Position.Y - confidenceLabel.Height/2.0;
confidenceLabel.RenderTransform = new TranslateTransform(centerX, centerY);
this.Container.Children.Add(confidenceLabel);
} else {
Console.WriteLine(e.RecognizedPosture.Identifier + " is not " + this.WantedPosture.Identifier +".");
}
}