Image Text Sentiment Analysis Using Vision And Text Analytics API

Introduction

With the ever-growing use of social media platforms like FaceBook, Twitter, LinkedIn to promote business, analyzing what the users feel and what feedback they share regarding the business is of paramount importance. One such scenario is where the users post their feedback in images on the concerned company's social media pages.  It is of great importance that the companies analyze what the users post on their social media pages as it will give them an overall idea of the sentiment of the users towards the services offered by the company, which in turn will help them plan their marketing strategies accordingly.

Microsoft Cognitive Services 

As per Microsoft, 

Microsoft Cognitive Services (formerly Project Oxford) are a set of APIs, SDKs and services available to the developers to make their applications more intelligent, engaging and discover able. 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. 

Scope

This article explains the concept of the Sentiment analysis of the text detected from an Image using a Sample Console Application. The article assumes that the user is familiar with the basic concepts of C# and knows how to consume the REST APIs in the C# code. In this sample application, images from a SampleImage folder are read and then the image is sent to the Computer Vision API to detect the text from the image. Once the Computer Vision API returns the JSON payload, the detected text is sent to the Text Analytics API to detect the sentiment score. 

Pre Implementation

Computer Vision API Account

In order to use the Computer Vision API in the sample application, first, an API account for the Computer Vision API needs to be created. Once this is done, the API will be available to integrate the Computer Vision API in the sample application. Th efollowing screenshot shows the process to do so.

Microsoft Cognitive Services

Microsoft Cognitive Services

Once the API account is created, select the account from the dashboard and the following window is shown. Access keys and end points are required from this window which will be used to create a connection to the Computer Vision API.

Microsoft Cognitive Services

Microsoft Cognitive Services

Text Analytics API Account

In order to use the Text Analytics API in the sample application, first, an API account for the Text Analytics API needs to be created. Once this is done, the API will be available to integrate the Text Analytics in the Sample Application. The following screenshot shows the process to do so.

Microsoft Cognitive Services

Microsoft Cognitive Services

Once the API account is created, select the account from the dashboard and the following window is visible, the access keys and end point are required from this window which will be used to create a connection to the Text Analytics API.

Microsoft Cognitive Services
 
Microsoft Cognitive Services

Design - Constants

The constants class is used to store the constant values that are used in the application. Following is the constants class used in the application.

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading.Tasks;  
  6.    
  7. namespace ImageTextSentimentDetection  
  8. {  
  9.     public class Constants  
  10.     {  
  11.         /// <summary>  
  12.         /// Key Name that is used to pass the subscrption Key Value in the Request Headers  
  13.         /// </summary>  
  14.         public static string SubscriptionKeyName = "Ocp-Apim-Subscription-Key";  
  15.    
  16.         /// <summary>  
  17.         /// Uri for the Computer Vision APi to which the Request Will be routed  
  18.         /// </summary>  
  19.         public static string VisionApiUri = "https://southeastasia.api.cognitive.microsoft.com/vision/v1.0";  
  20.    
  21.         /// <summary>  
  22.         /// Uri for the Text Analytics Api to which the Request will be routed.  
  23.         /// </summary>  
  24.         public static string TextAnalyticsApiUri = "https://southeastasia.api.cognitive.microsoft.com/text/analytics/v2.0";  
  25.    
  26.         /// <summary>  
  27.         /// Path to the SampleImages Folder  
  28.         /// </summary>  
  29.         public static string SampleImagesFolderPath = @"..\..\SampleImages";  
  30.    
  31.         /// <summary>  
  32.         /// Vision APi Subscription Key Value. This needs to be populated before Starting the Sample  
  33.         /// </summary>  
  34.         public static string VisionApiSubcriptionKey = "Enter key here";  
  35.    
  36.         /// <summary>  
  37.         /// Text Analytics Subscription Key value. This Needs to be Populated before Starting the Sample  
  38.         /// </summary>  
  39.        // public static string TextAnalyticsApiSubscriptionKey = "Enter key here";  
  40.    
  41.    
  42.     }  
  43. }  

Computer Vision API Response Class

