@@ -34,13 +34,17 @@ public enum DisplayFrameType
34
34
BodyJoints ,
35
35
BackgroundRemoved ,
36
36
FaceOnColor ,
37
- FaceOnInfrared
37
+ FaceOnInfrared ,
38
+ FaceGame
38
39
}
39
40
40
41
public sealed partial class MainPage : Page , INotifyPropertyChanged
41
42
{
42
43
private const DisplayFrameType DEFAULT_DISPLAYFRAMETYPE = DisplayFrameType . Infrared ;
43
44
45
+ private const double FACE_AIMING_ACCURACY = 1.0 ;
46
+ private const double FACE_AIMING_SENSITIVITY = 0.01 ;
47
+
44
48
/// <summary>
45
49
/// The highest value that can be returned in the InfraredFrame.
46
50
/// It is cast to a float for readability in the visualization code.
@@ -113,6 +117,10 @@ public sealed partial class MainPage : Page, INotifyPropertyChanged
113
117
//Cat assets
114
118
private Image [ ] catEyeRightOpen , catEyeRightClosed , catEyeLeftOpen , catEyeLeftClosed , catNose ;
115
119
120
+ //Face Orientation Shaping
121
+ private double prevPitch = 0.0f ;
122
+ private double prevYaw = 0.0f ;
123
+
116
124
public event PropertyChangedEventHandler PropertyChanged ;
117
125
public string StatusText
118
126
{
@@ -391,6 +399,13 @@ private void SetupCurrentDisplay(DisplayFrameType newDisplayFrameType)
391
399
this . FacePointsCanvas . Height = infraredFrameDescription . Height ;
392
400
break ;
393
401
402
+ case DisplayFrameType . FaceGame :
403
+ colorFrameDescription = this . kinectSensor . ColorFrameSource . FrameDescription ;
404
+ this . CurrentFrameDescription = colorFrameDescription ;
405
+ this . FacePointsCanvas . Width = colorFrameDescription . Width ;
406
+ this . FacePointsCanvas . Height = colorFrameDescription . Height ;
407
+ break ;
408
+
394
409
default :
395
410
break ;
396
411
}
@@ -540,16 +555,69 @@ private void Reader_MultiSourceFrameArrived(MultiSourceFrameReader sender, Multi
540
555
DrawFaceOnInfrared ( ) ;
541
556
}
542
557
break ;
558
+ case DisplayFrameType . FaceGame :
559
+ FaceGameLookUpdate ( ) ;
560
+ break ;
543
561
default :
544
562
break ;
545
563
}
546
564
}
547
565
566
+ private void FaceGameLookUpdate ( )
567
+ {
568
+ this . FacePointsCanvas . Children . Clear ( ) ;
569
+ FaceFrameResult [ ] results = faceManager . GetLatestFaceFrameResults ( ) ;
570
+ for ( int i = 0 ; i < results . Count ( ) ; i ++ )
571
+ {
572
+ if ( results [ i ] != null )
573
+ {
574
+ foreach ( KeyValuePair < FacePointType , Point > facePointKVP in
575
+ results [ i ] . FacePointsInColorSpace )
576
+ {
577
+ if ( facePointKVP . Value . X == 0.0 || facePointKVP . Value . Y == 0.0 )
578
+ {
579
+ break ;
580
+ }
581
+ Size ellipseSize = new Size ( 10 , 10 ) ;
582
+ Ellipse ellipse = new Ellipse ( ) ;
583
+ ellipse . Width = ellipseSize . Width ;
584
+ ellipse . Height = ellipseSize . Height ;
585
+ ellipse . Fill = new SolidColorBrush ( Colors . Red ) ;
586
+ Canvas . SetLeft ( ellipse , facePointKVP . Value . X - ( ellipseSize . Width / 2 ) ) ;
587
+ Canvas . SetTop ( ellipse , facePointKVP . Value . Y - ( ellipseSize . Height / 2 ) ) ;
588
+ this . FacePointsCanvas . Children . Add ( ellipse ) ;
589
+ }
590
+
591
+ double pitch , roll , yaw = 0 ;
592
+
593
+ ExtractFaceRotationInDegrees ( results [ i ] . FaceRotationQuaternion , out pitch , out yaw , out roll ) ;
594
+
595
+ double pitchDiff = Math . Abs ( pitch - prevPitch ) ;
596
+ double yawDiff = Math . Abs ( yaw - prevYaw ) ;
597
+ if ( pitchDiff > FACE_AIMING_ACCURACY ||
598
+ yawDiff > FACE_AIMING_ACCURACY )
599
+ {
600
+ this . DXScenePanel . SetYawPitch (
601
+ - ( float ) ( yaw * FACE_AIMING_SENSITIVITY ) ,
602
+ ( float ) ( pitch * FACE_AIMING_SENSITIVITY ) ) ;
603
+ prevPitch = pitch ;
604
+ prevYaw = yaw ;
605
+ }
606
+
607
+ if ( results [ i ] . FaceProperties [ FaceProperty . MouthOpen ] == DetectionResult . Yes )
608
+ {
609
+ this . DXScenePanel . Fire ( ) ;
610
+ }
611
+ break ;
612
+ }
613
+ }
614
+ }
615
+
548
616
private void DrawFaceOnInfrared ( )
549
617
{
550
618
FacePointsCanvas . Children . Clear ( ) ;
551
619
FaceFrameResult [ ] results = faceManager . GetLatestFaceFrameResults ( ) ;
552
- for ( int i = 0 ; i < results . Count ( ) ; i ++ )
620
+ for ( int i = 0 ; i < results . Count ( ) ; i ++ )
553
621
{
554
622
if ( results [ i ] != null )
555
623
{
@@ -869,6 +937,19 @@ private void RenderPixelArray(byte[] pixels)
869
937
this . FrameDisplayImage . Source = this . bitmap ;
870
938
}
871
939
940
+ private static void ExtractFaceRotationInDegrees ( Vector4 rotQuaternion , out double pitch , out double yaw , out double roll )
941
+ {
942
+ double x = rotQuaternion . X ;
943
+ double y = rotQuaternion . Y ;
944
+ double z = rotQuaternion . Z ;
945
+ double w = rotQuaternion . W ;
946
+
947
+ // convert face rotation quaternion to Euler angles in degrees
948
+ pitch = Math . Atan2 ( 2 * ( ( y * z ) + ( w * x ) ) , ( w * w ) - ( x * x ) - ( y * y ) + ( z * z ) ) / Math . PI * 180.0 ;
949
+ yaw = Math . Asin ( 2 * ( ( w * y ) - ( x * z ) ) ) / Math . PI * 180.0 ;
950
+ roll = Math . Atan2 ( 2 * ( ( x * y ) + ( w * z ) ) , ( w * w ) + ( x * x ) - ( y * y ) - ( z * z ) ) / Math . PI * 180.0 ;
951
+ }
952
+
872
953
private void InfraredButton_Click ( object sender , RoutedEventArgs e )
873
954
{
874
955
SetupCurrentDisplay ( DisplayFrameType . Infrared ) ;
@@ -914,5 +995,10 @@ interface IBufferByteAccess
914
995
{
915
996
unsafe void Buffer ( out byte * pByte ) ;
916
997
}
998
+
999
+ private void FaceGameButton_Click ( object sender , RoutedEventArgs e )
1000
+ {
1001
+ SetupCurrentDisplay ( DisplayFrameType . FaceGame ) ;
1002
+ }
917
1003
}
918
1004
}
0 commit comments