Using Azure Face API With ASP.NET MVC

In this article, we are going to learn how to User Azure Face API with ASP.NET MVC in a step by step way.

You can download the Source code from here.

Why do we use Azure Face API?

By using Azure Face API, we can detect, identify, analyze, organize, and tag faces in photos. Before using Azure API, I used to use JavaScript library (jquery.facedetection)  http://facedetection.jaysalvat.com/ which is only used to detect if it is a face or not but does not provide an analysis of faces, such as Gender, Smile, Age etc.

Using Azure Face API, we can get all face analysis and sentiments.
Azure Face API

Icons made by Freepik from www.flaticon.com are licensed by CC 3.0 BY

Note

After downloading the source code, just change the “subscriptionKey” to make it work.

Process Flow

  1. Creating an ASP.NET MVC project.
  2. Get an API key for using Face API
  3. Using HTML Canvas to capture photo and detect faces
  4. Finally, displaying Azure Face API Response

Creating an ASP.NET MVC project

After opening IDE, next, we are going to create an ASP.NET MVC project. For doing that, just click File - New - Project.

After choosing a project, a new dialog will pop up with the name "New Project". In that, we are going to choose Visual C# Project TemplatesàWeb à ASP.NET Web Application. Then, we are going to name the project as " WebCamApp".

After naming the project, click on OK button to create the project. A new dialog will pop up with the name “New ASP.NET Project”; from that, we are going to choose “MVC” templates for creating "MVC" application and we are not going to use any authentication in this application. For that, we are going to choose “No Authentication”. After that, finally, click on the OK button to create the project.

Azure Face API

After completing with creating the project, next, we are going to get Face API Key from Azure portal.

Getting an API key for using Face API
Azure Face API

Credit: Icons made by Round icons from www.flaticon.com  is licensed by CC 3.0 BY.

In order to get an API key, you must register at Microsoft portal.

After registering yourself, just access cognitive-services at the below URL.

https://azure.microsoft.com/en-in/try/cognitive-services/

Below is a snapshot of the View which will appear after accessing the URL.

Azure Face API

In the above View, you can see various cognitive-services. We are first going to work on Face API service. So, just click on Face API “Get API Key” button. A dialog will pop up for Sign-in with the various option. You can choose one and log in to the portal.

Azure Face API

After logging in, you will see Face API service you subscribed along with the API keys.

Azure Face API

After getting the keys, we are going to add CamCaptureAzure Controller.

Adding CamCaptureAzure Controller

For adding a controller, just right click on Controller folder and then choose -> Add -> inside that, choose to Add New item. A new dialog will pop up for adding a new item. Inside that, choose "MVC Controller Class" and name your controller as " CamCaptureAzure " and click on the "Add" button to create a CamCaptureAzure Controller.

Azure Face API

After adding a controller, we are going to add "Capture Action Method" in it for handling the HTTP GET Request.

Adding Capture Action Method

Azure Face API

After adding Capture Action Method, we are going to add Capture View.

Adding Capture View

Azure Face API

On this Capture view, we are going to Use Html 5 Video, Canvas Tag to capture Photo, and along with that I am also going to Add Capture, Delete, Download button on view along with ResponseTable div in which we are going to update Azure Face API Response.

Snapshot of view with video and canvas tag 

Azure Face API

