Cognitive Services face API in WPF

Cognitive Services

Earlier this year, Microsoft announced its suite services called Cognitive Services. Microsoft Cognitive Services allow you to build intelligent applications using machine learning APIs without writing a ton of code.
 
As defined:
 
Microsoft Cognitive Services are a set of APIs, SDKs and services available to developers to make their applications more intelligent, engaging and discoverable. Microsoft Cognitive Services expands on Microsoft’s evolving portfolio of machine learning APIs and enables developers to easily add intelligent features – such as emotion and video detection; facial, speech and vision recognition; and speech and language understanding – into their applications. Our vision is for more personal computing experiences and enhanced productivity aided by systems that increasingly can see, hear, speak, understand and even begin to reason. 
 
In this article, I will demonstrate how to build a simple WPF application that uses Cognitive Services' Face API to detect faces in photos.

Getting Started

  • Start Visual Studio 2015
  • From the file menu, select New, then Project
  • Select Windows template
  • Select .NET Framework 4.6.1
  • Select WPF Application
  • Enter Name
  • Browse save location
  • Click OK


Right click on project and click on Manage NuGet Packages.


Search Newstonsoft.Json in Browse tab and select stable version and click Install.


Now install one more package using Manage NuGet Package Manager “Microsoft>ProjectOxford.Face” and click Install.


 

Click Accept on License Acceptance.


Now you need to generate a subscription key. Click on this url https://www.microsoft.com/cognitive-services/en-us/face-api and Face from APIs from Header and click get Started to get a free key.


Now select Face-Preview and accept term and click Next.


Now you can see your subscriptions with key, click on show or copy the keys.


Now let’s write code.

XAML Code

  1. <Window x:Class="CognitiveServicesFaceAPI_WPFSample.MainWindow"   
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"   
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"   
  4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   
  5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"   
  6. xmlns:local="clr-namespace:CognitiveServicesFaceAPI_WPFSample"   
  7. mc:Ignorable="d"   
  8. Title="MainWindow" Height="550" Width="725">   
  9. <Grid x:Name="BackPanel">   
  10. <Image x:Name="imgPhoto" Stretch="Uniform" Margin="0,0,0,30"/>   
  11. <Button x:Name="btnBrowse" Margin="20,5" Height="20"   
  12. VerticalAlignment="Bottom" Content="Browse..."   
  13. Click="btnBrowse_Click"/>   
  14. </Grid>   
  15. </Window>  
Xaml.cs Code 

  1. using Microsoft.ProjectOxford.Face;   
  2. using Microsoft.ProjectOxford.Face.Contract;   
  3. using System;   
  4. using System.IO;   
  5. using System.Linq;   
  6. using System.Threading.Tasks;   
  7. using System.Windows;   
  8. using System.Windows.Media;   
  9. using System.Windows.Media.Imaging;  
  10. namespace CognitiveServicesFaceAPI_WPFSample  
  11. {  
  12.   
  13. /// <summary>   
  14. /// Interaction logic for MainWindow.xaml   
  15. /// </summary>  
  16.   
  17. public partial class MainWindow : Window   
  18. {  
  19.   
  20. private readonly IFaceServiceClient objFaceServiceClient = new FaceServiceClient("subscription key");   
  21. public MainWindow()   
  22. {   
  23. InitializeComponent();   
  24. }  
  25.   
  26. private async void btnBrowse_Click(object sender, RoutedEventArgs e)   
  27. {  
  28.   
  29. var openDlg = new Microsoft.Win32.OpenFileDialog();   
  30. openDlg.Filter = "JPEG Image(*.jpg)|*.jpg";   
  31. bool? result = openDlg.ShowDialog(this);   
  32. if (!(bool)result)   
  33. {   
  34. return;   
  35. }  
  36.   
  37. string filePath = openDlg.FileName;   
  38. Uri fileUri = new Uri(filePath);   
  39. BitmapImage bitmapSource = new BitmapImage();   
  40. bitmapSource.BeginInit();   
  41. bitmapSource.CacheOption = BitmapCacheOption.None;   
  42. bitmapSource.UriSource = fileUri;   
  43. bitmapSource.EndInit();   
  44. imgPhoto.Source = bitmapSource;   
  45. Title = "Detecting...";   
  46. FaceRectangle[] faceRects = await UploadAndTrackFaces(filePath);   
  47. Title = String.Format("Detection Finished. {0} face(s) detected", faceRects.Length);  
  48.   
  49. if (faceRects.Length > 0)   
  50. {   
  51. DrawingVisual visual = new DrawingVisual();   
  52. DrawingContext drawingContext = visual.RenderOpen();  
  53. drawingContext.DrawImage(bitmapSource,   
  54. new Rect(0, 0, bitmapSource.Width, bitmapSource.Height));   
  55. double dpi = bitmapSource.DpiX;   
  56. double resizeFactor = 96 / dpi;   
  57. foreach (var faceRect in faceRects)   
  58. {  
  59.   
  60. drawingContext.DrawRectangle(   
  61. Brushes.Transparent,   
  62. new Pen(Brushes.Red, 2),   
  63. new Rect(   
  64. faceRect.Left * resizeFactor,   
  65. faceRect.Top * resizeFactor,   
  66. faceRect.Width * resizeFactor,   
  67. faceRect.Height * resizeFactor   
  68. )   
  69. );   
  70. }  
  71.   
  72. drawingContext.Close();   
  73. RenderTargetBitmap faceWithRectBitmap = new RenderTargetBitmap(   
  74. (int)(bitmapSource.PixelWidth * resizeFactor),   
  75. (int)(bitmapSource.PixelHeight * resizeFactor),   
  76. 96,   
  77. 96,   
  78. PixelFormats.Pbgra32);  
  79.   
  80. faceWithRectBitmap.Render(visual);  
  81. imgPhoto.Source = faceWithRectBitmap;  
  82.   
  83. }  
  84.   
  85. }  
  86.   
  87. private async Task<FaceRectangle[]> UploadAndTrackFaces(string imageFilePath)   
  88. {  
  89.   
  90. try   
  91. {   
  92. using (Stream imageFileStream = File.OpenRead(imageFilePath))   
  93. {  
  94.   
  95. var faces = await objFaceServiceClient.DetectAsync(imageFileStream);   
  96. var faceRects = faces.Select(face => face.FaceRectangle);  
  97.   return faceRects.ToArray();   
  98. }   
  99. }   
  100. catch (Exception)  
  101. {   
  102. return new FaceRectangle[0];   
  103. }   
  104. }   
  105. }   
  106. }  
Now let’s run the project. As you can see when click on Browse button and select image from drive and wait little bit. As you can see in given picture, it show 2 face(s) detected. 


Let’s browse one more picture with more faces. As you can see clearly in the following photo, 4 faces are detected.


Conclusion

In this article, we have seen how to use Microsoft Cognitive Service face API in WPF to detect faces. If you have any question or comments, drop me a comment or message in C# corner comments section.