Uso del atributo HeadPose

En esta guía verá cómo puede usar el atributo HeadPose de una cara detectada para habilitar algunos escenarios clave.

Importante

Los atributos de caras se pueden predecir mediante algoritmos estadísticos. No obstante, es posible que no sean siempre precisos. Tenga cuidado al tomar decisiones basadas en datos de atributos. Absténgase de utilizar estos atributos contra la suplantación de identidad. En su lugar, se recomienda usar la detección Face Liveness. Para más información, consulte Tutorial: Detección de vivacidad en caras.

Giro del rectángulo de cara

El rectángulo facial, que se devuelve con cada rostro detectado, marca la ubicación y el tamaño de la cara en la imagen. De forma predeterminada, el rectángulo siempre se alinea con la imagen (sus lados son vertical y horizontal); esto puede resultar ineficaz para enmarcar caras en ángulo. En casos en los que desea recortar mediante programación las caras de una imagen, es mejor ser capaz de girar el rectángulo de recorte.

La aplicación de ejemplo Azure AI Face WPF (Windows Presentation Foundation) usa el atributo HeadPose para girar los rectángulos de cara detectados.

Exploración del código de ejemplo

El atributo HeadPose permite girar mediante programación el rectángulo de cara. Si especifica este atributo cuando se detectan caras (consulte Llamada a la API de detección), podrá realizar consultas en él más adelante. El siguiente método de la aplicación Azure AI Face WPF recibe una lista de objetos DetectedFace y devuelve una lista de objetos Face. Aquí Face es una clase personalizada que almacena datos de cara, incluidas las coordenadas del rectángulo actualizado. Se calculan nuevos valores para top, left, width y height y un nuevo campo FaceAngle especifica el giro.

/// <summary>
/// Calculate the rendering face rectangle
/// </summary>
/// <param name="faces">Detected face from service</param>
/// <param name="maxSize">Image rendering size</param>
/// <param name="imageInfo">Image width and height</param>
/// <returns>Face structure for rendering</returns>
public static IEnumerable<Face> CalculateFaceRectangleForRendering(IList<DetectedFace> faces, int maxSize, Tuple<int, int> imageInfo)
{
    var imageWidth = imageInfo.Item1;
    var imageHeight = imageInfo.Item2;
    var ratio = (float)imageWidth / imageHeight;
    int uiWidth = 0;
    int uiHeight = 0;
    if (ratio > 1.0)
    {
        uiWidth = maxSize;
        uiHeight = (int)(maxSize / ratio);
    }
    else
    {
        uiHeight = maxSize;
        uiWidth = (int)(ratio * uiHeight);
    }

    var uiXOffset = (maxSize - uiWidth) / 2;
    var uiYOffset = (maxSize - uiHeight) / 2;
    var scale = (float)uiWidth / imageWidth;

    foreach (var face in faces)
    {
        var left = (int)(face.FaceRectangle.Left * scale + uiXOffset);
        var top = (int)(face.FaceRectangle.Top * scale + uiYOffset);

        // Angle of face rectangles, default value is 0 (not rotated).
        double faceAngle = 0;

        // If head pose attributes have been obtained, re-calculate the left & top (X & Y) positions.
        if (face.FaceAttributes?.HeadPose != null)
        {
            // Head pose's roll value acts directly as the face angle.
            faceAngle = face.FaceAttributes.HeadPose.Roll;
            var angleToPi = Math.Abs((faceAngle / 180) * Math.PI);

            // _____       | / \ |
            // |____|  =>  |/   /|
            //             | \ / |
            // Re-calculate the face rectangle's left & top (X & Y) positions.
            var newLeft = face.FaceRectangle.Left +
                face.FaceRectangle.Width / 2 -
                (face.FaceRectangle.Width * Math.Sin(angleToPi) + face.FaceRectangle.Height * Math.Cos(angleToPi)) / 2;

            var newTop = face.FaceRectangle.Top +
                face.FaceRectangle.Height / 2 -
                (face.FaceRectangle.Height * Math.Sin(angleToPi) + face.FaceRectangle.Width * Math.Cos(angleToPi)) / 2;

            left = (int)(newLeft * scale + uiXOffset);
            top = (int)(newTop * scale + uiYOffset);
        }

        yield return new Face()
        {
            FaceId = face.FaceId?.ToString(),
            Left = left,
            Top = top,
            OriginalLeft = (int)(face.FaceRectangle.Left * scale + uiXOffset),
            OriginalTop = (int)(face.FaceRectangle.Top * scale + uiYOffset),
            Height = (int)(face.FaceRectangle.Height * scale),
            Width = (int)(face.FaceRectangle.Width * scale),
            FaceAngle = faceAngle,
        };
    }
}

Presentación del rectángulo actualizado

A partir de aquí, puede usar los objetos Face devueltos en la pantalla. Las siguientes líneas de FaceDetectionPage.xaml muestran cómo se representa el nuevo rectángulo a partir de estos datos:

 <DataTemplate>
    <Rectangle Width="{Binding Width}" Height="{Binding Height}" Stroke="#FF26B8F4" StrokeThickness="1">
        <Rectangle.LayoutTransform>
            <RotateTransform Angle="{Binding FaceAngle}"/>
        </Rectangle.LayoutTransform>
    </Rectangle>
</DataTemplate>

Pasos siguientes

  • Consulte la aplicación Azure AI Face WPF en GitHub para ver un ejemplo práctico de rectángulos de cara girados.
  • O bien, consulte la aplicación del ejemplo de HeadPose para Face, que realiza el seguimiento del atributo HeadPose en tiempo real para detectar movimientos de cabeza.