Complete Code Snippet of Capture View

  1. @{  
  2.     Layout = null;  
  3. }  
  4. <!DOCTYPE html>  
  5. <html>  
  6. <head>  
  7.     <meta charset="utf-8">  
  8.     <meta http-equiv="X-UA-Compatible" content="IE=edge">  
  9.     <meta name="viewport" content="width=device-width, initial-scale=1">  
  10.     <title>Demo: Take a Selfie with JavaScript</title>  
  11.     <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">  
  12.     <link href="~/CamScripts/css/styles.css" rel="stylesheet" />  
  13.     <link href="~/Content/bootstrap.css" rel="stylesheet" />  
  14.     <link href="https://use.fontawesome.com/releases/v5.0.6/css/all.css" rel="stylesheet">  
  15. </head>  
  16. <body>  
  17.     <h3>  
  18.         Demo: Take a Photo  
  19.     </h3>  
  20.     <div class="container">  
  21.         <div class="row">  
  22.             <div class="col-md-2"></div>  
  23.             <div class="col-md-6">  
  24.                 <div class="app">  
  25.                     <a href="#" id="start-camera" class="visible">Touch here to start the app.</a>  
  26.                     <video id="camera-stream"></video>  
  27.                     <img id="snap">  
  28.                     <p id="error-message">  
  29.                     </p>  
  30.   
  31.                     <!-- Hidden canvas element. Used for taking snapshot of video. -->  
  32.                     <canvas width="300" height="400"></canvas>  
  33.                 </div>  
  34.             </div>  
  35.   
  36.             <div class="row">  
  37.                 <div class="controls">  
  38.                     <div style="font-size:1.8em; color:Tomato">  
  39.                         <a href="#" id="take-photo" title="Take Photo">  
  40.                             <i class="fas fa-camera-retro fa-sm btn btn-default">  
  41.                                 Capture  
  42.                             </i>  
  43.                         </a>  
  44.                     </div>  
  45.                     <br />  
  46.                     <div style="font-size:1.8em; color:Tomato">  
  47.                         <a href="#" id="delete-photo" title="Delete Photo" class="disabled">  
  48.                             <i class="fas fa-trash fa-sm btn btn-default">  
  49.                                 Delete  
  50.                             </i>  
  51.                         </a>  
  52.                     </div>  
  53.                     <br />  
  54.                     <div style="font-size:1.8em; color:Tomato">  
  55.                         <a href="#" id="download-photo" download="selfie.png" title="Save Photo"  
  56.                            class="disabled">  
  57.                             <i class="fas fa-download fa-sm btn btn-default">  
  58.                                 Download  
  59.                             </i>  
  60.                         </a>  
  61.                     </div>  
  62.                     
  63.                 </div>  
  64.             </div>  
  65.   
  66.             <div class="col-md-2"></div>  
  67.         </div>  
  68.   
  69.         <div class="row">  
  70.             <div class="col-md-12">  
  71.                 <div id="ResponseTable">  
  72.                 </div>  
  73.             </div>  
  74.         </div>  
  75.     </div>  
  76.   
  77.     <style>  
  78.         .contant {  
  79.             border: 1px solid #ddd;  
  80.             border-radius: 4px;  
  81.             width: 500px;  
  82.             padding: 20px;  
  83.             margin: 0 auto;  
  84.             text-align: center;  
  85.         }  
  86.     </style>  
  87. </body>  
  88. </html> 

After completing with adding view next we are going save application and test capture view by accessing it.

Snapshot of Capture View

Azure Face API

After accessing Capture View, next, we are going to add code for capturing a photo on click of capture button, on delete we are going to delete a photo which we have captured and on download, you can download your photo.

After adding View next, we are going to add [HttpPost] method Capture.

Adding [HttpPost] Capture Method

This method will take base64String as input and this string will be converted to bytes and then sent to MakeAnalysisRequest method for analyzing the photo, and also we are storing this image in CapturedPhotos folder.

Code Snippet of [HttpPost] Capture method

  1. [HttpPost]  
  2. public async Task<dynamic> Capture(string base64String)  
  3. {  
  4.   
  5.     if (!string.IsNullOrEmpty(base64String))  
  6.     {  
  7.         var imageParts = base64String.Split(',').ToList<string>();  
  8.         byte[] imageBytes = Convert.FromBase64String(imageParts[1]);  
  9.         DateTime nm = DateTime.Now;  
  10.         string date = nm.ToString("yyyymmddMMss");  
  11.         var path = Server.MapPath("~/CapturedPhotos/" + date + "CamCapture.jpg");  
  12.   
  13.         var response = await MakeAnalysisRequest(imageBytes);  
  14.   
  15.         System.IO.File.WriteAllBytes(path, imageBytes);  
  16.         return Json(data: response);  
  17.     }  
  18.     else  
  19.     {  
  20.         return Json(data: false);  
  21.     }  
  22. }  

