Use the face client library to quickly realize the analysis of the face---C#

Show results:

insert image description here

Step 1: Install the face client library and window-related libraries

Add the following using directives:

///人脸客户端库
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;

using Microsoft.Azure.CognitiveServices.Vision.Face;
using Microsoft.Azure.CognitiveServices.Vision.Face.Models;

///窗口相关库
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;

Step 2: Declare and initialize related variables

Create variables for the resource's key and endpoint
// 添加你自己的密钥
private static string subscriptionKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxx";
// 添加终结点
private static string faceEndpoint = "https://cnsoft.cognitiveservices.azure.cn/";
Client Constructor
private readonly IFaceClient faceClient = new FaceClient(
    new ApiKeyServiceClientCredentials(subscriptionKey),
    new System.Net.Http.DelegatingHandler[] { }
);

FaceClient: This class represents the authorization to use the face service, which is required to use all face functions. Please instantiate this class with your subscription information, then use it to generate instances of other classes.

Picture-related variables
// 检测到的人脸的列表
private IList<DetectedFace> faceList;
// 检测到的人脸描述 字符串数组
private string[] faceDescriptions;
// 显示图像的调整大小因子。
private double resizeFactor;

DectectedFace: This class represents all data that has been detected from a single face in the image. You can use it to retrieve detailed information about a face.

window toolbar
private const string defaultStatusBarText =
    "Place the mouse pointer over a face to see the face description.";

Step 3: MainWindow Window Constructor

public MainWindow()
        {
            //初始化窗口组件
            InitializeComponent();
            //如果字符串格式良好,为人脸客户端终结点赋值
            if (Uri.IsWellFormedUriString(faceEndpoint, UriKind.Absolute))
            {
                faceClient.Endpoint = faceEndpoint;
            }
            else//否则的话显示错误信息
            {
                MessageBox.Show(faceEndpoint,
                    "Invalid URI", MessageBoxButton.OK, MessageBoxImage.Error);
                Environment.Exit(0);
            }
            
        }

Uri.IsWellFormedUriString(String, UriKind): This method indicates whether the string is well-formed by attempting to construct a URI from the string, and ensures that the string does not require further escaping.

Step 4: Method: BrowseButton_Click realizes clicking the button to get the display image and calls the UploadAndDetectFaces method to display a rectangle around the face

        private async void BrowseButton_Click(object sender, RoutedEventArgs e)
        {
            //从用户获取图片文件
            var openDlg = new Microsoft.Win32.OpenFileDialog();
            //指定图片格式
            openDlg.Filter = "JPEG Image(*.jpg)|*.jpg";
            //判断是否获取成功
            bool? result = openDlg.ShowDialog(this);

            // Return if canceled.
            if (!(bool)result)
            {
                return;
            }

            / 显示图片
            string filePath = openDlg.FileName;

            Uri fileUri = new Uri(filePath);
            BitmapImage bitmapSource = new BitmapImage();

            bitmapSource.BeginInit();
            bitmapSource.CacheOption = BitmapCacheOption.None;
            bitmapSource.UriSource = fileUri;
            bitmapSource.EndInit();

            FacePhoto.Source = bitmapSource;
            

            
            / 检测所有的人脸
            Title = "Detecting...";
            faceList = await UploadAndDetectFaces(filePath);//上传并检测
            Title = String.Format(
                "Detection Finished. {0} face(s) detected", faceList.Count);

            if (faceList.Count > 0)
            {
                // 准备从人脸周围话矩形
                DrawingVisual visual = new DrawingVisual();
                DrawingContext drawingContext = visual.RenderOpen();
                drawingContext.DrawImage(bitmapSource,
                    new Rect(0, 0, bitmapSource.Width, bitmapSource.Height));
                double dpi = bitmapSource.DpiX;
                // 一些图片可能没有dpi
                resizeFactor = (dpi == 0) ? 1 : 96 / dpi;
                faceDescriptions = new String[faceList.Count];

                for (int i = 0; i < faceList.Count; ++i)
                {
                    DetectedFace face = faceList[i];

                    // 在人脸周围画矩形
                    drawingContext.DrawRectangle(
                        Brushes.Transparent,
                        new Pen(Brushes.Red, 2),
                        new Rect(
                            face.FaceRectangle.Left * resizeFactor,
                            face.FaceRectangle.Top * resizeFactor,
                            face.FaceRectangle.Width * resizeFactor,
                            face.FaceRectangle.Height * resizeFactor
                            )
                    );

                    // 将人脸的相关描述进行存储
                    faceDescriptions[i] = FaceDescription(face);
                }
                if (faceList.Count > 0)
                {
                    TheEmotion.Text = "复制下面全部信息:\n" + faceDescriptions[0];
                }
                drawingContext.Close();

                // 显示人脸周围的矩形
                RenderTargetBitmap faceWithRectBitmap = new RenderTargetBitmap(
                    (int)(bitmapSource.PixelWidth * resizeFactor),
                    (int)(bitmapSource.PixelHeight * resizeFactor),
                    96,
                    96,
                    PixelFormats.Pbgra32);

                faceWithRectBitmap.Render(visual);
                FacePhoto.Source = faceWithRectBitmap;

                // 设置显示人脸描述的工具栏
                faceDescriptionStatusBar.Text = defaultStatusBarText;
            }
        }

