// ====================================================================
// Ref des librairies Microsoft.Kinect
// ====================================================================

using Microsoft.Kinect;
using Microsoft.Kinect.Toolkit.FaceTracking;

// ====================================================================
// Initialisation du KinectSensor et du FaceTracker
// ====================================================================
// Initialize all the necessary streams:
// - ColorStream with default format
// - DepthStream with Near mode and lowest resolution
// - SkeletonStream with tracking in NearReange and Seated mode.
// ====================================================================

kinectSensor.ColorStream.Enable();

kinectSensor.DepthStream.Range = DepthRange.Near;
kinectSensor.DepthStream.Enable(DepthImageFormat.Resolution80x60Fps30);

kinectSensor.SkeletonStream.EnableTrackingInNearRange = true;
kinectSensor.SkeletonStream.TrackingMode = SkeletonTrackingMode.Seated;
kinectSensor.SkeletonStream.Enable(
    new TransformSmoothParameters() {
        Correction = 0.5f, 
        JitterRadius = 0.05f, 
        MaxDeviationRadius = 0.05f, 
        Prediction = 0.5f, 
        Smoothing = 0.5f 
    });

// Listen to the AllFramesReady event to receive KinectSensor's data.
kinectSensor.AllFramesReady += new EventHandler(kinectSensor_AllFramesReady);

// Initialize data arrays
colorPixelData = new byte[kinectSensor.ColorStream.FramePixelDataLength];
depthPixelData = new short[kinectSensor.DepthStream.FramePixelDataLength];
skeletonData = new Skeleton[6];

// Starts the Sensor
kinectSensor.Start();

// Initialize a new FaceTracker with the KinectSensor
faceTracker = new FaceTracker(kinectSensor);


// ====================================================================
//Obtenir une représentation du visage
// ====================================================================
using (ColorImageFrame colorImageFrame = e.OpenColorImageFrame())
{
    if (colorImageFrame == null)
        return;
    colorImageFrame.CopyPixelDataTo(colorPixelData);
}

using (DepthImageFrame depthImageFrame = e.OpenDepthImageFrame())
{
    if (depthImageFrame == null)
        return;
    depthImageFrame.CopyPixelDataTo(depthPixelData);
}

using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
{
    if (skeletonFrame == null)
        return;
    skeletonFrame.CopySkeletonDataTo(skeletonData);
}

var skeleton = skeletonData.FirstOrDefault(s => s.TrackingState == SkeletonTrackingState.Tracked);
if (skeleton == null)
    return;

FaceTrackFrame faceFrame = faceTracker.Track(kinectSensor.ColorStream.Format, colorPixelData,
                                              kinectSensor.DepthStream.Format, depthPixelData,
                                              skeleton);

// ====================================================================
//Dessin simplifié du visage
// ====================================================================


<Window x:Class="AwesomeFaceTracking.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid>
            <Canvas x:Name="MainCanvas" Width="500" Height="500">
                <Canvas.RenderTransform>
                    <TransformGroup>
                        <RotateTransform x:Name="CanvasRotate" CenterX="250" CenterY="250" />
                    </TransformGroup>
                </Canvas.RenderTransform>
                <Ellipse Width="300" Height="300" x:Name="Face"  StrokeThickness="2" Stroke="Black" Canvas.Left="105" Canvas.Top="6" />
                <Ellipse Width="30" Height="30" x:Name="LeftEye" Stroke="Black" StrokeThickness="2" Canvas.Left="289" Canvas.Top="102" />
                <Ellipse Canvas.Left="194" Canvas.Top="102" x:Name="RightEye" Height="30" Stroke="Black" StrokeThickness="2" Width="30" />
                <Ellipse Canvas.Left="224" Canvas.Top="239" Height="18" x:Name="Mouth" Stroke="Black" StrokeThickness="2" Width="64" >
                    <Ellipse.RenderTransform>
                        <ScaleTransform x:Name="MouthScaleTransform" CenterX="32" CenterY="9" ScaleX="1" ScaleY="1"/>
                    </Ellipse.RenderTransform>
                </Ellipse>

                <Rectangle Width="70" Stroke="Black" Fill="Black" StrokeThickness="10" Height="5" Canvas.Left="169" Canvas.Top="80">
                    <Rectangle.RenderTransform>
                        <TransformGroup>
                            <TranslateTransform x:Name="RightBrow" />
                            <RotateTransform x:Name="RightBrowRotate" CenterX="50" Angle="0" />
                        </TransformGroup>
                    </Rectangle.RenderTransform>
                </Rectangle>

                <Rectangle  Width="70" Stroke="Black" Fill="Black" StrokeThickness="10" Height="5" Canvas.Left="274" Canvas.Top="80" >
                    <Rectangle.RenderTransform>
                        <TransformGroup>
                            <TranslateTransform x:Name="LeftBrow" />
                            <RotateTransform x:Name="LeftBrowRotate" CenterX="20" Angle="0" />
                        </TransformGroup>
                    </Rectangle.RenderTransform>
                </Rectangle>
                <Rectangle Canvas.Left="207" Canvas.Top="148" Fill="Black" Height="5" Stroke="Black" StrokeThickness="10" Width="50">
                    <Rectangle.RenderTransform>
                        <TransformGroup>
                            <RotateTransform Angle="-70" CenterX="50" />
                        </TransformGroup>
                    </Rectangle.RenderTransform>
                </Rectangle>
                <Rectangle Canvas.Left="246" Canvas.Top="190" Fill="Black" Height="5" Stroke="Black" StrokeThickness="10" Width="15">
                    <Rectangle.RenderTransform>
                        <TransformGroup>
                            <RotateTransform Angle="0" CenterX="50" />
                        </TransformGroup>
                    </Rectangle.RenderTransform>
                </Rectangle>
            </Canvas>
        </Grid>
    </Grid>
</Window>





// ====================================================================
// Consommation de la frame !
// ====================================================================

if (faceFrame.TrackSuccessful)
{
    // Récupération des coefficients AU
    var AUCoeff = faceFrame.GetAnimationUnitCoefficients();

    // -1 <= x <= 0  => bouche fermée
    // 0 < x < 1 => bouche entrouverte
    // x == 1 => bouche entièrement ouverte
    var jawLowerer = AUCoeff[AnimationUnit.JawLower];
    jawLowerer = jawLowerer < 0 ? 0 : jawLowerer;
    MouthScaleTransform.ScaleY = jawLowerer * 5 + 0.1;
    MouthScaleTransform.ScaleX = (AUCoeff[AnimationUnit.LipStretcher] + 1);

    // Élévation des sourcils
    LeftBrow.Y = RightBrow.Y = (AUCoeff[AnimationUnit.BrowLower]) * 40;

    // Ínclinaison des sourcils
    RightBrowRotate.Angle = (AUCoeff[AnimationUnit.BrowRaiser] * 20);
    LeftBrowRotate.Angle = -RightBrowRotate.Angle;

    // Inclinaison du visage par rapport à l'axe Z
    CanvasRotate.Angle = faceFrame.Rotation.Z;
}