Share via


Använda attributet HeadPose

I den här guiden får du se hur du kan använda headpose-attributet för ett identifierat ansikte för att aktivera vissa viktiga scenarier.

Viktigt!

Ansiktsattribut förutsägs med hjälp av statistiska algoritmer. De kanske inte alltid är korrekta. Var försiktig när du fattar beslut baserat på attributdata. Avstå från att använda dessa attribut för förfalskning. I stället rekommenderar vi att du använder ansiktsigenkänning. Mer information finns i Självstudie: Identifiera livskraft i ansikten.

Rotera ansiktsrektangeln

Ansiktsrektangeln, som returneras med varje identifierat ansikte, markerar platsen och storleken på ansiktet i bilden. Som standard är rektangeln alltid justerad mot bilden (sidorna är lodräta och vågräta). Detta kan vara ineffektivt för att rama in vinklade ansikten. I situationer där du vill beskära ansikten programmatiskt i en bild är det bättre att kunna rotera rektangeln för att beskära.

Exempelappen Azure AI Face WPF (Windows Presentation Foundation) använder attributet HeadPose för att rotera sina identifierade ansiktsrektanglar.

Utforska exempelkoden

Du kan programmatiskt rotera ansiktsrektangeln med hjälp av attributet HeadPose. Om du anger det här attributet när du identifierar ansikten (se Anropa identifierings-API:et) kan du köra frågor mot det senare. Följande metod från Azure AI Face WPF-appen tar en lista över DetectedFace-objekt och returnerar en lista över ansiktsobjekt . Ansiktet här är en anpassad klass som lagrar ansiktsdata, inklusive de uppdaterade rektangelkoordinaterna. Nya värden beräknas för övre, vänstra, bredd och höjd, och ett nytt fält FaceAngle anger rotationen.

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

Visa den uppdaterade rektangeln

Härifrån kan du använda de returnerade ansiktsobjekten på skärmen. Följande rader från FaceDetectionPage.xaml visar hur den nya rektangeln återges från dessa data:

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

Nästa steg

  • Se Azure AI Face WPF-appen på GitHub för ett fungerande exempel på roterade ansiktsrektanglar.
  • Eller se exempelappen Face HeadPose , som spårar headpose-attributet i realtid för att identifiera huvudrörelser.