Step 5: Method FacePhoto_MouseMove: When the mouse moves to the face rectangle, the relevant face description information is displayed

        private void FacePhoto_MouseMove(object sender, MouseEventArgs e)
        {
            // 如果这个REST还没有完成,直接 return
            if (faceList == null)
                return;

            // 找到图片相对于鼠标的位置
            Point mouseXY = e.GetPosition(FacePhoto);

            ImageSource imageSource = FacePhoto.Source;
            BitmapSource bitmapSource = (BitmapSource)imageSource;

            //调整比例
            var scale = FacePhoto.ActualWidth / (bitmapSource.PixelWidth / resizeFactor);

            // 检查是否在矩形内
            bool mouseOverFace = false;

            for (int i = 0; i < faceList.Count; ++i)
            {
                FaceRectangle fr = faceList[i].FaceRectangle;
                double left = fr.Left * scale;
                double top = fr.Top * scale;
                double width = fr.Width * scale;
                double height = fr.Height * scale;

                // 展示信息如果在矩形内
                if (mouseXY.X >= left && mouseXY.X <= left + width &&
                    mouseXY.Y >= top && mouseXY.Y <= top + height)
                {
                    faceDescriptionStatusBar.Text = faceDescriptions[i];
                    mouseOverFace = true;
                    break;
                }
            }

            // 如果不在显示默认信息
            if (!mouseOverFace) faceDescriptionStatusBar.Text = defaultStatusBarText;
        }

Step 6: Method UploadAndDetectFaces: upload image and call DetectWithStreamAsync

        private async Task<IList<DetectedFace>> UploadAndDetectFaces(string imageFilePath)
        {
            // 人脸属性的返回列表
            IList<FaceAttributeType?> faceAttributes =
                new FaceAttributeType?[]
                {
                    FaceAttributeType.Gender, FaceAttributeType.Age,
                    FaceAttributeType.Smile, FaceAttributeType.Emotion,
                    FaceAttributeType.Glasses, FaceAttributeType.Hair
                };

            // 调用人脸API
            try
            {
                using (Stream imageFileStream = File.OpenRead(imageFilePath))
                {
                    IList<DetectedFace> faceList =
                        await faceClient.Face.DetectWithStreamAsync(
                            imageFileStream, true, false, faceAttributes);
                    return faceList;
                }
            }
            // 调用出错
            catch (APIErrorException f)
            {
                MessageBox.Show(f.Message);
                return new List<DetectedFace>();
            }
            // Catch 并且展示所有错误信息
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "Error");
                return new List<DetectedFace>();
            }
        }

Step 7: Method FaceDescription: Process the string of face description

