Używanie atrybutu HeadPose

W tym przewodniku dowiesz się, jak za pomocą atrybutu HeadPose wykrytej twarzy włączyć niektóre kluczowe scenariusze.

Ważne

Atrybuty twarzy są przewidywane za pomocą algorytmów statystycznych. Nie zawsze mogą być dokładne. Zachowaj ostrożność podczas podejmowania decyzji na podstawie danych atrybutów. Należy powstrzymać się od używania tych atrybutów do ochrony przed fałszowaniem. Zamiast tego zalecamy użycie wykrywania na żywo twarzy. Aby uzyskać więcej informacji, zobacz Samouczek: wykrywanie liveness na twarzach.

Obróć prostokąt twarzy

Prostokąt twarzy zwrócony z każdą wykrytą twarzą oznacza lokalizację i rozmiar twarzy na obrazie. Domyślnie prostokąt jest zawsze wyrównany do obrazu (jego boki są pionowe i poziome); może to być nieefektywne w przypadku tworzenia ramek pod kątem twarzy. W sytuacjach, w których chcesz programowo przycinać twarze na obrazie, lepiej jest obracać prostokąt do przycinania.

Przykładowa aplikacja azure AI Face WPF (Windows Presentation Foundation) używa atrybutu HeadPose do obracania wykrytych prostokątów twarzy.

Poznawanie przykładowego kodu

Prostokąt twarzy można obracać programowo przy użyciu atrybutu HeadPose. Jeśli określisz ten atrybut podczas wykrywania twarzy (zobacz Wywoływanie interfejsu API wykrywania), będzie można wykonać zapytanie później. Poniższa metoda z aplikacji Azure AI Face WPF pobiera listę obiektów DetectedFace i zwraca listę obiektów rozpoznawania twarzy. Oto klasa niestandardowa, która przechowuje dane twarzy, w tym zaktualizowane współrzędne prostokąta. Nowe wartości są obliczane dla góry, lewej, szerokości i wysokości, a nowe pole FaceAngle określa rotację.

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

Wyświetlanie zaktualizowanego prostokąta

W tym miejscu możesz użyć zwróconych obiektów twarzy na ekranie. Następujące wiersze z pliku FaceDetectionPage.xaml pokazują, jak nowy prostokąt jest renderowany z tych danych:

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

Następne kroki

  • Zobacz aplikację Azure AI Face WPF w witrynie GitHub, aby zapoznać się z działającym przykładem obróconych prostokątów twarzy.
  • Możesz też zobaczyć przykładową aplikację Face HeadPose, która śledzi atrybut HeadPose w czasie rzeczywistym w celu wykrywania ruchów głowy.