Facebook
From Harmless Rhinoceros, 5 Years ago, written in Plain Text.
Embed
Download Paste or View Raw
Hits: 256
  1.  
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using System.Windows;
  8. using System.Windows.Input;
  9. using System.Windows.Media;
  10. using System.Windows.Media.Imaging;
  11. using Microsoft.ProjectOxford.Common.Contract;
  12. using Microsoft.ProjectOxford.Face;
  13. using Microsoft.ProjectOxford.Face.Contract;
  14.  
  15. namespace WpfAppFace
  16. {
  17.     public partial class MainWindow : Window
  18.     {
  19.         // Replace the first parameter with your valid subscription key.
  20.         //
  21.         // Replace or verify the region in the second parameter.
  22.         //
  23.         // You must use the same region in your REST API call as you used to obtain your subscription keys.
  24.         // For example, if you obtained your subscription keys from the westus region, replace
  25.         // "westcentralus" in the URI below with "westus".
  26.         //
  27.         // NOTE: Free trial subscription keys are generated in the westcentralus region, so if you are using
  28.         // a free trial subscription key, you should not need to change this region.
  29.         private readonly IFaceServiceClient faceServiceClient =
  30.             new FaceServiceClient("525704c19bf845aa8b5b119683772268", "https://westcentralus.api.cognitive.microsoft.com/face/v1.0");
  31.  
  32.         Face[] faces;                   // The list of detected faces.
  33.         String[] faceDescriptions;      // The list of descriptions for the detected faces.
  34.         double resizeFactor;            // The resize factor for the displayed image.
  35.  
  36.         public MainWindow()
  37.         {
  38.             InitializeComponent();
  39.         }
  40.  
  41.         // Displays the image and calls Detect Faces.
  42.  
  43.         private async void BrowseButton_Click(object sender, RoutedEventArgs e)
  44.         {
  45.             // Get the image file to scan from the user.
  46.             var openDlg = new Microsoft.Win32.OpenFileDialog();
  47.  
  48.             openDlg.Filter = "JPEG Image(*.jpg)|*.jpg";
  49.             bool? result = openDlg.ShowDialog(this);
  50.  
  51.             // Return if canceled.
  52.             if (!(bool)result)
  53.             {
  54.                 return;
  55.             }
  56.  
  57.             // Display the image file.
  58.             string filePath = openDlg.FileName;
  59.  
  60.             Uri fileUri = new Uri(filePath);
  61.             BitmapImage bitmapSource = new BitmapImage();
  62.  
  63.             bitmapSource.BeginInit();
  64.             bitmapSource.CacheOption = BitmapCacheOption.None;
  65.             bitmapSource.UriSource = fileUri;
  66.             bitmapSource.EndInit();
  67.  
  68.             FacePhoto.Source = bitmapSource;
  69.  
  70.             // Detect any faces in the image.
  71.             Title = "Detecting...";
  72.             faces = await UploadAndDetectFaces(filePath);
  73.             Title = String.Format("Detection Finished. {0} face(s) detected", faces.Length);
  74.  
  75.             if (faces.Length > 0)
  76.             {
  77.                 // Prepare to draw rectangles around the faces.
  78.                 DrawingVisual visual = new DrawingVisual();
  79.                 DrawingContext drawingContext = visual.RenderOpen();
  80.                 drawingContext.DrawImage(bitmapSource,
  81.                     new Rect(0, 0, bitmapSource.Width, bitmapSource.Height));
  82.                 double dpi = bitmapSource.DpiX;
  83.                 resizeFactor = 96 / dpi;
  84.                 faceDescriptions = new String[faces.Length];
  85.  
  86.                 for (int i = 0; i < faces.Length; ++i)
  87.                 {
  88.                     Face face = faces[i];
  89.  
  90.                     // Draw a rectangle on the face.
  91.                     drawingContext.DrawRectangle(
  92.                         Brushes.Transparent,
  93.                         new Pen(Brushes.Red, 2),
  94.                         new Rect(
  95.                             face.FaceRectangle.Left * resizeFactor,
  96.                             face.FaceRectangle.Top * resizeFactor,
  97.                             face.FaceRectangle.Width * resizeFactor,
  98.                             face.FaceRectangle.Height * resizeFactor
  99.                             )
  100.                     );
  101.  
  102.                     // Store the face description.
  103.                     faceDescriptions[i] = FaceDescription(face);
  104.                 }
  105.  
  106.                 drawingContext.Close();
  107.  
  108.                 // Display the image with the rectangle around the face.
  109.                 RenderTargetBitmap faceWithRectBitmap = new RenderTargetBitmap(
  110.                     (int)(bitmapSource.PixelWidth * resizeFactor),
  111.                     (int)(bitmapSource.PixelHeight * resizeFactor),
  112.                     96,
  113.                     96,
  114.                     PixelFormats.Pbgra32);
  115.  
  116.                 faceWithRectBitmap.Render(visual);
  117.                 FacePhoto.Source = faceWithRectBitmap;
  118.  
  119.                 // Set the status bar text.
  120.                 faceDescriptionStatusBar.Text = "Place the mouse pointer over a face to see the face description.";
  121.             }
  122.         }
  123.  
  124.         // Displays the face description when the mouse is over a face rectangle.
  125.  
  126.         private void FacePhoto_MouseMove(object sender, MouseEventArgs e)
  127.         {
  128.             // If the REST call has not completed, return from this method.
  129.             if (faces == null)
  130.                 return;
  131.  
  132.             // Find the mouse position relative to the image.
  133.             Point mouseXY = e.GetPosition(FacePhoto);
  134.  
  135.             ImageSource imageSource = FacePhoto.Source;
  136.             BitmapSource bitmapSource = (BitmapSource)imageSource;
  137.  
  138.             // Scale adjustment between the actual size and displayed size.
  139.             var scale = FacePhoto.ActualWidth / (bitmapSource.PixelWidth / resizeFactor);
  140.  
  141.             // Check if this mouse position is over a face rectangle.
  142.             bool mouseOverFace = false;
  143.  
  144.             for (int i = 0; i < faces.Length; ++i)
  145.             {
  146.                 FaceRectangle fr = faces[i].FaceRectangle;
  147.                 double left = fr.Left * scale;
  148.                 double top = fr.Top * scale;
  149.                 double width = fr.Width * scale;
  150.                 double height = fr.Height * scale;
  151.  
  152.                 // Display the face description for this face if the mouse is over this face rectangle.
  153.                 if (mouseXY.X >= left && mouseXY.X <= left + width && mouseXY.Y >= top && mouseXY.Y <= top + height)
  154.                 {
  155.                     faceDescriptionStatusBar.Text = faceDescriptions[i];
  156.                     mouseOverFace = true;
  157.                     break;
  158.                 }
  159.             }
  160.  
  161.             // If the mouse is not over a face rectangle.
  162.             if (!mouseOverFace)
  163.                 faceDescriptionStatusBar.Text = "Place the mouse pointer over a face to see the face description.";
  164.         }
  165.  
  166.         // Uploads the image file and calls Detect Faces.
  167.  
  168.         private async Task<Face[]> UploadAndDetectFaces(string imageFilePath)
  169.         {
  170.             // The list of Face attributes to return.
  171.             IEnumerable<FaceAttributeType> faceAttributes =
  172.                 new FaceAttributeType[] { FaceAttributeType.Gender, FaceAttributeType.Age, FaceAttributeType.Smile, FaceAttributeType.Emotion, FaceAttributeType.Glasses, FaceAttributeType.Hair };
  173.  
  174.             // Call the Face API.
  175.             try
  176.             {
  177.                 using (Stream imageFileStream = File.OpenRead(imageFilePath))
  178.                 {
  179.                     Face[] faces = await faceServiceClient.DetectAsync(imageFileStream, returnFaceId: true, returnFaceLandmarks: false, returnFaceAttributes: faceAttributes);
  180.                     return faces;
  181.                 }
  182.             }
  183.             // Catch and display Face API errors.
  184.             catch (FaceAPIException f)
  185.             {
  186.                 MessageBox.Show(f.ErrorMessage, f.ErrorCode);
  187.                 return new Face[0];
  188.             }
  189.             // Catch and display all other errors.
  190.             catch (Exception e)
  191.             {
  192.                 MessageBox.Show(e.Message, "Error");
  193.                 return new Face[0];
  194.             }
  195.         }
  196.  
  197.         // Returns a string that describes the given face.
  198.  
  199.         private string FaceDescription(Face face)
  200.         {
  201.             StringBuilder sb = new StringBuilder();
  202.  
  203.             sb.Append("Face: ");
  204.  
  205.             // Add the gender, age, and smile.
  206.             sb.Append(face.FaceAttributes.Gender);
  207.             sb.Append(", ");
  208.             sb.Append(face.FaceAttributes.Age);
  209.             sb.Append(", ");
  210.             sb.Append(String.Format("smile {0:F1}%, ", face.FaceAttributes.Smile * 100));
  211.  
  212.             // Add the emotions. Display all emotions over 10%.
  213.             sb.Append("Emotion: ");
  214.             EmotionScores emotionScores = face.FaceAttributes.Emotion;
  215.             if (emotionScores.Anger >= 0.1f) sb.Append(String.Format("anger {0:F1}%, ", emotionScores.Anger * 100));
  216.             if (emotionScores.Contempt >= 0.1f) sb.Append(String.Format("contempt {0:F1}%, ", emotionScores.Contempt * 100));
  217.             if (emotionScores.Disgust >= 0.1f) sb.Append(String.Format("disgust {0:F1}%, ", emotionScores.Disgust * 100));
  218.             if (emotionScores.Fear >= 0.1f) sb.Append(String.Format("fear {0:F1}%, ", emotionScores.Fear * 100));
  219.             if (emotionScores.Happiness >= 0.1f) sb.Append(String.Format("happiness {0:F1}%, ", emotionScores.Happiness * 100));
  220.             if (emotionScores.Neutral >= 0.1f) sb.Append(String.Format("neutral {0:F1}%, ", emotionScores.Neutral * 100));
  221.             if (emotionScores.Sadness >= 0.1f) sb.Append(String.Format("sadness {0:F1}%, ", emotionScores.Sadness * 100));
  222.             if (emotionScores.Surprise >= 0.1f) sb.Append(String.Format("surprise {0:F1}%, ", emotionScores.Surprise * 100));
  223.  
  224.             // Add glasses.
  225.             sb.Append(face.FaceAttributes.Glasses);
  226.             sb.Append(", ");
  227.  
  228.             // Add hair.
  229.             sb.Append("Hair: ");
  230.  
  231.             // Display baldness confidence if over 1%.
  232.             if (face.FaceAttributes.Hair.Bald >= 0.01f)
  233.                 sb.Append(String.Format("bald {0:F1}% ", face.FaceAttributes.Hair.Bald * 100));
  234.  
  235.             // Display all hair color attributes over 10%.
  236.             HairColor[] hairColors = face.FaceAttributes.Hair.HairColor;
  237.             foreach (HairColor hairColor in hairColors)
  238.             {
  239.                 if (hairColor.Confidence >= 0.1f)
  240.                 {
  241.                     sb.Append(hairColor.Color.ToString());
  242.                     sb.Append(String.Format(" {0:F1}% ", hairColor.Confidence * 100));
  243.                 }
  244.             }
  245.  
  246.             // Return the built string.
  247.             return sb.ToString();
  248.         }
  249.     }
  250. }
  251.  
  252.  
  253.  
  254.