Partilhar via


Utilizar o atributo HeadPose

Neste guia, você aprenderá como usar o atributo HeadPose de um rosto detetado para habilitar alguns cenários-chave.

Importante

Os atributos faciais são previstos usando algoritmos estatísticos. Podem nem sempre ser precisas. Tenha cuidado ao tomar decisões com base em dados de atributos. Abster-se de usar esses atributos para anti-falsificação. Em vez disso, recomendamos o uso da deteção de vivacidade facial. Para obter mais informações, consulte Tutorial : Detetar vivacidade em rostos.

Rodar o retângulo facial

O retângulo facial, retornado a cada face detetada, marca a localização e o tamanho do rosto na imagem. Por padrão, o retângulo está sempre alinhado com a imagem (seus lados são verticais e horizontais); Isso pode ser ineficiente para enquadrar rostos angulados. Em situações em que você deseja cortar rostos de forma programática em uma imagem, é melhor poder girar o retângulo para cortar.

O aplicativo de exemplo Azure AI Face WPF (Windows Presentation Foundation) usa o atributo HeadPose para girar seus retângulos faciais detetados.

Explore o código de exemplo

Você pode girar programaticamente o retângulo facial usando o atributo HeadPose. Se você especificar esse atributo ao detetar rostos (consulte Chamar a API de deteção), poderá consultá-lo mais tarde. O método a seguir do aplicativo Azure AI Face WPF usa uma lista de objetos FaceDetectionResult e retorna uma lista de objetos Face . Aqui, Face é uma classe personalizada que armazena dados de rosto, incluindo as coordenadas de retângulo atualizadas. Novos valores são calculados para cima, esquerda, largura e altura, e um novo campo FaceAngle especifica a rotação.

/// <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<FaceDetectionResult> 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,
        };
    }
}

Exibir o retângulo atualizado

A partir daqui, pode utilizar os objetos Face devolvidos no seu ecrã. As seguintes linhas de FaceDetectionPage.xaml mostram como o novo retângulo é renderizado a partir desses dados:

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

Próximo passo

Consulte o aplicativo Azure AI Face WPF no GitHub para obter um exemplo prático de retângulos de face rotacionados.