After understanding Capture method, next, we are going to understand MakeAnalysisRequest method.

MakeAnalysisRequest method which takes Bytes as an input parameter. 

This method takes photo bytes as input, 

  1. static async Task<string> MakeAnalysisRequest(byte[] imageBytes)  
  2. {  

Setting Subscription-Key and uriBase

After that we are providing subscriptionKey, uriBase parameters which we have received after subscribing to the Face API Service, 

  1. const string subscriptionKey = "7b48c82#########################";  
  2. const string uriBase = "https://westcentralus.api.cognitive.microsoft.com/face/v1.0/detect";  

Next, we are going to create an instance of HttpClient class to send an async Post request to access FACE API service.

  1. HttpClient client = new HttpClient();  

Setting headers for sending Subscription-Key

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

Setting Request parameters

In this part we are going to set the parameter which we want to receive as response.

  1. string requestParameters = "returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes=age, gender, headPose, smile, facialHair, glasses, emotion,hair,makeup,occlusion,accessories,blur,exposure,noise";  

Creating URI

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

Make POST Request call

  1. HttpResponseMessage response;  
  2.   
  3. // Request body. Posts a locally stored JPEG image.  
  4. byte[] byteData = imageBytes;  
  5.   
  6. using (ByteArrayContent content = new ByteArrayContent(byteData))  
  7. {  
  8.     // This example uses content type "application/octet-stream".  
  9.     // The other content types you can use are "application/json" and "multipart/form-data".  
  10.     content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");  
  11.   
  12.     // Execute the REST API call.  
  13.     response = await client.PostAsync(uri, content);  
  14.   
  15.     // Get the JSON response.  
  16.     string contentString = await response.Content.ReadAsStringAsync();  
  17.   
  18.     // Display the JSON response.  
  19.   
  20.     return JsonPrettyPrint(contentString);  
  21.   
  22. }  

Formatting return json

  1. /// <summary>  
  2. /// Formats the given JSON string by adding line breaks and indents.  
  3. /// </summary>  
  4. /// <param name="json">The raw JSON string to format.</param>  
  5. /// <returns>The formatted JSON string.</returns>  
  6. static string JsonPrettyPrint(string json)  
  7. {  
  8.     if (string.IsNullOrEmpty(json))  
  9.         return string.Empty;  
  10.   
  11.     json = json.Replace(Environment.NewLine, "").Replace("\t""");  
  12.   
  13.     StringBuilder sb = new StringBuilder();  
  14.     bool quote = false;  
  15.     bool ignore = false;  
  16.     int offset = 0;  
  17.     int indentLength = 3;  
  18.   
  19.     foreach (char ch in json)  
  20.     {  
  21.         switch (ch)  
  22.         {  
  23.             case '"':  
  24.                 if (!ignore) quote = !quote;  
  25.                 break;  
  26.             case '\'':  
  27.                 if (quote) ignore = !ignore;  
  28.                 break;  
  29.         }  
  30.   
  31.         if (quote)  
  32.             sb.Append(ch);  
  33.         else  
  34.         {  
  35.             switch (ch)  
  36.             {  
  37.                 case '{':  
  38.                 case '[':  
  39.                     sb.Append(ch);  
  40.                     sb.Append(Environment.NewLine);  
  41.                     sb.Append(new string(' ', ++offset * indentLength));  
  42.                     break;  
  43.                 case '}':  
  44.                 case ']':  
  45.                     sb.Append(Environment.NewLine);  
  46.                     sb.Append(new string(' ', --offset * indentLength));  
  47.                     sb.Append(ch);  
  48.                     break;  
  49.                 case ',':  
  50.                     sb.Append(ch);  
  51.                     sb.Append(Environment.NewLine);  
  52.                     sb.Append(new string(' ', offset * indentLength));  
  53.                     break;  
  54.                 case ':':  
  55.                     sb.Append(ch);  
  56.                     sb.Append(' ');  
  57.                     break;  
  58.                 default:  
  59.                     if (ch != ' ') sb.Append(ch);  
  60.                     break;  
  61.             }  
  62.         }  
  63.     }  
  64.   
  65.     return sb.ToString().Trim();  
  66. }  

Complete Code Snippet of MakeAnalysisRequest

  1. /// <summary>  
  2. ///  Gets the analysis of the specified image bytes by using the Computer Vision REST API.  
  3. /// </summary>  
  4. /// <param name="imageBytes"></param>  
  5. /// <returns></returns>  
  6. static async Task<string> MakeAnalysisRequest(byte[] imageBytes)  
  7. {  
  8.     const string subscriptionKey = "7b48c8#########################";  
  9.     const string uriBase = "https://westcentralus.api.cognitive.microsoft.com/face/v1.0/detect";  
  10.   
  11.     HttpClient client = new HttpClient();  
  12.   
  13.     // Request headers.  
  14.     client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey);  
  15.   
  16.     // Request parameters. A third optional parameter is "details".  
  17.     string requestParameters = "returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes=age,gender,headPose,smile,facialHair,glasses,emotion,hair,makeup,occlusion,accessories,blur,exposure,noise";  
  18.   
  19.     // Assemble the URI for the REST API Call.  
  20.     string uri = uriBase + "?" + requestParameters;  
  21.   
  22.     HttpResponseMessage response;  
  23.   
  24.     // Request body. Posts a locally stored JPEG image.  
  25.     byte[] byteData = imageBytes;  
  26.   
  27.     using (ByteArrayContent content = new ByteArrayContent(byteData))  
  28.     {  
  29.         // This example uses content type "application/octet-stream".  
  30.         // The other content types you can use are "application/json" and "multipart/form-data".  
  31.         content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");  
  32.   
  33.         // Execute the REST API call.  
  34.         response = await client.PostAsync(uri, content);  
  35.   
  36.         // Get the JSON response.  
  37.         string contentString = await response.Content.ReadAsStringAsync();  
  38.   
  39.         // Display the JSON response.  
  40.   
  41.         return JsonPrettyPrint(contentString);  
  42.   
  43.     }  
  44. }  