This class is used to convert the json payload received from the Computer Vision API into a C# class which can be used later on for extracting text. The class is generated using the sample json payload received from the Computer Vision API. The class structure will change if the response received is changed. 

  1. // To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:  
  2. //  
  3. //    using ImageTextSentimentDetection;  
  4. //  
  5. //    var data = ComputerVisionSuccessFullResponseClass.FromJson(jsonString);  
  6.    
  7. namespace ImageTextSentimentDetection  
  8. {  
  9.     using System;  
  10.     using System.Net;  
  11.     using System.Collections.Generic;  
  12.    
  13.     using Newtonsoft.Json;  
  14.    
  15.     public partial class ComputerVisionSuccessFullResponseClass  
  16.     {  
  17.         [JsonProperty("language")]  
  18.         public string Language { get; set; }  
  19.    
  20.         [JsonProperty("textAngle")]  
  21.         public double TextAngle { get; set; }  
  22.    
  23.         [JsonProperty("orientation")]  
  24.         public string Orientation { get; set; }  
  25.    
  26.         [JsonProperty("regions")]  
  27.         public Region[] Regions { get; set; }  
  28.     }  
  29.    
  30.     public partial class Region  
  31.     {  
  32.         [JsonProperty("boundingBox")]  
  33.         public string BoundingBox { get; set; }  
  34.    
  35.         [JsonProperty("lines")]  
  36.         public Line[] Lines { get; set; }  
  37.     }  
  38.    
  39.     public partial class Line  
  40.     {  
  41.         [JsonProperty("boundingBox")]  
  42.         public string BoundingBox { get; set; }  
  43.    
  44.         [JsonProperty("words")]  
  45.         public Word[] Words { get; set; }  
  46.     }  
  47.    
  48.     public partial class Word  
  49.     {  
  50.         [JsonProperty("boundingBox")]  
  51.         public string BoundingBox { get; set; }  
  52.    
  53.         [JsonProperty("text")]  
  54.         public string Text { get; set; }  
  55.     }  
  56.    
  57.     public partial class ComputerVisionSuccessFullResponseClass  
  58.     {  
  59.         public static ComputerVisionSuccessFullResponseClass FromJson(string json)  
  60.         {  
  61.             return JsonConvert.DeserializeObject<ComputerVisionSuccessFullResponseClass>(json, Converter.Settings);  
  62.         }  
  63.     }  
  64.    
  65.     public static class Serialize  
  66.     {  
  67.         public static string ToJson(this ComputerVisionSuccessFullResponseClass self)  
  68.         {  
  69.             return JsonConvert.SerializeObject(self, Converter.Settings);  
  70.         }  
  71.     }  
  72.    
  73.     public class Converter  
  74.     {  
  75.         public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings  
  76.         {  
  77.             MetadataPropertyHandling = MetadataPropertyHandling.Ignore,  
  78.             DateParseHandling = DateParseHandling.None,  
  79.         };  
  80.     }  
  81. }  

Text Analytics Response Class

This class is used to convert the JSON payload received from the Text Analytics API into a C# class which can be used later on for extracting text. The class is generated using the sample JSON payload received from the Text Analytics Api. The class structure will change if the response received is changed.

  1. // To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:  
  2. //  
  3. //    using ImageTextSentimentDetection;  
  4. //  
  5. //    var data = TextAnalyticsResponseClass.FromJson(jsonString);  
  6.    
  7. namespace ImageTextSentimentDetection  
  8. {  
  9.     using System;  
  10.     using System.Net;  
  11.     using System.Collections.Generic;  
  12.    
  13.     using Newtonsoft.Json;  
  14.    
  15.     public partial class TextAnalyticsResponseClass  
  16.     {  
  17.         [JsonProperty("documents")]  
  18.         public Document[] Documents { get; set; }  
  19.    
  20.         [JsonProperty("errors")]  
  21.         public Error[] Errors { get; set; }  
  22.     }  
  23.    
  24.     public partial class Document  
  25.     {  
  26.         [JsonProperty("score")]  
  27.         public long Score { get; set; }  
  28.    
  29.         [JsonProperty("id")]  
  30.         public string Id { get; set; }  
  31.     }  
  32.    
  33.     public partial class Error  
  34.     {  
  35.         [JsonProperty("id")]  
  36.         public string Id { get; set; }  
  37.    
  38.         [JsonProperty("message")]  
  39.         public string Message { get; set; }  
  40.     }  
  41.    
  42.     public partial class TextAnalyticsResponseClass  
  43.     {  
  44.         public static TextAnalyticsResponseClass FromJson(string json)  
  45.         {  
  46.             return JsonConvert.DeserializeObject<TextAnalyticsResponseClass>(json, Converter.Settings);  
  47.         }  
  48.     }  
  49.    
  50. }  

Helper Classes

Helper classes are created to cater to each of the Cognitive API calls. One class caters to the Computer Vision API call while the other class caters to the Text Analytics API call. Each of them is discussed below.

VisionHelper 

