C# 人脸识别

首先说明一下,该人脸识别算法不是用代码实现的,是调用微软云的人脸识别,此处仅仅叙述调用的方法,以及数据的处理。

话不多说,正文开始。

  • 首先注册微软云的账户,在产品中查找“人脸”,获取账户的免费api使用。微软云提供终结点和秘钥。(“快速入门指南”中,微软提供了一个C#控制台应用程序的demo,本博客的关键代码参考该项目)如图:
  • 使用vs2017,新建C#wpf应用程序。
  • 桌面布局如下,这个是wpf应用程序的代码布局,效果,如下图
    <Window x:Class="WpfFaceDetect.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfFaceDetect"
            mc:Ignorable="d"
            Title="MainWindow" Height="400" Width="650">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="413*"/>
                <ColumnDefinition Width="230*"/>
            </Grid.ColumnDefinitions>
            <Image x:Name="image" HorizontalAlignment="Left" Height="300" VerticalAlignment="Top" Width="400"/>
            <Button Content="打开文件" HorizontalAlignment="Left" Margin="56.95,25,0,0" VerticalAlignment="Top" Width="100" Height="50" Cursor="Hand" FontSize="18" FontFamily="STSong" RenderTransformOrigin="0.303,0.36" Click="Button_Click" FontWeight="Bold" Grid.Column="1"/>
            <ListBox x:Name="listBox" HorizontalAlignment="Left" Height="220" Margin="400,80,0,0" VerticalAlignment="Top" Width="240" FontSize="16" FontFamily="STSong" Grid.ColumnSpan="2"/>
            <Label x:Name="lab_result" Content="未选择图片" HorizontalAlignment="Left" Margin="0,300,0,0" VerticalAlignment="Top" Grid.ColumnSpan="2" Height="70" Width="640" FontFamily="STSong" FontSize="16"/>
    
        </Grid>
    </Window>
    

下面就是全部的代码

faceDetect.cs

using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace WpfFaceDetect
{
    class faceDetect
    {
        // Replace <Subscription Key> with your valid subscription key.
        const string subscriptionKey = "1415759b75fb46ff9c45ad7db517c7fe";

        // NOTE: You must use the same region in your REST call as you used to
        // obtain your subscription keys. For example, if you obtained your
        // subscription keys from westus, replace "westcentralus" in the URL
        // below with "westus".
        //
        // Free trial subscription keys are generated in the westcentralus region.
        // If you use a free trial subscription key, you shouldn't need to change
        // this region.
        const string uriBase =
            "https://westcentralus.api.cognitive.microsoft.com/face/v1.0/detect";
        /// <summary>
        /// Gets the analysis of the specified image by using the Face REST API.
        /// </summary>
        /// <param name="imageFilePath">The image file.</param>
        public static async Task<string> MakeAnalysisRequest(string imageFilePath)
        {
            HttpClient client = new HttpClient();

            // Request headers.
            client.DefaultRequestHeaders.Add(
                "Ocp-Apim-Subscription-Key", subscriptionKey);

            // Request parameters. A third optional parameter is "details".
            string requestParameters = "returnFaceId=true&returnFaceLandmarks=false" +
                "&returnFaceAttributes=age,gender,headPose,smile,facialHair,glasses," +
                "emotion,hair,makeup,occlusion,accessories,blur,exposure,noise";

            // Assemble the URI for the REST API Call.
            string uri = uriBase + "?" + requestParameters;

            HttpResponseMessage response;

            // Request body. Posts a locally stored JPEG image.
            byte[] byteData = GetImageAsByteArray(imageFilePath);

            using (ByteArrayContent content = new ByteArrayContent(byteData))
            {
                // This example uses content type "application/octet-stream".
                // The other content types you can use are "application/json"
                // and "multipart/form-data".
                content.Headers.ContentType =
                    new MediaTypeHeaderValue("application/octet-stream");

                // Execute the REST API call.
                response = await client.PostAsync(uri, content);

                // Get the JSON response.
                string contentString = await response.Content.ReadAsStringAsync();

                // Display the JSON response.


                //Console.WriteLine("\nResponse:\n");
                //Console.WriteLine(JsonPrettyPrint(contentString));
                //Console.WriteLine("\nPress Enter to exit...");
                //return JsonPrettyPrint(contentString);
                return contentString;
            }
        }

        /// <summary>
        /// Returns the contents of the specified file as a byte array.
        /// </summary>
        /// <param name="imageFilePath">The image file to read.</param>
        /// <returns>The byte array of the image data.</returns>
        public static byte[] GetImageAsByteArray(string imageFilePath)
        {
            using (FileStream fileStream =
                new FileStream(imageFilePath, FileMode.Open, FileAccess.Read))
            {
                BinaryReader binaryReader = new BinaryReader(fileStream);
                return binaryReader.ReadBytes((int)fileStream.Length);
            }
        }
    }
}

MainWindow.cs

using Microsoft.Win32;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media.Imaging;

namespace WpfFaceDetect
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
            listBox.Items.Add("初始化成功");
        }
        
        /// <summary>
        /// 按钮响应事件,执行以下几个功能
        ///     打开文件对话框,选择文件
        ///     将选择的文件显示在界面上
        ///     将图片进行识别,获取返回信息(返回的信息是标准的json格式)
        ///     处理json文件,获取信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            listBox.Items.Add("选择文件");

            //打开文件资源管理器
            OpenFileDialog openFileDialog = new OpenFileDialog();
            //默认打开路径
            openFileDialog.InitialDirectory = "E:\\pictreTest\\";
            //文件过滤器
            openFileDialog.Filter = openFileDialog.Filter = "jpg文件|*.jpg*|png文件|*.png*|全部文件|*.*";
            openFileDialog.RestoreDirectory = true;
            //确认选择的文件
            if (openFileDialog.ShowDialog() == true)
            {
                lab_result.Content = "请稍等。。";

                string filename = openFileDialog.FileName;
                listBox.Items.Add("确认选择文件,文件是:\n\t" + filename);
                //显示文件在界面上
                bool openImageResult = showImage(filename);
                listBox.Items.Add("正在打开文件。。");
                //文件打开结果判定
                if (openImageResult)
                {
                    listBox.Items.Add("文件打开成功");
                    listBox.Items.Add("请稍后。。");
                    //人脸识别的判定
                    var result = await faceDetect.MakeAnalysisRequest(filename);

                    /*
                     * use reference "Newtonsoft.Json"
                     * 需要注意的是,注意json文件的格式,定义类的时候注意相应的内容
                     * json文件'[]'内的内容是一个数组,需要使用下面形式的List<Object>的样式,
                     * 然后使用获取数组中元素的方式获取每个对象即可
                     * 
                     * json'{}'内的内容是一个对象,直接获取就可以,使用
                     *          Object name = JsonConvert.DeserializeObject<Object>(jsonString)
                     * 获取对象之后直接使用即可
                     */
                    //处理返回数据
                    List<RootObject> root = JsonConvert.DeserializeObject<List<RootObject>>(result);
                    RootObject rootObject = root[0];

                    string genger = rootObject.faceAttributes.gender;
                    string age = rootObject.faceAttributes.age;
                    string emotion = ForeachClass.GetMaxProperties(rootObject.faceAttributes.emotion);
                    string glasses = rootObject.faceAttributes.glasses;
                    listBox.Items.Add("请查看结果");
                    //打印处理新年西
                    printInformation(genger,age,emotion,glasses);
                }
                else
                {
                    listBox.Items.Add("文件打开失败,请重试!");
                }
            }
            else
            {
                listBox.Items.Add("取消文件选择");
                listBox.Items.Add("您未选择任何文件");
            }
        }
        
        /// <summary>
        /// 打印处理过的信息,信息显示在label上
        /// </summary>
        /// <param name="genger">gender</param>
        /// <param name="age">age</param>
        /// <param name="emotion">emotion</param>
        /// <param name="glasses">glasses</param>
        private void printInformation(string genger, string age, string emotion, string glasses)
        {
            string answer = "性别是:" + genger + "\t\t年龄是:" + age + "\n"
                       + "情感是:" + emotion + "\t\t眼镜:\t" + glasses;
            lab_result.Content = answer;
        }
        
        /// <summary>
        /// 将选中的文件显示在界面上
        /// </summary>
        /// <param name="filename">文件路径</param>
        /// <returns>是否显示成功</returns>
        private bool showImage(string filename)
        {
            try
            {

                string path = filename;//获取图片绝对路径
                BitmapImage im = new BitmapImage(new Uri(path, UriKind.Absolute));//打开图片
                image.Source = im;//将控件和图片绑定,logo为Image控件名称
                return true;
            }
            catch
            {
                return false;
            }
        }

    }
}