Now we have completed creating Capture method and MakeAnalysisRequest method.

Next, we are going to add CanvasAzureScript.js in this CamScripts folder. In this script we are going to capture photo and send base64string with Ajax Post to Capture [HttpPost] request.

Capturing photo code is written in CanvasAzureScript.js

Azure Face API

Complete Code Snippet of Ajax Post Request

In takeSnapshot function, we are capturing a photo using HTML Canvas and sending base64string to Uploadsubmit function, in the Uploadsubmit function we have written ajax post which will call capture method which takes base64string as input.

After taking base64string as input it will call POST async request to Azure Face API and send a response back to ajax request.

We are going to display the response on View.

  1. function takeSnapshot() {  
  2.         // Here we're using a trick that involves a hidden canvas element.    
  3.   
  4.         var hidden_canvas = document.querySelector('canvas'),  
  5.             context = hidden_canvas.getContext('2d');  
  6.   
  7.         var width = video.videoWidth,  
  8.             height = video.videoHeight;  
  9.   
  10.         if (width && height) {  
  11.   
  12.             // Setup a canvas with the same dimensions as the video.  
  13.             hidden_canvas.width = width;  
  14.             hidden_canvas.height = height;  
  15.   
  16.             // Make a copy of the current frame in the video on the canvas.  
  17.             context.drawImage(video, 0, 0, width, height);  
  18.   
  19.             // Storing Base64String  
  20.             var datacaptured = hidden_canvas.toDataURL('image/jpeg');  
  21.   
  22.             // Ajax Post to Save Image in Folder  
  23.             Uploadsubmit(datacaptured);  
  24.             // Turn the canvas image into a dataURL that can be used as a src for our photo.  
  25.             return datacaptured;  
  26.         }  
  27.     }  
  28.   
  29.  function Uploadsubmit(datacaptured) {  
  30.   
  31.         if (datacaptured != "") {  
  32.             $.ajax({  
  33.                 type: 'POST',  
  34.                 url: ("/CamCaptureAzure/Capture"),  
  35.                 dataType: 'json',  
  36.                 data: { base64String: datacaptured },  
  37.                 success: function (data) {  
  38.                     if (data == false) {  
  39.   
  40.                         alert("Photo Captured is not Proper!");  
  41.                         $('#ResponseTable').empty();  
  42.                     }  
  43.                     else {  
  44.   
  45.                         if (data.length == 9)  
  46.                         {  
  47.                             $('#ResponseTable').empty();  
  48.                             alert("Its not a Face!");  
  49.                         } else  
  50.                         {  
  51.                             var _faceAttributes = JSON.parse(data);  
  52.   
  53.                             $('#ResponseTable').empty();  
  54.                             var _responsetable = "";  
  55.                             var _emotiontable = "";  
  56.                             _responsetable += '<div class="panel panel-default"><div class="panel-heading">Azure Face API Response</div>';  
  57.                             _responsetable += "<div class='panel-body'>"  
  58.                             _responsetable +='<table class="table table-bordered"><thead><tr> <th>Smile</th> <th>Gender</th> <th>Age</th> <th>Glasses</th></tr></thead>';  
  59.                             _responsetable += '<tr> <th>' +  
  60.                                 _faceAttributes[0].faceAttributes.smile +  
  61.                                 '</th><th>' +  
  62.                                 _faceAttributes[0].faceAttributes.gender +  
  63.                                 '</th><th>' +  
  64.                                 _faceAttributes[0].faceAttributes.age +  
  65.                                 '</th> <th>' +  
  66.                                 _faceAttributes[0].faceAttributes.glasses +  
  67.                                 '</th></tr>';  
  68.                             _responsetable += "</table>"  
  69.                              
  70.   
  71.                             _responsetable += '<table class="table table-bordered"><thead><tr> <th>Anger</th> <th>Contempt</th> <th>Disgust</th> <th>Fear</th>  <th>Happiness</th>  <th>Neutral</th> <th>Sadness</th> <th>Surprise</th> </tr></thead>';  
  72.   
  73.                             _responsetable += '<tr><th>' +  
  74.                                 _faceAttributes[0].faceAttributes.emotion.anger +  
  75.                                 '</th><th>' +  
  76.                                 _faceAttributes[0].faceAttributes.emotion.contempt +  
  77.                                 '</th><th>' +  
  78.                                 _faceAttributes[0].faceAttributes.emotion.disgust +  
  79.                                 '</th><th>' +  
  80.                                 _faceAttributes[0].faceAttributes.emotion.fear +  
  81.                                 '</th><th>' +  
  82.                                 _faceAttributes[0].faceAttributes.emotion.happiness +  
  83.                                 '</th><th>' +  
  84.                                 _faceAttributes[0].faceAttributes.emotion.neutral +  
  85.                                 '</th><th>' +  
  86.                                 _faceAttributes[0].faceAttributes.emotion.sadness +  
  87.                                 '</th><th>' +  
  88.                                 _faceAttributes[0].faceAttributes.emotion.surprise +  
  89.                                 '</th></tr>';  
  90.                             _responsetable += "</table></div></div>";  
  91.                               
  92.                             $('#ResponseTable').append(_responsetable);  
  93.                         
  94.                         }  
  95.                     }  
  96.                 }  
  97.             });  
  98.         }  
  99.   
  100.     }  