This class caters to the calls made to the Computer Vision API. In this current sample, the DetectTextInImage method in the class is used to call the Computer Vision API. This method passes the image to the API in 'application/octet-stream' format. It deserializes the JSON payload into the class created earlier and extracts out the detected text. The class is as follows.

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading.Tasks;  
  6. using Newtonsoft.Json.Serialization;  
  7. using System.Net.Http;  
  8. using System.Net.Http.Headers;  
  9. using System.Web;  
  10.    
  11. namespace ImageTextSentimentDetection  
  12. {  
  13.     public class VisionHelper  
  14.     {  
  15.         public static string DetectTextInImage(byte[] imageBytes)  
  16.         {  
  17.             string detectedText = String.Empty;  
  18.    
  19.             var queryString = HttpUtility.ParseQueryString(String.Empty);  
  20.    
  21.             HttpClient client = new HttpClient();  
  22.    
  23.             using (var content = new ByteArrayContent(imageBytes))  
  24.             {  
  25.                 client.DefaultRequestHeaders.Add(Constants.SubscriptionKeyName, Constants.VisionApiSubcriptionKey);  
  26.    
  27.                 queryString["language"] = "unk";  
  28.                 queryString["detectOrientation "] = "false";  
  29.                 content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");  
  30.                 var uriString = Constants.VisionApiUri + "/ocr?" + queryString;  
  31.                 HttpResponseMessage response = new HttpResponseMessage();  
  32.                 response = client.PostAsync(uriString, content).Result;  
  33.    
  34.                 var responseJson = response.Content.ReadAsStringAsync().Result;  
  35.    
  36.                 if (response.StatusCode == System.Net.HttpStatusCode.OK)  
  37.                 {  
  38.                     var data = ComputerVisionSuccessFullResponseClass.FromJson(responseJson);  
  39.    
  40.                     foreach (Region region in data.Regions)  
  41.                     {  
  42.                         foreach (Line line in region.Lines)  
  43.                         {  
  44.                             foreach (Word word in line.Words)  
  45.                             {  
  46.                                 detectedText = detectedText + " " + word.Text;  
  47.                             }  
  48.                         }  
  49.                     }  
  50.                 }  
  51.                 else  
  52.                 {  
  53.                     detectedText = "Error Occured While Calling Computer Vision Api";  
  54.                 }  
  55.                 return detectedText;  
  56.             }  
  57.    
  58.         }  
  59.     }  
  60. }  

SentimentHelper 

This class caters to the Text Analytics API call from the Sample Application. In the current context, the DetectSentiment method in the class accepts the detected string as input. It then creates the JSON payload and then invokes the Text Analytics API. It deserializes the JSON payload received from the API call into the response class and extracts out the sentiment score. This method is designed to pass only one detected text at a time to the Text Analytics API, but it can be modified as required. The class is as follows.

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading.Tasks;  
  6. using Newtonsoft.Json;  
  7. using System.Net.Http;  
  8. using System.Net.Http.Headers;  
  9. using System.Web;  
  10.    
  11. namespace ImageTextSentimentDetection  
  12. {  
  13.     public class SentimentHelper  
  14.     {  
  15.         public static string DetectSentiment(string detectedText)  
  16.         {  
  17.             string sentimentScore = String.Empty;  
  18.             string jsonText = "{\"documents\":[{\"language\":\"en\",\"id\":\"1\",\"text\":\"" + detectedText + "\"}]}";  
  19.    
  20.             HttpClient client = new HttpClient();  
  21.             byte[] detectedTextBytes = Encoding.UTF8.GetBytes(jsonText);  
  22.             using (var content = new ByteArrayContent(detectedTextBytes))  
  23.             {  
  24.                 var queryString = HttpUtility.ParseQueryString(String.Empty);  
  25.                 client.DefaultRequestHeaders.Add(Constants.SubscriptionKeyName, Constants.TextAnalyticsApiSubscriptionKey);  
  26.                 var uriString = Constants.TextAnalyticsApiUri + "/sentiment?" + queryString;  
  27.                 content.Headers.ContentType = new MediaTypeHeaderValue("application/json");  
  28.                 HttpResponseMessage response = new HttpResponseMessage();  
  29.                 response = client.PostAsync(uriString, content).Result;  
  30.    
  31.                 if (response.StatusCode == System.Net.HttpStatusCode.OK)  
  32.                 {  
  33.                     var data = TextAnalyticsResponseClass.FromJson(response.Content.ReadAsStringAsync().Result);  
  34.                     foreach (var document in data.Documents)  
  35.                     {  
  36.                         sentimentScore = Convert.ToString(document.Score);  
  37.                     }  
  38.                 }  
  39.                 else  
  40.                 {  
  41.                     sentimentScore = "Error";  
  42.                 }  
  43.    
  44.             }  
  45.    
  46.    
  47.                 return sentimentScore;  
  48.         }  
  49.    
  50.     }  
  51. }  

Console Application

