استخدام سمة HeadPose

في هذا الدليل، سترى كيف يمكنك استخدام سمة HeadPose للوجه المكتشف لتمكين بعض السيناريوهات الرئيسية.

هام

يتم التنبؤ بسمات الوجه مـن خلال استخدام الخوارزميات الإحصائية. قد لا تكون دائمًا دقيقة. توخي الحذر عند اتخاذ قرارات استنادًا إلى بيانات السمة. يرجى الامتناع عن استخدام هذه السمات لمكافحة تزييف هوية. بدلا من ذلك، نوصي باستخدام الكشف عن Face Liveness. لمزيد من المعلومات، يرجى الرجوع إلى البرنامج التعليمي: الكشف عن الحياة في الوجوه.

تدوير مستطيل الوجه

يشير مستطيل الوجه، الذي يتم إرجاعه مع كل وجه تم اكتشافه، إلى موقع وحجم الوجه في الصورة. بشكل افتراضي، تتم محاذاة المستطيل دائمًا مع الصورة (جوانبها رأسية وأفقية)؛ قد يكون هذا غير فعال لتأطير الوجوه بزاوية. في المواقف التي تريد فيها اقتصاص الوجوه في صورة برمجيًّا، من الأفضل أن تكون قادرًا على تدوير المستطيل لاقتصاصه.

يستخدم تطبيق نموذج Azure الذكاء الاصطناعي Face WPF (Windows Presentation Foundation) السمة HeadPose لتدوير مستطيلات الوجه المكتشفة.

استكشاف التعليمة البرمجية العينة

يمكنك تدوير مستطيل الوجه برمجيًّا باستخدام سمة HeadPose. إذا حددت هذه السمة عند اكتشاف الوجوه (راجع استدعاء API للاكتشاف )، فستتمكن من الاستعلام عنها لاحقًا. يأخذ الأسلوب التالي من تطبيق Azure الذكاء الاصطناعي Face WPF قائمة بعناصر DetectedFace ويعيد قائمة كائنات 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>

الخطوات التالية