private string FaceDescription(DetectedFace face)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("Face: ");

            //添加性别年龄和微笑描述
            sb.Append(face.FaceAttributes.Gender);
            sb.Append(", ");
            sb.Append(face.FaceAttributes.Age);
            sb.Append(", ");
            sb.Append(String.Format("smile {0:F1}% ", face.FaceAttributes.Smile * 100));
            sb.Append("\n");

            // 添加情绪描述
          
            Emotion emotionScores = face.FaceAttributes.Emotion;

            sb.Append("anger: "+ emotionScores.Anger + "\n");
            sb.Append("contempt: " + emotionScores.Contempt + "\n");
            sb.Append("disgust: " + emotionScores.Disgust + "\n");
            sb.Append("fear: " + emotionScores.Fear + "\n");
            sb.Append("happiness: " + emotionScores.Happiness + "\n");
            sb.Append("neutral: " + emotionScores.Neutral + "\n");
            sb.Append("sadness: " + emotionScores.Sadness + "\n");
            sb.Append("surprise: " + emotionScores.Surprise + "\n");
            

            // 添加是否戴眼镜
            sb.Append("ifhasGlasses: "+face.FaceAttributes.Glasses);
            sb.Append("\n ");

            // 添加头发描述
            sb.Append("Hair: ");

            //秃头率
            if (face.FaceAttributes.Hair.Bald >= 0.01f)
                sb.Append(String.Format("bald {0:F1}% ", face.FaceAttributes.Hair.Bald * 100));

            // 头发颜色
            IList<HairColor> hairColors = face.FaceAttributes.Hair.HairColor;
            foreach (HairColor hairColor in hairColors)
            {
                if (hairColor.Confidence >= 0.1f)
                {
                    sb.Append(hairColor.Color.ToString());
                    sb.Append(String.Format(" {0:F1}% ", hairColor.Confidence * 100));
                }
            }

            // R返回字符串
            return sb.ToString();
        }

full code

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
// using System.Windows.Controls;
// using System.Windows.Data;
// using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
// using System.Windows.Navigation;
// using System.Windows.Shapes;
using Microsoft.Azure.CognitiveServices.Vision.Face;
using Microsoft.Azure.CognitiveServices.Vision.Face.Models;

