Использование атрибута HeadPose

Из этого руководства вы узнаете, как использовать атрибут HeadPose обнаруженного лица для реализации некоторых распространенных сценариев.

Важно!

Прогноз атрибутов лица осуществляется с помощью статистических алгоритмов. Они не всегда точны. Будьте внимательны, когда принимаете решения, основываясь на данных атрибутах. Пожалуйста, воздержаться от использования этих атрибутов для защиты от спуфингов. Вместо этого рекомендуется использовать обнаружение Распознавания лиц в реальном времени. Дополнительные сведения см. в руководстве по обнаружению активности лиц.

Вращение прямоугольной рамки вокруг лица

Прямоугольная рамка вокруг лица, которая возвращается вместе с каждым обнаруженным лицом, отмечает расположение и размер этого лица на изображении. По умолчанию прямоугольник всегда выравнивается по изображению (его стороны расположены вертикально и горизонтально), но это не всегда удобно, если лицо повернуто под углом. Если нужно обрезать лицо в изображении с помощью программных средств, полезно иметь возможность поворачивать прямоугольник для обрезки.

Пример приложения WPF для распознавания лиц Azure (Windows Presentation Foundation) использует атрибут HeadPose для поворота обнаруженных прямоугольников лиц.

Изучение примера кода

Вы можете программно вращать прямоугольную рамку вокруг лица с помощью атрибута HeadPose. Указав этот атрибут при обнаружении лиц (как описано в статье Получение данных определения лиц), вы сможете позднее получить его значение. Следующий метод из приложения WPF распознавания лиц Azure принимает список объектов DetectedFace и возвращает список объектов Face. Здесь Face является пользовательским классом, который хранит данные о лицах, в том числе обновленные координаты прямоугольника. Вычисляются новые значения параметров top (верхний край), left (левый край), width (ширина) и height (высота), а новое поле FaceAngle обозначает вращение.

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

Отображение обновленного прямоугольника

Здесь вы можете использовать полученные объекты Face для отображения на экране. В следующих строках из файла FaceDetectionPage.xaml показано, как отображается новый прямоугольник на основе этих данных:

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

Следующие шаги

  • Ознакомьтесь с приложением WPF для распознавания лиц Azure на сайте GitHub для работы с повернутых прямоугольников лиц.
  • Также вы можете ознакомиться с примером приложения Face HeadPose, которое отслеживает атрибут HeadPose в реальном времени для обнаружения движений головой.