The console application greets the user and advises the user to ensure that the Subscription keys for the Computer Vision API and Text Analytics API are generated and added to the Constants class. It then asks the user to confirm to proceed by Accepting [Y/N] input. Once done, it reads the files stored in the SampleImages projects and calls the helpers on each of the images. Following is the Console Application class.

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading.Tasks;  
  6. using System.IO;  
  7. using System.Reflection;  
  8. using System.Globalization;  
  9. namespace ImageTextSentimentDetection  
  10. {  
  11.     public class ImageTextSentimentDetctionApp  
  12.     {  
  13.         static void Main(string[] args)  
  14.         {  
  15.             string visionApiSubcriptionKey = String.Empty;  
  16.             string textAnalyticsApiSubscriptionKey = String.Empty;  
  17.    
  18.             Console.WriteLine("Welcome to the Image Text Detection Sample Application");  
  19.             Console.WriteLine("This Application will Get the Images From the SampleImages Folder");  
  20.             Console.WriteLine("Once the Image is read, the Sample APplication Will call Computer Vision Api and Try to Detect Text in the Image"); ;  
  21.             Console.WriteLine("ON SuccessFull Detection of text, the Application will use Text Analystics To Detect The Sentiment of APi");  
  22.             Console.WriteLine("To Run this Sample Application, You need to generate the Subscription Key for the Computer Vision and Text Analytics Api.");  
  23.             Console.WriteLine("Do You Wish To Continue? Press Y for yes and N for No");  
  24.             try  
  25.             {  
  26.                 if (Convert.ToString(Console.ReadKey().Key).ToUpper() == "Y")  
  27.                 {  
  28.                     Console.WriteLine(Environment.NewLine);  
  29.                     Console.WriteLine("Starting The Application Flow");  
  30.                        
  31.                     foreach (string imageFile in Directory.GetFiles(Constants.SampleImagesFolderPath, "*.jpg"))  
  32.                     {  
  33.                         var imageFileInfo = new FileInfo(imageFile);  
  34.    
  35.                         byte[] imageBytes = File.ReadAllBytes(imageFileInfo.FullName);  
  36.                            
  37.                         Console.WriteLine("File Name of the FileRead :" + imageFileInfo.Name);  
  38.                         Console.WriteLine("Initiating the Image TextDetection");  
  39.                         string detectedText = VisionHelper.DetectTextInImage(imageBytes);  
  40.                         if (detectedText.Contains("Error"))  
  41.                             break;  
  42.                         Console.WriteLine("Text Detected in Image:" + detectedText);  
  43.                         Console.WriteLine("Starting Sentiment Score analysis for the detected text");  
  44.                         string sentimentScore = SentimentHelper.DetectSentiment(detectedText);  
  45.                         if (sentimentScore.Contains("Error"))  
  46.                             break;  
  47.                         Console.WriteLine("Sentiment Score for the Detected Text is :" + sentimentScore);  
  48.                     }  
  49.                 }  
  50.                 else  
  51.                 {  
  52.                     Console.WriteLine("Thank You For Visiting the Application Will Exit Now.");  
  53.                 }  
  54.             }  
  55.             catch (Exception ex)  
  56.             {  
  57.                 Console.WriteLine("Sorry an Exception Was Caught!!");  
  58.                 Console.WriteLine("Following are the Exception Details");  
  59.                 Console.WriteLine(ex.Message);  
  60.             }  
  61.             Console.WriteLine("Press Any Key To Exit");  
  62.             Console.ReadKey();  
  63.    
  64.         }  
  65.     }  
  66. }  

Testing

Following are the images that were used to test the Sample application.

Microsoft Cognitive Services

Microsoft Cognitive Services

The Result obtained from the Test Console Application is as follows:

Microsoft Cognitive Services

The actual results of the text analysis for the text detected from above test messages when done on the Microsoft Demo Page ( For Details See References) are shown below.

Visual result for the sentiment analysis of the text in the first test image is as shown below.

Microsoft Cognitive Services

 

Visual result for the sentiment analysis of the text in the second test image is as shown below.

Microsoft Cognitive Services

Conclusion

The test results as observed from the Sample Console Application as well as from the Microsoft Demo Tool are exactly the same proving the successful consumption of the Computer Vision API and Text Analytics API.

See also:

The following links can be used for extra reading related to the topic discussed in this article.

  1. Logic Apps: Optical Character Recognition From Image and Detected Text Analysis Using Microsoft Cognitive Computer Vision API, Text Analytics API and Logic Apps
  2. Getting started with Cognitive Services - Vision
  3. Logic Apps: Face Verification Using Microsoft Cognitive Services Face API and Logic Apps
  4. Cognitive Services: Emotion API Overview

References

Following material was referred to while writing this article.

  1. What is Cognitive Services?
  2. Text Analytics API
  3. Text Analytics Api Operations
  4. Computer Vision API
  5. Computer Vision Api Operations


Similar Articles