namespace C14_WPF_EmotionAcuiring
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    
    public partial class MainWindow : Window
    {
        // <snippet_mainwindow_fields>
        // Add your Face subscription key to your environment variables.
        private static string subscriptionKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx";
        // Add your Face endpoint to your environment variables.
        private static string faceEndpoint = "https://cnsoft.cognitiveservices.azure.cn/";

        private readonly IFaceClient faceClient = new FaceClient(
            new ApiKeyServiceClientCredentials(subscriptionKey),
            new System.Net.Http.DelegatingHandler[] { });

        // The list of detected faces.
        private IList<DetectedFace> faceList;
        // The list of descriptions for the detected faces.
        private string[] faceDescriptions;
        // The resize factor for the displayed image.
        private double resizeFactor;

        private const string defaultStatusBarText =
            "Place the mouse pointer over a face to see the face description.";
        // </snippet_mainwindow_fields>

        // <snippet_mainwindow_constructor>
        public MainWindow()
        {
            InitializeComponent();

            if (Uri.IsWellFormedUriString(faceEndpoint, UriKind.Absolute))
            {
                faceClient.Endpoint = faceEndpoint;
            }
            else
            {
                MessageBox.Show(faceEndpoint,
                    "Invalid URI", MessageBoxButton.OK, MessageBoxImage.Error);
                Environment.Exit(0);
            }
            
        }
        // </snippet_mainwindow_constructor>

        // <snippet_browsebuttonclick_start>
        // Displays the image and calls UploadAndDetectFaces.
        private async void BrowseButton_Click(object sender, RoutedEventArgs e)
        {
            // Get the image file to scan from the user.
            var openDlg = new Microsoft.Win32.OpenFileDialog();

            openDlg.Filter = "JPEG Image(*.jpg)|*.jpg";
            bool? result = openDlg.ShowDialog(this);

            // Return if canceled.
            if (!(bool)result)
            {
                return;
            }

            // Display the image file.
            string filePath = openDlg.FileName;

            Uri fileUri = new Uri(filePath);
            BitmapImage bitmapSource = new BitmapImage();

            bitmapSource.BeginInit();
            bitmapSource.CacheOption = BitmapCacheOption.None;
            bitmapSource.UriSource = fileUri;
            bitmapSource.EndInit();

            FacePhoto.Source = bitmapSource;
            // </snippet_browsebuttonclick_start>

            // <snippet_browsebuttonclick_mid>
            // Detect any faces in the image.
            Title = "Detecting...";
            faceList = await UploadAndDetectFaces(filePath);
            Title = String.Format(
                "Detection Finished. {0} face(s) detected", faceList.Count);

            if (faceList.Count > 0)
            {
                // Prepare to draw rectangles around the faces.
                DrawingVisual visual = new DrawingVisual();
                DrawingContext drawingContext = visual.RenderOpen();
                drawingContext.DrawImage(bitmapSource,
                    new Rect(0, 0, bitmapSource.Width, bitmapSource.Height));
                double dpi = bitmapSource.DpiX;
                // Some images don't contain dpi info.
                resizeFactor = (dpi == 0) ? 1 : 96 / dpi;
                faceDescriptions = new String[faceList.Count];

                for (int i = 0; i < faceList.Count; ++i)
                {
                    DetectedFace face = faceList[i];

                    // Draw a rectangle on the face.
                    drawingContext.DrawRectangle(
                        Brushes.Transparent,
                        new Pen(Brushes.Red, 2),
                        new Rect(
                            face.FaceRectangle.Left * resizeFactor,
                            face.FaceRectangle.Top * resizeFactor,
                            face.FaceRectangle.Width * resizeFactor,
                            face.FaceRectangle.Height * resizeFactor
                            )
                    );

                    // Store the face description.
                    faceDescriptions[i] = FaceDescription(face);
                }
                if (faceList.Count > 0)
                {
                    TheEmotion.Text = "复制下面全部信息:\n" + faceDescriptions[0];
                }
                drawingContext.Close();

                // Display the image with the rectangle around the face.
                RenderTargetBitmap faceWithRectBitmap = new RenderTargetBitmap(
                    (int)(bitmapSource.PixelWidth * resizeFactor),
                    (int)(bitmapSource.PixelHeight * resizeFactor),
                    96,
                    96,
                    PixelFormats.Pbgra32);

                faceWithRectBitmap.Render(visual);
                FacePhoto.Source = faceWithRectBitmap;

                // Set the status bar text.
                faceDescriptionStatusBar.Text = defaultStatusBarText;
            }
            // </snippet_browsebuttonclick_mid>
            // <snippet_browsebuttonclick_end>
        }
        // </snippet_browsebuttonclick_end>

        // <snippet_mousemove_start>
        // Displays the face description when the mouse is over a face rectangle.
        private void FacePhoto_MouseMove(object sender, MouseEventArgs e)
        {
            // </snippet_mousemove_start>

            // <snippet_mousemove_mid>
            // If the REST call has not completed, return.
            if (faceList == null)
                return;

            // Find the mouse position relative to the image.
            Point mouseXY = e.GetPosition(FacePhoto);

            ImageSource imageSource = FacePhoto.Source;
            BitmapSource bitmapSource = (BitmapSource)imageSource;

            // Scale adjustment between the actual size and displayed size.
            var scale = FacePhoto.ActualWidth / (bitmapSource.PixelWidth / resizeFactor);

            // Check if this mouse position is over a face rectangle.
            bool mouseOverFace = false;

            for (int i = 0; i < faceList.Count; ++i)
            {
                FaceRectangle fr = faceList[i].FaceRectangle;
                double left = fr.Left * scale;
                double top = fr.Top * scale;
                double width = fr.Width * scale;
                double height = fr.Height * scale;

                // Display the face description if the mouse is over this face rectangle.
                if (mouseXY.X >= left && mouseXY.X <= left + width &&
                    mouseXY.Y >= top && mouseXY.Y <= top + height)
                {
                    faceDescriptionStatusBar.Text = faceDescriptions[i];
                    mouseOverFace = true;
                    break;
                }
            }

            // String to display when the mouse is not over a face rectangle.
            if (!mouseOverFace) faceDescriptionStatusBar.Text = defaultStatusBarText;
            // </snippet_mousemove_mid>
            // <snippet_mousemove_end>
        }
        // </snippet_mousemove_end>

        // <snippet_uploaddetect>
        // Uploads the image file and calls DetectWithStreamAsync.
        private async Task<IList<DetectedFace>> UploadAndDetectFaces(string imageFilePath)
        {
            // The list of Face attributes to return.
            IList<FaceAttributeType?> faceAttributes =
                new FaceAttributeType?[]
                {
                    FaceAttributeType.Gender, FaceAttributeType.Age,
                    FaceAttributeType.Smile, FaceAttributeType.Emotion,
                    FaceAttributeType.Glasses, FaceAttributeType.Hair
                };

            // Call the Face API.
            try
            {
                using (Stream imageFileStream = File.OpenRead(imageFilePath))
                {
                    // The second argument specifies to return the faceId, while
                    // the third argument specifies not to return face landmarks.
                    IList<DetectedFace> faceList =
                        await faceClient.Face.DetectWithStreamAsync(
                            imageFileStream, true, false, faceAttributes);
                    return faceList;
                }
            }
            // Catch and display Face API errors.
            catch (APIErrorException f)
            {
                MessageBox.Show(f.Message);
                return new List<DetectedFace>();
            }
            // Catch and display all other errors.
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "Error");
                return new List<DetectedFace>();
            }
        }
        // </snippet_uploaddetect>

        // <snippet_facedesc>
        // Creates a string out of the attributes describing the face.
        private string FaceDescription(DetectedFace face)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("Face: ");

            // Add the gender, age, and smile.
            sb.Append(face.FaceAttributes.Gender);
            sb.Append(", ");
            sb.Append(face.FaceAttributes.Age);
            sb.Append(", ");
            sb.Append(String.Format("smile {0:F1}% ", face.FaceAttributes.Smile * 100));
            sb.Append("\n");

            // Add the emotions. Display all emotions over 10%.
          
            Emotion emotionScores = face.FaceAttributes.Emotion;

            sb.Append("anger: "+ emotionScores.Anger + "\n");
            sb.Append("contempt: " + emotionScores.Contempt + "\n");
            sb.Append("disgust: " + emotionScores.Disgust + "\n");
            sb.Append("fear: " + emotionScores.Fear + "\n");
            sb.Append("happiness: " + emotionScores.Happiness + "\n");
            sb.Append("neutral: " + emotionScores.Neutral + "\n");
            sb.Append("sadness: " + emotionScores.Sadness + "\n");
            sb.Append("surprise: " + emotionScores.Surprise + "\n");
            

            // Add glasses.
            sb.Append("ifhasGlasses: "+face.FaceAttributes.Glasses);
            sb.Append("\n ");

            // Add hair.
            sb.Append("Hair: ");

            // Display baldness confidence if over 1%.
            if (face.FaceAttributes.Hair.Bald >= 0.01f)
                sb.Append(String.Format("bald {0:F1}% ", face.FaceAttributes.Hair.Bald * 100));

            // Display all hair color attributes over 10%.
            IList<HairColor> hairColors = face.FaceAttributes.Hair.HairColor;
            foreach (HairColor hairColor in hairColors)
            {
                if (hairColor.Confidence >= 0.1f)
                {
                    sb.Append(hairColor.Color.ToString());
                    sb.Append(String.Format(" {0:F1}% ", hairColor.Confidence * 100));
                }
            }

            // Return the built string.
            return sb.ToString();
        }
        // </snippet_facedesc>
    }
}


Guess you like

Origin blog.csdn.net/weixin_47138646/article/details/122173909