Utilizar o atributo HeadPose

Neste guia, você verá como pode usar o atributo HeadPose de um rosto detetado para habilitar alguns cenários importantes.

Importante

Os atributos faciais são previstos através do uso de algoritmos estatísticos. Podem nem sempre ser precisas. Tenha cuidado ao tomar decisões com base em dados de atributos. Por favor, evite 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 faces (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 DetectedFace e retorna uma lista de objetos Face. Face aqui é uma classe personalizada que armazena dados de face, 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<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,
        };
    }
}

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óximos passos

  • Consulte o aplicativo Azure AI Face WPF no GitHub para obter um exemplo prático de retângulos de face rotacionados.
  • Ou consulte o aplicativo Face HeadPose Sample, que rastreia o atributo HeadPose em tempo real para detetar movimentos da cabeça.