WHAT'S NEW?
Loading...

Image recognition using third party web service (recognize.im)

In this example I am going to show you how to consume with C# a third party image recognition web service (REST). First we need to create a new (30 days free) account in our web service provider: www.recognize.im. Remember to save your account settings to make the connection: client_id, clapi_key and api_key. Then upload some images to your new account and save these images in small size to be used by our new application. I used some star wars images, you will see in the code below. Once all of these steps are finished we can start with our app.


Create a new solution in your VS with two projects inside. A console application will be the interface between the user and the second project, a library which saves all the logic for the web service.
Here below you can see the interface application stored in our console project. It gives some image options to our user. Then the user select one by writing the number reference and we make a call to our library.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using OneFlowApp;

namespace OneFlowApp
{
    class Program
    {
        //Data members
        private static string client_id;
        private static string clapi_key;
        private static string api_key;
        private static string url;
        private static Dictionary<int, string> images;

        private static void Main(string[] args)
        {
            Program p = new Program();
            p.run();
        }

        private Program()
        {
            client_id = ""; //API User ID
            clapi_key = ""; //CLAPI user key
            api_key = ""; //API user key
            url = @"http://recognize.im/v2/recognize/single/";
            images = new Dictionary<int, string> {
                    {1, "anakinT.jpg"}, {2, "kenobiT.jpg"}, {3, "lukeT.jpg"},
                    {4, "vaderT.jpg"}, {5, "winduT.jpg"}, {6, "yodaT.jpg"}};
        }

        private void run()
        {
            Console.WriteLine("\n|-| Star Wars characters recognition system |-|\n");
            Console.WriteLine("\rPlease select a character (1-6) from the list below and press enter:\n");
            Console.WriteLine("1.Anakin\n2.Kenobi\n3.Luke\n4.Vader\n5.Windu\n6.Yoda");

            string opt = Console.ReadLine();
            short selection;
            if (Int16.TryParse(opt, out selection)) {
                if (selection > 0 && selection < 7) {
                    string imagePath = AppDomain.CurrentDomain.BaseDirectory + "..\\..\\Resources\\" + images[selection].ToString();
                    RestService rest = new RestService(api_key, url);
                    Dictionary<string, object> response = rest.sendData(imagePath);
                    if (response.ContainsKey("status") && response["status"].ToString() == "0") {
                        ArrayList responseArray = (ArrayList)response["objects"];
                        Dictionary<string, object> responseImage = (Dictionary<string, object>)responseArray[0];
                        Console.WriteLine("Match found! ID: " + responseImage["id"].ToString() + ", Name: " + responseImage["name"].ToString());
                    }
                    else if (response["status"].ToString() == "1") {
                        Console.WriteLine("Error: " + response["message"].ToString());
                    }
                    else if (response["status"].ToString() == "2") Console.WriteLine("No match found.");
                    else Console.WriteLine("No match found.");
                }
                else Console.WriteLine("Not valid option.");
                Console.ReadLine();
            }
            else {
                Console.WriteLine("Error: wrong selection");
                Console.ReadLine();
            }
        }
    }
}
In this part of the code we read the answer from the recognize server to know if it has been able to recognize the image sent. We get different kind of errors and only number “0” means that everything worked fine. In this case we can show the image reference name in the console view.
if (response.ContainsKey("status") && response["status"].ToString() == "0") {
    ArrayList responseArray = (ArrayList)response["objects"];
    Dictionary responseImage = (Dictionary)responseArray[0];
    Console.WriteLine("Match found! ID: " + responseImage["id"].ToString() + ", Name: " + responseImage["name"].ToString());
}
else if (response["status"].ToString() == "1") {
    Console.WriteLine("Error: " + response["message"].ToString());
}
else if (response["status"].ToString() == "2") Console.WriteLine("No match found.");
else Console.WriteLine("No match found.");
Here below you have the main class of our library. It tries to open a connection to the web service sending the image that we have stored in our computer. Remember this image is smaller than the one we have in our recognize.im account.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Security.Cryptography;
using System.Web.Script.Serialization;

namespace OneFlowApp
{
    public class RestService
    {
        string _url;
        string _apiKey;

        public RestService(string apiKey, string url)
        {
            _url = url;
            _apiKey = apiKey;
        }

        public Dictionary<string, object> sendData(string imagePath)
        {
            //open image
            FileStream image = File.OpenRead(imagePath);

            byte[] data = new byte[image.Length];
            image.Read(data, 0, data.Length);

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_url);
            request.Method = "POST";
            request.Headers["x-itraff-hash"] = getMD5(_apiKey, data);
            request.ContentType = "image/jpeg";
            request.Accept = "application/json";
            request.ContentLength = data.Length;
  
            using (Stream requestStream = request.GetRequestStream()) 
            { 
                // Send the file as body request. 
                requestStream.Write(data, 0, data.Length); 
                requestStream.Close(); 
            }

            //get response
            using (WebResponse response = request.GetResponse()) {
                using (Stream stream = response.GetResponseStream()) {
                    //read json response
                    StreamReader reader = new StreamReader(stream, Encoding.UTF8);
                    String responseString = reader.ReadToEnd();

                    //deserialize json response into Dictionary<string, string>
                    var jss = new JavaScriptSerializer();
                    var dict = jss.Deserialize<Dictionary<string, object>>(responseString);
                    return dict;
                }
            }
        }

        /// <summary>
        /// CryptoService
        /// </summary>
        /// <param name="api_key"></param>
        /// <param name="imageBytes"></param>
        /// <returns></returns>
        private static String getMD5(String api_key, byte[] imageBytes)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] api = System.Text.Encoding.ASCII.GetBytes(api_key);
            byte[] glued = new byte[api.Length + imageBytes.Length];

            System.Buffer.BlockCopy(api, 0, glued, 0, api.Length);
            System.Buffer.BlockCopy(imageBytes, 0, glued, api.Length, imageBytes.Length);

            byte[] retVal = md5.ComputeHash(glued);

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < retVal.Length; i++) {
                sb.Append(retVal[i].ToString("x2"));
            }

            md5.Clear();

            return sb.ToString();
        }

    }
}

The getMD5 method tries to return a string object with the api_key and the image selected by the user encrypted using a predefined algorithm. Later we will use this string in the x-itraff-hash parameter inside our request object (HttpWebRequest). We also add “POST” method, the content type as “image/jpeg”, accept a Json application and the length of the data to be sent. After receive the answer we need to deserialize the dictionary gave by the web service using JavaScriptSerializer class and return the answer to our main class, in this example: Program.cs.
References:

0 comments:

Post a Comment