Cognitive Services – Bing Visual Search

Spread the love

The Bing Visual Search API returns information about an image that you provide. In this tutorial we will create a simple console application, that sends a Bing Visual Search API request and displays the JSON search results.

Prerequisites

To use the Bing Web Search API you need to create a Cognitive Services API account with access to the Bing Search APIs. If you don’t have an Azure subscription, you can create a free account.

Create your first Bing Visual Search query

Create a new Console solution in Visual Studio 2017.
Add the following code in the Program.cs

using System;
using System.Text;
using System.Net;
using System.IO;
using System.Collections.Generic;

namespace BingVisualSearch
{

    class Program
    {
        

        // Replace the accessKey string value with your valid subscription key.
        const string accessKey = "<SubscriptionKey>";

        const string uriBase = "https://api.cognitive.microsoft.com/bing/v7.0/images/visualsearch";

        // Set the path to the image that you want to get insights of. 
        static string imagePath = @"<ImagePath>";

        // Boundary strings for form data in body of POST.
        const string CRLF = "\r\n";
        static string BoundaryTemplate = "batch_{0}";
        static string StartBoundaryTemplate = "--{0}";
        static string EndBoundaryTemplate = "--{0}--";

        const string CONTENT_TYPE_HEADER_PARAMS = "multipart/form-data; boundary={0}";
        const string POST_BODY_DISPOSITION_HEADER = "Content-Disposition: form-data; name=\"image\"; filename=\"{0}\"" + CRLF +CRLF;