Now we are going to add this script reference on view as we can see in the below code snippet of Capture View.

Code Snippet of Capture View after adding script reference

  1. @{  
  2.     Layout = null;  
  3. }  
  4. <!DOCTYPE html>  
  5. <html>  
  6. <head>  
  7.     <meta charset="utf-8">  
  8.     <meta http-equiv="X-UA-Compatible" content="IE=edge">  
  9.     <meta name="viewport" content="width=device-width, initial-scale=1">  
  10.     <title>Demo: Take a Selfie With JavaScript</title>  
  11.     <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">  
  12.     <link href="~/CamScripts/css/styles.css" rel="stylesheet" />  
  13.     <link href="~/Content/bootstrap.css" rel="stylesheet" />  
  14.     <link href="https://use.fontawesome.com/releases/v5.0.6/css/all.css" rel="stylesheet">  
  15. </head>  
  16. <body>  
  17.   
  18.     <div class="container">  
  19.   
  20.         <div class="panel panel-info">  
  21.             <div class="panel-heading">Take a Photo</div>  
  22.             <div class="panel-body">  
  23.   
  24.                 <div class="row">  
  25.                     <div class="col-md-4 col-lg-4 col-sm-4"></div>  
  26.                     <div class="col-md-4 col-lg-4 col-sm-4">  
  27.                         <div class="app">  
  28.                             <a href="#" id="start-camera" class="visible">Touch here to start the app.</a>  
  29.                             <video id="camera-stream"></video>  
  30.                             <img id="snap">  
  31.                             <p id="error-message">  
  32.                             </p>  
  33.   
  34.                             <!-- Hidden canvas element. Used for taking snapshot of video. -->  
  35.                             <canvas width="300" height="400"></canvas>  
  36.                         </div>  
  37.                     </div>  
  38.                     <div class="col-md-4 col-lg-4 col-sm-4">  
  39.                          
  40.                             <div class="controls">  
  41.                                 <div style="font-size:1.5em; color:Tomato">  
  42.                                     <a href="#" id="take-photo" title="Take Photo">  
  43.                                         <i class="fas fa-camera-retro fa-sm btn btn-default">  
  44.                                             Capture  
  45.                                         </i>  
  46.                                     </a>  
  47.                                 </div>  
  48.                                 <br />  
  49.                                 <div style="font-size:1.5em; color:Tomato">  
  50.                                     <a href="#" id="delete-photo" title="Delete Photo" class="disabled">  
  51.                                         <i class="fas fa-trash fa-sm btn btn-default">  
  52.                                             Delete  
  53.                                         </i>  
  54.                                     </a>  
  55.                                 </div>  
  56.                                 <br />  
  57.                                 <div style="font-size:1.5em; color:Tomato">  
  58.                                     <a href="#" id="download-photo" download="selfie.png" title="Save Photo"  
  59.                                        class="disabled">  
  60.                                         <i class="fas fa-download fa-sm btn btn-default">  
  61.                                             Download  
  62.                                         </i>  
  63.                                     </a>  
  64.                                 </div>  
  65.   
  66.                             </div>  
  67.                         </div>  
  68.   
  69.                     </div>  
  70.                 </div>  
  71.   
  72.                 <div class="row">  
  73.                     <div class="col-md-12">  
  74.                         <div id="ResponseTable">  
  75.                         </div>  
  76.                     </div>  
  77.                 </div>  
  78.   
  79.             </div>  
  80.         </div>  
  81.   
  82.     </div>  
  83.   
  84.     <script src="~/CamScripts/CanvasAzureScript.js"></script>  
  85.     <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>  
  86.     <script src="~/Scripts/bootstrap.min.js"></script>  
  87.     <style>  
  88.         .contant {  
  89.             border: 1px solid #ddd;  
  90.             border-radius: 4px;  
  91.             width: 500px;  
  92.             padding: 20px;  
  93.             margin: 0 auto;  
  94.             text-align: center;  
  95.         }  
  96.     </style>  
  97. </body>  
  98. </html>  

Now after adding reference of scripts on View, next we going to save the application and Run it to see a demo of how it works.

  1. We have captured photo
  2. Analyze photo
  3. Display response

Captured photo

Azure Face API

Debugging browser view while taking Snapshot

Azure Face API

Debugging View while sending Base64string to Capture Method

Azure Face API

 Debugging View of Capture Method which receives Base64string 

Azure Face API

Response from Azure Face API

Azure Face API

Response from Azure Face API in browser Debugging view.

Azure Face API
Azure Face API

Final Output

Azure Face API

Conclusion

In this article, we have learned how to use Azure Face API with MVC applications in simple steps. We started with creating an MVC project then Getting Azure Face API Key.  Further, we have created Controller, Action Methods, and View and finally, captured photo using HTML 5 canvas and sent to capture method using Ajax POST. The base64string is sent to Azure API for analyzing and getting response.

Note

After downloading source code just change “subscriptionKey” to make it work.