指的一提的是,微软提供的api的返回内容是标准的json格式文件,json文件解析可以参考https://www.cnblogs.com/zxtceq/p/6610214.html   针对该api的返回内容,有这样的返回文件,也就是说,所有的处理结果返回的json都是这样的标准结构,那么处理的类就有RootObject.cs文件的内容

[
    {
      "faceId": "a9aca673-34c6-4215-9c00-38edde342fe1",
      "faceRectangle": {
         "top": 255,
         "left": 504,
         "width": 469,
         "height": 469
      },
      "faceAttributes": {
         "smile": 0.001,
         "headPose": {
            "pitch": 0.0,
            "roll": -3.1,
            "yaw": -8.6
         },
         "gender": "female",
         "age": 22.0,
         "facialHair": {
            "moustache": 0.0,
            "beard": 0.0,
            "sideburns": 0.0
         },
         "glasses": "NoGlasses",
         "emotion": {
            "anger": 0.0,
            "contempt": 0.007,
            "disgust": 0.0,
            "fear": 0.0,
            "happiness": 0.001,
            "neutral": 0.986,
            "sadness": 0.006,
            "surprise": 0.0
         },
         "blur": {
            "blurLevel": "medium",
            "value": 0.33
         },
         "exposure": {
            "exposureLevel": "goodExposure",
            "value": 0.66
         },
         "noise": {
            "noiseLevel": "high",
            "value": 1.0
         },
         "makeup": {
            "eyeMakeup": true,
            "lipMakeup": false
         },
         "accessories": [
            
         ],
         "occlusion": {
            "foreheadOccluded": false,
            "eyeOccluded": false,
            "mouthOccluded": false
         },
         "hair": {
            "bald": 0.23,
            "invisible": false,
            "hairColor": [
               {
                  "color": "gray",
                  "confidence": 0.92
               },
               {
                  "color": "blond",
                  "confidence": 0.91
               },
               {
                  "color": "other",
                  "confidence": 0.55
               },
               {
                  "color": "black",
                  "confidence": 0.45
               },
               {
                  "color": "brown",
                  "confidence": 0.16
               },
               {
                  "color": "red",
                  "confidence": 0.05
               }
            ]
         }
      }
   }
]


