{"id":3645,"date":"2020-05-13T17:28:10","date_gmt":"2020-05-13T14:28:10","guid":{"rendered":"https:\/\/imagga.com\/blog\/?p=3645"},"modified":"2020-05-13T17:38:09","modified_gmt":"2020-05-13T14:38:09","slug":"how-to-use-the-imagga-visual-similarity-search","status":"publish","type":"post","link":"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/","title":{"rendered":"How to use the Imagga visual similarity search"},"content":{"rendered":"<p>In this article we&#8217;ll put the <a href=\"https:\/\/imagga.com\/solutions\/visual-search\">Imagga API for visual similarity<\/a> to use with a demo that you can try yourself. The technology allows you to add a bunch of images to a visual search index, and then query it, using unlabeled pictures.<\/p>\n<p><em>Use case:<\/em> Say you want to do stock photo suggestions &#8211; the customer uploads an image that they want to find similar stock photos to. You&#8217;ll make an index with your stock photos, and query it with each new incoming photo. You&#8217;ll receive the most visually similar images from the API, filter them however you want and suggest those to the client.<\/p>\n<p>In a few steps we&#8217;ll make a python script that creates a visual search index from a small set of images, and then queries it with a given image file to get the most similar pics from the initial set.<\/p>\n<h1>Prerequisites<\/h1>\n<p>To get started you need to have some basic coding knowledge and have python (&gt;3.5) installed (<a href=\"https:\/\/www.python.org\/downloads\/\">download link<\/a>).<\/p>\n<p>You can download <a href=\"https:\/\/imagga.com\/blog\/?attachment_id=3773\">all of the code and test images, used in this tutorial (3.4MB zip)<\/a>.<\/p>\n<h4>Project structure:<\/h4>\n<ul>\n<li><em><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">create_index.py<\/code><\/em> &#8211; contains the code to feed the images to the visual search index and train it.<\/li>\n<li><em><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">search_index.py<\/code><\/em> &#8211; takes a single image path as an argument, searches the index for it and prints the API response<\/li>\n<li><em><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">delete_index.py<\/code><\/em> &#8211; self-explanatory<\/li>\n<\/ul>\n<p><em>The scripts use relative paths for the images, so you should call them from within the project folder.<\/em><\/p>\n<ul>\n<li><em><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">test_images<\/code><\/em> &#8211; a folder with several images for use with the <em><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">search_index.py<\/code><\/em> script<\/li>\n<li><em><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">index_creation_set<\/code><\/em> &#8211; a folder with images that the <em><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">create_index.py<\/code><\/em> script feeds to the index. Here&#8217;s a preview:<\/li>\n<\/ul>\n<h1><img class=\"hoverZoomLink alignnone wp-image-3683 size-medium\" style=\"font-size: 15px;\" src=\"https:\/\/imagga.com\/blog\/wp-content\/uploads\/2020\/05\/image_set_previews-1-675x600.png\" alt=\"\" width=\"675\" height=\"600\" srcset=\"https:\/\/imagga.com\/blog\/wp-content\/uploads\/2020\/05\/image_set_previews-1-675x600.png 675w, https:\/\/imagga.com\/blog\/wp-content\/uploads\/2020\/05\/image_set_previews-1-768x683.png 768w, https:\/\/imagga.com\/blog\/wp-content\/uploads\/2020\/05\/image_set_previews-1.png 854w\" sizes=\"(max-width: 675px) 100vw, 675px\" \/><\/h1>\n<h1>Creating the visual search index<\/h1>\n<p>Here&#8217;s the code of <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"atomic\">create_index.py<\/code><em>, <\/em>which we&#8217;ll examine to understand the API usage:<\/p>\n<div style=\"width: 100%; height: 300px; overflow: scroll;\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"atomic\">import os\r\nimport requests\r\nimport time\r\n\r\n\r\nAPI_KEY = 'acc_xxxxxxxxxxxxxxx'\r\nAPI_SECRET = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'\r\n\r\nAPI_ENDPOINT = 'https:\/\/api.imagga.com\/v2'\r\nCATEGORIZER = 'general_v3'  # The default general purpose categorizer\r\nINDEX_NAME = 'similarity_tutorial_v1'\r\n\r\ncategorizer_endpoint = '%s\/categories\/%s' % (API_ENDPOINT, CATEGORIZER)\r\nindex_endpoint = ('%s\/similar-images\/categories\/%s\/%s' %\r\n                  (API_ENDPOINT, CATEGORIZER, INDEX_NAME))\r\ntickets_endpoint = '%s\/tickets' % API_ENDPOINT\r\n\r\n\r\ndef feed_image(image_path):\r\n    image_name, extension = os.path.splitext(os.path.basename(image_path))\r\n\r\n    # Make the API call\r\n    response = requests.post(\r\n        categorizer_endpoint,\r\n        auth=(API_KEY, API_SECRET),\r\n        files={'image': open(image_path, 'rb')},\r\n        params={'save_id': image_name, 'save_index': INDEX_NAME})\r\n\r\n    # Check for errors\r\n    try:\r\n        status = response.json()['status']\r\n        if status['type'] != 'success':\r\n            print('API reported error:', status['text'])\r\n            return False\r\n    except Exception as e:\r\n        print('Exception occured during handling the feeding response')\r\n        print(e)\r\n        return False\r\n\r\n    return True\r\n\r\n\r\ndef train_index():\r\n    ticket_id = ''\r\n\r\n    # Make the API call\r\n    response = requests.put(index_endpoint, auth=(API_KEY, API_SECRET))\r\n\r\n    # Get the completion ticket\r\n    try:\r\n        ticket_id = response.json()['result']['ticket_id']\r\n    except Exception as e:\r\n        print('Exception occured when processing the train call response')\r\n        print(e, response.content)\r\n\r\n    return ticket_id\r\n\r\n\r\ndef is_resolved(ticket_id):\r\n    resolved = False\r\n\r\n    # Make the API call\r\n    response = requests.get(\r\n        '%s\/%s' % (tickets_endpoint, ticket_id), auth=(API_KEY, API_SECRET))\r\n\r\n    # Check for errors\r\n    try:\r\n        resolved = response.json()['result']['is_final']\r\n    except Exception as e:\r\n        print('Exception occured during the ticket status check')\r\n        print(e)\r\n\r\n    return resolved\r\n\r\n\r\ndef main():\r\n    # Feed the visual search index with images\r\n    successful_feeds = 0\r\n    failed_feeds = 0\r\n\r\n    for image in os.scandir('.\/index_creation_set'):\r\n        successful = feed_image(image.path)\r\n        if successful:\r\n            successful_feeds += 1\r\n        else:\r\n            failed_feeds += 1\r\n\r\n        print('At image %s: %s' % (successful_feeds, image.path))\r\n\r\n    # Report\r\n    if not successful_feeds:\r\n        print('No images were fed successfully. Exiting')\r\n        return\r\n\r\n    print(\r\n        '%s out of %s images fed successfully' %\r\n        (successful_feeds, successful_feeds + failed_feeds))\r\n\r\n    # Train the index\r\n    ticket_id = train_index()\r\n\r\n    if not ticket_id:\r\n        print('No ticket id. Exiting')\r\n        return\r\n\r\n    # Wait for the training to complete\r\n    time_started = time.time()\r\n    while not is_resolved(ticket_id):\r\n        t_passed = (time.time() - time_started) \/\/ 1000\r\n        print(\r\n            'Waiting for training to finish (time elapsed: %.1fs)' % t_passed)\r\n\r\n        time.sleep(0.5)\r\n\r\n    print('Training done.')\r\n\r\n\r\nif __name__ == '__main__':\r\n    main()\r\n<\/pre>\n<\/div>\n<p>At the top of the file we have the API credentials (mock examples here):<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">API_KEY = 'acc_xxxxxxxxxxxxxxx'\r\nAPI_SECRET = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'<\/pre>\n<p>You can <a href=\"https:\/\/imagga.com\/auth\/signup\/hacker\">signup<\/a>\u00a0for a free account to get these credentials. After creating an account, you\u2019ll find these values on your\u00a0<a href=\"https:\/\/imagga.com\/profile\/dashboard\">dashboard<\/a> and you can replace them in the script. That&#8217;s all the manual setup you&#8217;ll need.<\/p>\n<p>Then we prepare some names:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">API_ENDPOINT = 'https:\/\/api.imagga.com\/v2'\r\nCATEGORIZER = 'general_v3'\u00a0 # The default general purpose categorizer\r\nINDEX_NAME = 'similarity_tutorial_v1'<\/pre>\n<p><em><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">API_ENDPOINT<\/code><\/em> is the Imagga API address.<br \/>\n<em><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">INDEX_NAME<\/code><\/em>\u00a0 is the name I&#8217;ve chosen for our test index.<br \/>\n<em><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">CATEGORIZER<\/code><\/em> is the image categorizer to be used to create the visual search index. As mentioned in the code &#8211; the <em><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">general_v3<\/code> <\/em>categorizer is the default choice. The data with which the categorizer was trained determines the index behavior. Therefore if you want to do visual search for a specific dataset (with distinct visual features) the best choice will be to use a <a href=\"https:\/\/imagga.com\/solutions\/custom-categorization\">custom model<\/a> as a categorizer.<\/p>\n<p>Lastly we define the API endpoints as global variables (since it&#8217;s just a test script):<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">categorizer_endpoint = '%s\/categories\/%s' % (API_ENDPOINT, CATEGORIZER)\r\nindex_endpoint = ('%s\/similar-images\/categories\/%s\/%s' %\r\n                  (API_ENDPOINT, CATEGORIZER, INDEX_NAME))\r\ntickets_endpoint = '%s\/tickets' % API_ENDPOINT<\/pre>\n<h3>The file contains 4 functions:<\/h3>\n<ul>\n<li><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">main()<\/code> &#8211; feeds all the images from the index_creation_set folder to the index, calls the index training and waits until the latter finishes<\/li>\n<li><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">feed_image(image_path)<\/code> &#8211; feeds a single image to the index<\/li>\n<li><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">train_index()<\/code> &#8211; calls the index training<\/li>\n<li><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">is_resolved(ticket_id)<\/code> &#8211; checks if the training is done<\/li>\n<\/ul>\n<h2><em>The script starts execution with the main() function:<\/em><\/h2>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">def main():\r\n    # Feed the visual search index with images\r\n    successful_feeds = 0\r\n    failed_feeds = 0\r\n\r\n    for image in os.scandir('.\/index_creation_set'):\r\n        print('At image %s: %s' % (successful_feeds, image.path))\r\n\r\n        successful = feed_image(image.path)\r\n        if successful:\r\n            successful_feeds += 1\r\n        else:\r\n            failed_feeds += 1\r\n\r\n    # Report\r\n    if not successful_feeds:\r\n        print('No images were fed successfully. Exiting')\r\n        return\r\n\r\n    print(\r\n        '%s out of %s images fed successfully' %\r\n        (successful_feeds, successful_feeds + failed_feeds))\r\n\r\n    # Train the index\r\n    ticket_id = train_index()\r\n\r\n    if not ticket_id:\r\n        print('No ticket id. Exiting')\r\n        return\r\n\r\n    # Wait for the training to complete\r\n    time_started = time.time()\r\n    while not is_resolved(ticket_id):\r\n        t_passed = (time.time() - time_started) \/\/ 1000\r\n        print(\r\n            'Waiting for training to finish (time elapsed: %.1fs)' % t_passed)\r\n\r\n        time.sleep(0.5)\r\n\r\n    print('Training done.')<\/pre>\n<h4>There are a few key lines of code here and the rest is basically made up of progress and error print statements.<\/h4>\n<p>Feed all the images to the index:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">for image in os.scandir('.\/index_creation_set'):\r\n    successful = feed_image(image.path)<\/pre>\n<p>Train the index.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">ticket_id = train_index()<\/pre>\n<p>The API call that invokes the training returns a ticket_id with its response, which is used below to check if the training is completed. A check is made every 0.5 seconds whether the training is completed:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">while not is_resolved(ticket_id):\r\n    t_passed = (time.time() - time_started) \/\/ 1000\r\n    print(\r\n        'Waiting for training to finish (time elapsed: %.1fs)' % t_passed)\r\n\r\n    time.sleep(0.5)<\/pre>\n<h2><em>The function feed_image(image_path)<\/em><\/h2>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">def feed_image(image_path):\r\n    file_name = os.path.basename(image_path)\r\n    image_name, extension = os.path.splitext(file_name)\r\n\r\n    # Make the API call\r\n    response = requests.post(\r\n        categorizer_endpoint,\r\n        auth=(API_KEY, API_SECRET),\r\n        files={'image': open(image_path, 'rb')},\r\n        params={'save_id': image_name, 'save_index': INDEX_NAME})\r\n\r\n    # Check for errors\r\n    try:\r\n        status = response.json()['status']\r\n        if status['type'] != 'success':\r\n            print('API reported error:', status['text'])\r\n            return False\r\n    except Exception as e:\r\n        print('Exception occured during handling the feeding response')\r\n        print(e)\r\n        return False\r\n\r\n    return True<\/pre>\n<p>Here the main action is the API call, which is a POST request to the <a href=\"https:\/\/docs.imagga.com\/#categories-categorizer_id\">\/categorizers\/&lt;categorizer_id&gt; endpoint<\/a>. As mentioned earlier we use the default categorizer, but you can check out the available categorizers with a GET request to <a href=\"https:\/\/docs.imagga.com\/#categorizers\">\/categorizers<\/a>.<\/p>\n<p>With the request parameters we specify the authentication credentials and the file to be uploaded. Again there &#8211; the <em><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">save_id<\/code><\/em> parameter specifies the ID which the image will be associated with in the index. The latter is specified by the <em><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">save_index<\/code><\/em> parameter. <strong>The ID of the image is important, because that&#8217;s what you&#8217;ll receive as a response when you query the index with a similar image.\u00a0<\/strong>In this demo we use the image name as an ID.<\/p>\n<h2>The function <em>train_index()<\/em><\/h2>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">def train_index():\r\n    ticket_id = ''\r\n\r\n    # Make the API call\r\n    response = requests.put(index_endpoint, auth=(API_KEY, API_SECRET))\r\n\r\n    # Get the completion ticket\r\n    try:\r\n        ticket_id = response.json()['result']['ticket_id']\r\n    except Exception as e:\r\n        print('Exception occured when processing the train call response')\r\n        print(e, response.content)\r\n\r\n    return ticket_id<\/pre>\n<p>It&#8217;s a plain PUT request to the <a href=\"https:\/\/docs.imagga.com\/#similar_images-categories-categorizer_id-index_id\">\/similar-images\/categories\/&lt;categorizer_id&gt;\/&lt;index_id&gt; endpoint<\/a>. The response returns JSON content where a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">ticket_id<\/code> is specified. The ticket API is used to check for task completion (and event resolution in general).<\/p>\n<h2>Here&#8217;s how the is_resolved(ticket_id) function polls for the training completion status<\/h2>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">def is_resolved(ticket_id):\r\n    resolved = False\r\n\r\n    # Make the API call\r\n    response = requests.get(\r\n        '%s\/%s' % (tickets_endpoint, ticket_id), auth=(API_KEY, API_SECRET))\r\n\r\n    # Check for errors\r\n    try:\r\n        resolved = response.json()['result']['is_final']\r\n    except Exception as e:\r\n        print('Exception occured during the ticket status check')\r\n        print(e)\r\n\r\n    return resolved<\/pre>\n<p>A simple GET call to the <a href=\"https:\/\/docs.imagga.com\/#tickets\">\/tickets\/&lt;ticket_id&gt; endpoint<\/a>. The response contains an <em><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">is_final<\/code><\/em> boolean, which, in this case, corresponds to the training status.<\/p>\n<h1>Using the visual search index<\/h1>\n<p><em>In <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">search_index.py<\/code> <\/em>(snippet below) you can see that the function <em><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">search_index(image_path)<\/code> <\/em>makes a POST request to the <a href=\"https:\/\/docs.imagga.com\/#similar_images-categories-categorizer_id-index_id\">\/similar-images\/categories\/&lt;categorizer_id&gt;\/&lt;index_id&gt; endpoint<\/a> to retrieve the IDs of the most visually similar images from the index. That&#8217;s our query call. The optional parameter <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">distance<\/code> is given to filter the results to those that are most similar. In this case the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">DISTANCE_THRESHOLD<\/code> is set to 1.4, but you should choose a distance that fits you use case. In most cases looking at the results for several samples will give you a good idea for what might be suitable for your needs. You can choose not to filter the results by distance at all (just omit the parameter).<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">import os\r\nimport json\r\nimport requests\r\nimport argparse\r\n\r\nfrom create_index import API_KEY, API_SECRET, index_endpoint\r\n\r\nDISTANCE_THRESHOLD = 1.4\r\n\r\n\r\ndef search_index(image_path):\r\n    if not os.path.exists(image_path):\r\n        print('Path is invalid:', image_path)\r\n        return None\r\n\r\n    search_result = None\r\n    with open(image_path, 'rb') as image_file:\r\n        response = requests.post(\r\n            index_endpoint,\r\n            params={'distance': DISTANCE_THRESHOLD},\r\n            files={'image': image_file},\r\n            auth=(API_KEY, API_SECRET))\r\n\r\n    try:\r\n        search_result = response.json()['result']\r\n    except Exception as e:\r\n        print('Exception occured during reading the search response')\r\n        print(e, response.content, response.status_code)\r\n\r\n    return search_result\r\n\r\n\r\ndef main():\r\n    parser = argparse.ArgumentParser()\r\n    parser.add_argument('image_path', help='Image to search for')\r\n\r\n    args = parser.parse_args()\r\n\r\n    result = search_index(args.image_path)\r\n    if not result:\r\n        print('No result obtained')\r\n\r\n    print('Search result:')\r\n    print(json.dumps(result, indent=4))\r\n\r\n\r\nif __name__ == '__main__':\r\n    main()\r\n<\/pre>\n<h1>Running the scripts<\/h1>\n<p>In the console we call the training:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">python create_index.py<\/pre>\n<p>Then if the script reports success we can test the visual search:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">python search_index.py query_test_images\/beach_volleyball.JPEG<\/pre>\n<p>If you want to delete the index and start anew:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-linenumbers=\"false\">python delete_index.py<\/pre>\n<h2>Here are some example results<\/h2>\n<p>The response JSON contains a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">result<\/code> and a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">status<\/code> field. The <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">result<\/code> field holds the categorizer labels for the image in the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">categories<\/code> list, and the search index results are in the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">images<\/code> list with their <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">distance<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">id<\/code>. Below you&#8217;ll find the visualizations for the top-3 results for each of the test images, and the JSONs for the corresponding API responses (with a distance filter of 1.4).<\/p>\n<h4>Response for the <em>beach_volleyball.JPEG:<\/em><\/h4>\n<p><img class=\"alignnone size-full wp-image-3675\" src=\"https:\/\/imagga.com\/blog\/wp-content\/uploads\/2020\/05\/beach_volleyball_results.png\" alt=\"\" width=\"732\" height=\"500\" \/><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"json\">{\r\n    \"categories\": [\r\n        {\r\n            \"confidence\": 78.8192367553711,\r\n            \"name\": {\r\n                \"en\": \"volleyball.n.02\"\r\n            }\r\n        },\r\n        {\r\n            \"confidence\": 10.889087677002,\r\n            \"name\": {\r\n                \"en\": \"volleyball_net.n.01\"\r\n            }\r\n        },\r\n        {\r\n            \"confidence\": 1.0372930765152,\r\n            \"name\": {\r\n                \"en\": \"swimming_trunks.n.01\"\r\n            }\r\n        }\r\n    ],\r\n    \"count\": 2,\r\n    \"images\": [\r\n        {\r\n            \"distance\": 0.910576224327087,\r\n            \"id\": \"volleyball\"\r\n        },\r\n        {\r\n            \"distance\": 1.27113902568817,\r\n            \"id\": \"table_tennis\"\r\n        }\r\n    ]\r\n}<\/pre>\n<h4>Response for the <em>dogs_2.JPEG:<\/em><\/h4>\n<p><img class=\"alignnone size-medium wp-image-3676\" src=\"https:\/\/imagga.com\/blog\/wp-content\/uploads\/2020\/05\/dogs_2_results.png\" alt=\"\" width=\"732\" height=\"500\" \/><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"json\">{\r\n    \"categories\": [\r\n        {\r\n            \"confidence\": 62.049072265625,\r\n            \"name\": {\r\n                \"en\": \"walker_hound.n.01\"\r\n            }\r\n        },\r\n        {\r\n            \"confidence\": 33.7763175964355,\r\n            \"name\": {\r\n                \"en\": \"english_foxhound.n.01\"\r\n            }\r\n        },\r\n        {\r\n            \"confidence\": 3.91585564613342,\r\n            \"name\": {\r\n                \"en\": \"beagle.n.01\"\r\n            }\r\n        }\r\n    ],\r\n    \"count\": 3,\r\n    \"images\": [\r\n        {\r\n            \"distance\": 1.25044810771942,\r\n            \"id\": \"dogs_1\"\r\n        },\r\n        {\r\n            \"distance\": 1.37776911258698,\r\n            \"id\": \"dog_1\"\r\n        },\r\n        {\r\n            \"distance\": 1.39786684513092,\r\n            \"id\": \"penguins\"\r\n        }\r\n    ]\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<h4>Response for the <em>lesser_panda_3.JPEG:<\/em><\/h4>\n<p><img class=\"alignnone size-medium wp-image-3677\" src=\"https:\/\/imagga.com\/blog\/wp-content\/uploads\/2020\/05\/lesser_panda_3_results.png\" alt=\"\" width=\"732\" height=\"500\" \/><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"json\">{\r\n    \"categories\": [\r\n        {\r\n            \"confidence\": 99.9105606079102,\r\n            \"name\": {\r\n                \"en\": \"lesser_panda.n.01\"\r\n            }\r\n        }\r\n    ],\r\n    \"count\": 3,\r\n    \"images\": [\r\n        {\r\n            \"distance\": 0.376796960830688,\r\n            \"id\": \"lesser_panda_1\"\r\n        },\r\n        {\r\n            \"distance\": 0.62762051820755,\r\n            \"id\": \"lesser_panda_2\"\r\n        },\r\n        {\r\n            \"distance\": 1.33433437347412,\r\n            \"id\": \"bird_1\"\r\n        }\r\n    ]\r\n}<\/pre>\n<h4>Response for the <em>man_with_burger.JPEG:<\/em><\/h4>\n<p><img class=\"alignnone size-medium wp-image-3678\" src=\"https:\/\/imagga.com\/blog\/wp-content\/uploads\/2020\/05\/man_wtih_burger_results.png\" alt=\"\" width=\"732\" height=\"500\" \/><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">{\r\n    \"categories\": [\r\n        {\r\n            \"confidence\": 22.9423999786377,\r\n            \"name\": {\r\n                \"en\": \"ladle.n.01\"\r\n            }\r\n        },\r\n        {\r\n            \"confidence\": 8.98854541778564,\r\n            \"name\": {\r\n                \"en\": \"wineglass.n.01\"\r\n            }\r\n        },\r\n        {\r\n            \"confidence\": 5.89485549926758,\r\n            \"name\": {\r\n                \"en\": \"maraca.n.01\"\r\n            }\r\n        },\r\n        {\r\n            \"confidence\": 3.46249604225159,\r\n            \"name\": {\r\n                \"en\": \"strainer.n.01\"\r\n            }\r\n        },\r\n        {\r\n            \"confidence\": 3.08541393280029,\r\n            \"name\": {\r\n                \"en\": \"goblet.n.01\"\r\n            }\r\n        },\r\n        {\r\n            \"confidence\": 2.84574699401855,\r\n            \"name\": {\r\n                \"en\": \"spatula.n.01\"\r\n            }\r\n        },\r\n        {\r\n            \"confidence\": 2.77523231506348,\r\n            \"name\": {\r\n                \"en\": \"alcoholic.n.01\"\r\n            }\r\n        },\r\n        {\r\n            \"confidence\": 1.77907812595367,\r\n            \"name\": {\r\n                \"en\": \"wooden_spoon.n.02\"\r\n            }\r\n        },\r\n        {\r\n            \"confidence\": 1.404292345047,\r\n            \"name\": {\r\n                \"en\": \"ping-pong_ball.n.01\"\r\n            }\r\n        },\r\n        {\r\n            \"confidence\": 1.33869755268097,\r\n            \"name\": {\r\n                \"en\": \"granadilla.n.04\"\r\n            }\r\n        },\r\n        {\r\n            \"confidence\": 1.21686482429504,\r\n            \"name\": {\r\n                \"en\": \"golfer.n.01\"\r\n            }\r\n        }\r\n    ],\r\n    \"count\": 2,\r\n    \"images\": [\r\n        {\r\n            \"distance\": 1.2667555809021,\r\n            \"id\": \"meal\"\r\n        },\r\n        {\r\n            \"distance\": 1.35286629199982,\r\n            \"id\": \"volleyball\"\r\n        }\r\n    ]\r\n}<\/pre>\n<div id=\"hzImg\" style=\"border: 1px solid #ffffff; line-height: 0; overflow: hidden; padding: 2px; margin: 0px; position: absolute; z-index: 2147483647; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.33) 3px 3px 9px 5px; opacity: 1; top: 496px; left: 477px; background-color: #ffffff; cursor: pointer; pointer-events: none; display: none;\"><\/div>\n<div id=\"hzImg\" style=\"border: 1px solid #ffffff; line-height: 0; overflow: hidden; padding: 2px; margin: 0px; position: absolute; z-index: 2147483647; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.33) 3px 3px 9px 5px; opacity: 1; top: 269px; left: 0px; background-color: #ffffff; cursor: pointer; pointer-events: none; display: none;\"><\/div>\n<div id=\"hzImg\" style=\"border: 1px solid #ffffff; line-height: 0; overflow: hidden; padding: 2px; margin: 0px; position: absolute; z-index: 2147483647; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.33) 3px 3px 9px 5px; opacity: 1; top: 360px; left: 0px; background-color: #ffffff; cursor: pointer; pointer-events: none; display: none;\"><\/div>\n<div id=\"hzImg\" style=\"border: 1px solid #ffffff; line-height: 0; overflow: hidden; padding: 2px; margin: 0px; position: absolute; z-index: 2147483647; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.33) 3px 3px 9px 5px; opacity: 1; top: 788px; left: 0px; background-color: #ffffff; cursor: pointer; pointer-events: none; display: none;\"><\/div>\n<div id=\"hzImg\" style=\"border: 1px solid #ffffff; line-height: 0; overflow: hidden; padding: 2px; margin: 0px; position: absolute; z-index: 2147483647; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.33) 3px 3px 9px 5px; opacity: 1; top: 347px; left: 477px; background-color: #ffffff; cursor: pointer; pointer-events: none; display: none;\"><\/div>\n<div id=\"hzImg\" style=\"border: 1px solid #ffffff; line-height: 0; overflow: hidden; padding: 2px; margin: 0px; position: absolute; z-index: 2147483647; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.33) 3px 3px 9px 5px; opacity: 1; top: 513px; left: 135px; background-color: #ffffff; cursor: pointer; pointer-events: none; display: none;\"><\/div>\n<div id=\"hzImg\" style=\"border: 1px solid #ffffff; line-height: 0; overflow: hidden; padding: 2px; margin: 0px; position: absolute; z-index: 2147483647; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.33) 3px 3px 9px 5px; opacity: 1; top: 744px; left: 0px; background-color: #ffffff; cursor: pointer; pointer-events: none; display: none;\"><\/div>\n","protected":false},"excerpt":{"rendered":"<p>In this article we&#8217;ll put the Imagga API for visual similarity to use with a demo that you can try [&hellip;]<\/p>\n","protected":false},"author":18,"featured_media":3777,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[211],"tags":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v17.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>How to use the Imagga visual similarity search - Imagga Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to use the Imagga visual similarity search - Imagga Blog\" \/>\n<meta property=\"og:description\" content=\"In this article we&#8217;ll put the Imagga API for visual similarity to use with a demo that you can try [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/\" \/>\n<meta property=\"og:site_name\" content=\"Imagga Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/imagga\/\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-13T14:28:10+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-05-13T14:38:09+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/imagga.com\/blog\/wp-content\/uploads\/2020\/05\/AdobeStock_27029802-e1589380009891.jpeg\" \/>\n\t<meta property=\"og:image:width\" content=\"1900\" \/>\n\t<meta property=\"og:image:height\" content=\"978\" \/>\n<meta name=\"twitter:card\" content=\"summary\" \/>\n<meta name=\"twitter:creator\" content=\"@imagga\" \/>\n<meta name=\"twitter:site\" content=\"@imagga\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Petko Ditchev\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https:\/\/imagga.com\/blog\/#organization\",\"name\":\"Imagga\",\"url\":\"https:\/\/imagga.com\/blog\/\",\"sameAs\":[\"https:\/\/www.facebook.com\/imagga\/\",\"https:\/\/twitter.com\/imagga\",\"https:\/\/www.linkedin.com\/company\/imagga\/\",\"https:\/\/twitter.com\/imagga\"],\"logo\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/imagga.com\/blog\/#logo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/imagga.com\/blog\/wp-content\/uploads\/2017\/04\/logo_white_blog.svg\",\"contentUrl\":\"https:\/\/imagga.com\/blog\/wp-content\/uploads\/2017\/04\/logo_white_blog.svg\",\"width\":\"27\",\"height\":\"29\",\"caption\":\"Imagga\"},\"image\":{\"@id\":\"https:\/\/imagga.com\/blog\/#logo\"}},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/imagga.com\/blog\/#website\",\"url\":\"https:\/\/imagga.com\/blog\/\",\"name\":\"Imagga Blog\",\"description\":\"Image recognition in the cloud\",\"publisher\":{\"@id\":\"https:\/\/imagga.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/imagga.com\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/imagga.com\/blog\/wp-content\/uploads\/2020\/05\/AdobeStock_27029802-e1589380009891.jpeg\",\"contentUrl\":\"https:\/\/imagga.com\/blog\/wp-content\/uploads\/2020\/05\/AdobeStock_27029802-e1589380009891.jpeg\",\"width\":1900,\"height\":978},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#webpage\",\"url\":\"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/\",\"name\":\"How to use the Imagga visual similarity search - Imagga Blog\",\"isPartOf\":{\"@id\":\"https:\/\/imagga.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#primaryimage\"},\"datePublished\":\"2020-05-13T14:28:10+00:00\",\"dateModified\":\"2020-05-13T14:38:09+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/imagga.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to use the Imagga visual similarity search\"}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#webpage\"},\"author\":{\"@id\":\"https:\/\/imagga.com\/blog\/#\/schema\/person\/e9077aecd0b894d63563ead5cf2cd725\"},\"headline\":\"How to use the Imagga visual similarity search\",\"datePublished\":\"2020-05-13T14:28:10+00:00\",\"dateModified\":\"2020-05-13T14:38:09+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#webpage\"},\"wordCount\":1020,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/imagga.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/imagga.com\/blog\/wp-content\/uploads\/2020\/05\/AdobeStock_27029802-e1589380009891.jpeg\",\"articleSection\":[\"Code Hacks\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#respond\"]}]},{\"@type\":\"Person\",\"@id\":\"https:\/\/imagga.com\/blog\/#\/schema\/person\/e9077aecd0b894d63563ead5cf2cd725\",\"name\":\"Petko Ditchev\",\"url\":\"https:\/\/imagga.com\/blog\/author\/petko\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to use the Imagga visual similarity search - Imagga Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/","og_locale":"en_US","og_type":"article","og_title":"How to use the Imagga visual similarity search - Imagga Blog","og_description":"In this article we&#8217;ll put the Imagga API for visual similarity to use with a demo that you can try [&hellip;]","og_url":"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/","og_site_name":"Imagga Blog","article_publisher":"https:\/\/www.facebook.com\/imagga\/","article_published_time":"2020-05-13T14:28:10+00:00","article_modified_time":"2020-05-13T14:38:09+00:00","og_image":[{"width":1900,"height":978,"url":"https:\/\/imagga.com\/blog\/wp-content\/uploads\/2020\/05\/AdobeStock_27029802-e1589380009891.jpeg","type":"image\/jpeg"}],"twitter_card":"summary","twitter_creator":"@imagga","twitter_site":"@imagga","twitter_misc":{"Written by":"Petko Ditchev","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Organization","@id":"https:\/\/imagga.com\/blog\/#organization","name":"Imagga","url":"https:\/\/imagga.com\/blog\/","sameAs":["https:\/\/www.facebook.com\/imagga\/","https:\/\/twitter.com\/imagga","https:\/\/www.linkedin.com\/company\/imagga\/","https:\/\/twitter.com\/imagga"],"logo":{"@type":"ImageObject","@id":"https:\/\/imagga.com\/blog\/#logo","inLanguage":"en-US","url":"https:\/\/imagga.com\/blog\/wp-content\/uploads\/2017\/04\/logo_white_blog.svg","contentUrl":"https:\/\/imagga.com\/blog\/wp-content\/uploads\/2017\/04\/logo_white_blog.svg","width":"27","height":"29","caption":"Imagga"},"image":{"@id":"https:\/\/imagga.com\/blog\/#logo"}},{"@type":"WebSite","@id":"https:\/\/imagga.com\/blog\/#website","url":"https:\/\/imagga.com\/blog\/","name":"Imagga Blog","description":"Image recognition in the cloud","publisher":{"@id":"https:\/\/imagga.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/imagga.com\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"ImageObject","@id":"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#primaryimage","inLanguage":"en-US","url":"https:\/\/imagga.com\/blog\/wp-content\/uploads\/2020\/05\/AdobeStock_27029802-e1589380009891.jpeg","contentUrl":"https:\/\/imagga.com\/blog\/wp-content\/uploads\/2020\/05\/AdobeStock_27029802-e1589380009891.jpeg","width":1900,"height":978},{"@type":"WebPage","@id":"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#webpage","url":"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/","name":"How to use the Imagga visual similarity search - Imagga Blog","isPartOf":{"@id":"https:\/\/imagga.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#primaryimage"},"datePublished":"2020-05-13T14:28:10+00:00","dateModified":"2020-05-13T14:38:09+00:00","breadcrumb":{"@id":"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/imagga.com\/blog\/"},{"@type":"ListItem","position":2,"name":"How to use the Imagga visual similarity search"}]},{"@type":"Article","@id":"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#article","isPartOf":{"@id":"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#webpage"},"author":{"@id":"https:\/\/imagga.com\/blog\/#\/schema\/person\/e9077aecd0b894d63563ead5cf2cd725"},"headline":"How to use the Imagga visual similarity search","datePublished":"2020-05-13T14:28:10+00:00","dateModified":"2020-05-13T14:38:09+00:00","mainEntityOfPage":{"@id":"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#webpage"},"wordCount":1020,"commentCount":0,"publisher":{"@id":"https:\/\/imagga.com\/blog\/#organization"},"image":{"@id":"https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#primaryimage"},"thumbnailUrl":"https:\/\/imagga.com\/blog\/wp-content\/uploads\/2020\/05\/AdobeStock_27029802-e1589380009891.jpeg","articleSection":["Code Hacks"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/imagga.com\/blog\/how-to-use-the-imagga-visual-similarity-search\/#respond"]}]},{"@type":"Person","@id":"https:\/\/imagga.com\/blog\/#\/schema\/person\/e9077aecd0b894d63563ead5cf2cd725","name":"Petko Ditchev","url":"https:\/\/imagga.com\/blog\/author\/petko\/"}]}},"_links":{"self":[{"href":"https:\/\/imagga.com\/blog\/wp-json\/wp\/v2\/posts\/3645"}],"collection":[{"href":"https:\/\/imagga.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/imagga.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/imagga.com\/blog\/wp-json\/wp\/v2\/users\/18"}],"replies":[{"embeddable":true,"href":"https:\/\/imagga.com\/blog\/wp-json\/wp\/v2\/comments?post=3645"}],"version-history":[{"count":80,"href":"https:\/\/imagga.com\/blog\/wp-json\/wp\/v2\/posts\/3645\/revisions"}],"predecessor-version":[{"id":3782,"href":"https:\/\/imagga.com\/blog\/wp-json\/wp\/v2\/posts\/3645\/revisions\/3782"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/imagga.com\/blog\/wp-json\/wp\/v2\/media\/3777"}],"wp:attachment":[{"href":"https:\/\/imagga.com\/blog\/wp-json\/wp\/v2\/media?parent=3645"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/imagga.com\/blog\/wp-json\/wp\/v2\/categories?post=3645"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/imagga.com\/blog\/wp-json\/wp\/v2\/tags?post=3645"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}