        static void Main()
        {
            try
            {
                Console.OutputEncoding = System.Text.Encoding.UTF8;

                if (accessKey.Length == 32)
                {
                    if (IsImagePathSet(imagePath))
                    {
                        var filename = GetImageFileName(imagePath);
                        Console.WriteLine("Getting image insights for image: " + filename);
                        var imageBinary = GetImageBinary(imagePath);

                        // Set up POST body.
                        var boundary = string.Format(BoundaryTemplate, Guid.NewGuid());
                        var startFormData = BuildFormDataStart(boundary, filename);
                        var endFormData = BuildFormDataEnd(boundary);
                        var contentTypeHdrValue = string.Format(CONTENT_TYPE_HEADER_PARAMS, boundary);

                        var json = BingImageSearch(startFormData, endFormData, imageBinary, contentTypeHdrValue);

                        Console.WriteLine("\nJSON Response:\n");
                        Console.WriteLine(json);
                    }
                }
                else
                {
                    Console.WriteLine("Invalid Bing Visual Search API subscription key!");
                    Console.WriteLine("Please paste yours into the source code.");
                }

                Console.Write("\nPress Enter to exit ");
                Console.ReadLine();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }



        /// <summary>
        /// Verify that imagePath exists.
        /// </summary>
        static Boolean IsImagePathSet(string path)
        {
            if (string.IsNullOrEmpty(path))
                throw new ArgumentException("Image path is null or empty.");

            if (!File.Exists(path))
                throw new ArgumentException("Image path does not exist.");

            var size = new FileInfo(path).Length;

            if (size > 1000000)
                throw new ArgumentException("Image is greater than the 1 MB maximum size.");

            return true;
        }



        /// <summary>
        /// Get the binary characters of an image.
        /// </summary>
        static byte[] GetImageBinary(string path)
        {
            return File.ReadAllBytes(path);
        }


        /// <summary>
        /// Get the image's filename.
        /// </summary>
        static string GetImageFileName(string path)
        {
            return new FileInfo(path).Name;
        }


        /// <summary>
        /// Build the beginning part of the form data.
        /// </summary>
        static string BuildFormDataStart(string boundary, string filename)
        {
            var startBoundary = string.Format(StartBoundaryTemplate, boundary);

            var requestBody = startBoundary + CRLF;
            requestBody += string.Format(POST_BODY_DISPOSITION_HEADER, filename);

            return requestBody;
        }


        /// <summary>
        /// Build the ending part of the form data.
        /// </summary>
        static string BuildFormDataEnd(string boundary)
        {
            return CRLF + CRLF + string.Format(EndBoundaryTemplate, boundary) + CRLF;
        }



        /// <summary>
        /// Calls the Bing visual search endpoint and returns the JSON response.
        /// </summary>
        static string BingImageSearch(string startFormData, string endFormData, byte[] image, string contentTypeValue)
        {
            WebRequest request = HttpWebRequest.Create(uriBase);
            request.ContentType = contentTypeValue;
            request.Headers["Ocp-Apim-Subscription-Key"] = accessKey;
            request.Method = "POST";

            // Writes the boundary and Content-Disposition header, then writes
            // the image binary, and finishes by writing the closing boundary.
            using (Stream requestStream = request.GetRequestStream())
            {
                StreamWriter writer = new StreamWriter(requestStream);
                writer.Write(startFormData);
                writer.Flush();
                requestStream.Write(image, 0, image.Length);
                writer.Write(endFormData);
                writer.Flush();
                writer.Close();
            }


            HttpWebResponse response = (HttpWebResponse)request.GetResponseAsync().Result;
            string json = new StreamReader(response.GetResponseStream()).ReadToEnd();

            return json;
        }


    }
}

Replace the accessKey value with your subscription key and the imagePath value with the path of the image to upload in the above code.
Run the program to get the results. The JSON result looks like the following code snippet:

{
  "_type": "ImageKnowledge",
  "instrumentation": {
    "_type": "ResponseInstrumentation",
    "pingUrlBase": null,
    "pageLoadPingUrl": null
  },
  "tags": [
    {
      "displayName": "",
      "actions": [
        {
          "_type": "ImageModuleAction",
          "actionType": "PagesIncluding",
          "data": {
            "value": [
              {
                "webSearchUrl": "https://www.bing.com/images/search?view=detailv2&FORM=OIIRPO&id=9EBFC54040A027AF74D7C1C7A76B30E05C6CA7DE&simid=608003926767305369",
                "webSearchUrlPingSuffix": null,
                "name": "The Iris (14) | Bernard Spragg. NZ | Flickr",
                "thumbnailUrl": "https://tse2.mm.bing.net/th?id=OIP.UsjRoYknBEQS4c9lxHVtqwHaJB&pid=Api",
                "datePublished": "2018-04-26T16:59:00Z",
                "contentUrl": "https://c1.staticflickr.com/9/8188/8096408296_bee9588558_b.jpg",
                "contentUrlPingSuffix": null,
                "hostPageUrl": "https://www.flickr.com/photos/volvob12b/8096408296",
                "hostPageUrlPingSuffix": null,
                "contentSize": "430199 B",
                "encodingFormat": "jpeg",
                "hostPageDisplayUrl": "https://www.flickr.com/photos/volvob12b/8096408296",
                "width": 840,
                "height": 1024,
                "thumbnail": {
                  "width": 474,
                  "height": 577,
                  "url": null
                },
                "imageInsightsToken": "ccid_UsjRoYkn*mid_9EBFC54040A027AF74D7C1C7A76B30E05C6CA7DE*simid_608003926767305369*thid_OIP.UsjRoYknBEQS4c9lxHVtqwHaJB",
                "insightsMetadata": {
                  "pagesIncludingCount": 1,
                  "availableSizesCount": 2,
                  "shoppingSourcesCount": 0,
                  "recipeSourcesCount": 0,
                  "aggregateOffer": null
                },
                "imageId": "9EBFC54040A027AF74D7C1C7A76B30E05C6CA7DE",
                "accentColor": "5E10BB",
                "text": null,
                "displayText": null
              }
            ]
          },
          "image": null,
          "webSearchUrl": null,
          "webSearchUrlPingSuffix": null,
          "displayName": null
        },
        {
          "_type": null,
          "actionType": "MoreSizes",
          "data": null,
          "image": {
            "webSearchUrl": "https://www.bing.com/images/search?view=detailv2&FORM=OIIRPO",
            "webSearchUrlPingSuffix": null,
            "name": "",
            "thumbnailUrl": null,
            "datePublished": "0001-01-01T00:00:00",
            "contentUrl": null,
            "contentUrlPingSuffix": null,
            "hostPageUrl": null,
            "hostPageUrlPingSuffix": null,
            "contentSize": "624419 B",
            "encodingFormat": "png",
            "hostPageDisplayUrl": "",
            "width": 576,
            "height": 445,
            "thumbnail": {
              "width": 0,
              "height": 0,
              "url": null
            },
            "imageInsightsToken": null,
            "insightsMetadata": {
              "pagesIncludingCount": 1,
              "availableSizesCount": 2,
              "shoppingSourcesCount": 0,
              "recipeSourcesCount": 0,
              "aggregateOffer": null
            },
            "imageId": null,
            "accentColor": "5E10BB",
            "text": null,
            "displayText": null
          },
          "webSearchUrl": null,
          "webSearchUrlPingSuffix": null,
          "displayName": null
        },
        {
          "_type": "ImageModuleAction",
          "actionType": "VisualSearch",
          "data": {
            "value": [
              {
                "webSearchUrl": "https://www.bing.com/images/search?view=detailv2&FORM=OIIRPO&id=9EBFC54040A027AF74D765ED21136615198945E7&simid=608045063953778746",
                "webSearchUrlPingSuffix": null,
                "name": "The Iris (14) | Bernard Spragg. NZ | Flickr",
                "thumbnailUrl": "https://tse4.mm.bing.net/th?id=OIP.DIpMOYu8yc3i4MCJJRsuoQAAAA&pid=Api",
                "datePublished": "2018-04-26T16:59:00Z",
                "contentUrl": "https://c1.staticflickr.com/9/8188/8096408296_bee9588558.jpg",
                "contentUrlPingSuffix": null,
                "hostPageUrl": "https://www.flickr.com/photos/volvob12b/8096408296",
                "hostPageUrlPingSuffix": null,
                "contentSize": "201704 B",
                "encodingFormat": "jpeg",
                "hostPageDisplayUrl": "https://www.flickr.com/photos/volvob12b/8096408296",
                "width": 410,
                "height": 500,
                "thumbnail": {
                  "width": 410,
                  "height": 500,
                  "url": null
                },
                "imageInsightsToken": "ccid_DIpMOYu8*mid_9EBFC54040A027AF74D765ED21136615198945E7*simid_608045063953778746*thid_OIP.DIpMOYu8yc3i4MCJJRsuoQAAAA",
                "insightsMetadata": {
                  "pagesIncludingCount": 1,
                  "availableSizesCount": 2,
                  "shoppingSourcesCount": 0,
                  "recipeSourcesCount": 0,
                  "aggregateOffer": null
                },
                "imageId": "9EBFC54040A027AF74D765ED21136615198945E7",
                "accentColor": "5F11BA",
                "text": null,
                "displayText": null
              },
              {
                "webSearchUrl": "https://www.bing.com/images/search?view=detailv2&FORM=OIIRPO&id=593891D6308A17CEF06C3714F884336EC858EAAE&simid=608021428779484842",
                "webSearchUrlPingSuffix": null,
                "name": "Summary California | Download PDF",
                "thumbnailUrl": "https://tse1.mm.bing.net/th?id=OIP.Z3PTuKW-Ub1KWdT9-ZcgawHaHn&pid=Api",
                "datePublished": "2018-01-08T03:01:00Z",
                "contentUrl": "https://upload.wikimedia.org/wikipedia/commons/5/59/Iris_douglasiana_1.jpg",
                "contentUrlPingSuffix": null,
                "hostPageUrl": "http://form-review.b9ad.pro-us-east-1.openshiftapps.com/irs/summary-california/",
                "hostPageUrlPingSuffix": null,
                "contentSize": "289392 B",
                "encodingFormat": "jpeg",
                "hostPageDisplayUrl": "form-review.b9ad.pro-us-east-1.openshiftapps.com/irs/summary...",
                "width": 1200,
                "height": 1234,
                "thumbnail": {
                  "width": 474,
                  "height": 487,
                  "url": null
                }
              ...
              ...

 

2 Comments

  1. Hmm it appears like your site ate my first comment (it was super
    long) so I guess I’ll just sum it up what I had written and say, I’m thoroughly enjoying your
    blog. I as well am an aspiring blog writer but I’m still new to the whole thing.
    Do you have any suggestions for newbie blog writers?
    I’d certainly appreciate it.

    Jarred

Leave a Reply

Your email address will not be published. Required fields are marked *