В прошлой статье я рассказал, что такое Microsoft Project Oxford и как создать бота на Telegram который определяет пол и возраст по фото на PHP.

Но сегодня, я покажу пример WPF приложения с использованием Microsoft Project Oxford Client SDK и C# на подобии How-Old.net



Приступим:

1) Открываем Visual Studio 2015 и создаем проект WPF



2) Следующим шагом нам нужно установить через Manage NuGet Packages — Newtonsoft.Json



3) Открываем MainWindow.xaml и добавляем Image и Button

<Image x:Name="FacePhoto" HorizontalAlignment="Left" Height="240" Margin="72,25,0,0" VerticalAlignment="Top" Width="381"/>
 <Button x:Name="button" Content="Нажми меня" HorizontalAlignment="Left" Height="28" Margin="72,281,0,0" VerticalAlignment="Top" Width="381" Click="button_Click"/>


4) Переходим к коду, добавляем код на кнопку, для загрузки фотографии
 private async void button_Click(object sender, RoutedEventArgs e)
        {
         
            var openDlg = new Microsoft.Win32.OpenFileDialog();

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

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


5) Теперь нужно установить так же через Manage NuGet Packages — Microsoft.ProjectOxford.Face



6) Теперь нужно подключить следующие директивы

using Microsoft.ProjectOxford.Face;
using Microsoft.ProjectOxford.Face.Contract;


После того как все приготовления сделаны, приступаем к самому интересному =)

7) Создаем пременную которая будет хранить ключ API

private readonly IFaceServiceClient faceServiceClient = new FaceServiceClient("key");


8) Функции которая будет обрабатывать фото.

private async Task<FaceRectangle[]> UploadAndDetectFaces(string imageFilePath)
        {
            List<FaceAttributeType> FaceAG = new List<FaceAttributeType>();
            a.Add(FaceAttributeType.Age);
            a.Add(FaceAttributeType.Gender);// параметры которые хотим узнать

            try
            {
                using (Stream imageFileStream = File.OpenRead(imageFilePath))
                {
                    var faces = await faceServiceClient.DetectAsync(imageFileStream, true, false, FaceAG); // отправляем фото на анализ
                    var faceRects = faces.Select(face => face.FaceRectangle); // получаем список лиц
                    var faceA = faces.Select(face => face.FaceAttributes);// получаем атрибуты - пол и возраст
                    faceAtr = faceA.ToArray();
                    return faceRects.ToArray();
                }
            }
            catch (Exception)
            {
                return new FaceRectangle[0];
            }
        }


Вот и все, теперь осталось немного оформить приложение, обведем лица на фото и выведем пол и возраст.

Для удобства подключил консоль, куда буду выводить возраст и пол.

Идем в функцию обработчика кнопки и добавляем туда следующий код:

            Title = "Анализ...";
            FaceRectangle[] faceRects = await UploadAndDetectFaces(filePath);
            Title = String.Format("Найдено. {0} лиц", faceRects.Length);

            
            if (faceRects.Length > 0)
            {
                DrawingVisual visual = new DrawingVisual();
                DrawingContext drawingContext = visual.RenderOpen();
                drawingContext.DrawImage(bitmapSource,
                    new Rect(0, 0, bitmapSource.Width, bitmapSource.Height));
                double dpi = bitmapSource.DpiX;
                double resizeFactor = 96 / dpi;

                foreach (var faceRect in faceRects)
                {
                    drawingContext.DrawRectangle(
                        Brushes.Transparent,
                        new Pen(Brushes.Red, 2),
                        new Rect(
                            faceRect.Left * resizeFactor,
                            faceRect.Top * resizeFactor,
                            faceRect.Width * resizeFactor,
                            faceRect.Height * resizeFactor
                            )
                    );
                }

                drawingContext.Close();
                RenderTargetBitmap faceWithRectBitmap = new RenderTargetBitmap(
                    (int)(bitmapSource.PixelWidth * resizeFactor),
                    (int)(bitmapSource.PixelHeight * resizeFactor),
                    96,
                    96,
                    PixelFormats.Pbgra32);

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

            foreach (var fecea in faceAtr)
            {
                Console.WriteLine("Возраст: {0}", fecea.Age);
                Console.WriteLine("Пол: {0}", fecea.Gender);
                Console.WriteLine();

            }


В итоге у нас получится следующее



На этом все, небольшой пример приложения готов, всем удачи!

Комментарии (14)


  1. qrck13
    22.04.2016 16:31
    +1

    Точность этого фреймворка — явно хуже чем ± 0.1 года, в лучшем случае ± 5-10 лет. Выглядит не очень грамотно в подобном случае отображение возраста с точностью до десятых долей.


    1. qrck13
      22.04.2016 16:36
      +2

      P.S. Испытал how-old.net на массе фоток с одной и той-же прогулки, т.е. снятых в один и тот-же день, одним и тем-же фотоаппаратом, при примерно одинаковой освещенности. Возраст супруги от фотки к фотке, сервис определяет в диапазоне от 26 до 48 лет, мой — от 38 до 55. А возраст моей 7-ми летней дочки — определяет в диапазоне от 5 до 31 (!!!) года.


      1. m08pvv
        23.04.2016 13:30
        +2

        А возраст моей 7-ми летней дочки — определяет в диапазоне от 5 до 31 (!!!) года.

        Дети быстро взрослеют.


  1. kirilldudka
    22.04.2016 16:37

    Прошлый ответ случайно отклонил, о точности говорить сложно т.к, на некоторых фотографиях определяется достаточно точно, конечно многое зависит и от качество фото (тени, косметика, ракурс), достаточно, вспомнить фото девушек в соц сетях, когда непонятно ей 20 или 12 =)

    Суть топика было в том, чтобы показать как работать с апи и не более.


    1. Alexeyco
      22.04.2016 17:27
      +1

      достаточно, вспомнить фото девушек в соц сетях, когда непонятно ей 20 или 12 =)
      Когда не понятно, парень это или девушка


      1. kirilldudka
        22.04.2016 17:50

        Тогда не нужно разбираться, нужно бежать


        1. Alexeyco
          22.04.2016 23:15

          Уточните, пожалуйста, бежать куда именно?


          1. MuratovTM
            23.04.2016 15:01

            Здесь скорей имеется ввиду не куда, а откуда… :)


  1. KvanTTT
    22.04.2016 18:28
    +2

    В посте описаны тривиальные вещи, а таких статей куча. Не знаю, зачем это на хабре.


  1. lazarevgb
    24.04.2016 17:26

    var faces = await faceServiceClient.DetectAsync(imageFileStream, true, false, FaceAG);
    Кидает исключение FaceAPIException. Подскажите, пожалуйста, как решается такая проблема?


    1. kirilldudka
      24.04.2016 17:26

      HTTP статус какой?


      1. Ronniel95
        25.04.2016 10:08

        Та же проблема, а что за статус?


        1. kirilldudka
          25.04.2016 16:54

          скрин, пожалуйста


          1. Ronniel95
            26.04.2016 16:53

            Exception thrown: 'Microsoft.ProjectOxford.Face.FaceAPIException' in mscorlib.dll