RootObject.cs

using System;
using System.Collections.Generic;
using System.Reflection;

namespace WpfFaceDetect
{
    public class FaceRectangle
    {
        public string top { get; set; }
        public string left { get; set; }
        public string width { get; set; }
        public string height { get; set; }
    }

    public class HeadPose
    {
        public string pitch { get; set; }
        public string roll { get; set; }
        public string yaw { get; set; }
    }

    public class FacialHair
    {
        public string moustache { get; set; }
        public string beard { get; set; }
        public string sideburns { get; set; }
    }

    public class Emotion
    {
        public string anger { get; set; }
        public string contempt { get; set; }
        public string disgust { get; set; }
        public string fear { get; set; }
        public string happiness { get; set; }
        public string neutral { get; set; }
        public string sadness { get; set; }
        public string surprise { get; set; }
    }
    public class ForeachClass
    {
        /// <summary>
        /// C#反射遍历对象属性
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="model">对象</param>
        public static void ForeachClassProperties<T>(T model)
        {
            Type t = model.GetType();
            PropertyInfo[] PropertyList = t.GetProperties();
            foreach (PropertyInfo item in PropertyList)
            {
                string name = item.Name;
                object value = item.GetValue(model, null);
            }
        }
        public static string GetMaxProperties(Emotion model)
        {
            string resultName = "";
            double resultValue = 0.0;
            Type t = model.GetType();
            PropertyInfo[] PropertyList = t.GetProperties();
            foreach (PropertyInfo item in PropertyList)
            {
                string name = item.Name;
                object value = item.GetValue(model, null);
                double inValue = Double.Parse(value.ToString());
                if(inValue > resultValue)
                {
                    resultValue = inValue;
                    resultName = name;
                }
            }
            return resultName;
        }
    }

    public class Blur
    {
        public string blurLevel { get; set; }
        public string value { get; set; }
    }

    public class Exposure
    {
        public string exposureLevel { get; set; }
        public string value { get; set; }
    }

    public class Noise
    {
        public string noiseLevel { get; set; }
        public string value { get; set; }
    }

    public class Makeup
    {
        public string eyeMakeup { get; set; }
        public string lipMakeup { get; set; }
    }

    public class Accessories
    {
    }

    public class Occlusion
    {
        public string foreheadOccluded { get; set; }
        public string eyeOccluded { get; set; }
        public string mouthOccluded { get; set; }
    }

    public class HairColor
    {
        public string color { get; set; }
        public string confidence { get; set; }
    }

    public class Hair
    {
        public string bald { get; set; }
        public string invisible { get; set; }
        public List<HairColor> hairColor { get; set; }
    }

    public class FaceAttributes
    {
        public string smile { get; set; }
        public HeadPose headPose { get; set; }
        public string gender { get; set; }
        public string age { get; set; }
        public FacialHair facialHair { get; set; }
        public string glasses { get; set; }
        public Emotion emotion { get; set; }
        public Blur blur { get; set; }
        public Exposure exposure { get; set; }
        public Noise noise { get; set; }
        public Makeup makeup { get; set; }
        public List<Accessories> accessories { get; set; }
        public Occlusion occlusion { get; set; }
        public Hair hair { get; set; }
       
    }
    public class RootObject
    {
        public string faceId { get; set; }
        public FaceRectangle faceRectangle { get; set; }
        public FaceAttributes faceAttributes { get; set; }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值