NAV Navbar
Logo
shell python

IBM Research AI for Fashion

The IBM Research AI for fashion project aims to build a suite of APIs for the fashion industry primarily leveraging deep learning, natural language processing and computer vision.

The usecases are targeted towards end consumers, online retailers, buyers, merchandisers and designers. Developers/in-house IT team can use these APIs to build their own applications. Central to this is a curated domain specific taxonomy/knowledge graph, fashion related content and text/image annotators tuned to the domain of fashion.

Python SDK

Authentication

# Pass the API key in the header.
curl 'api_endpoint_here' -H "X-Api-Key: your_api_key"

# If you are making a GET request, 
# you may also pass in the API key as a parameter.
curl "api_endpoint_here"?api_key=your_api_key
# We will use the requests HTTP library for python for all the examples.
# http://docs.python-requests.org

import requests

url = 'api_endpoint_here'
headers = {'X-Api-Key': 'your_api_key'}
response = requests.get(url,headers=headers)

# If you are making a GET request, 
# you may also pass in the API key as a parameter.
url = 'api_endpoint_here'
payload = {'api_key': 'your_api_key'}
response = requests.get(url,params=payload)

Make sure to replace your_api_key with your API key.

Cognitive Fashion uses API keys to allow access to the API. The API key has to be included in all API requests to the server.

The preferred way is to include it in a header that looks like the following:

curl "api_endpoint_here" -H "X-Api-Key: your_api_key"

If you are making a GET request, you may also pass in the API key as a parameter:

curl "api_endpoint_here"?api_key=your_api_key

Data collection

# Set X-Data-Collection-Opt-Out to true in the header.
curl 'api_endpoint_here' -H  "X-Data-Collection-Opt-Out: true"

# If you are making a GET request, 
# you may also set the data_collection_opt_out parameter to true.
curl "api_endpoint_here"?data_collection_opt_out=true
import requests

url = 'api_endpoint_here'

# Set X-Data-Collection-Opt-Out to true in the header.
headers = {}
headers['X-Api-Key'] = 'your_api_key'
headers['X-Data-Collection-Opt-Out'] = 'true'

response = requests.get(url,headers=headers)

url = 'api_endpoint_here'

# If you are making a GET request, you may also set the 
# data_collection_opt_out parameter to true.
params = {}
params['api_key'] = 'your_api_key'
params['data_collection_opt_out'] = 'true'

response = requests.get(url,params=params)

By default, most APIs log requests and their results. For example, the visual search API by default will save the user uploaded image. Logging is done only to improve the accuracy of the APIs. The logged data is not shared or made public. However, you have the option of opting out. To prevent the service from accessing your data for further API improvements, set the X-Data-Collection-Opt-Out header parameter to true. For example, for visual search API this will delete the user uploaded image from our servers as soon as the computations are done.

The preferred way is to include it in a header that looks like the following:

curl 'api_endpoint_here' -H "X-Data-Collection-Opt-Out: true"

If you are making a GET request, you may also set the data_collection_opt_out parameter to true.

curl "api_endpoint_here"?data_collection_opt_out=true

Fashion quote

import requests
from urlparse import urljoin

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header.
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Define the API end point.
api_endpoint = '/v1/fashion_quote'

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,headers=headers)

print response.status_code
print response.json()

Sample json response

{
 "quote": "Simplicity is the keynote of all true elegance.",
 "author": "Coco Chanel"
}

This endpoint gets a random quote about fashion. Think of this as our Hello, world! albiet a more interesting one which you can actually use on your websites.

End point

GET /v1/fashion_quote

Catalog

The APIs come in two flavors. Some APIs work on top of a simple user input and do not require access to the product catalog. However some APIs (like visual search) operate on top of a client catalog. The first step is to upload the product catalog. These are some end points for uploading, accessing, modifying and deleting a product catalog.

We use the term catalog to refer to a collection of product jsons. A product json consists of any available product meta-data and info about the product images.

Product JSON format

Sample product json document for catalog ingestion.

{
 "id": "109FA16AWWWDR9D03Y10", 
 "gender": "female",  
 "name": "109f women brown & yellow printed dress", 
 "url": "http://www.abof.com/product/109FA16AWWWDR9D03Y10-109F-Women-Brown-&-Yellow-Printed-Dress", 
 "date": "2016-10-12", 
 "out_of_stock": "no",
 "category": "dress", 
 "taxonomy": "women;dress", 
 "age_group": [
  "teenager", 
  "adult"
 ], 
 "images": {
  "1": {
   "camera_focus": "full", 
   "pose": "front", 
   "ignore": "no",
   "image_url": "http://images.abofcdn.com/catalog/images/2016/109FA16AWWWDR9D03Y10/Front_Large.jpg", 
   "model_worn": "yes",
   "image_type": "primary"
  }, 
  "3": {
   "camera_focus": "detail", 
   "pose": "UNK", 
   "ignore": "yes",
   "image_url": "http://images.abofcdn.com/catalog/images/2016/109FA16AWWWDR9D03Y10/Detail_Large.jpg", 
   "model_worn": "no",
   "image_type": "secondary"
  }, 
  "2": {
   "camera_focus": "full", 
   "pose": "right", 
   "ignore": "no",
   "image_url": "http://images.abofcdn.com/catalog/images/2016/109FA16AWWWDR9D03Y10/Right_Large.jpg", 
   "model_worn": "yes",
   "image_type": "secondary"
  }, 
  "4": {
   "camera_focus": "full", 
   "pose": "back", 
   "ignore": "no",
   "image_url": "http://images.abofcdn.com/catalog/images/2016/109FA16AWWWDR9D03Y10/Back_Large.jpg", 
   "model_worn": "yes",
   "image_type": "secondary"
  }
 }, 
 "color": [
  "copper",
  "brown",
  "yellow"
 ], 
 "pattern": [
  "printed"
 ], 
 "fabric": [
  "polyester"
 ], 
 "brand": [
  "109f"
 ], 
 "occasion": [
  "brunch"
 ],  
 "season": [
  "summer"
 ], 
 "attributes": [
  "round neck",
  "sleeveless"
 ], 
 "description": "Brown and yellow printed dress, has a round neck with tie-up detail on one shoulder, sleeveless, elasticized detail along the waistline, side slits", 
 "style_tip": "Club this dress with a pair of sandals. Add on a statement neckpiece for a stylish allure.", 
 "available_sizes": [
  "XS", 
  "S", 
  "M", 
  "L", 
  "XL"
 ], 
 "price": 2199.0, 
 "sale_price": 1100.0, 
 "sale_percentage": 50.0,
 "currency": "INR",
 "visual_search_category": ["dress"],
 "visual_browse_category": ["dress"]
}

We refer to any apparel, accessory, or footwear as a product in the table below. A product in a catalog is represented as a json object with fields specified below. Ingesting the catalog means uploading these json files for all products in the catalog via an API call.

Try to populate as much information available for each product into these fields in the json document. Except for the fields in bold (id, gender, name (for natural language search), images(for visual search and visual browse)) all other fields are optional. However the performance of the natural language search is heavily dependent on the richness of these structured fields and is recommended that you provide as much information as possible.

field type description
id string A unique identifier for the product for which there is a product page and a set of product images associated with it.
gender string The gender for which the product is intended for, can be male, female or unisex. Use UNK if not known.
name string The name of the product. This is generally a free text brief description of the product.
url string The corresponding url of the product page.
date string The date when the item was entered into the catalog, in YYYY-MM-DD format. You can also include time, like, 2015-01-01T12:10:30Z.
out_of_stock string Can either be yes or no. This is the field that need to be changed to yes when a product goes out of stock. By default all search queries will not return out-of-stock products. Note that typically out of stock is at the SKU level. Ideally make this yes only when all SKUs for this product are out of stock. You will typically use this when the product will be replenished. If you think the product will be discontinued and not available again you can delete that product entirely.
category string The product category.
taxonomy string The complete product taxonomy separated via ;.
age_group list string The age group for which the product is intended for. Some suggested tags : baby, kid, teenager, adult.
images list of dict A list of images available for the product with image_id as the key and the following fields in the dict.
image_id The image id (string).
image_url The image url. The actual image will be automatically downloaded from this url. The image format can be in JPEG,PNG,BMP, or GIF. Note that this url should be publicly accessible for us to download the image.
image_filename You can optionally specify an image filename. The image will be downloaded to the specified image filename.
image_type Can be either primary or secondary. You can use this field also to categorize images.
ignore You can use this field to select what kind of images should be used for visual browse/search. If yes then the image will not be downloaded and excluded from visual browse/search. In the example on the right, we ignore all images which have close-up of some details in the product.
model_worn If yes then the image corresponds to the model wearing the particular product. If no refers to image of the the product only. Use UNK if not known.
pose Refers to the pose/orientation in which the image is taken. Can take one of the following values: front, back, left, right, top, UNK.
camera_focus Which part of the model the camera is focused on. Can take one of the following values: full (complete view of the model, entire body), top (upper part of the model above the waist, used in shirts etc.), bottom (lower part of the model below the waist, used in trousers etc.), portrait (model face, normally up to the shoulder), detail (a close-up of some details in the product), outfit (complete view of the model, entire body along with other apparel and accessories), UNK.
The fields image_filename,image_type,ignore,model_worn, pose, and camera_focus are optional.
color list of string A list of terms that describe the colors in the product.
pattern list of string A list of terms that describe the pattern on the fabric.
fabric list of string A list of terms that describe the fabric used in the product.
brand list of string A list of terms that describe the brand name of the product.
occasion list of string A list of terms that describe occasion for which this product can be worn.
season list of string A list of terms that describe the season for which this product can be worn.
attributes list of string A list of terms that describe other attributes like sleeve length, collar etc. of the product.
description string A detailed free text description of the product if available.
style_tip string A detailed free text style tip if available. Typically this suggests what to pair this with.
available_sizes list of string A list of available sizes for the product.
price float The regular list price of the product.
sale_price float The sale price of the product if the product is on sale. If the product is not on sale make this equal to the regular price.
Note that the natural language search by default will use the sale_price field for the queries that deal with price.
sale_percentage float The sale percentage. This is useful for queries related to sale percentages.
currency string The currency used, specified as a 3 letter ISO 4217 currency code.
The following two fields below are for category based visual search and visual browse. For more details refer to the Visual Search API.
visual_search_category list of string A list of categories (or buckets) this product belongs to. This field is used to support category based visual search.
visual_browse_category list of string A list of categories (or buckets) this product belongs to. This field is used to support category based visual browse.

Add product to a catalog

#------------------------------------------------------------------------------
# Add product to a catalog.    
# POST /v1/catalog/{catalog_name}/products/{id}
# params - download_images
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

#------------------------------------------------------------------------------
# API URL
#------------------------------------------------------------------------------
api_gateway_url = props['api_gateway_url']

#------------------------------------------------------------------------------
# HEADERS
#------------------------------------------------------------------------------
headers = {}
# API key
headers['X-Api-Key'] = props['X-Api-Key']
# Data collection opt out.
headers['X-Data-Collection-Opt-Out'] = props['X-Data-Collection-Opt-Out']

#------------------------------------------------------------------------------
# OPTIONAL QUERY PARAMETERS
#------------------------------------------------------------------------------
params = {}

#------------------------------------------------------------------------------
# download_images : str, optional (default: 'true') 
# By default all the images in the json will be downloaded.  
# Set this to 'false' if you do not want to download the images.  
#------------------------------------------------------------------------------
params['download_images'] = 'true'

#------------------------------------------------------------------------------
# PATH PARAMETERS
#------------------------------------------------------------------------------
# Catalog name.
catalog_name = props['catalog_name']

#------------------------------------------------------------------------------
# ADD A BUNCH OF PRODUCTS
#------------------------------------------------------------------------------

# Some sample data where each product in the catalog is in a json format.
catalog_folder = os.path.join(props['catalog_folder'],'jsons')
json_filenames = [f for f in os.listdir(catalog_folder) if not f.startswith('.')]

for filename in json_filenames:
    # Load the json file.
    with open(os.path.join(catalog_folder,filename),'r') as f:
        data = json.loads(f.read())

    api_endpoint = '/v1/catalog/%s/products/%s'%(catalog_name,data['id'])

    url = urljoin(api_gateway_url,api_endpoint)

    response = requests.post(url,
                             headers=headers,
                             data=json.dumps(data),
                             params=params)

    print response.status_code
    pprint(response.json())

Sample json response

{
 "time_ms": "560.34",
 "version": 1,
 "id": "ABOFA15AWWWTP1101602",
 "n_images": 7,
 "n_images_downloaded": 5,
 "n_images_ignored": 2,
 "n_images_error": 0,
 "n_images_existing": 0,
 "images_error": []
}

Add a product json to a catalog and download the images.

Anytime you add a json to a catalog for the first time a new catalog will be automatically created with the name specified in the parameters catalog_name. The same catalog_name will have to be used for other end points.

End point

POST /v1/catalog/{catalog_name}/products/{id}

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
id path (Required) The product id.
data application/json (Required) The json object file in the the format specified earlier.
download_images query By default all the images specified in the json will be downloaded. Set this to false if you do not want to download the images. This is mainly useful when we have a local copy of the images or are not using visual search. true

Response

Parameter Description
time_ms The time taken in milliseconds.
id The product id.
version The version number. Every update will be assigned a new version number.
n_images The total number of images in the json file.
n_images_downloaded The actual number of images successfully downloaded.
n_images_ignored The total number of images ignored (as specified by the field ignore in images in the product json.).
n_images_error The number of images for which there was some error in downloading.
n_images_existing The number of images which were already downloaded.
images_error The is of the images for which there was some error in downloading.

Get product from a catalog

#-----------------------------------------------------------------------------
# Get product from a catalog.  
# GET /v1/catalog/{catalog_name}/products/{id}
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

#------------------------------------------------------------------------------
# API URL
#------------------------------------------------------------------------------
api_gateway_url = props['api_gateway_url']

#------------------------------------------------------------------------------
# HEADERS
#------------------------------------------------------------------------------
headers = {}
# API key
headers['X-Api-Key'] = props['X-Api-Key']
# Data collection opt out.
headers['X-Data-Collection-Opt-Out'] = props['X-Data-Collection-Opt-Out']

#------------------------------------------------------------------------------
# OPTIONAL QUERY PARAMETERS
#------------------------------------------------------------------------------
params = {}

#------------------------------------------------------------------------------
# PATH PARAMETERS
#------------------------------------------------------------------------------
# Catalog name.
catalog_name = props['catalog_name']

# product id
id = 'SKLTS16AMCWSH8SH20'

#------------------------------------------------------------------------------
# API END POINT
#------------------------------------------------------------------------------
api_endpoint = '/v1/catalog/%s/products/%s'%(catalog_name,id)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,
                        headers=headers,
                        params=params)

print response.status_code
pprint(response.json())

#------------------------------------------------------------------------------
# ACCESSING IMAGES.
#------------------------------------------------------------------------------
results = response.json()

for image_id in results['data']['images']:
    image_url = results['data']['images'][image_id]['image_url']
    image_filename = results['data']['images'][image_id]['image_filename']
    image_location = '/v1/catalog/%s/images/%s'%(catalog_name,image_filename)
    image_url_local = '%s?api_key=%s'%(urljoin(api_gateway_url,image_location),props['X-Api-Key'])
    print('%s %s \n %s \n %s \n %s'%(id,image_id,
                                     image_filename,
                                     image_url,
                                     image_url_local)
    )

Sample json response

{
 "time_ms": "1.99",
 "id": "20DRA16FWCWFT9010970",
 "version": 2,
 "found": true,
 "data": {
  "color": [
   "copper"
  ],
  "taxonomy": "women;footwear;sandals-heels",
  "age_group": [
   "teenager",
   "adult"
  ],
  "currency": "INR",
  "images": {
   "1": {
    "camera_focus": "UNK",
    "pose": "front",
    "ignore": "no",
    "image_url": "http://images.abofcdn.com/catalog/images/2015/20DRA16FWCWFT9010970/Front_Large.jpg",
    "model_worn": "yes",
    "image_filename": "20DRA16FWCWFT9010970_1_front_UNK.jpg"
   },
   "3": {
    "camera_focus": "UNK",
    "pose": "right",
    "ignore": "no",
    "image_url": "http://images.abofcdn.com/catalog/images/2015/20DRA16FWCWFT9010970/Right_Large.jpg",
    "model_worn": "yes",
    "image_filename": "20DRA16FWCWFT9010970_3_right_UNK.jpg"
   },
   "2": {
    "camera_focus": "UNK",
    "pose": "left",
    "ignore": "no",
    "image_url": "http://images.abofcdn.com/catalog/images/2015/20DRA16FWCWFT9010970/Left_Large.jpg",
    "model_worn": "yes",
    "image_filename": "20DRA16FWCWFT9010970_2_left_UNK.jpg"
   },
   "5": {
    "camera_focus": "UNK",
    "pose": "top",
    "ignore": "no",
    "image_url": "http://images.abofcdn.com/catalog/images/2015/20DRA16FWCWFT9010970/Top_Large.jpg",
    "model_worn": "yes",
    "image_filename": "20DRA16FWCWFT9010970_5_top_UNK.jpg"
   },
   "4": {
    "camera_focus": "detail",
    "pose": "UNK",
    "ignore": "yes",
    "image_url": "http://images.abofcdn.com/catalog/images/2015/20DRA16FWCWFT9010970/Detail_Large.jpg",
    "model_worn": "yes",
    "image_filename": "20DRA16FWCWFT9010970_4_UNK_detail.jpg"
   },
   "6": {
    "camera_focus": "full",
    "pose": "front",
    "ignore": "yes",
    "image_url": "http://images.abofcdn.com/catalog/images/2015/20DRA16FWCWFT9010970/Look_Large.jpg",
    "model_worn": "yes",
    "image_filename": "20DRA16FWCWFT9010970_6_front_full.jpg"
   }
  },
  "available_sizes": [
   "36",
   "37",
   "38",
   "39",
   "40",
   "41"
  ],
  "style_tip": "For a comfortable and stylish look, team these sandals with a pair of shorts and a T-shirt. Add on a watch to complete the look.",
  "id": "20DRA16FWCWFT9010970",
  "category": "flats",
  "fabric": [
   "upper: faux suede, sole: tpr"
  ],
  "pattern": "UNK",
  "sale_percentage": 9.966555183946488,
  "sale_price": 1346.0,
  "brand": "20dresses",
  "description": "Pointy-toed brown sandals with low top styling, has a faux suede upper, stylized lace-ups across the mid-foot that connects to form an ankle loop, patterned outsole",
  "season": "UNK",
  "price": 1495.0,
  "occasion": "UNK",
  "date": "2016-10-12",
  "name": "20dresses women brown sandals",
  "url": "http://www.abof.com/product/20DRA16FWCWFT9010970-20Dresses-Women-Brown-Sandals",
  "gender": "female",
  "attributes": "UNK",
  "out_of_stock": "no"
 }
}

Get the product json from a catalog.

End point

GET /v1/catalog/{catalog_name}/products/{id}

Request

Parameter Type Description
catalog_name path (Required) The catalog name.
id path (Required) The product id.

Response

Parameter Description
time_ms The time taken in milliseconds.
id The product id.
version The version number. Every update will be assigned a new version number.
data The product json.

Delete product from a catalog

#------------------------------------------------------------------------------
# Delete product from a catalog.
# DELETE /v1/catalog/{catalog_name}/products/{id}
# params - delete_images
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

#------------------------------------------------------------------------------
# API URL
#------------------------------------------------------------------------------
api_gateway_url = props['api_gateway_url']

#------------------------------------------------------------------------------
# HEADERS
#------------------------------------------------------------------------------
headers = {}
# API key
headers['X-Api-Key'] = props['X-Api-Key']
# Data collection opt out.
headers['X-Data-Collection-Opt-Out'] = props['X-Data-Collection-Opt-Out']

#------------------------------------------------------------------------------
# OPTIONAL QUERY PARAMETERS
#------------------------------------------------------------------------------
params = {}

#------------------------------------------------------------------------------
# delete_images : str, optional (default: 'false') 
#
# Set this to 'true' if you want to delete the images.  
#------------------------------------------------------------------------------
params['delete_images'] = 'false'

#------------------------------------------------------------------------------
# PATH PARAMETERS
#------------------------------------------------------------------------------
# Catalog name.
catalog_name = props['catalog_name']

# product id
id = 'SKLTS16AMCWSH8SH20'

#------------------------------------------------------------------------------
# API END POINT
#------------------------------------------------------------------------------
api_endpoint = '/v1/catalog/%s/products/%s'%(catalog_name,id)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.delete(url,
                           headers=headers,
                           params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "deleted": true,
 "time_ms": "4.01",
 "version": 4,
 "id": "SKLTS16AMCWSH8SH20"
}

Delete the product from a catalog.

End point

DELETE /v1/catalog/{catalog_name}/products/{id}

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
id path (Required) The product id.
delete_images query By default when you delete a product the images are not deleted. Set this to true if you want to delete the images. false

Response

Parameter Description
time_ms The time taken in milliseconds.
id The product id.
version The version number.
deleted This will be true if the product was successfully deleted.

Update product in a catalog

#------------------------------------------------------------------------------
# Update product in a catalog.  
# PUT  /v1/catalog/{catalog_name}/products/{id}
# params - download_images
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

#------------------------------------------------------------------------------
# API URL
#------------------------------------------------------------------------------
api_gateway_url = props['api_gateway_url']

#------------------------------------------------------------------------------
# HEADERS
#------------------------------------------------------------------------------
headers = {}
# API key
headers['X-Api-Key'] = props['X-Api-Key']
# Data collection opt out.
headers['X-Data-Collection-Opt-Out'] = props['X-Data-Collection-Opt-Out']

#------------------------------------------------------------------------------
# OPTIONAL QUERY PARAMETERS
#------------------------------------------------------------------------------
params = {}

#------------------------------------------------------------------------------
# download_images : str, optional (default: 'true') 
# By default all the images in the json will be downloaded.  
# Set this to 'false' if you do not want to download the images.  
#------------------------------------------------------------------------------
params['download_images'] = 'true'

#------------------------------------------------------------------------------
# PATH PARAMETERS
#------------------------------------------------------------------------------
# Catalog name.
catalog_name = props['catalog_name']

# product id
id = 'SKLTS16AMCWSH8SH20'

#------------------------------------------------------------------------------
# Data
#------------------------------------------------------------------------------
data = {}
data['out_of_stock'] = 'yes'

#------------------------------------------------------------------------------
# API END POINT
#------------------------------------------------------------------------------
api_endpoint = '/v1/catalog/%s/products/%s'%(catalog_name,id)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.put(url,
                        headers=headers,
                        params=params,
                        json=data)

print response.status_code
pprint(response.json())

Sample json response

{
 "time_ms": "12.83",
 "version": 6,
 "id": "20DRA16FWCWFT9010970"
}

Update the product in a catalog. This is useful to make partial/full updates to a product in the catalog. For example

End point

PUT /v1/catalog/{catalog_name}/products/{id}

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
id path (Required) The product id.
data application/json (Required) The json object file in the the format specified earlier containing only the modifications.
download_images query By default all the images specified in the json will be downloaded. Set this to false if you do not want to download the images. true

Response

Parameter Description
time_ms The time taken in milliseconds.
id The product id.
version The version number. Every new update creates a new version number.

Add metadata to a catalog

#------------------------------------------------------------------------------
# Add metadata to a catalog.    
# POST /v1/catalog/{catalog_name}
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

#------------------------------------------------------------------------------
# API URL
#------------------------------------------------------------------------------
api_gateway_url = props['api_gateway_url']

#------------------------------------------------------------------------------
# HEADERS
#------------------------------------------------------------------------------
headers = {}
# API key
headers['X-Api-Key'] = props['X-Api-Key']
# Data collection opt out.
headers['X-Data-Collection-Opt-Out'] = props['X-Data-Collection-Opt-Out']

#------------------------------------------------------------------------------
# OPTIONAL QUERY PARAMETERS
#------------------------------------------------------------------------------
params = {}

#------------------------------------------------------------------------------
# PATH PARAMETERS
#------------------------------------------------------------------------------
# Catalog name.
catalog_name = props['catalog_name']

#------------------------------------------------------------------------------
# Metadata
# Post any metadata you want to track for the catalog. Suggested fields
#------------------------------------------------------------------------------
data={}
#A friendly name for display purposes.
data['friendly_name'] = 'sample' 
# The url of the hero image.
data['hero_image_url'] = 'https://cognitivefashion.github.io/img/portfolio/logo_cf.svg' 
# A brief description.
data['description'] = 'A sample catalog to test IBM Research AI for Fashion APIs.' 

#------------------------------------------------------------------------------
# API END POINT
#------------------------------------------------------------------------------
api_endpoint = 'v1/catalog/%s'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.post(url,
                         headers=headers,
                         params=params,
                         json=data)

print response.status_code
pprint(response.json())

Sample json response

{
 "time_ms": "2.87",
 "catalog_name": "sample_catalog",
 "metadata": {
  "friendly_name": "sample",
  "description": "A sample catalog to test IBM Research AI for Fashion APIs.",
  "hero_image_url": "https://cognitivefashion.github.io/img/portfolio/logo_cf.svg"
 }
}

Add any extrat metadata to a catalog

You can add any meta data you want to track. Suggested fields could include

End point

POST /v1/catalog/{catalog_name}

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
id path (Required) The product id.
data application/json (Required) The json object file containing the metadata as key value pairs.

Response

Parameter Description
time_ms The time taken in milliseconds.
catalog_name The catalog name.
metadata The uploaded metadata.

Get info about a catalog

#------------------------------------------------------------------------------
# Get info about a product catalog.  
# GET /v1/catalog/{catalog_name}
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

#------------------------------------------------------------------------------
# API URL
#------------------------------------------------------------------------------
api_gateway_url = props['api_gateway_url']

#------------------------------------------------------------------------------
# HEADERS
#------------------------------------------------------------------------------
headers = {}
# API key
headers['X-Api-Key'] = props['X-Api-Key']
# Data collection opt out.
headers['X-Data-Collection-Opt-Out'] = props['X-Data-Collection-Opt-Out']

#------------------------------------------------------------------------------
# OPTIONAL QUERY PARAMETERS
#------------------------------------------------------------------------------
params = {}

#------------------------------------------------------------------------------
# PATH PARAMETERS
#------------------------------------------------------------------------------
# Catalog name.
catalog_name = props['catalog_name']

#------------------------------------------------------------------------------
# API END POINT
#------------------------------------------------------------------------------
api_endpoint = 'v1/catalog/%s'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,
                        headers=headers,
                        params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "num_of_products": 7,
 "time_ms": "9.22",
 "num_of_images": 24,
 "catalog_name": "sample_catalog",
 "metadata": {
  "friendly_name": "sample",
  "description": "A sample catalog to test IBM Research AI for Fashion APIs.",
  "hero_image_url": "https://cognitivefashion.github.io/img/portfolio/logo_cf.svg"
 }
}

Get some info about the product catalog. Currently this returns the number of products, the number of images and the metadata.

End point

GET /v1/catalog/{catalog_name}

Request

Parameter Type Description
catalog_name path (Required) The catalog name.

Response

Parameter Description
time_ms The time taken in milliseconds.
catalog_name The catalog name.
num_of_products Number of products in the catalog.
num_of_images Number of images in the catalog.
metadata The metadata.

Delete a catalog

#------------------------------------------------------------------------------
# Delete a product catalog.
# DELETE /v1/catalog/{catalog_name}
# params : delete_images
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

#------------------------------------------------------------------------------
# API URL
#------------------------------------------------------------------------------
api_gateway_url = props['api_gateway_url']

#------------------------------------------------------------------------------
# HEADERS
#------------------------------------------------------------------------------
headers = {}
# API key
headers['X-Api-Key'] = props['X-Api-Key']
# Data collection opt out.
headers['X-Data-Collection-Opt-Out'] = props['X-Data-Collection-Opt-Out']

#------------------------------------------------------------------------------
# OPTIONAL QUERY PARAMETERS
#------------------------------------------------------------------------------
params = {}

#------------------------------------------------------------------------------
# delete_images : str, optional(default: 'true')
# By default deletes all the catalog images unless this is set to 'false'.     
#------------------------------------------------------------------------------
params['delete_images'] = 'false'

#------------------------------------------------------------------------------
# PATH PARAMETERS
#------------------------------------------------------------------------------
# Catalog name.
catalog_name = props['catalog_name']

#------------------------------------------------------------------------------
# API END POINT
#------------------------------------------------------------------------------
api_endpoint = '/v1/catalog/%s'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.delete(url,
                           headers=headers,
                           params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "deleted": true,
 "time_ms": "360.34",
 "catalog_name": "sample_catalog"
}

Delete a product catalog. Also deletes all the downloaded images.

End point

DELETE /v1/catalog/{catalog_name}

Request

Parameter Type Description
catalog_name path (Required) The catalog name.
Parameter Type Description Default
catalog_name path (Required) The catalog name.
delete_images query By default deletes all the catalog images unless this is set to false. true

Response

Parameter Description
time_ms The time taken in milliseconds.
catalog_name The catalog name.
deleted This returns true is the catalog was successfully deleted.

Get all catalog names

#------------------------------------------------------------------------------
# Get all catalog names. 
# GET /v1/catalog_names
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

#------------------------------------------------------------------------------
# API URL
#------------------------------------------------------------------------------
api_gateway_url = props['api_gateway_url']

#------------------------------------------------------------------------------
# HEADERS
#------------------------------------------------------------------------------
headers = {}
# API key
headers['X-Api-Key'] = props['X-Api-Key']
# Data collection opt out.
headers['X-Data-Collection-Opt-Out'] = props['X-Data-Collection-Opt-Out']

#------------------------------------------------------------------------------
# OPTIONAL QUERY PARAMETERS
#------------------------------------------------------------------------------
params = {}

#------------------------------------------------------------------------------
# PATH PARAMETERS
#------------------------------------------------------------------------------
# Catalog name.
catalog_name = props['catalog_name']

#------------------------------------------------------------------------------
# API END POINT
#------------------------------------------------------------------------------
api_endpoint = 'v1/catalog_names'

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,
                        headers=headers,
                        params=params)

print response.status_code
pprint(response.json())

Sample json response

{
  "catalog_names": ["sample_catalog",
                    "sample_catalog_2"],
  "time_ms": "3.78"
}

Get all the catalog names.

End point

GET /v1/catalog_names

Request

Response

Parameter Description
time_ms The time taken in milliseconds.
catalog_names The catalog names.

Get catalog image

http://api_gateway_url/v1/catalog/sample_catalog/images/SKLTS16AMCWSH8SH20_5.jpg

http://api_gateway_url/v1/catalog/sample_catalog/images/SKLTS16AMCWSH8SH20_5.jpg?top_left_x=100&top_left_y=100&width=64&height=64

#-----------------------------------------------------------------------------
# Get product from a catalog.  
# GET /v1/catalog/{catalog_name}/products/{id}
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

#------------------------------------------------------------------------------
# API URL
#------------------------------------------------------------------------------
api_gateway_url = props['api_gateway_url']

#------------------------------------------------------------------------------
# HEADERS
#------------------------------------------------------------------------------
headers = {}
# API key
headers['X-Api-Key'] = props['X-Api-Key']
# Data collection opt out.
headers['X-Data-Collection-Opt-Out'] = props['X-Data-Collection-Opt-Out']

#------------------------------------------------------------------------------
# OPTIONAL QUERY PARAMETERS
#------------------------------------------------------------------------------
params = {}

#------------------------------------------------------------------------------
# PATH PARAMETERS
#------------------------------------------------------------------------------
# Catalog name.
catalog_name = props['catalog_name']

# product id
id = 'SKLTS16AMCWSH8SH20'

#------------------------------------------------------------------------------
# API END POINT
#------------------------------------------------------------------------------
api_endpoint = '/v1/catalog/%s/products/%s'%(catalog_name,id)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,
                        headers=headers,
                        params=params)

print response.status_code
pprint(response.json())

#------------------------------------------------------------------------------
# ACCESSING IMAGES.
#------------------------------------------------------------------------------
results = response.json()

for image_id in results['data']['images']:
    image_url = results['data']['images'][image_id]['image_url']
    image_filename = results['data']['images'][image_id]['image_filename']
    image_location = '/v1/catalog/%s/images/%s'%(catalog_name,image_filename)
    image_url_local = '%s?api_key=%s'%(urljoin(api_gateway_url,image_location),props['X-Api-Key'])
    print('%s %s \n %s \n %s \n %s'%(id,image_id,
                                     image_filename,
                                     image_url,
                                     image_url_local)
    )

Sample json response

Get an image in the catalog.

You can also pass the bounding box in the parameters to return a crop.

End point

GET /v1/catalog/{catalog_name}/images/{image_name}

Request

Parameter Type Description
catalog_name path (Required) The catalog name.
image_name path (Required) The image name.
top_left_x The x co-ordinate of the top left corner of the bounding box.
top_left_y The y co-ordinate of the top left corner of the bounding box.
width The width of the bounding box.
height The height of the bounding box.

Response

#------------------------------------------------------------------------------
# Basic text search
# GET /v1/catalog/{catalog_name}/text_search
# params : query_text, max_number_of_results
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

#------------------------------------------------------------------------------
# API URL
#------------------------------------------------------------------------------
api_gateway_url = props['api_gateway_url']

#------------------------------------------------------------------------------
# HEADERS
#------------------------------------------------------------------------------
headers = {}
# API key
headers['X-Api-Key'] = props['X-Api-Key']
# Data collection opt out.
headers['X-Data-Collection-Opt-Out'] = props['X-Data-Collection-Opt-Out']

#------------------------------------------------------------------------------
# OPTIONAL QUERY PARAMETERS
#------------------------------------------------------------------------------
params = {}

#------------------------------------------------------------------------------
# query_text : string
#   the search query
#------------------------------------------------------------------------------
params['query_text'] = 'skult'

#------------------------------------------------------------------------------
# max_number_of_results : int
#   maximum number of results to return
#   (defaults to 12)    
#------------------------------------------------------------------------------
params['max_number_of_results'] = 12

#------------------------------------------------------------------------------
# PATH PARAMETERS
#------------------------------------------------------------------------------
# Catalog name.
catalog_name = props['catalog_name']

#------------------------------------------------------------------------------
# API END POINT
#------------------------------------------------------------------------------
api_endpoint = '/v1/catalog/%s/text_search'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,
                        headers=headers,
                        params=params)

print response.status_code
pprint(response.json())

#------------------------------------------------------------------------------
# Get more info about the relevant results
#------------------------------------------------------------------------------
for product in response.json()['products']:
    id = product['id']
    api_endpoint = '/v1/catalog/%s/products/%s'%(catalog_name,id)
    url = urljoin(api_gateway_url,api_endpoint)
    response = requests.get(url,headers=headers)
    print('%s %s'%(id,response.json()['data']['name']))

Sample json response

{
 "time_ms": "41.15",
 "products": [
  {
   "id": "ABOFA15AMCWJG10448"
  },
  {
   "id": "ABOFA15AMCWJG10449"
  }
 ]
}

Search the product catalog using a simple text query (e.g. joggers).

End point

GET /v1/catalog/{catalog_name}/text_search

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
query_text query (Required) The text query. (e.g. joggers)
max_number_of_results query The maximum number of results to return. 12

Response

Parameter Description
time_ms The time taken in milliseconds.
products A sorted list of products in the catalog relevant to the query.
id The id of the product.

Visual Search

A collection of APIs for enabling a better search experience using the catalog images. Visual search helps a consumer discover exact match or show similar fashion products based on image search. These APIs support the following two variants:

  1. Visual Search (Search the look) Consumer can upload any fashion image of his/her liking and visual search will show visually similar products that exist in the catalog.

  2. Visual Browse (Show me more like this) A user clicks on an existing apparel/accessory image in the catalog and visual browse will fetch and display visually similar looking products from the catalog. This is a more interactive way of browsing the catalog based on visual search.

  3. Category based Visual Search/Browse (Visual Search and Visual Browse in a specific category) The visual search and visual browse APIs also support searching in a specific category. For example, in visual search, the user can upload any image and specify the category to search in (for example, show me similar looks like this in the dress category). To enable this use visual_search_category (for visual search) and visual_browse_category (for visual browse) field in the product json.

    visual_search_category - A list of categories(or buckets) this product belongs to (for example, data['visual_search_category'] = ['dress']). This field is used to support category based visual search.

    visual_browse_category - A list of categories(or buckets) this product belongs to (for example, data['visual_browse_category'] = ['sheath dress']). This field is used to support category based visual browse.

    A separate visual search index will be built with images from a particular category. While in most cases this will be same as category field in principle this field can be differnet. For example, shirts could be the category while the visual_search_category could be women shirts.

    The field can also support multiple category values. For example, data['visual_search_category'] = ['tops','blouses']. This means that the images corresponding to this product will be included in the visual search index for both tops and blouses.

Build visual search index

#------------------------------------------------------------------------------
# Build the visual search index.
# POST /v1/catalog/{catalog_name}/visual_search_index
# params - per_category_index
#          full_index
#          group_by
#          group_by_k 
#------------------------------------------------------------------------------

import os
import json
import requests
try:
    from urllib.parse import urljoin
except ImportError:
    from urlparse import urljoin
from pprint import pprint

from props import *

#------------------------------------------------------------------------------
# API URL
#------------------------------------------------------------------------------
api_gateway_url = props['api_gateway_url']

#------------------------------------------------------------------------------
# HEADERS
#------------------------------------------------------------------------------
headers = {}
# API key
headers['X-Api-Key'] = props['X-Api-Key']
# Data collection opt out
headers['X-Data-Collection-Opt-Out'] = props['X-Data-Collection-Opt-Out']

#------------------------------------------------------------------------------
# OPTIONAL QUERY PARAMETERS
#------------------------------------------------------------------------------
params = {}

#------------------------------------------------------------------------------
# per_category_index : str, optional (default: 'false')
#
# If this is set to 'true' builds a separate visual search index for each 
# category as specified in the field data['visual_search_category'].
#------------------------------------------------------------------------------
params['per_category_index'] = 'true'

#------------------------------------------------------------------------------
# full_index : str, optional (default: 'true')   
#
# If this is set to 'true' builds the the full visual search index along with
# the separate visual search index for each visual search/browse category. 
# By default the full visual search index is build along with the separate 
# index for each category. Make this 'false' only if you do not see the need 
# for the full visual search index.
#------------------------------------------------------------------------------
#params['full_index'] = 'false'

#------------------------------------------------------------------------------
# group_by : boolean, optional(default:'false')
#
#    If this is set to True the group_by option is enabled. This
#    groups the results from visual search into distinct groups 
#    according to various criteria. Currently the group_by option 
#    works only when full_index is set to True. If full_index is 
#    False the group_by is disabled.
#
# group_by_k : int, optional(default:5).
#
#    The number of nearest neighbors to use for group_by.
#------------------------------------------------------------------------------
#params['group_by'] = 'true'
#params['group_by_k'] = 5

#------------------------------------------------------------------------------
# PATH PARAMETERS
#------------------------------------------------------------------------------
# Catalog name.
catalog_name = props['catalog_name']

#------------------------------------------------------------------------------
# API END POINT
#------------------------------------------------------------------------------
api_endpoint = '/v1/catalog/%s/visual_search_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.post(url,
                         headers=headers,
                         params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "started": true,
 "time_ms": "0.55",
 "catalog_name": "sample_catalog"
}

Build the visual search index.

Before you can start using the visual search and visual browse APIs the visual search index has to be built first. This API computes the feature representations for all the catalog images and then builds a visual search index(each each category) for fast nearest neighbor retrieval.

End point

POST /v1/catalog/{catalog_name}/visual_search_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
per_category_index query If this is set to true builds a separate visual search index for each category as specified in the field data['visual_search_category'] and data['visual_browse_category']. false
full_index query If this is set to true builds the the full visual search index along with the separate visual search index for each visual search category. By default the full visual search index is built. Make this false only if you do not see the need for the full visual search index. true
group_by query If this is set to true the group_by option is enabled. This will allow the results from visual search to be grouped into distinct groups according to various criteria. Currently the group_by option works only when full_index is set to true. If full_index is false the group_by option is disabled. false
group_by_k query The number of nearest neighbors to use for group_by. 5

Response

Parameter Description
time_ms The time taken in milliseconds.
catalog_name The catalog name.
started This is true if the index building was started. You can query the status of the index building with the GET endpoint.

Get visual search index status

#------------------------------------------------------------------------------
# Get the status of the visual search index. 
# GET  /v1/catalog/{catalog_name}/visual_search_index
#------------------------------------------------------------------------------

import os
import json
import requests
try:
    from urllib.parse import urljoin
except ImportError:
    from urlparse import urljoin
from pprint import pprint

from props import *

#------------------------------------------------------------------------------
# API URL
#------------------------------------------------------------------------------
api_gateway_url = props['api_gateway_url']

#------------------------------------------------------------------------------
# HEADERS
#------------------------------------------------------------------------------
headers = {}
# API key
headers['X-Api-Key'] = props['X-Api-Key']
# Data collection opt out.
headers['X-Data-Collection-Opt-Out'] = props['X-Data-Collection-Opt-Out']

#------------------------------------------------------------------------------
# OPTIONAL QUERY PARAMETERS
#------------------------------------------------------------------------------
params = {}

#------------------------------------------------------------------------------
# PATH PARAMETERS
#------------------------------------------------------------------------------
# Catalog name.
catalog_name = props['catalog_name']

#------------------------------------------------------------------------------
# API END POINT
#------------------------------------------------------------------------------
api_endpoint = '/v1/catalog/%s/visual_search_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,
                        headers=headers,
                        params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "status": {
  "status": "done",
  "visual_search_index": {
   "num_of_images_missing_features": "0",
   "num_of_images_indexed": "28",
   "num_of_images_ignored": "10"
  },
  "num_of_products": "8",
  "start_time": "2018-10-26 09:15:33.013153",
  "index_updated": "true",
  "finish_time": "2018-10-26 09:15:40.012162",
  "visual_search_index_by_category": {
   "upper": {
    "num_of_images_missing_features": "0",
    "num_of_images_indexed": "12",
    "num_of_images_ignored": "26"
   },
   "lower": {
    "num_of_images_missing_features": "0",
    "num_of_images_indexed": "8",
    "num_of_images_ignored": "30"
   },
   "full": {
    "num_of_images_missing_features": "0",
    "num_of_images_indexed": "8",
    "num_of_images_ignored": "30"
   },
   "shirt": {
    "num_of_images_missing_features": "0",
    "num_of_images_indexed": "8",
    "num_of_images_ignored": "30"
   },
   "t-shirt": {
    "num_of_images_missing_features": "0",
    "num_of_images_indexed": "4",
    "num_of_images_ignored": "34"
   },
   "kurta": {
    "num_of_images_missing_features": "0",
    "num_of_images_indexed": "4",
    "num_of_images_ignored": "34"
   },
   "dress": {
    "num_of_images_missing_features": "0",
    "num_of_images_indexed": "4",
    "num_of_images_ignored": "34"
   },
   "joggers": {
    "num_of_images_missing_features": "0",
    "num_of_images_indexed": "8",
    "num_of_images_ignored": "30"
   }
  },
  "num_of_products_by_category": {
   "upper": "4",
   "lower": "2",
   "full": "2",
   "shirt": "2",
   "t-shirt": "2",
   "joggers": "2",
   "dress": "1",
   "kurta": "1"
  },
  "num_of_images": "38",
  "feature_computation": {
   "num_of_images_error": "0",
   "num_of_images_ignored": "10",
   "num_of_images_existing": "0",
   "num_of_images_processed": "28"
  },
  "num_of_images_by_category": {
   "upper": "18",
   "lower": "10",
   "full": "10",
   "shirt": "10",
   "t-shirt": "8",
   "kurta": "5",
   "dress": "5",
   "joggers": "10"
  }
 },
 "time_ms": "32.12",
 "catalog_name": "sample_catalog"
}

Get the status of the visual search index.

End point

GET /v1/catalog/{catalog_name}/visual_search_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.

Response

Parameter Description
time_ms The time taken in milliseconds.
catalog_name The catalog name.
status A json containing various info about the current status of the index building process.
status The current status of the index building process. The status can be one of starting,computing_features,building_index,or done. The index is built when the status becomes done.
start_time The time when the index building started.
finish_time The time when the index building finished.
num_of_products The total number of products in the catalog.
num_of_products_by_category The number of products in the catalog bucketed by visual_search_category and visual_browse_category.
num_of_images The total number of images in the catalog.
num_of_images_by_category The number of images in the catalog bucketed by visual_search_category and visual_browse_category.
feature_computation Info about feature computation.
num_of_images_error The number of images for which there was some error in feature computation.
num_of_images_ignored The number of images that were ignored.
num_of_images_existing The number of images for which the features were already computed (in case of building a new index with new products being added).
num_of_images_processed The total number of images for which the features were computed.
visual_search_index Info about the index building.
num_of_images_missing_features The number of images for which there was no feature found.
num_of_images_ignored The number of images that were ignored.
num_of_images_index The total number of images finally indexed.
visual_search_index_by_category Same info as visual_search_index but bucketed by visual_search_category and visual_browse_category.

Delete visual search index

#------------------------------------------------------------------------------
# Delete the visual search index. 
# DELETE  /v1/catalog/{catalog_name}/visual_search_index
#------------------------------------------------------------------------------

import os
import json
import requests
try:
    from urllib.parse import urljoin
except ImportError:
    from urlparse import urljoin
from pprint import pprint

from props import *

#------------------------------------------------------------------------------
# API URL
#------------------------------------------------------------------------------
api_gateway_url = props['api_gateway_url']

#------------------------------------------------------------------------------
# HEADERS
#------------------------------------------------------------------------------
headers = {}
# API key
headers['X-Api-Key'] = props['X-Api-Key']
# Data collection opt out.
headers['X-Data-Collection-Opt-Out'] = props['X-Data-Collection-Opt-Out']

#------------------------------------------------------------------------------
# OPTIONAL QUERY PARAMETERS
#------------------------------------------------------------------------------
params = {}

#------------------------------------------------------------------------------
# PATH PARAMETERS
#------------------------------------------------------------------------------
# Catalog name.
catalog_name = props['catalog_name']

#------------------------------------------------------------------------------
# API END POINT
#------------------------------------------------------------------------------
api_endpoint = '/v1/catalog/%s/visual_search_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.delete(url,
                           headers=headers,
                           params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "deleted": true,
 "time_ms": "39.63",
 "catalog_name": "sample_catalog"
}

Delete the visual search index.

End point

DELETE /v1/catalog/{catalog_name}/visual_search_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.

Response

Parameter Description
time_ms The time taken in milliseconds.
catalog_name The catalog name.
deleted This is true if the index was successfully deleted.

Visual Browse

#------------------------------------------------------------------------------
# Visual Browse
#
# Get other visually similar products in the catalog.
# GET /v1/catalog/{catalog_name}/visual_search/{id}/{image_id}
# params - max_number_of_results
#          per_category_index
#          category
#          unique_products
#          sort_option
#          use_cache
#------------------------------------------------------------------------------

import os
import json
import requests
try:
    from urllib.parse import urljoin
except ImportError:
    from urlparse import urljoin
from pprint import pprint

from props import *

#------------------------------------------------------------------------------
# API URL
#------------------------------------------------------------------------------
api_gateway_url = props['api_gateway_url']

#------------------------------------------------------------------------------
# HEADERS
#------------------------------------------------------------------------------
headers = {}
# API key
headers['X-Api-Key'] = props['X-Api-Key']
# Data collection opt out.
headers['X-Data-Collection-Opt-Out'] = props['X-Data-Collection-Opt-Out']

#------------------------------------------------------------------------------
# OPTIONAL QUERY PARAMETERS
#------------------------------------------------------------------------------
params = {}

#------------------------------------------------------------------------------
# max_number_of_results : int, optional (default: 12)
#
# The maximum number of results to return. 
#------------------------------------------------------------------------------
params['max_number_of_results'] = 5

#------------------------------------------------------------------------------
# per_category_index : str, optional (default: 'false')
#
# If this is set to 'true' does visual browse only in the categories specifed 
# in the data['visual_search_category'] field. 
#------------------------------------------------------------------------------
params['per_category_index'] = 'true'

#------------------------------------------------------------------------------
# category : str, optional (default: None) 
#
# Optionally you can also specify a list of categories to search.
# This is specified as a comma separated string, for example, 
# `category=tops,blouses`. The categories have to be valid 
# categories specified in the data['visual_browse_category'] field.
#------------------------------------------------------------------------------
#params['category'] = 'shirt,dress'

#------------------------------------------------------------------------------
# unique_products : str, optional (default: 'false')
#
# By default visual browse uses all images available for a product.
# Hence, sometimes in the search results the same product id can 
# appear multiple times (with a different image_id). If this 
# parameter is set to 'true' then the results are post-filtered 
# to contain only unique products (the best matching image_id is
# retained).  
#------------------------------------------------------------------------------
#params['unique_products'] = 'true'

#------------------------------------------------------------------------------
# sort_option : str, optional (default: 'visual_similarity')
#
# 'visual_similarity'  : Results are sorted by visual similarity.
# 'apparel_similarity' : Re-sorts the results from using apparel similarity.
# 'color_similarity'   : Re-sorts the results from using color similarity.
#------------------------------------------------------------------------------
#params['sort_option'] = 'apparel_similarity'
#params['sort_option'] = 'color_similarity'

#------------------------------------------------------------------------------
# use_cache : str, optional (default: 'true')
#
# The first time visual browse is called it caches the results.
# On subsequent calls the API directly retrieves the results from the cache 
# unless use_cache='false'.  
#------------------------------------------------------------------------------
params['use_cache'] = 'false'

#------------------------------------------------------------------------------
# PATH PARAMETERS
#------------------------------------------------------------------------------
# Catalog name.
catalog_name = props['catalog_name']

# The product id.
id ='ABOFA15AMCWJG10449'

# The image id.
image_id = '1'

#------------------------------------------------------------------------------
# API END POINT
#------------------------------------------------------------------------------
api_endpoint = '/v1/catalog/%s/visual_browse/%s/%s'%(catalog_name,
                                                     id,
                                                     image_id)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,
                        headers=headers,
                        params=params)

print(response.url)
print(response.status_code)
pprint(response.json())

#------------------------------------------------------------------------------
# FRIENDLY RESPONSE
#------------------------------------------------------------------------------
results = response.json()

for product in results['products']:
    id = product['id']
    image_id = product['image_id']
    score = product['similarity']
    # Get the image_url and image_filename by querying the catalog
    api_endpoint = '/v1/catalog/%s/products/%s'%(catalog_name,id)
    url = urljoin(api_gateway_url,api_endpoint)
    response = requests.get(url,headers=headers)
    image_url = response.json()['data']['images'][image_id]['image_url']
    image_filename = response.json()['data']['images'][image_id]['image_filename']
    image_location = '/v1/catalog/%s/images/%s'%(catalog_name,image_filename)
    image_url_local = '%s?api_key=%s'%(urljoin(api_gateway_url,image_location),props['X-Api-Key'])
    print('%s %s %1.2f %s'%(id,image_id,score,image_url_local))

Sample json response

{
 "sort_option": "visual_similarity",
 "time_ms": "6.81",
 "cache": false,
 "visual_browse_category": [
  "joggers"
 ],
 "per_category_index": true,
 "products": [
  {
   "image_id": "1",
   "visual_browse_category": "joggers",
   "id": "ABOFA15AMCWJG10449",
   "similarity": 0.9999680509281461
  },
  {
   "image_id": "3",
   "visual_browse_category": "joggers",
   "id": "ABOFA15AMCWJG10449",
   "similarity": 0.6284773349761963
  },
  {
   "image_id": "2",
   "visual_browse_category": "joggers",
   "id": "ABOFA15AMCWJG10449",
   "similarity": 0.6176716089248657
  },
  {
   "image_id": "4",
   "visual_browse_category": "joggers",
   "id": "ABOFA15AMCWJG10448",
   "similarity": 0.47411400079727173
  },
  {
   "image_id": "3",
   "visual_browse_category": "joggers",
   "id": "ABOFA15AMCWJG10448",
   "similarity": 0.45831894874572754
  }
 ]
}

Find other similar images in the product catalog for a given image based on visual appearance.

End point

GET /v1/catalog/{catalog_name}/visual_browse/{id}/{image_id}

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
id path (Required) The product id.
image_id path (Required) The image id.
max_number_of_results query The maximum number of results to return. 12
per_category_index query If this is set to true does visual browse only in the categories specifed in the data['visual_browse_category']` field. false
category query Optionally you can also spaecify a list of categories to search. This is specified as a comma separated string, for example, category=tops,blouses. The categories have to be valid categories specified in the data[‘visual_browse_category’] field.
use_cache query The first time visual browse is called it caches the results. On subsequent requests we directly retrieve the results from the cache unless use_cache=false. true
sort_option query The sort option to use. Can be either visual_similarity (Results are sorted by visual similarity.) or apparel_similarity (Re-sorts the results from visual browse using a combination of visual similarity and textual similarity based on the avaialble meta data.) visual_similarity
unique_products query By default visual browse uses all images available for a product. Hence, sometimes in the search results the same product id can appear multiple times (with a different image_id). If this parameter is set to ‘true’ then the results are post-filtered to contain only unique products (the best matching image_id is retained). false

Response

Parameter Description
time_ms The time taken in milliseconds.
cache Indicates whether cache was used or not.
per_category_index Indicates whetehr category based visual search was used or not.
visual_browse_category The list of visual browse categories used.
sort_option The sort_option used.
products A sorted list of other visually similar images. The first item in the list is the specified image.
image_id The image id.
id The product id.
similarity The similarity score in the range from 0(dissimilar) to 1(similar).
visual_browse_category The visual browse category for the product.

Get visual browse categories

#------------------------------------------------------------------------------
# Get all visual browse categories 
# GET /v1/catalog/{catalog_name}/visual_browse_categories
#------------------------------------------------------------------------------

import os
import json
import requests
try:
    from urllib.parse import urljoin
except ImportError:
    from urlparse import urljoin
from pprint import pprint

from props import *

#------------------------------------------------------------------------------
# API URL
#------------------------------------------------------------------------------
api_gateway_url = props['api_gateway_url']

#------------------------------------------------------------------------------
# HEADERS
#------------------------------------------------------------------------------
headers = {}
# API key
headers['X-Api-Key'] = props['X-Api-Key']
# Data collection opt out.
headers['X-Data-Collection-Opt-Out'] = props['X-Data-Collection-Opt-Out']

#------------------------------------------------------------------------------
# OPTIONAL QUERY PARAMETERS
#------------------------------------------------------------------------------
params = {}

#------------------------------------------------------------------------------
# PATH PARAMETERS
#------------------------------------------------------------------------------
# Catalog name.
catalog_name = props['catalog_name']

#------------------------------------------------------------------------------
# API END POINT
#------------------------------------------------------------------------------
api_endpoint = '/v1/catalog/%s/visual_browse_categories'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,
                        headers=headers,
                        params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "time_ms": "14.88",
 "counts": {
  "num_of_products": 8,
  "num_of_products_by_category": {
   "t-shirt": 2,
   "kurta": 1,
   "dress": 1,
   "shirt": 2,
   "joggers": 2
  },
  "num_of_images": 38,
  "num_of_images_by_category": {
   "t-shirt": 8,
   "kurta": 5,
   "dress": 5,
   "shirt": 10,
   "joggers": 10
  }
 },
 "categories": [
  "t-shirt",
  "joggers",
  "dress",
  "shirt",
  "kurta"
 ]
}

Get all visual browse categories

End point

GET /v1/catalog/{catalog_name}/visual_browse_categories

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.

Response

Parameter Description
time_ms The time taken in milliseconds.
categories The visual browse categories.
counts The counts of the visual browse categories.
#------------------------------------------------------------------------------
# Get visually similar products in the catalog for an uploaded image.
# POST /v1/catalog/{catalog_name}/visual_search
# params - max_number_of_results
#          per_category_index
#          categories
#          sort_option    
#          visual_search_categories_threshold
#          unique_products
#          group_by
#------------------------------------------------------------------------------

import os
import json
import requests
try:
    from urllib.parse import urljoin
except ImportError:
    from urlparse import urljoin
from pprint import pprint

from props import *

#------------------------------------------------------------------------------
# API URL
#------------------------------------------------------------------------------
api_gateway_url = props['api_gateway_url']

#------------------------------------------------------------------------------
# HEADERS
#------------------------------------------------------------------------------
headers = {}
# API key
headers['X-Api-Key'] = props['X-Api-Key']
# Data collection opt out.
headers['X-Data-Collection-Opt-Out'] = props['X-Data-Collection-Opt-Out']

#------------------------------------------------------------------------------
# OPTIONAL QUERY PARAMETERS
#------------------------------------------------------------------------------

params = {}
#------------------------------------------------------------------------------
# max_number_of_results : int, optional (default: 12)
#
# The maximum number of results to return. 
#------------------------------------------------------------------------------
params['max_number_of_results'] = 5

#------------------------------------------------------------------------------
# category : str, optional (default: None) 
#
# Optionally you can also specify a list of categories to search.
# This is specified as a comma separated string, for example, 
# `category=tops,blouses`. The categories have to be valid 
# categories specified in the data['visual_search_category'] field.
#------------------------------------------------------------------------------
#params['category'] = 'kurta,dress'

#------------------------------------------------------------------------------
# per_category_index : str, optional (default: 'false')
#
# If this is set to 'true' first predicts the visual search category for the
# uploaded image and then does visual search with the predicted categories.
#------------------------------------------------------------------------------
params['per_category_index'] = 'true'

#------------------------------------------------------------------------------
# visual_search_categories_threshold : float, optional (default: 0.0)
#
# Use the prdictions from the visual search categories classifier
# only if the confidence score is greater than this value. 
#------------------------------------------------------------------------------
params['visual_search_categories_threshold'] = 0.25

#------------------------------------------------------------------------------
# reweight_similarity_scores : str, optional (default: 'false')
#
# If true multiplies the visual similarity scores by the (normalized) category 
# classifier prediction scores.    
#------------------------------------------------------------------------------
#params['reweight_similarity_scores'] = 'false'

#------------------------------------------------------------------------------
# sort_option : str, optional (default: 'visual_similarity')
#
# 'visual_similarity'  : Results are sorted by visual similarity.
# 'apparel_similarity' : Re-sorts the results from using apparel similarity.
# 'color_similarity'   : Re-sorts the results from using color similarity.
#------------------------------------------------------------------------------
#params['sort_option'] = 'apparel_similarity'
#params['sort_option'] = 'color_similarity'

#------------------------------------------------------------------------------
# unique_products : str, optional (default: 'false')
#
# By default visual browse uses all images available for a product.
# Hence, sometimes in the search results the same product id can 
# appear multiple times (with a different image_id). If this 
# parameter is set to 'true' then the results are post-filtered 
# to contain only unique products (the best matching image_id is
# retained).  
#------------------------------------------------------------------------------
#params['unique_products'] = 'true'

#------------------------------------------------------------------------------
# - group_by : str, optional (default: None)  
#    This field can be used to group the results from visual search 
#    into distinct groups according to various criteria. 
#------------------------------------------------------------------------------
#params['group_by'] = 'color'
#params['group_by'] = 'visual'
#params['group_by'] = 'visual,color'

#------------------------------------------------------------------------------
# PATH PARAMETERS
#------------------------------------------------------------------------------
# Catalog name.
catalog_name = props['catalog_name']

#------------------------------------------------------------------------------
# API END POINT
#------------------------------------------------------------------------------
api_endpoint = 'v1/catalog/%s/visual_search'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

#------------------------------------------------------------------------------
# Three options to pass the image
#------------------------------------------------------------------------------

# OPTION 1 : Directly post the image
headers['Content-Type'] = 'image/jpeg'
response = requests.post(url,
                         headers=headers,
                         params=params,
                         data=open('test_image_4.jpeg','rb'))

"""       
# OPTION 2 : Pass the image url
params['image_url'] = 'http://images.abofcdn.com/catalog/images/2015/ABOFA15AMCWJG1044901/Right_Medium.jpg'
response = requests.post(url,
                         headers=headers,
                         params=params)
"""

"""
# OPTION 3 : using multipart
image_filename = 'test_image_2.jpeg'
with open(image_filename,'rb') as images_file:
    response = requests.post(url,
                             headers=headers,
                             params=params,
                             files={'image': (image_filename,images_file,'image/jpeg')})   
"""

print response.url
print response.status_code
pprint(response.json())


#------------------------------------------------------------------------------
# FRIENDLY RESPONSE
#------------------------------------------------------------------------------
results = response.json()

image_location = '%s?api_key=%s'%(urljoin(api_gateway_url,results['image_location']),
                                  props['X-Api-Key'])
print('[user uploaded image] %s'%(image_location))

for product in results['products']:
    id = product['id']
    image_id = product['image_id']
    score = product['similarity']
    # Get the image_url and image_filename by querying the catalog
    api_endpoint = '/v1/catalog/%s/products/%s'%(catalog_name,id)
    url = urljoin(api_gateway_url,api_endpoint)
    response = requests.get(url,headers=headers)
    image_url = response.json()['data']['images'][image_id]['image_url']
    image_filename = response.json()['data']['images'][image_id]['image_filename']
    image_location = '/v1/catalog/%s/images/%s'%(catalog_name,image_filename)
    image_url_local = '%s?api_key=%s'%(urljoin(api_gateway_url,image_location),props['X-Api-Key'])
    print('%s %s %1.2f %s'%(id,image_id,score,image_url_local))

Sample json response

{
 "image_location": "/v1/images/ed802be3-afaf-4e84-bc0a-95a4cdee9268.jpe",
 "sort_option": "visual_similarity",
 "time_ms": "572.09",
 "per_category_index": true,
 "visual_search_category": [
  "upper"
 ],
 "visual_search_category_predictions": {
  "upper": 0.5216091680340469,
  "outer": 0.028820261858555796,
  "pant": 0.007078210662257334,
  "dress": 0.39006669973059616,
  "shorts": 0.0016162813953428667
 },
 "products": [
  {
   "image_id": "1",
   "visual_search_category": "upper",
   "id": "LPJNA16AMDMTE91642",
   "similarity": 0.47364169359207153
  },
  {
   "image_id": "2",
   "visual_search_category": "upper",
   "id": "LPJNA16AMDMTE91642",
   "similarity": 0.449137806892395
  },
  {
   "image_id": "1",
   "visual_search_category": "upper",
   "id": "LPJNA16AMDMTE91662",
   "similarity": 0.424848735332489
  },
  {
   "image_id": "2",
   "visual_search_category": "upper",
   "id": "SKLTS16AMCWSH8SP01",
   "similarity": 0.42225950956344604
  },
  {
   "image_id": "3",
   "visual_search_category": "upper",
   "id": "SKLTS16AMCWSH8SP01",
   "similarity": 0.42015230655670166
  }
 ]
}

Find other similar images in the product catalog for a given uploaded image based on visual appearance.

End point

POST /v1/catalog/{catalog_name}/visual_search

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
data image/jpeg (Required) The image. The image can be in PNG, JPEG, BMP, or GIF.
max_number_of_results query maximum number of results to return 12
category query Optionally you can also specify a list of categories to search. This is specified as a comma separated string, for example, category=tops,blouses. The categories have to be valid categories specified in the data['visual_search_category']` field.
per_category_index query If this is set to true first predicts the visual search category for the uploaded image and then does visual search with the predicted categories. false
visual_search_categories_threshold query Use the predictions from the visual search categories classifier only if the confidence score is greater than this value. 0.0
reweight_similarity_scores query If true multiplies the visual similarity scores by the (normalized) category classifier prediction scores. false
sort_option query The sort option to use. Can be either visual_similarity (Results are sorted by visual similarity.) or apparel_similarity (Re-sorts the results using a combination of visual similarity and textual similarity based on the avaialble meta data.) or color_similarity (Re-sorts the results using a combination of visual similarity and color similarity based on the avaialble meta data.). visual_similarity
unique_products query By default visual browse uses all images available for a product. Hence, sometimes in the search results the same product id can appear multiple times (with a different image_id). If this parameter is set to ‘true’ then the results are post-filtered to contain only unique products (the best matching image_id is retained). false
group_by query This field can be used to group the results from visual search into distinct groups according to various criteria. This is specfied as a comma separated string, for example, group_by=color,pattern. This would group results with similar color and pattern into a distinct group. The group is accessed by the field group_id in the results. Note that the field has to be a valid field avaialble in the product json. There is also a special field called visual which uses the total visual apprarance to group the reuslts rather than one specific attribute, for example, group_by=visual,color. In order to use this feature group_by should also be set to true when building the visual search index. The final set of returned results are sorted by the group size. This is currently an experimental feature and following are the suggested values to try are group_by=visual,group_by=color and group_by=visual,color.

Response

Parameter Description
time_ms The time taken in milliseconds.
image_location The path to the user uploaded image. This is not avaiable if you set the X-Data-Collection-Opt-Out header parameter to true.
products A sorted list of other visually similar images.
image_id The image id.
id The product id.
similarity The similarity score in the range from 0(dissimilar) to 1 (similar).
Parameter Description
time_ms The time taken in milliseconds.
image_location The path to the user uploaded image. This is not avaiable if you set the X-Data-Collection-Opt-Out header parameter to true.
per_category_index Indicates whetehr category based visual search was used or not.
visual_search_category The list of visual search categories used.
visual_search_category_predictions The top-5 predictions from the visual search category classifier.
products A sorted list of other visually similar images. The first item in the list is the specified image.
image_id The image id.
id The product id.
similarity The similarity score in the range from 0(dissimilar) to 1(similar).
visual_search_category The visual search category for the product.

Get visual search categories

#------------------------------------------------------------------------------
# Get all visual search categories 
# GET /v1/catalog/{catalog_name}/visual_search_categories
#------------------------------------------------------------------------------

import os
import json
import requests
try:
    from urllib.parse import urljoin
except ImportError:
    from urlparse import urljoin
from pprint import pprint

from props import *

#------------------------------------------------------------------------------
# API URL
#------------------------------------------------------------------------------
api_gateway_url = props['api_gateway_url']

#------------------------------------------------------------------------------
# HEADERS
#------------------------------------------------------------------------------
headers = {}
# API key
headers['X-Api-Key'] = props['X-Api-Key']
# Data collection opt out.
headers['X-Data-Collection-Opt-Out'] = props['X-Data-Collection-Opt-Out']

#------------------------------------------------------------------------------
# OPTIONAL QUERY PARAMETERS
#------------------------------------------------------------------------------
params = {}

#------------------------------------------------------------------------------
# PATH PARAMETERS
#------------------------------------------------------------------------------
# Catalog name.
catalog_name = props['catalog_name']

#------------------------------------------------------------------------------
# API END POINT
#------------------------------------------------------------------------------
api_endpoint = '/v1/catalog/%s/visual_search_categories'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,
                        headers=headers,
                        params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "time_ms": "4.78",
 "counts": {
  "num_of_products": 8,
  "num_of_products_by_category": {
   "upper": 4,
   "lower": 2,
   "dress": 2
  },
  "num_of_images": 38,
  "num_of_images_by_category": {
   "upper": 18,
   "lower": 10,
   "dress": 10
  }
 },
 "categories": [
  "upper",
  "lower",
  "dress"
 ]
}

Get all visual search categories

End point

GET /v1/catalog/{catalog_name}/visual_search_categories

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.

Response

Parameter Description
time_ms The time taken in milliseconds.
categories The visual search categories.
counts The counts of the visual search categories.

(Category) Visual Search ++

Visual search supports a field called visual_search_category which allows us to build a separate visual search for each category. The earlier set of APIs allows the user to specify this field manually and duing query the user has to specify the category interested in along with the image.

The APIs below use a pre-trained classifier to automatically predict the visual search category based on the product images. During search when the user uploads an image we use the category classifier to automatically predict the category and then do visual search using the appropriate index.

Predict categories

#------------------------------------------------------------------------------
# Predict the visual search categories based on product images
# POST /v1/catalog/{catalog_name}/predict/visual_search_categories
# params - clear_cache
#          ignore_non_primary_images
#          visual_search_categories_threshold
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

#------------------------------------------------------------------------------
# API URL
#------------------------------------------------------------------------------
api_gateway_url = props['api_gateway_url']

#------------------------------------------------------------------------------
# HEADERS
#------------------------------------------------------------------------------
headers = {}
# API key
headers['X-Api-Key'] = props['X-Api-Key']
# Data collection opt out.
headers['X-Data-Collection-Opt-Out'] = props['X-Data-Collection-Opt-Out']

#------------------------------------------------------------------------------
# OPTIONAL QUERY PARAMETERS
#------------------------------------------------------------------------------
params = {}

#------------------------------------------------------------------------------
# clear_cache : str, optional (default: false)
#
# If 'visual_search_category' is already present in the product then
# we do not change it unless clear_cache=ture.
#------------------------------------------------------------------------------
params['clear_cache'] = 'true'

#------------------------------------------------------------------------------
# ignore_non_primary_images : str, optional (default: false)
#
# If true uses only the primary images (specified in the field 
# data['images'][image_id]['image_type'] = 'primary') and 
# ignores all other images.
# If false uses all the available images for the product.
# All images with data['images'][image_id]['ignore'] = 'yes' 
# are ignored.
#------------------------------------------------------------------------------
#params['ignore_non_primary_images'] = 'false'

#------------------------------------------------------------------------------
# visual_search_categories_threshold : float, optional (default: 0.0)
#
# Use the predictions from the visual search categories classifier
# only if the confidence score is greate than this value. 
#------------------------------------------------------------------------------
#params['visual_search_categories_threshold'] = 0.15

#------------------------------------------------------------------------------
# PATH PARAMETERS
#------------------------------------------------------------------------------
# Catalog name.
catalog_name = props['catalog_name']

#------------------------------------------------------------------------------
# API END POINT
#------------------------------------------------------------------------------
api_endpoint = '/v1/catalog/%s/predict/visual_search_categories'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.post(url,
                         headers=headers,
                         params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "status": {
  "status": "starting",
  "num_of_products": "8",
  "start_time": "2018-06-21 14:52:17.252757",
  "prediction": {
   "num_of_images_error": "0",
   "num_of_images_ignored": "10",
   "num_of_images_existing": "0",
   "num_of_images_processed": "0"
  },
  "finish_time": "UNK",
  "num_of_images": "38"
 },
 "time_ms": "0.68",
 "catalog_name": "sample_catalog"
}

Predict the visual search categories based on product images

This API uses a pre-trained classifier to automatically predict the visual search category based on the product images. The predicted visual search catgories are populated in the field data['visual_search_category']. Once you ingest the catalog you will call this API to populate the ‘visual_search_category’ field and then proceed with building the visual search index.

End point

POST /v1/catalog/{catalog_name}/predict/visual_search_categories

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
clear_cache query If visual_search_category is already present in the product then we do not change it unless clear_cache=true. false
ignore_non_primary_images query If true uses only the primary images (specified in the field data['images'][image_id]['image_type'] = 'primary') and ignores all other images. If false uses all the available images for the product. All images with data['images'][image_id]['ignore'] = 'yes' are ignored. false
visual_search_categories_threshold query Use the predictions from the visual search categories classifier only if the confidence score is greate than this value. 0.0

Response

Parameter Description
time_ms The time taken in milliseconds.
catalog_name The catalog name.
status A json containing various info about the current status of the prediction.
status The current status of the prediction. The status can be one of starting,'predicting_visual_search_categories',or done. The prediction is done when the status becomes done.
start_time The time when started.
finish_time The time when finished.
num_of_products The total number of products in the catalog.
num_of_images The total number of images in the catalog.
prediction Info about prediction.
num_of_images_error The number of images for which there was some error.
num_of_images_ignored The number of images that were ignored.
num_of_images_existing The number of images for which the predictions were already computed (in case of building a new index with new products being added).
num_of_images_processed The total number of images for which the predictions were computed.

Get status

#------------------------------------------------------------------------------
# Get the status of the visual search categories prediction
# GET /v1/catalog/{catalog_name}/predict/visual_search_categories
#------------------------------------------------------------------------------
import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

#------------------------------------------------------------------------------
# API URL
#------------------------------------------------------------------------------
api_gateway_url = props['api_gateway_url']

#------------------------------------------------------------------------------
# HEADERS
#------------------------------------------------------------------------------
headers = {}
# API key
headers['X-Api-Key'] = props['X-Api-Key']
# Data collection opt out.
headers['X-Data-Collection-Opt-Out'] = props['X-Data-Collection-Opt-Out']

#------------------------------------------------------------------------------
# OPTIONAL QUERY PARAMETERS
#------------------------------------------------------------------------------
params = {}

#------------------------------------------------------------------------------
# PATH PARAMETERS
#------------------------------------------------------------------------------
# Catalog name.
catalog_name = props['catalog_name']

#------------------------------------------------------------------------------
# API END POINT
#------------------------------------------------------------------------------
api_endpoint = '/v1/catalog/%s/predict/visual_search_categories'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,
                        headers=headers,
                        params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "status": {
  "status": "done",
  "num_of_products": "8",
  "start_time": "2018-06-21 14:52:17.252757",
  "prediction": {
   "num_of_images_error": "0",
   "num_of_images_ignored": "10",
   "num_of_images_existing": "0",
   "num_of_images_processed": "28"
  },
  "finish_time": "2018-06-21 14:52:28.204947",
  "num_of_images": "38"
 },
 "time_ms": "1.20",
 "catalog_name": "sample_catalog"
}

Get the status of the visual search categories prediction

End point

GET /v1/catalog/{catalog_name}/predict/visual_search_categories

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.

Response

Parameter Description
time_ms The time taken in milliseconds.
catalog_name The catalog name.
status A json containing various info about the current status of the prediction.
status The current status of the prediction. The status can be one of starting,'predicting_visual_search_categories',or done. The prediction is done when the status becomes done.
start_time The time when started.
finish_time The time when finished.
num_of_products The total number of products in the catalog.
num_of_images The total number of images in the catalog.
prediction Info about prediction.
num_of_images_error The number of images for which there was some error.
num_of_images_ignored The number of images that were ignored.
num_of_images_existing The number of images for which the predictions were already computed (in case of building a new index with new products being added).
num_of_images_processed The total number of images for which the predictions were computed.

Natural Language Search

The Natural Language Search (NLS) for fashion allows the user to search a fashion e-commerce catalog using complex natural language queries. Below are a few sample queries that NLS can handle:

NLS enables the user to query the product catalog in a more natural language as you would have a conversation with seasoned sales assistant. This functionality enables a user to ask his query (requirements) in a more natural manner than the conventional keywords and filter based search. NLS can be seen as replacement for conventional search based on filters and a precursor to a full conversation system. NLS will work on existing product text attributes in product catalog.

Following is a list of some of the features that NLS supports:

  1. Leverages the underlying IBM Fashion Taxonomy : NLS is heavily tuned for the fashion domain and leverages the underlying IBM fashion taxonomy. IBM fashion taxonomy is a semi-automatically curated comprehensive hierarchical fashion taxonomy for apparel,footwear, and accessories along with their attributes and relations. The taxonomy is curated from several fashion resources and then hand tuned by domain experts. This enables NLS to a very nuanced understanding of user requirements in the domain of fashion.

  2. Understands various fashion attributes and user constraints : NLS is grounded in the fashion taxonomy and can understand various attributes in the query such as gender, category name (apparel,shoes,accessories), color, pattern/print, fabric/material, brand, price, size, occasion, sale/discount other category specific attributes (like sleeves, collar, etc.). NLS can understand all the constraints on user requirements even when they are expressed in a very natural manner in the form of long complex natural language queries (e.g. ‘Show me red floral dresses for my niece under 1k on sale.’).

  3. Internally handles query synonyms : IBM Fashion taxonomy is used to map segments of user utterances to nodes in the Fashion taxonomy. This mapping enables understanding of fashion concepts even when they are expressed in many different ways. For example, the user may search for a ‘tee’ whereas the item may be tagged as a ‘t-shirt’ in the catalog. NLS understands various synonyms and also common query words for different apparel and accessories.

  4. Appropriate semantic query back off : The NLS capability allows showing relevant results to a user query even when there are no enough products that exactly matches with the user requirements. For example, if there are no ‘red floral dresses’ in the catalog then NLS has a built in back-off strategy that removes attributes (along with color expansion and similar brands substitution) till it finds sufficient number of products. For example, in this case it would first back off to ‘orange/tomato/red floral dresses’ and then to ‘red dresses’ and eventually to ‘dresses’.

  5. Color Substitution : If the user searches for a specific color (say ‘golden colored dresses’) and that particular color is not available then we search for other color that look very similar (for example, yellow, yellow green, khaki etc.). The IBM Fashion Taxonomy also includes a detailed taxonomy specific to colors and their corresponding names. Is also provides a notion of visual semantic distance between two colors.

  6. Brand Substitution : A similar back-off strategy is incorporated for a limited set of brands. If the user searches for a specific brand (say ‘adidas shoes’) and that particular brand is not available then we search for other similar brands (for example, ‘puma shoes’). The notion is brand similarity is based on the visual appearance of products and is computed using our visual similarity asset.

  7. Spelling and phonetic corrections tuned to fashion taxonomy : Users usually make mistakes when searching with natural language queries. NLS can handles common spelling mistakes in a user query. The spelling correction module is aware of all the fashion related concepts and brands.

  8. Themes and collections capsules : NLS offers limited support for search related to themes and collections (e.g. athleisure, monochrome, indigo, ethnic etc. ). We automatically curate the set of apparel, accessories and their attributes that define a fashion theme from various fashion blogs and when the user searches for a theme (say athleisure) then we show items from the catalog that are relevant to that theme.

  9. Dynamically evolving fashion taxonomy : Fashion evolves constantly and hence IBM fashion taxonomy is dynamically updated at regular intervals to include the current fashion terms and trends. Since NLS is delivered as a REST API the user will always have access to the latest fashion taxonomy.

#------------------------------------------------------------------------------
# Natural Language Search 
# GET /v1/catalog/{catalog_name}/natural_language_search
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Catalog name.
catalog_name = 'sample_catalog'

api_endpoint = '/v1/catalog/%s/natural_language_search'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

params = {}
params['query_text'] = 'Watson show me some shrigs for my neice'
# Optional parameters.
params['max_number_of_results'] = 12
params['max_number_of_backoffs'] = 5

response = requests.get(url,headers=headers,params=params)

print response.status_code
print response.json()

# Get more info about the relevant results
for product in response.json()['products']:
    id = product['id']
    api_endpoint = '/v1/catalog/%s/products/%s'%(catalog_name,id)
    url = urljoin(api_gateway_url,api_endpoint)
    response = requests.get(url,headers=headers)
    print('%s %s'%(id,response.json()['data']['name']))

Sample json response

{
 "time_ms": "18.14",
 "products": [
  {
   "id": "20DRA16FWCWHL9015309",
   "backoff_number": 0
  },
  {
   "id": "20DRA16FWCWPP9014709",
   "backoff_number": 0
  }
 ]
}

Search the product catalog using a natural language query (e.g. Show me some black graphic print tees on sale.).

End point

GET /v1/catalog/{catalog_name}/natural_language_search

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
query_text query (Required) The natural language search query. (e.g. Show me some red graphic print tees under 1k.`)
max_number_of_results query The maximum number of results to return. 12
max_number_of_backoffs query The maximum number of backoffs to use if there are no exact matches. Set this to 0 if you do not want any backoffs. 5

Response

Parameter Description
time_ms The time taken in milliseconds.
products A sorted list of products in the catalog relevant to the query.
id The id of the product.
backoff_number An integer specifying if backoff was used for retrieving this result. (0 corresponds to no backoff, 1 corresponds to backoff once and so on)

Get elasticsearch queries

#------------------------------------------------------------------------------
# elasticsearch queries 
# GET /v1/natural_language_search/elasticsearch_queries
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

api_endpoint = '/v1/natural_language_search/elasticsearch_queries'

url = urljoin(api_gateway_url,api_endpoint)

params = {}
params['query_text'] = 'Show me some peach graphic print tees for my neice under 1k on sale.'
# Optional parameters.
params['max_number_of_results'] = 12
params['max_number_of_backoffs'] = 5

response = requests.get(url,headers=headers,params=params)

print response.status_code
print response.json()

Sample json response

{
  "time_ms": "6.35", 
  "elasticsearch_queries": [
  {"sort": [{"sale_price": {"order": "desc"}}], "query": {"bool": {"minimum_should_match": 1, "filter": [{"bool": {"must": [{"range": {"sale_price": {"lte": 1000}}}, {"range": {"sale_price": {"gte": 1}}}, {"terms": {"gender": ["female", "women"]}}, {"term": {"out_of_stock": "no"}}]}}], "should": [{"multi_match": {"query": "t-shirt", "type": "phrase", "fields": ["category^2.0", "name^1.0"]}}, {"multi_match": {"query": "tee", "type": "phrase", "fields": ["category^2.0", "name^1.0"]}}], "must": [{"multi_match": {"query": "red", "type": "phrase", "fields": ["color^5.0", "name^1.0"]}}, {"bool": {"minimum_should_match": 1, "should": [{"multi_match": {"query": "graphic", "type": "phrase", "fields": ["pattern^5.0", "name^2.0", "description^1.0"]}}, {"multi_match": {"query": "printed", "type": "phrase", "fields": ["pattern^5.0", "name^2.0", "description^1.0"]}}, {"multi_match": {"query": "print", "type": "phrase", "fields": ["pattern^5.0", "name^2.0", "description^1.0"]}}]}}]}}, "from": 0, "size": 12}, 
  {"sort": [{"sale_price": {"order": "desc"}}], "query": {"bool": {"minimum_should_match": 1, "filter": [{"bool": {"must": [{"range": {"sale_price": {"lte": 1000}}}, {"range": {"sale_price": {"gte": 1}}}, {"terms": {"gender": ["female", "women"]}}, {"term": {"out_of_stock": "no"}}]}}], "should": [{"multi_match": {"query": "t-shirt", "type": "phrase", "fields": ["category^2.0", "name^1.0"]}}, {"multi_match": {"query": "tee", "type": "phrase", "fields": ["category^2.0", "name^1.0"]}}], "must": [{"bool": {"minimum_should_match": 1, "should": [{"multi_match": {"query": "tomato", "type": "phrase", "fields": ["color^5.0", "name^1.0"]}}, {"multi_match": {"query": "orange", "type": "phrase", "fields": ["color^5.0", "name^1.0"]}}, {"multi_match": {"query": "red", "type": "phrase", "fields": ["color^5.0", "name^1.0"]}}]}}, {"bool": {"minimum_should_match": 1, "should": [{"multi_match": {"query": "graphic", "type": "phrase", "fields": ["pattern^5.0", "name^2.0", "description^1.0"]}}, {"multi_match": {"query": "printed", "type": "phrase", "fields": ["pattern^5.0", "name^2.0", "description^1.0"]}}, {"multi_match": {"query": "print", "type": "phrase", "fields": ["pattern^5.0", "name^2.0", "description^1.0"]}}]}}]}}, "from": 0, "size": 12}, 
  {"sort": [{"sale_price": {"order": "desc"}}], "query": {"bool": {"minimum_should_match": 1, "filter": [{"bool": {"must": [{"range": {"sale_price": {"lte": 1000}}}, {"range": {"sale_price": {"gte": 1}}}, {"terms": {"gender": ["female", "women"]}}, {"term": {"out_of_stock": "no"}}]}}], "must": [{"multi_match": {"query": "red", "type": "phrase", "fields": ["color^5.0", "name^1.0"]}}], "should": [{"multi_match": {"query": "t-shirt", "type": "phrase", "fields": ["category^2.0", "name^1.0"]}}, {"multi_match": {"query": "tee", "type": "phrase", "fields": ["category^2.0", "name^1.0"]}}]}}, "from": 0, "size": 12}, 
  {"sort": [{"sale_price": {"order": "desc"}}], "query": {"bool": {"filter": [{"bool": {"must": [{"range": {"sale_price": {"lte": 1000}}}, {"range": {"sale_price": {"gte": 1}}}, {"terms": {"gender": ["female", "women"]}}, {"term": {"out_of_stock": "no"}}]}}], "minimum_should_match": 1, "should": [{"multi_match": {"query": "t-shirt", "type": "phrase", "fields": ["category^2.0", "name^1.0"]}}, {"multi_match": {"query": "tee", "type": "phrase", "fields": ["category^2.0", "name^1.0"]}}]}}, "from": 0, "size": 12}, 
  {"sort": [{"sale_price": {"order": "desc"}}], "query": {"bool": {"minimum_should_match": 1, "filter": [{"bool": {"must": [{"range": {"sale_price": {"lte": 1000}}}, {"range": {"sale_price": {"gte": 1}}}, {"terms": {"gender": ["female", "women"]}}, {"term": {"out_of_stock": "no"}}]}}], "should": [{"multi_match": {"query": "graphic", "type": "phrase", "fields": ["pattern^5.0", "name^2.0", "description^1.0"]}}, {"multi_match": {"query": "printed", "type": "phrase", "fields": ["pattern^5.0", "name^2.0", "description^1.0"]}}, {"multi_match": {"query": "print", "type": "phrase", "fields": ["pattern^5.0", "name^2.0", "description^1.0"]}}], "must": [{"multi_match": {"query": "knit shirt", "type": "phrase", "fields": ["category^2.0", "name^1.0"]}}, {"multi_match": {"query": "red", "type": "phrase", "fields": ["color^5.0", "name^1.0"]}}]}}, "from": 0, "size": 12}, 
  {"sort": [{"sale_price": {"order": "desc"}}], "query": {"bool": {"filter": [{"bool": {"must": [{"range": {"sale_price": {"lte": 1000}}}, {"range": {"sale_price": {"gte": 1}}}, {"terms": {"gender": ["female", "women"]}}, {"term": {"out_of_stock": "no"}}]}}], "must": [{"multi_match": {"query": "knit shirt", "type": "phrase", "fields": ["category^2.0", "name^1.0"]}}, {"multi_match": {"query": "red", "type": "phrase", "fields": ["color^5.0", "name^1.0"]}}]}}, "from": 0, "size": 12}
  ]
}

Parse any fashion related query (e.g. Show me some red graphic print tees for my neice under 1k on sale.) in natural language and return a list of elasticsearch queries in the query DSL format. The queries are ordered from specific to general queries. The suggested usage is to first fire the first query. If there are no sufficient results then fire the next query and so on. The queries use the field names as specified in the product JSON format.

End point

GET /v1/natural_language_search/elasticsearch_queries

Request

Parameter Type Description Default
query_text query (Required) The natural language search query. (e.g. Show me some red graphic print tees for my neice under 1k on sale.)
max_number_of_results query The maximum number of results to return. 12
max_number_of_backoffs query The maximum number of backoffs to use if there are no exact matches. Set this to 0 if you do not want any backoffs. 5

Response

Parameter Description
time_ms The time taken in milliseconds.
elasticsearch_queries A list of elasticsearch queries (ordered from specific to general) in the query DSL format.

Parse fashion query/text

#------------------------------------------------------------------------------
# Parse fashion query/text. 
# GET /v1/natural_language_search/parse
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

api_endpoint = '/v1/natural_language_search/parse'

url = urljoin(api_gateway_url,api_endpoint)

params = {}
params['query_text'] = 'Show me some red graphic print tees for my neice under 1k on sale.'

response = requests.get(url,headers=headers,params=params)

print response.status_code
print response.json()

Sample json response

{
 "parse": [
  {
   "apparel": {
    "synonyms": [
     "t-shirt",
     "tee"
    ],
    "hypernyms": [
     "knit shirt"
    ],
    "name": "tee",
    "hyponyms": []
   },
   "attributes": {
    "color": [
     {
      "similar_colors": [
       "red",
       "tomato",
       "orange"
      ],
      "synonyms": [
       "red"
      ],
      "name": "red"
     }
    ],
    "pattern": [
     {
      "synonyms": [
       "graphic"
      ],
      "name": "graphic"
     },
     {
      "synonyms": [
       "printed",
       "print"
      ],
      "name": "print"
     }
    ],
    "price": {
     "currency": "rupee",
     "upper_limit": 1000,
     "lower_limit": 0,
     "sale_percentage_lower_limit": 1
    }
   },
   "remaining_tokens": [],
   "gender": "female"
  }
 ],
 "time_ms": "2.85"
}

Given any natural language fashion query this endpoint parses the query and returns an intermediate structured parse of the query.

End point

GET /v1/natural_language_search/parse

Request

Parameter Type Description Default
query_text query (Required) The natural language search query. (e.g. Show me some red graphic print tees for my neice under 1k on sale.)

Response

Parameter Description
time_ms The time taken in milliseconds.
parse A list of structured parse of the natural language query grounded in the fashion taxonomy (see the sample json). For gender agnostic queries returns two parses one for each gender. If the text contains multiple apparel returns one parse for each apparel.

Get search terms

#------------------------------------------------------------------------------
# Get search terms. 
# GET /v1/natural_language_search/search_terms
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

api_endpoint = '/v1/natural_language_search/search_terms'

url = urljoin(api_gateway_url,api_endpoint)

params = {}
params['query_text'] = 'Show me some red graphic print tees for my neice under 1k on sale.'

response = requests.get(url,headers=headers,params=params)

print response.status_code
print response.json()

Sample json response

{
 "time_ms": "3.13",
 "search_terms": [
  {
   "apparel": [
    "t-shirt",
    "tee"
   ],
   "color": [
    "red"
   ],
   "pattern": [
    "graphic",
    "printed",
    "print"
   ],
   "apparel_hypernyms": [
    "knit shirt"
   ],
   "similar_colors": [
    "tomato",
    "orange",
    "red"
   ]
  }
 ]
}

Parse a fashion related natural language query and generate search terms for its constituent apparel and various attributes. These search terms are used to compose the final elasticsearch/solr query and includes synonyms and hyponyms for the apparel and attributes.

End point

GET /v1/natural_language_search/search_terms

Request

Parameter Type Description Default
query_text query (Required) The natural language search query. (e.g. Show me some red graphic print tees for my neice under 1k on sale.)

Response

Parameter Description
time_ms The time taken in milliseconds.
search_terms A list of search terms corresponding to each parse.

Spelling Correction

#------------------------------------------------------------------------------
# Spelling correction. 
# GET /v1/natural_language_search/spell_correct
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

api_endpoint = '/v1/natural_language_search/spell_correct'

url = urljoin(api_gateway_url,api_endpoint)

params = {}
params['query_text'] = 'show me some purlep floaral dreses for my wife'

response = requests.get(url,headers=headers,params=params)

print response.status_code
print response.json()

Sample json response

{
 "time_ms": "0.24",
 "corrected_text": "show me some purple floral dress for my wife"
}

Correct any spelling mistakes in the query. This is a lightweight spelling correction module that is tuned to the fasion taxonomy.

End point

GET /v1/natural_language_search/spell_correct

Request

Parameter Type Description Default
query_text query (Required) The natural language search query. (e.g. show me some purlep floaral dreses for my wife.)

Response

Parameter Description
time_ms The time taken in milliseconds.
corrected_text The text with the spelling corrected.

Visual Attributes

Given a fashion image (containing apparel,accessories,or footwear) identify the main product category along with the different attributes. The category and attributes are grounded in a standardized fashion taxonomy.

Some use cases for visual attributes include:

Get visual attributes for iconic/non-iconic fashion images

Given a fashion image (containing apparel,accessories,or footwear) identify the detect differnt product category along with the different attributes. The attributes predicted shall be consistent with the predicted category, e.g. sleeve length won’t be predicted for category jeans.

#------------------------------------------------------------------------------
# Get visual attributes for a given iconic/non-iconic image.
# GET /v1/visualattributes
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Parameters.
params = {}
# Optional parameters.
params['threshold'] = 0.2
#params['image_type'] = 'iconic'
params['image_type'] = 'non-iconic'

api_endpoint = '/v1/visualattributes'

url = urljoin(api_gateway_url,api_endpoint)

# Three options to pass the image

# OPTION 1 : Directly post the image
headers['Content-Type'] = 'image/jpeg'
response = requests.post(url,
                         headers=headers,
                         params=params,
                         data=open('test_image_2.jpeg','rb'))

"""            
# OPTION 2 : Pass the image url
params['image_url'] = 'http://vg-images.condecdn.net/image/oDXPOxw65EZ/crop/405'
response = requests.post(url,
                         headers=headers,
                         params=params)
"""

"""
# OPTION 3 : using multipart
image_filename = 'test_image_1.jpeg'
with open(image_filename,'rb') as images_file:
    response = requests.post(url,
                             headers=headers,
                             params=params,
                             files={'image': (image_filename,images_file,'image/jpeg')})   
"""

print response.status_code
pprint(response.json())

# Human friendly repsonse.

results = response.json()

image_location = '%s?api_key=%s'%(urljoin(api_gateway_url,results['image_location']),
                                  props['X-Api-Key'])
print('[original image] %s'%(image_location))

for entity in results['entities']:
    entity_swatch = '%s&api_key=%s'%(urljoin(api_gateway_url,entity['image_location']),
                                    props['X-Api-Key'])
    print('[%1.2f][%s][%s]'%(entity['category']['score'][entity['category']['value']],
                                     entity['category']['value'],
                                     entity_swatch)) 
    for attribute in entity['attributes']:
        print('[%1.2f][%s][%s]'%(entity['attributes'][attribute]['score'][entity['attributes'][attribute]['value']],
                                 attribute,
                                 entity['attributes'][attribute]['value']))

Sample json response

{
 "time_ms": "2823.04",
 "image_location": "/v1/images/23e67de5-1ac0-487d-9e7f-619e91e685a7.jpe",
 "entities": [
  {
   "category": {
    "score": {
     "palazzo": 0.22113326648841536,
     "salwar": 0.06767382153963641,
     "pant": 0.5747724771499634
    },
    "value": "pant"
   },
   "attributes": {
    "style": {
     "score": {
      "fusion": 0.1323334127664566,
      "maternity": 0.12990465760231018,
      "casual": 0.13776597380638123
     },
     "value": "casual"
    },
    "rise": {
     "score": {
      "mid rise": 0.9471921920776367,
      "high rise": 0.003534807590767741,
      "low rise": 0.04925554618239403
     },
     "value": "mid rise"
    },
    "fabric": {
     "score": {
      "polyester": 0.14030905067920685,
      "rayon": 0.10886745154857635,
      "cotton": 0.3303784728050232
     },
     "value": "cotton"
    },
    "fit": {
     "score": {
      "regular": 0.8877512812614441,
      "slim": 0.05478856340050697,
      "loose": 0.012176275253295898
     },
     "value": "regular"
    },
    "color": {
     "score": {
      "pink": 0.13715988397598267,
      "multicoloured": 0.18392638862133026,
      "red": 0.2667190730571747
     },
     "value": "red"
    },
    "pattern": {
     "score": {
      "solid": 0.8236303329467773,
      "embellished": 0.07058356702327728,
      "embroidered": 0.04244432970881462
     },
     "value": "solid"
    },
    "material": {
     "score": {
      "leather": 0.1788148432970047,
      "polyurethane": 0.8198845982551575,
      "cotton": 0.000506136566400528
     },
     "value": "polyurethane"
    },
    "age_gender": {
     "score": {
      "boys": 0.021265005692839622,
      "girls": 0.28132501244544983,
      "women": 0.6916653513908386
     },
     "value": "women"
    },
    "length": {
     "score": {
      "ankle length": 0.06449545174837112,
      "full length": 0.8689517974853516,
      "regular length": 0.05531088262796402
     },
     "value": "full length"
    }
   },
   "bounding_box": {
    "width": 292,
    "score": 0.5747724771499634,
    "top_left_x": 155,
    "top_left_y": 246,
    "height": 642
   },
   "id": "1",
   "image_location": "/v1/images/23e67de5-1ac0-487d-9e7f-619e91e685a7.jpe?top_left_x=155&top_left_y=246&width=292&height=642"
  },
  {
   "category": {
    "layer_type": "UNK",
    "score": {
     "person": 0.7402761578559875
    },
    "product_type": "UNK",
    "value": "person"
   },
   "image_location": "/v1/images/23e67de5-1ac0-487d-9e7f-619e91e685a7.jpe?top_left_x=163&top_left_y=5&width=278&height=877",
   "bounding_box": {
    "width": 278,
    "score": 0.7402761578559875,
    "top_left_x": 163,
    "top_left_y": 5,
    "height": 877
   },
   "id": "2"
  },
  {
   "category": {
    "score": {
     "sandal": 0.4261542558670044,
     "sandals": 0.3518989313999086,
     "boots": 0.054356454120087605
    },
    "value": "sandal"
   },
   "attributes": {
    "heel height": {
     "score": {
      "medium: 2.5-3.5 inch": 1.0,
      "low: 1.5-2.5 inch": 2.6993671187192092e-11,
      "high: above 3.5 inch": 1.1122387733042416e-11
     },
     "value": "medium: 2.5-3.5 inch"
    }
   },
   "bounding_box": {
    "width": 111,
    "score": 0.4261542558670044,
    "top_left_x": 240,
    "top_left_y": 823,
    "height": 63
   },
   "id": "3",
   "image_location": "/v1/images/23e67de5-1ac0-487d-9e7f-619e91e685a7.jpe?top_left_x=240&top_left_y=823&width=111&height=63"
  },
  {
   "category": {
    "score": {
     "sandal": 0.2754097878932953,
     "pumps": 0.09048446886142614,
     "sandals": 0.13116798881638747
    },
    "value": "sandal"
   },
   "attributes": {
    "heel height": {
     "score": {
      "medium: 2.5-3.5 inch": 7.981193630257621e-05,
      "low: 1.5-2.5 inch": 5.3353110334396475e-15,
      "high: above 3.5 inch": 0.999920129776001
     },
     "value": "high: above 3.5 inch"
    }
   },
   "bounding_box": {
    "width": 115,
    "score": 0.2754097878932953,
    "top_left_x": 328,
    "top_left_y": 833,
    "height": 55
   },
   "id": "4",
   "image_location": "/v1/images/23e67de5-1ac0-487d-9e7f-619e91e685a7.jpe?top_left_x=328&top_left_y=833&width=115&height=55"
  },
  {
   "category": {
    "score": {
     "blouse": 0.06075274238587225,
     "sweater": 0.05060515634194118,
     "shirt": 0.31577786803245544
    },
    "value": "shirt"
   },
   "attributes": {
    "style": {
     "score": {
      "party": 0.007760034408420324,
      "casual": 0.9074917435646057,
      "formal": 0.07398669421672821
     },
     "value": "casual"
    },
    "rise": {
     "score": {
      "mid rise": 0.9999979734420776,
      "high rise": 1.1497794903669867e-11,
      "low rise": 1.994056219700724e-06
     },
     "value": "mid rise"
    },
    "fabric": {
     "score": {
      "polyester": 0.10793536901473999,
      "blend": 0.06727375090122223,
      "cotton": 0.4398740828037262
     },
     "value": "cotton"
    },
    "fit": {
     "score": {
      "relaxed": 0.011904584243893623,
      "regular": 0.8485410213470459,
      "slim": 0.11031126230955124
     },
     "value": "regular"
    },
    "color": {
     "score": {
      "pink": 0.2812502682209015,
      "green": 0.1360998898744583,
      "yellow": 0.07928851246833801
     },
     "value": "pink"
    },
    "pattern": {
     "score": {
      "solid": 0.881832480430603,
      "printed": 0.044556956738233566,
      "textured": 0.029497725889086723
     },
     "value": "solid"
    },
    "sleeve style": {
     "score": {
      "cap sleeves": 0.9173927307128906,
      "roll up sleeves": 0.08121675252914429,
      "puff sleeves": 0.0013715812237933278
     },
     "value": "cap sleeves"
    },
    "age_gender": {
     "score": {
      "men": 0.018686337396502495,
      "girls": 0.058831632137298584,
      "women": 0.9153407216072083
     },
     "value": "women"
    },
    "length": {
     "score": {
      "waist length": 0.09034832566976547,
      "thigh length": 0.020926641300320625,
      "hip length": 0.8840341567993164
     },
     "value": "hip length"
    },
    "sleeve length": {
     "score": {
      "short sleeves": 0.0034761312417685986,
      "3/4th sleeves": 0.0034854754339903593,
      "long sleeves": 0.9906822443008423
     },
     "value": "long sleeves"
    },
    "neck": {
     "score": {
      "v neck": 0.2768712639808655,
      "round neck": 0.11630632728338242,
      "polo neck": 0.21823753416538239
     },
     "value": "v neck"
    }
   },
   "bounding_box": {
    "width": 204,
    "score": 0.31577786803245544,
    "top_left_x": 183,
    "top_left_y": 138,
    "height": 233
   },
   "id": "5",
   "image_location": "/v1/images/23e67de5-1ac0-487d-9e7f-619e91e685a7.jpe?top_left_x=183&top_left_y=138&width=204&height=233"
  },
  {
   "category": {
    "layer_type": "UNK",
    "score": {
     "face": 0.8626712560653687
    },
    "product_type": "UNK",
    "value": "face"
   },
   "image_location": "/v1/images/23e67de5-1ac0-487d-9e7f-619e91e685a7.jpe?top_left_x=217&top_left_y=30&width=97&height=104",
   "bounding_box": {
    "width": 97,
    "score": 0.8626712560653687,
    "top_left_x": 217,
    "top_left_y": 30,
    "height": 104
   },
   "id": "6"
  }
 ]
}

End point

GET /v1/visualattributes

Request

Parameter Type Description Default
data image/jpeg (Required) The image. The image can be in PNG, JPEG, BMP, or GIF.
threshold query Threshold for detections, ignore entities whose score is below this threshold value. 0.2
iamge_type query Can be either iconic or non-iconic. iconic

Instead of the posting the image data you can also pass an image url.

Parameter Type Description
image_url query (Required) The image url.

You can also pass the image using multipart/form-data with the fieldname image.

Response

Parameter Description
time_ms The time taken for prediction in milliseconds.
entities A list of detected entities. Each element of the list contains the following fields.
bounding_box The bounding box for the deteted entity containing the following fields.
top_left_x The x co-ordinate of the top left corner of the bounding box.
top_left_y The y co-ordinate of the top left corner of the bounding box.
width The width of the bounding box.
height The height of the bounding box.
score The confidence score.
category The top-3 product categories predicted along with their respective confidence levels and the final predicted category.
attributes The attributes and their top-3 values predicted along with the respective confidence levels.
image_location The image location of the detected entity

Detectors

A collection of APIs for detecting person, apparel, accessories and footwear in an image.

Detect persons in an image

#------------------------------------------------------------------------------
# Detect persons in a fashion image.
# POST /v1/detect_person
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header.
headers = {'X-Api-Key': props['X-Api-Key']}

params = {}
# Optional parameters.
params['model'] = 'fast' # default
#params['model'] = 'accurate'

api_endpoint = '/v1/detect_person'

url = urljoin(api_gateway_url,api_endpoint)

# Three options to pass the image

# OPTION 1 : Directly post the image
headers['Content-Type'] = 'image/jpeg'
response = requests.post(url,
                         headers=headers,
                         params=params,
                         data=open('test_image_3.jpeg','rb'))

"""
# OPTION 2 : Pass the image url
params['image_url'] = 'http://vg-images.condecdn.net/image/oDXPOxw65EZ/crop/405'
response = requests.post(url,
                         headers=headers,
                         params=params)
"""

"""
# OPTION 3 : using multipart
image_filename = 'test_image_3.jpeg'
with open(image_filename,'rb') as images_file:
    response = requests.post(url,
                             headers=headers,
                             params=params,
                             files={'image': (image_filename,images_file,'image/jpeg')})   
"""

print response.status_code
pprint(response.json())


# Human friendly repsonse.

results = response.json()

image_location = '%s?api_key=%s'%(urljoin(api_gateway_url,results['image_location']),
                                  props['X-Api-Key'])
print('[original image] %s'%(image_location))

for entity in results['persons']:
    entity_swatch = '%s&api_key=%s'%(urljoin(api_gateway_url,entity['image_location']),
                                    props['X-Api-Key'])
    print('[%1.2f][%s]'%(entity['score'],entity_swatch)) 

Sample json response

{
 "time_ms": "1934.55",
 "image_location": "/v1/images/4f394ff2-50fe-482a-a381-8e5f38136b3f.jpe",
 "persons": [
  {
   "image_location": "/v1/images/4f394ff2-50fe-482a-a381-8e5f38136b3f.jpe?top_left_x=41&top_left_y=14&width=184&height=493",
   "top_left_x": 41,
   "top_left_y": 14,
   "height": 493,
   "width": 184,
   "score": 0.737177
  },
  {
   "image_location": "/v1/images/4f394ff2-50fe-482a-a381-8e5f38136b3f.jpe?top_left_x=177&top_left_y=27&width=170&height=541",
   "top_left_x": 177,
   "top_left_y": 27,
   "height": 541,
   "width": 170,
   "score": 0.889102
  }
 ]
}

Detect and find the bounding boxes for all persons in an image.

End point

POST /v1/detect_person

Request

Parameter Type Description Default
data image/jpeg (Required) The image. The image can be in PNG, JPEG, BMP, or GIF.
model query Model can either be fast (faster but slightly less accurate model) or accurate (slower but more accurate model). fast

Instead of the posting the image data you can also pass an image url.

Parameter Type Description
image_url query (Required) The image url.

You can also pass the image using multipart/form-data with the fieldname image.

Response

Parameter Description
time_ms The time taken in milliseconds.
image_location The image location of the uploaded image.
persons A list of bounding boxes for all detected persons. Each element of the list contains the following fields.
top_left_x The x co-ordinate of the top left corner of the bounding box.
top_left_y The y co-ordinate of the top left corner of the bounding box.
width The width of the bounding box.
height The height of the bounding box.
score The confidence score (between 0 and 1) that the bounding box contains a person.
image_location The image location of the detected person.

Detect apparel in an image

#------------------------------------------------------------------------------
# Detect apparel,accessories and footwear in a fashion image.
# POST /v1/detect_apparel
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header.
headers = {'X-Api-Key': props['X-Api-Key']}

params = {}
# Optional parameters.
params['threshold'] = 0.2

api_endpoint = '/v1/detect_apparel'

url = urljoin(api_gateway_url,api_endpoint)

# Three options to pass the image

# OPTION 1 : Directly post the image
headers['Content-Type'] = 'image/jpeg'
response = requests.post(url,
                         headers=headers,
                         params=params,
                         data=open('test_image_2.jpeg','rb'))

"""
# OPTION 2 : Pass the image url
params['image_url'] = 'http://vg-images.condecdn.net/image/oDXPOxw65EZ/crop/405'
response = requests.post(url,
                         headers=headers,
                         params=params)
"""

"""
# OPTION 3 : using multipart
image_filename = 'test_image_3.jpeg'
with open(image_filename,'rb') as images_file:
    response = requests.post(url,
                             headers=headers,
                             params=params,
                             files={'image': (image_filename,images_file,'image/jpeg')})   
"""

print response.status_code
pprint(response.json())


# Human friendly repsonse.

results = response.json()

image_location = '%s?api_key=%s'%(urljoin(api_gateway_url,results['image_location']),
                                  props['X-Api-Key'])
print('[original image] %s'%(image_location))

for entity in results['entities']:
    entity_swatch = '%s&api_key=%s'%(urljoin(api_gateway_url,entity['image_location']),
                                    props['X-Api-Key'])
    print('[%1.2f][%s][%s]'%(entity['category']['score'][entity['category']['value']],
                                     entity['category']['value'],
                                     entity_swatch)) 

Sample json response

{
 "time_ms": "259.57",
 "image_location": "/v1/images/2e4e7b35-b8de-493f-8e90-e59080c65d73.jpe",
 "entities": [
  {
   "category": {
    "layer_type": "layer_2_lower_body",
    "score": {
     "pant": 0.5747724771499634
    },
    "product_type": "apparel",
    "value": "pant"
   },
   "image_location": "/v1/images/2e4e7b35-b8de-493f-8e90-e59080c65d73.jpe?top_left_x=168&top_left_y=276&width=266&height=609",
   "bounding_box": {
    "width": 266,
    "score": 0.5747724771499634,
    "top_left_x": 168,
    "top_left_y": 276,
    "height": 609
   },
   "id": "1"
  },
  {
   "category": {
    "layer_type": "UNK",
    "score": {
     "person": 0.7402761578559875
    },
    "product_type": "UNK",
    "value": "person"
   },
   "image_location": "/v1/images/2e4e7b35-b8de-493f-8e90-e59080c65d73.jpe?top_left_x=175&top_left_y=44&width=254&height=799",
   "bounding_box": {
    "width": 254,
    "score": 0.7402761578559875,
    "top_left_x": 175,
    "top_left_y": 44,
    "height": 799
   },
   "id": "2"
  },
  {
   "category": {
    "layer_type": "footwear",
    "score": {
     "sandal": 0.4261542558670044
    },
    "product_type": "footwear",
    "value": "sandal"
   },
   "image_location": "/v1/images/2e4e7b35-b8de-493f-8e90-e59080c65d73.jpe?top_left_x=245&top_left_y=825&width=101&height=59",
   "bounding_box": {
    "width": 101,
    "score": 0.4261542558670044,
    "top_left_x": 245,
    "top_left_y": 825,
    "height": 59
   },
   "id": "3"
  },
  {
   "category": {
    "layer_type": "footwear",
    "score": {
     "sandal": 0.2754097878932953
    },
    "product_type": "footwear",
    "value": "sandal"
   },
   "image_location": "/v1/images/2e4e7b35-b8de-493f-8e90-e59080c65d73.jpe?top_left_x=333&top_left_y=835&width=105&height=51",
   "bounding_box": {
    "width": 105,
    "score": 0.2754097878932953,
    "top_left_x": 333,
    "top_left_y": 835,
    "height": 51
   },
   "id": "4"
  },
  {
   "category": {
    "layer_type": "layer_2_upper_body",
    "score": {
     "shirt": 0.31577786803245544
    },
    "product_type": "apparel",
    "value": "shirt"
   },
   "image_location": "/v1/images/2e4e7b35-b8de-493f-8e90-e59080c65d73.jpe?top_left_x=192&top_left_y=148&width=186&height=213",
   "bounding_box": {
    "width": 186,
    "score": 0.31577786803245544,
    "top_left_x": 192,
    "top_left_y": 148,
    "height": 213
   },
   "id": "5"
  },
  {
   "category": {
    "layer_type": "UNK",
    "score": {
     "face": 0.8626712560653687
    },
    "product_type": "UNK",
    "value": "face"
   },
   "image_location": "/v1/images/2e4e7b35-b8de-493f-8e90-e59080c65d73.jpe?top_left_x=221&top_left_y=34&width=89&height=96",
   "bounding_box": {
    "width": 89,
    "score": 0.8626712560653687,
    "top_left_x": 221,
    "top_left_y": 34,
    "height": 96
   },
   "id": "6"
  }
 ]
}

Detect and find the bounding boxes for all apparel, accessories and footwear in an image.

End point

POST /v1/detect_apparel

Request

Parameter Type Description Default
data image/jpeg (Required) The image. The image can be in PNG, JPEG, BMP, or GIF.
threshold query Threshold for detections, ignore entities whose score is below this threshold value. 0.2

Instead of the posting the image data you can also pass an image url.

Parameter Type Description
image_url query (Required) The image url.

You can also pass the image using multipart/form-data with the fieldname image.

Response

Parameter Description
time_ms The time taken in milliseconds.
image_location The image location of the uploaded image.
entities A list of detected entities. Each element of the list contains the following fields.
bounding_box The bounding box for the deteted entity containing the following fields.
top_left_x The x co-ordinate of the top left corner of the bounding box.
top_left_y The y co-ordinate of the top left corner of the bounding box.
width The width of the bounding box.
height The height of the bounding box.
score The confidence score (between 0 and 1) that the bounding box contains a person.
category The category of deteted entity containing the following fields.
value The category label.
score The confidence score for the category label.
product_type Can be either apparel,accessories,footwear or UNK.
layer_type The layer type.
image_location The image location of the detected entity.

Colors

These are a few APIs for dealing with color terms.

A color term, also known as a color name, is a word or phrase that refers to a specific color. For example red is the color term used for a color with RGB values [255,0,0]. While the number of color terms are quite huge we internally organize our color terms into three color families:

Color similarities are computed using the Delta E (CIE2000) metric in the LAB space.

Get color terms

#------------------------------------------------------------------------------
# Get color terms. 
# GET /v1/colors/color_terms
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

api_endpoint = '/v1/colors/color_terms'

url = urljoin(api_gateway_url,api_endpoint)

# Parameters - required
params = {}
params['r'] = 106
params['g'] = 103
params['b'] = 95

# Parameters - optional
params['color_count'] = 3
params['color_family'] = 'full'
#params['color_family'] = 'universal'
#params['color_family'] = 'entrylevel'
#params['color_family'] = 'pantone'
params['method'] = 'accurate'
#params['method'] = 'fast'

response = requests.get(url,
                        headers=headers,
                        params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "time_ms": "234.64",
 "color_terms": [
  {
   "name": "dim gray",
   "pantone_rgb": [
    104,
    103,
    103
   ],
   "pantone_id": "pantone 18-0503 tcx gargoyle",
   "hex": "#696969",
   "universal_name": "gray",
   "rgb": [
    105,
    105,
    105
   ],
   "hsv": [
    0.0,
    0.0,
    0.4117647058823529
   ],
   "pantone_code": "18-0503 tcx",
   "pantone_name": "gargoyle",
   "entrylevel_name": "gray"
  },
  {
   "name": "charcoal gray",
   "pantone_rgb": [
    108,
    104,
    104
   ],
   "pantone_id": "pantone 18-0601 tcx charcoal gray",
   "hex": "#6c6868",
   "universal_name": "gray",
   "rgb": [
    108,
    104,
    104
   ],
   "hsv": [
    0.0,
    0.03703703703703709,
    0.4235294117647059
   ],
   "pantone_code": "18-0601 tcx",
   "pantone_name": "charcoal gray",
   "entrylevel_name": "gray"
  },
  {
   "name": "gunmetal",
   "pantone_rgb": [
    92,
    93,
    91
   ],
   "pantone_id": "pantone 18-0306 tcx gunmetal",
   "hex": "#5c5d5b",
   "universal_name": "gray",
   "rgb": [
    92,
    93,
    91
   ],
   "hsv": [
    90.0,
    0.02150537634408589,
    0.36470588235294116
   ],
   "pantone_code": "18-0306 tcx",
   "pantone_name": "gunmetal",
   "entrylevel_name": "gray"
  }
 ]
}

Get the closest color term for a given color (specified by RGB color model).

End point

GET /v1/colors/color_terms

Request

Parameter Type Description Default
r query (Required) The value for the red channel in the RGB color model (in the range 0 to 255).
g query (Required) The value for the green channel in the RGB color model (in the range 0 to 255).
b query (Required) The value for the blue channel in the RGB color model (in the range 0 to 255).
color_count query the number of similar color terms (maximum value of 10) 5
color_family query the color family, can be either universal, entrylevel, full or pantone full
method query The method to use to get the color names, can be either accurate (exact but slower) or fast (approximate but fast) accurate

Response

Parameter Description
time_ms The time taken in milliseconds.
color_terms A list of five closest color terms. Each field has the following field names.
rgb The RGB values for the color.
hsv The HSV values for the color.
hex The hex code for the color.
universal_name The best matching universal color name. Berlin and Kay, in a classic study of worldwide color naming, postulated the existence of 11 universal basic color terms across languages. We have included two more colors(olive and yellow green) as per the ISCC-NBS system.
entrylevel_name The best matching entry level color name. A slightly larger curated set of color names which we call entry level. A random person should be able to recognize these color names.
name The best guess for the color name based on all the colors available in our color taxonomy.

Get similar colors

#------------------------------------------------------------------------------
# Get other color terms similar to a given color term.
# GET /v1/colors/similar_colors
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header.
headers = {'X-Api-Key': props['X-Api-Key']}

api_endpoint = '/v1/colors/similar_colors'

url = urljoin(api_gateway_url,api_endpoint)

params = {}
params['color_term'] = 'purple'

# Optional parameters
params['color_count'] = 3
#params['color_family'] = 'universal'
#params['color_family'] = 'entrylevel'
#params['color_family'] = 'full'

# To serch within the pantone family
#params['color_term'] = 'pantone 19-3336 tcx sparkling grape'
#params['color_family'] = 'pantone'

response = requests.get(url,headers=headers,params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "similar_colors": [
  {
   "name": "patriarch",
   "pantone_rgb": [
    119,
    51,
    118
   ],
   "pantone_id": "pantone 19-3336 tcx sparkling grape",
   "hex": "#800080",
   "universal_name": "purple",
   "rgb": [
    128,
    0,
    128
   ],
   "hsv": [
    300.0,
    1.0,
    0.5019607843137255
   ],
   "pantone_code": "19-3336 tcx",
   "pantone_name": "sparkling grape",
   "entrylevel_name": "purple"
  },
  {
   "name": "violet",
   "pantone_rgb": [
    193,
    127,
    181
   ],
   "pantone_id": "pantone 16-3320 tcx violet",
   "hex": "#c17fb5",
   "universal_name": "pink",
   "rgb": [
    193,
    127,
    181
   ],
   "hsv": [
    310.9090909090909,
    0.34196891191709844,
    0.7568627450980392
   ],
   "pantone_code": "16-3320 tcx",
   "pantone_name": "violet",
   "entrylevel_name": "magenta"
  },
  {
   "name": "navy blue",
   "pantone_rgb": [
    64,
    63,
    111
   ],
   "pantone_id": "pantone 19-3832 tcx navy blue",
   "hex": "#403f6f",
   "universal_name": "purple",
   "rgb": [
    64,
    63,
    111
   ],
   "hsv": [
    241.25,
    0.43243243243243246,
    0.43529411764705883
   ],
   "pantone_code": "19-3832 tcx",
   "pantone_name": "navy blue",
   "entrylevel_name": "navy blue"
  }
 ],
 "time_ms": "0.11"
}

Get other color terms similar to a given color term.

End point

GET /v1/colors/similar_colors

Request

Parameter Type Description Default
color_term query (Required) The color term.
color_count query the number of similar color terms (maximum value of 10) 5
color_family query The color family to use to retrieve the similar colors. Can take values universal, entrylevel ,full or pantone entrylevel

Response

Parameter Description
time_ms The time taken in milliseconds.
similar_colors A list of five closest color terms. Each field has the following field names.
rgb The RGB values for the color.
hsv The HSV values for the color.
hex The hex code for the color.
universal_name The best matching universal color name. Berlin and Kay, in a classic study of worldwide color naming, postulated the existence of 11 universal basic color terms across languages. We have included two more colors(olive and yellow green) as per the ISCC-NBS system.
entrylevel_name The best matching entry level color name. A slightly larger curated set of color names which we call entry level. A random person should be able to recognize these color names.
name The best guess for the color name based on all the colors available in our color taxonomy.

Get color similarity

#------------------------------------------------------------------------------
# Get similarity score between two color terms. 
# GET /v1/colors/color_terms_similarity
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

api_endpoint = '/v1/colors/color_terms_similarity'

url = urljoin(api_gateway_url,api_endpoint)

params = {}
params['color_term_1'] = 'red'
params['color_term_2'] = 'pink'

response = requests.get(url,
                        headers=headers,
                        params=params)

print response.status_code
pprint(response.json())

Sample json response

{
  "similarity_score": 0.650632524978343,
  "time_ms": u'22.23'
}

Get similarity score between two color terms (eg. ‘red’ and ‘pink’).

Uses the CIEDE2000 metric to measure similarity between two color terms.

End point

GET /v1/colors/color_terms_similarity

Request

Parameter Type Description
color_term_1 query (Required) The first color term.
color_term_2 query (Required) The second color term.

Response

Parameter Description
time_ms The time taken in milliseconds.
similarity_score The similarity score (between 0 and 1) which indicates the similarity between the two color terms. Internally it uses the CIEDE2000 metric to measure similarity between two color terms.

Color Search

A collection of APIs for enabling catalog search based on colors.

Build color search index

#------------------------------------------------------------------------------
# Build the color search index.
# POST /v1/catalog/{catalog_name}/color_search_index
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

params = {}

# Optional parameters.
params['color_count'] = 3
params['quality'] = 1
params['image_max_dimension'] = 256
params['ignore_background'] = 'true'
params['model'] = 'person_fast'
params['fraction_pixels_threshold'] = 0.1

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/color_search_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.post(url,headers=headers,params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "status": {
  "status": "done",
  "color_computation": {
   "num_of_images_ignored": "14",
   "num_of_images_existing": "0",
   "num_of_images_error": "0",
   "num_of_images_processed": "46"
  },
  "finish_time": "2017-11-18 04:35:03.112859",
  "start_time": "2017-11-18 04:34:51.450504",
  "pid": "224",
  "index_updated": "true",
  "num_of_products": "10",
  "num_of_images": "60",
  "color_search_index": {
   "num_of_images_missing_colors": "0",
   "num_of_images_indexed": "46",
   "num_of_images_ignored": "14"
  }
 },
 "time_ms": "1.97"
}

Build the color search index.

Before you can start using the color search APIs the color search index has to be built. This API computes the dominant colors for all the uploaded images in the catalog and then builds an index for fast nearest neighbor retrieval.

End point

POST /v1/catalog/{catalog_name}/color_search_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
color_count query The maximum number of dominant colors to extract per image. 3
quality query This parameter provides a trade off between the computation time and the quality of the dominant colors. Larger the number faster is the dominant color computation but greater the chance that the colors will be missed. 1 is the highest quality. 1
image_max_dimension query You can set this parameters to resize the image for faster computation of dominant colors. If your images are of very high resolution you can set this parameter to a smaller value (suggested values 256-512) for faster computation. For any image if max(image width,image height) > image_max_dimension resizes the image such that max(image width,image height) = image_max_dimension. no image resizing
ignore_background query By default we use the entire image to compute the dominant colors. If we set this parameter to true we internally use some algorithms to ignore the background and mainly focus on the person or apparel. false
model query The model to use to ignore the background. Currently we use person detecors to focus only on the person. The following options are supported person_fast (faster but slightly less accurate model), person_accurate (slower but more accurate model) and person_basic (a basic person detector using standard body proportions). person_fast
fraction_pixels_threshold query Include only those colors whos fraction of pixels is greater than this number. 0.0
ignore_images_without_person query If true ignore images where person is not detected. If false and person is not detected then defaults to ‘person_basic’ false

Response

Parameter Description
time_ms The time taken in milliseconds.
status A json containing various info about the current status of the index building process.
status The current status of the index building process. The status can be one of computing_dominant_color,building_index,or done. The index is built when the status becomes done.
num_of_products The number of products in the catalog.
num_of_images The total number of images in the catalog.
start_time The time when the index building started.
finish_time The time when the index building finished.
color_computation Info about dominant color computation.
num_of_images_error The number of images for which there was some error in dominant color computation.
num_of_images_ignored The number of images that were ignored.
num_of_images_existing The number of images for which the dominant colors were already computed (in case of building a new index with new products added).
num_of_images_processed The total number of images for which the dominant colors were computed.
color_search_index Info about the index building.
num_of_images_missing_colors The number of images for which there was no dominant color was found.
num_of_images_ignored The number of images that were ignored.
num_of_images_indexed The total number of images finally indexed.

Get color search index status

#------------------------------------------------------------------------------
# Get the status of the color search index.
# GET /v1/catalog/{catalog_name}/color_search_index
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/color_search_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,headers=headers)

print response.status_code
pprint(response.json())

Sample json response

{
 "status": {
  "status": "done",
  "color_computation": {
   "num_of_images_ignored": "14",
   "num_of_images_existing": "0",
   "num_of_images_error": "0",
   "num_of_images_processed": "46"
  },
  "finish_time": "2017-11-18 04:35:03.112859",
  "start_time": "2017-11-18 04:34:51.450504",
  "pid": "224",
  "index_updated": "true",
  "num_of_products": "10",
  "num_of_images": "60",
  "color_search_index": {
   "num_of_images_missing_colors": "0",
   "num_of_images_indexed": "46",
   "num_of_images_ignored": "14"
  }
 },
 "time_ms": "1.97"
}

Get the status of the color search index.

End point

GET /v1/catalog/{catalog_name}/color_search_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.

Response

Parameter Description
time_ms The time taken in milliseconds.
status A json containing various info about the current status of the index building process.
status The current status of the index building process. The status can be one of computing_dominant_color,building_index,or done. The index is built when the status becomes done.
num_of_products The number of products in the catalog.
num_of_images The total number of images in the catalog.
start_time The time when the index building started.
finish_time The time when the index building finished.
color_computation Info about dominant color computation.
num_of_images_error The number of images for which there was some error in dominant color computation.
num_of_images_ignored The number of images that were ignored.
num_of_images_existing The number of images for which the dominant colors were already computed (in case of building a new index with new products added).
num_of_images_processed The total number of images for which the dominant colors were computed.
color_search_index Info about the index building.
num_of_images_missing_colors The number of images for which there was no dominant color was found.
num_of_images_ignored The number of images that were ignored.
num_of_images_indexed The total number of images finally indexed.

Delete the color search index

#------------------------------------------------------------------------------
# Delete the color search index.
# DELETE /v1/catalog/{catalog_name}/color_search_index
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/color_search_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.delete(url,headers=headers)

print response.status_code
pprint(response.json())

Sample json response

{
 "deleted": true,
 "time_ms": "8.88",
 "catalog_name": "sample_catalog"
}

Delete the color search index.

End point

DELETE /v1/catalog/{catalog_name}/color_search_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.

Response

Parameter Description
time_ms The time taken in milliseconds.
catalog_name The catalog name.
deleted This is true if the index was successfully deleted.

Color Search by RGB

http://api_gateway_url/v1/catalog/sample_catalog/color_search?r=255&g=0&b=0m&ax_number_of_results=5&api_key=your_api_key
#------------------------------------------------------------------------------
# Get similar color images in the catalog for a specified RGB value.
# GET /v1/catalog/{catalog_name}/color_search
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

params = {}

# Parameters.
params['r'] = 255
params['g'] = 0
params['b'] = 0
params['max_number_of_results'] = 5

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/color_search'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,
                        headers=headers,
                        params=params)


print response.status_code
pprint(response.json())

Sample json response

{
 "time_ms": "6.13",
 "products": [
  {
   "distance": 7.383520126342773,
   "image_id": "5",
   "rgb": [
    197,
    99,
    71
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Front_Medium.jpg",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_5.jpg"
  },
  {
   "distance": 9.618025779724121,
   "image_id": "1",
   "rgb": [
    196,
    106,
    76
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Look_Medium.jpg",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_1.jpg"
  },
  {
   "distance": 12.06448745727539,
   "image_id": "4",
   "rgb": [
    154,
    46,
    35
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Right_Medium.jpg",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_4.jpg"
  },
  {
   "distance": 19.470752716064453,
   "image_id": "2",
   "rgb": [
    128,
    41,
    38
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Left_Medium.jpg",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_2.jpg"
  },
  {
   "distance": 20.736268997192383,
   "image_id": "4",
   "rgb": [
    192,
    126,
    96
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Right_Medium.jpg",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_4.jpg"
  }
 ]
}

Get similar color images in the catalog for a specified RGB value.

End point

GET /v1/catalog/{catalog_name}/color_search

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
r query (Required) The value for the red channel in the RGB color model (in the range 0 to 255).
g query (Required) The value for the green channel in the RGB color model (in the range 0 to 255).
b query (Required) The value for the blue channel in the RGB color model (in the range 0 to 255).
max_number_of_results query maximum number of results to return 12

Response

Parameter Description
time_ms The time taken in milliseconds.
products A sorted list similar color images. Each item in the list has the following fields.
image_id The image id.
id The product id.
image_filename The image filename.
image_url The image url
distance The euclidean distance (in LAB space) between the color in the image to the color in the query.
rgb The RGB value of the matching color.

Color Search by name

http://api_gateway_url/v1/catalog/sample_catalog/color_search?color_term=red&ax_number_of_results=5&api_key=your_api_key
#------------------------------------------------------------------------------
# Get similar color images in the catalog for a specified color name..
# GET /v1/catalog/{catalog_name}/color_search
# params - color_term,max_number_of_results
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Parameters.
params = {}
params['color_term'] = 'red' 
params['max_number_of_results'] = 5

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/color_search'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,
                        headers=headers,
                        params=params)


print response.status_code
pprint(response.json())


Sample json response

{
 "time_ms": "11.09",
 "products": [
  {
   "distance": 51.287628173828125,
   "image_id": "4",
   "rgb": [
    154,
    46,
    35
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Right_Medium.jpg",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_4.jpg"
  },
  {
   "distance": 53.020751953125,
   "image_id": "5",
   "rgb": [
    197,
    99,
    71
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Front_Medium.jpg",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_5.jpg"
  },
  {
   "distance": 56.67232894897461,
   "image_id": "1",
   "rgb": [
    196,
    106,
    76
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Look_Medium.jpg",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_1.jpg"
  },
  {
   "distance": 64.99003601074219,
   "image_id": "2",
   "rgb": [
    128,
    41,
    38
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Left_Medium.jpg",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_2.jpg"
  },
  {
   "distance": 67.47423553466797,
   "image_id": "2",
   "rgb": [
    210,
    138,
    106
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Left_Medium.jpg",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_2.jpg"
  }
 ]
}

Get similar color images in the catalog for a specified color name.

End point

GET /v1/catalog/{catalog_name}/color_search

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
color_term query (Required) The color term (e.g. red).
max_number_of_results query maximum number of results to return 12

Response

Parameter Description
time_ms The time taken in milliseconds.
products A sorted list similar color images. Each item in the list has the following fields.
image_id The image id.
id The product id.
image_filename The image filename.
image_url The image url
distance The euclidean distance (in LAB space) between the color in the image to the color in the query.
rgb The RGB value of the matching color.

Color Search by id

http://api_gateway_url/v1/catalog/sample_catalog/color_search?id=SHRES16AWFSDR9346B&image_id=1&color_count=1&max_number_of_results=5&api_key=your_api_key
#------------------------------------------------------------------------------
# Get similar color images in the catalog for an existing image.
# GET /v1/catalog/{catalog_name}/color_search
# params - id,image_id,color_count,max_number_of_results
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Parameters.
params = {}
params['id'] = 'SHRES16AWFSDR9346B' 
params['image_id'] = '1'
params['color_count'] =  1
params['max_number_of_results'] = 5

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/color_search'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,
                        headers=headers,
                        params=params)


print response.status_code
pprint(response.json())

Sample json response

{
 "time_ms": "12.31",
 "products": [
  {
   "distance": 0.0,
   "image_id": "1",
   "rgb": [
    196,
    106,
    76
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Look_Medium.jpg",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_1.jpg"
  },
  {
   "distance": 4.095544338226318,
   "image_id": "5",
   "rgb": [
    197,
    99,
    71
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Front_Medium.jpg",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_5.jpg"
  },
  {
   "distance": 12.966226577758789,
   "image_id": "4",
   "rgb": [
    192,
    126,
    96
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Right_Medium.jpg",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_4.jpg"
  },
  {
   "distance": 13.747275352478027,
   "image_id": "2",
   "rgb": [
    210,
    138,
    106
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Left_Medium.jpg",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_2.jpg"
  },
  {
   "distance": 21.508577346801758,
   "image_id": "4",
   "rgb": [
    154,
    46,
    35
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Right_Medium.jpg",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_4.jpg"
  }
 ]
}

Get similar color images in the catalog for an existing image.

End point

GET /v1/catalog/{catalog_name}/color_search

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
id path (Required) The product id.
image_id path (Required) The image id.
color_count path The maximum number of dominant colors to search for in an image. 1
max_number_of_results query maximum number of results to return 12

Response

Parameter Description
time_ms The time taken in milliseconds.
products A sorted list similar color images. Each item in the list has the following fields.
image_id The image id.
id The product id.
image_filename The image filename.
image_url The image url
distance The euclidean distance (in LAB space) between the color in the image to the color in the query.
rgb The RGB value of the matching color.

Color Search by image

#------------------------------------------------------------------------------
# Get similar color images in the catalog for a given uploaded image.
# POST /v1/catalog/{catalog_name}/color_search
# params - color_count,image_max_dimension,max_number_of_results
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Parameters.
params = {}
params['color_count'] =  2
params['max_number_of_results'] = 5

headers['Content-Type'] = 'image/jpeg'

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/color_search'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.post(url,
                        headers=headers,
                        params=params,
                        data=open('test_image_2.jpeg','rb'))

print response.status_code
pprint(response.json())

Sample json response

{
 "time_ms": "689.53",
 "products": [
  {
   "distance": 1.9539705514907837,
   "image_id": "4",
   "rgb": [
    48,
    48,
    48
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2016/SKLTS16AMCWSH8SH2005/Look_Medium.jpg",
   "id": "SKLTS16AMCWSH8SH20",
   "image_filename": "SKLTS16AMCWSH8SH20_4.jpg"
  },
  {
   "distance": 4.879070281982422,
   "image_id": "5",
   "rgb": [
    45,
    42,
    45
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2016/SKLTS16AMCWSH8SP0150/Right_Medium.jpg",
   "id": "SKLTS16AMCWSH8SP01",
   "image_filename": "SKLTS16AMCWSH8SP01_5.jpg"
  },
  {
   "distance": 6.080552577972412,
   "image_id": "2",
   "rgb": [
    42,
    40,
    44
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2016/SKLTS16AMCWSH8SP0150/Front_Medium.jpg",
   "id": "SKLTS16AMCWSH8SP01",
   "image_filename": "SKLTS16AMCWSH8SP01_2.jpg"
  },
  {
   "distance": 6.821847438812256,
   "image_id": "3",
   "rgb": [
    40,
    38,
    42
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2016/SKLTS16AMCWSH8SP0150/Left_Medium.jpg",
   "id": "SKLTS16AMCWSH8SP01",
   "image_filename": "SKLTS16AMCWSH8SP01_3.jpg"
  },
  {
   "distance": 7.602819442749023,
   "image_id": "4",
   "rgb": [
    36,
    34,
    34
   ],
   "image_url": "http://images.abofcdn.com/catalog/images/2016/SKLTS16AMCWSH8SP0150/Look_Medium.jpg",
   "id": "SKLTS16AMCWSH8SP01",
   "image_filename": "SKLTS16AMCWSH8SP01_4.jpg"
  }
 ]
}

Get similar color images in the catalog for a given uploaded image.

End point

POST /v1/catalog/{catalog_name}/color_search

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
data image/jpeg (Required) The image. The image can be in PNG, JPEG,
max_number_of_results query maximum number of results to return 12
color_count path The maximum number of dominant colors to search for in an image. 1
image_max_dimension query You can set this parameters to resize the image for faster computation of dominant colors. If your image is of high resolution you can set this parameter to a smaller value (suggested values 256-512) for faster computation. For any image if max(image width,image height) > image_max_dimension resizes the image such that max(image width,image height) = image_max_dimension. no image resizing

Response

Parameter Description
time_ms The time taken in milliseconds.
products A sorted list similar color images. Each item in the list has the following fields.
image_id The image id.
id The product id.
image_filename The image filename.
image_url The image url
distance The euclidean distance (in LAB space) between the color in the image to the color in the query.
rgb The RGB value of the matching color.

Dominant Colors

A collection of APIs for computing the dominant colors for an user uploaded image, the entire catalog, and any image in the catalog.

Get dominant colors for an image

#------------------------------------------------------------------------------
# Dominant Colors for an user uploaded image. 
# POST /v1/colors/dominant_colors
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header.
headers = {'X-Api-Key': props['X-Api-Key']}

params = {}
# Optional parameters.
params['color_count'] = 5
params['quality'] = 1
#params['image_max_dimension'] = 256
params['ignore_background'] = 'true'
params['model'] = 'person_accurate'
#params['fraction_pixels_threshold'] = 0.1
params['color_name_method'] = 'accurate'
#params['color_name_method'] = 'fast'

api_endpoint = '/v1/colors/dominant_colors'

url = urljoin(api_gateway_url,api_endpoint)

# Three options to pass the image

# OPTION 1 : Directly post the image
headers['Content-Type'] = 'image/jpeg'
response = requests.post(url,
                         headers=headers,
                         params=params,
                         data=open('test_image_2.jpeg','rb'))

"""          
# OPTION 2 : Pass the image url
params['image_url'] = 'https://vg-images.condecdn.net/image/oDXPOxw65EZ/crop/405'
response = requests.post(url,
                         headers=headers,
"""

"""
# OPTION 3 : using multipart
image_filename = 'test_image_2.jpeg'
with open(image_filename,'rb') as images_file:
    response = requests.post(url,
                             headers=headers,
                             params=params,
                             files={'image': (image_filename,images_file,'image/jpeg')})   
""" 

print response.status_code
pprint(response.json())

# Human friendly repsonse.

results = response.json()

image_location = '%s?api_key=%s'%(urljoin(api_gateway_url,results['image_location']),
                                  props['X-Api-Key'])
print('[original image ] %s'%(image_location))

image_location = '%s&api_key=%s'%(urljoin(api_gateway_url,results['bounding_box']['image_location']),
                                  props['X-Api-Key'])
print('[bounding box   ] %s'%(image_location))

for color_info in results['dominant_colors']:
    print('[dominant colors] %s - %1.2f - %s - %s - %s - %s'%(color_info['hex'],
                                  color_info['fraction_pixels'],
                                  color_info['name'],
                                  color_info['entrylevel_name'],
                                  color_info['universal_name'],
                                  color_info['pantone_id']))

Sample json response

{
 "dominant_colors": [
  {
   "name": "tart orange",
   "pantone_rgb": [
    243,
    91,
    83
   ],
   "pantone_id": "pantone 17-1656 tcx hot coral",
   "hex": "#f5594b",
   "universal_name": "red",
   "rgb": [
    245,
    89,
    75
   ],
   "hsv": [
    4.941176470588232,
    0.6938775510204082,
    0.9607843137254902
   ],
   "pantone_code": "17-1656 tcx",
   "fraction_pixels": 0.5328356594179379,
   "pantone_name": "hot coral",
   "entrylevel_name": "tomato"
  },
  {
   "name": "pink lace",
   "pantone_rgb": [
    237,
    208,
    221
   ],
   "pantone_id": "pantone 12-2905 tcx cradle pink",
   "hex": "#fae0f3",
   "universal_name": "pink",
   "rgb": [
    250,
    224,
    243
   ],
   "hsv": [
    316.1538461538462,
    0.10399999999999998,
    0.9803921568627451
   ],
   "pantone_code": "12-2905 tcx",
   "fraction_pixels": 0.23604890187168667,
   "pantone_name": "cradle pink",
   "entrylevel_name": "pink"
  },
  {
   "name": "light hot pink",
   "pantone_rgb": [
    233,
    173,
    202
   ],
   "pantone_id": "pantone 14-2710 tcx lilac sachet",
   "hex": "#fbafe3",
   "universal_name": "pink",
   "rgb": [
    251,
    175,
    227
   ],
   "hsv": [
    318.94736842105266,
    0.3027888446215139,
    0.984313725490196
   ],
   "pantone_code": "14-2710 tcx",
   "fraction_pixels": 0.22574921562263334,
   "pantone_name": "lilac sachet",
   "entrylevel_name": "pink"
  },
  {
   "name": "bubblegum",
   "pantone_rgb": [
    230,
    121,
    142
   ],
   "pantone_id": "pantone 16-1723 tcx confetti",
   "hex": "#e37687",
   "universal_name": "pink",
   "rgb": [
    227,
    118,
    135
   ],
   "hsv": [
    350.64220183486236,
    0.48017621145374445,
    0.8901960784313725
   ],
   "pantone_code": "16-1723 tcx",
   "fraction_pixels": 0.0027913015254787408,
   "pantone_name": "confetti",
   "entrylevel_name": "pink"
  },
  {
   "name": "light salmon pink",
   "pantone_rgb": [
    231,
    139,
    144
   ],
   "pantone_id": "pantone 16-1720 tcx strawberry ice",
   "hex": "#e89694",
   "universal_name": "pink",
   "rgb": [
    232,
    150,
    148
   ],
   "hsv": [
    1.4285714285714448,
    0.3620689655172413,
    0.9098039215686274
   ],
   "pantone_code": "16-1720 tcx",
   "fraction_pixels": 0.0025749215622633344,
   "pantone_name": "strawberry ice",
   "entrylevel_name": "pink"
  }
 ],
 "time_ms": "13072.34",
 "bounding_box": {
  "image_location": "/v1/images/dc3a108d-c4fe-4d15-80fa-1f66518b21e6.jpe?top_left_x=165&top_left_y=24&width=260&height=842",
  "top_left_x": 165,
  "top_left_y": 24,
  "height": 842,
  "width": 260,
  "score": 0.841905,
  "model": "person_accurate"
 },
 "image_location": "/v1/images/dc3a108d-c4fe-4d15-80fa-1f66518b21e6.jpe"
}

Get the dominant colors for an image.

End point

POST /v1/colors/dominant_colors

Request

Parameter Type Description Default
data image/jpeg (Required) The image. The image can be in PNG, JPEG, BMP, or GIF.
color_count query The maximum number of dominant colors to extract per image. 3
quality query This parameter provides a trade off between the computation time and the quality of the dominant colors. Larger the number faster is the dominant color computation but greater the chance that the colors will be missed. 1 is the highest quality. 1
image_max_dimension query You can set this parameters to resize the image for faster computation of dominant colors. If your images are of very high resolution you can set this parameter to a smaller value (suggested values 256-512) for faster computation. For any image if max(image width,image height) > image_max_dimension resizes the image such that max(image width,image height) = image_max_dimension. no image resizing
ignore_background query By default we use the entire image to compute the dominant colors. If we set this parameter to true we internally use some algorithms to ignore the background and mainly focus on the person or apparel. false
model query The model to use to ignore the background. Currently we use person detecors to focus only on the person. The following options are supported person_fast (faster but slightly less accurate model), person_accurate (slower but more accurate model) and person_basic (a basic person detector using standard body proportions). person_fast
fraction_pixels_threshold query Include only those colors whos fraction of pixels is greater than this number. 0.0
color_name_method query The method to use to get the color names, can be either accurate (exact but slower) or fast (approximate but fast) accurate

Instead of the posting the image data you can also pass an image url.

Parameter Type Description
image_url query (Required) The image url.

You can also pass the image using multipart/form-data with the fieldname image.

Response

Parameter Description
time_ms The time taken in milliseconds.
image_location The uploaded image location.
dominant_colors A list of dominant colors for the image sorted in the decreasing order of the fraction of pixels. Each field in the list has the following fieldnames.
rgb The RGB values for the color.
hsv The HSV values for the color.
hex The hex code for the color.
universal_name The best matching universal color name. Berlin and Kay, in a classic study of worldwide color naming, postulated the existence of 11 universal basic color terms across languages. We have included two more colors(olive and yellow green) as per the ISCC-NBS system.
entrylevel_name The best matching entry level color name. A slightly larger curated set of color names which we call entry level. A random person should be able to recognize these color names.
name The best guess for the color name based on all the colors available in our color taxonomy.
fraction_pixels The fraction of pixels in the bounding box that can be attributed to this color.
bounding_box The region in the image used to compute the dominant colors and corresponds to the the bounding box for the central detected person. In case ignore_background is set to false this corresponds to the entire image.
top_left_x The x co-ordinate of the top left corner of the bounding box.
top_left_y The y co-ordinate of the top left corner of the bounding box.
width The width of the bounding box.
height The height of the bounding box.
score The confidence score (between 0 and 1) that the bounding box contains a person.
model The person detection model used.

Build dominant colors index

#------------------------------------------------------------------------------
# Build the dominant colors index.
# POST /v1/catalog/{catalog_name}/dominant_colors_index
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

params = {}

# Optional parameters.
params['colors'] = 20
params['max_colors_per_image'] = 2
params['fraction_pixels_threshold'] = 0.1
params['embedding'] = 'true'

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/dominant_colors_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.post(url,headers=headers,params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "status": {
  "status": "done",
  "num_of_products": "10",
  "results_updated": "true",
  "start_time": "2017-11-18 17:10:00.141319",
  "pid": "379",
  "dominant_colors": {
   "num_of_images_missing_colors": "0",
   "num_of_images_indexed": "46",
   "num_of_images_ignored": "14"
  },
  "finish_time": "2017-11-18 17:10:05.956428",
  "num_of_images": "60"
 },
 "time_ms": "2.51"
}

Build the dominant colors index.

This loads all the dominant colors for every image in the catalog and then clusters the colors to compute the dominant colors for the entire catalog. Before you can start querying for the dominant colors you need to call this API to start the clustering procedure.

End point

POST /v1/catalog/{catalog_name}/dominant_colors_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
colors query The number of dominant colors to compute. 10
max_colors_per_image query The maximum number of dominant colors to use per image. all available colors
fraction_pixels_threshold query Include only those colors whos fraction of pixels is greater than this number. 0.0
embedding query If true embeds the dominant colors in two dimensions using t-SNE embedding and returns the embedding as a grid assignment in the results. The optimal gird size is automatically computed based on the number of dominant colors requested. false

Response

Parameter Description
time_ms The time taken in milliseconds.
status A json containing various info about the current status of the index building process.
status The current status of the index building process. The status can be one of clustering or done. The index is built when the status becomes done.
num_of_products The number of products in the catalog.
num_of_images The total number of images in the catalog.
start_time The time when the index building started.
finish_time The time when the index building finished.
dominant_colors Info about dominant color.
num_of_images_missing_colors The number of images for which there was no dominant color was found.
num_of_images_ignored The number of images that were ignored.
num_of_images_indexed The total number of images finally indexed.

Get dominant colors index status

#------------------------------------------------------------------------------
# Get the status of the dominant colors index.
# GET /v1/catalog/{catalog_name}/dominant_colors_index
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/dominant_colors_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,headers=headers)

print response.status_code
pprint(response.json())

Sample json response

{
 "status": {
  "status": "done",
  "num_of_products": "10",
  "results_updated": "true",
  "start_time": "2017-11-18 17:10:00.141319",
  "pid": "379",
  "dominant_colors": {
   "num_of_images_missing_colors": "0",
   "num_of_images_indexed": "46",
   "num_of_images_ignored": "14"
  },
  "finish_time": "2017-11-18 17:10:05.956428",
  "num_of_images": "60"
 },
 "time_ms": "2.51"
}

Get the status of the dominant colors index.

End point

GET /v1/catalog/{catalog_name}/dominant_colors_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.

Response

Parameter Description
time_ms The time taken in milliseconds.
status A json containing various info about the current status of the index building process.
status The current status of the index building process. The status can be one of clustering or done. The index is built when the status becomes done.
num_of_products The number of products in the catalog.
num_of_images The total number of images in the catalog.
start_time The time when the index building started.
finish_time The time when the index building finished.
dominant_colors Info about dominant color.
num_of_images_missing_colors The number of images for which there was no dominant color was found.
num_of_images_ignored The number of images that were ignored.
num_of_images_indexed The total number of images finally indexed.

Delete the dominant colors index

#------------------------------------------------------------------------------
# Delete the dominant colors index.
# DELETE /v1/catalog/{catalog_name}/dominant_colors_index
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/dominant_colors_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.delete(url,headers=headers)

print response.status_code
pprint(response.json())

Sample json response

{
 "deleted": true,
 "time_ms": "8.88",
 "catalog_name": "sample_catalog"
}

Delete the dominant colors index.

End point

DELETE /v1/catalog/{catalog_name}/dominant_colors_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.

Response

Parameter Description
time_ms The time taken in milliseconds.
catalog_name The catalog name.
deleted This is true if the index was successfully deleted.

Get dominant colors for a catalog

#------------------------------------------------------------------------------
# Get the dominant colors for all images in the catalog.
# GET /v1/catalog/{catalog_name}/dominant_colors
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

params = {}
params['colors'] = 9

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/dominant_colors'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,headers=headers,params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "computed_on": "2018-04-01 13:51:12.278474",
 "time_ms": "3.24",
 "dominant_colors": [
  {
   "embedding_grid": [
    0.0,
    0.0
   ],
   "name": "bisque",
   "pantone_rgb": [
    218,
    192,
    167
   ],
   "pantone_id": "pantone 13-1011 tcx ivory cream",
   "popularity": 0.1891891891891892,
   "hex": "#dec1aa",
   "universal_name": "pink",
   "lab": [
    79.93886694122813,
    6.754293758508223,
    15.36922771034137
   ],
   "popularity_percentile": 100.0,
   "rgb": [
    222,
    193,
    170
   ],
   "n_instances": 7,
   "pantone_code": "13-1011 tcx",
   "hsv": [
    26.538461538461547,
    0.23423423423423428,
    0.8705882352941177
   ],
   "pantone_name": "ivory cream",
   "entrylevel_name": "tan"
  },
  {
   "embedding_grid": [
    1.0,
    0.0
   ],
   "name": "jet",
   "pantone_rgb": [
    42,
    43,
    45
   ],
   "pantone_id": "pantone 19-4004 tcx tap shoe",
   "popularity": 0.16216216216216217,
   "hex": "#2b2c2d",
   "universal_name": "black",
   "lab": [
    17.93853276291656,
    -0.2022203751522733,
    -0.8051385777718023
   ],
   "popularity_percentile": 83.33333333333334,
   "rgb": [
    43,
    44,
    45
   ],
   "n_instances": 6,
   "pantone_code": "19-4004 tcx",
   "hsv": [
    210.0000000000001,
    0.0444444444444444,
    0.17647058823529413
   ],
   "pantone_name": "tap shoe",
   "entrylevel_name": "black"
  },
  {
   "embedding_grid": [
    2.0,
    0.0
   ],
   "name": "silver sand",
   "pantone_rgb": [
    197,
    198,
    199
   ],
   "pantone_id": "pantone 14-4102 tcx glacier gray",
   "popularity": 0.16216216216216217,
   "hex": "#c4c6c6",
   "universal_name": "white",
   "lab": [
    79.72810735816829,
    -0.6892262565815765,
    -0.24903099362945103
   ],
   "popularity_percentile": 83.33333333333334,
   "rgb": [
    196,
    198,
    198
   ],
   "n_instances": 6,
   "pantone_code": "14-4102 tcx",
   "hsv": [
    180.0,
    0.010101010101010055,
    0.7764705882352941
   ],
   "pantone_name": "glacier gray",
   "entrylevel_name": "silver"
  },
  {
   "embedding_grid": [
    0.0,
    1.0
   ],
   "name": "granite gray",
   "pantone_rgb": [
    102,
    103,
    109
   ],
   "pantone_id": "pantone 18-4006 tcx quiet shade",
   "popularity": 0.10810810810810811,
   "hex": "#61636a",
   "universal_name": "gray",
   "lab": [
    42.0086797684853,
    0.7439991692389514,
    -4.226920295539904
   ],
   "popularity_percentile": 55.55555555555556,
   "rgb": [
    97,
    99,
    106
   ],
   "n_instances": 4,
   "pantone_code": "18-4006 tcx",
   "hsv": [
    226.66666666666663,
    0.08490566037735858,
    0.41568627450980394
   ],
   "pantone_name": "quiet shade",
   "entrylevel_name": "gray"
  },
  {
   "embedding_grid": [
    1.0,
    1.0
   ],
   "name": "copper red",
   "pantone_rgb": [
    209,
    111,
    82
   ],
   "pantone_id": "pantone 16-1441 tcx arabesque",
   "popularity": 0.10810810810810811,
   "hex": "#c5694a",
   "universal_name": "red",
   "lab": [
    54.52250103123478,
    33.8426536300997,
    33.601454680289436
   ],
   "popularity_percentile": 55.55555555555556,
   "rgb": [
    197,
    105,
    74
   ],
   "n_instances": 4,
   "pantone_code": "16-1441 tcx",
   "hsv": [
    15.121951219512198,
    0.6243654822335025,
    0.7725490196078432
   ],
   "pantone_name": "arabesque",
   "entrylevel_name": "tomato"
  },
  {
   "embedding_grid": [
    2.0,
    1.0
   ],
   "name": "steel teal",
   "pantone_rgb": [
    85,
    143,
    145
   ],
   "pantone_id": "pantone 17-4818 tcx bristol blue",
   "popularity": 0.10810810810810811,
   "hex": "#54919a",
   "universal_name": "gray",
   "lab": [
    56.55290842710919,
    -17.2649007031071,
    -10.93920065553089
   ],
   "popularity_percentile": 55.55555555555556,
   "rgb": [
    84,
    145,
    154
   ],
   "n_instances": 4,
   "pantone_code": "17-4818 tcx",
   "hsv": [
    187.71428571428572,
    0.4545454545454545,
    0.6039215686274509
   ],
   "pantone_name": "bristol blue",
   "entrylevel_name": "teal"
  },
  {
   "embedding_grid": [
    0.0,
    2.0
   ],
   "name": "platinum",
   "pantone_rgb": [
    239,
    235,
    231
   ],
   "pantone_id": "pantone 11-1001 tcx white alyssum",
   "popularity": 0.08108108108108109,
   "hex": "#ebe5e5",
   "universal_name": "white",
   "lab": [
    91.396105013505,
    2.0227459343862275,
    0.7108750672036868
   ],
   "popularity_percentile": 33.33333333333333,
   "rgb": [
    235,
    229,
    229
   ],
   "n_instances": 3,
   "pantone_code": "11-1001 tcx",
   "hsv": [
    0.0,
    0.025531914893616947,
    0.9215686274509803
   ],
   "pantone_name": "white alyssum",
   "entrylevel_name": "off white"
  },
  {
   "embedding_grid": [
    1.0,
    2.0
   ],
   "name": "pale turquoise",
   "pantone_rgb": [
    188,
    227,
    223
   ],
   "pantone_id": "pantone 12-5410 tcx bleached aqua",
   "popularity": 0.05405405405405406,
   "hex": "#bce9e9",
   "universal_name": "white",
   "lab": [
    89.32296955480805,
    -14.40754901948721,
    -4.797498595756533
   ],
   "popularity_percentile": 22.22222222222222,
   "rgb": [
    188,
    233,
    233
   ],
   "n_instances": 2,
   "pantone_code": "12-5410 tcx",
   "hsv": [
    180.0,
    0.19313304721030033,
    0.9137254901960784
   ],
   "pantone_name": "bleached aqua",
   "entrylevel_name": "sky blue"
  },
  {
   "embedding_grid": [
    2.0,
    2.0
   ],
   "name": "antique brass",
   "pantone_rgb": [
    202,
    153,
    120
   ],
   "pantone_id": "pantone 16-1331 tcx toast",
   "popularity": 0.02702702702702703,
   "hex": "#cc9773",
   "universal_name": "orange",
   "lab": [
    66.68024118683753,
    15.365610229684856,
    26.723238983154786
   ],
   "popularity_percentile": 11.11111111111111,
   "rgb": [
    204,
    151,
    115
   ],
   "n_instances": 1,
   "pantone_code": "16-1331 tcx",
   "hsv": [
    24.2696629213483,
    0.4362745098039216,
    0.8
   ],
   "pantone_name": "toast",
   "entrylevel_name": "tan"
  }
 ],
 "grid_size": [
  3,
  3
 ]
}

Get the dominant colors for all images in the catalog.

The dominant colors is to be interpreted as a representative of the cluster of similar colors.

End point

GET /v1/catalog/{catalog_name}/dominant_colors

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
colors query The number of dominant colors to return. 10

Response

Parameter Description
time_ms The time taken in milliseconds.
computed_on The time the dominant colors where computed.
grid_size The grid size for the embedding.
dominant_colors A list of dominant colors for the catalog sorted in the decreasing order of popularity. Each field in the list has the following fieldnames.
rgb The RGB values for the color.
hsv The HSV values for the color.
hex The hex code for the color.
universal_name The best matching universal color name. Berlin and Kay, in a classic study of worldwide color naming, postulated the existence of 11 universal basic color terms across languages. We have included two more colors(olive and yellow green) as per the ISCC-NBS system.
entrylevel_name The best matching entry level color name. A slightly larger curated set of color names which we call entry level. A random person should be able to recognize these color names.
name The best guess for the color name based on all the colors avaialable in our color taxonomy.
popularity A score between 0 and 1 indicating the popularity of the color.
popularity_percentile The corresponding percentile score.
n_instances The number of colors in the cluster.
embedding_grid The position in the grid.

Get dominant colors for a product

#------------------------------------------------------------------------------
# Get the dominant colors for an image in the catalog.
# GET /v1/catalog/{catalog_name}/dominant_colors/{id}/{image_id}
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header.
headers = {'X-Api-Key': props['X-Api-Key']}

# Query parameters.
params = {}
# Optional parameters.
#params['fraction_pixels_threshold'] = 0.1

# Path parameters
catalog_name = props['catalog_name'] 
id ='SHRES16AWFSDR9346B' 
image_id = '1'

api_endpoint = '/v1/catalog/%s/dominant_colors/%s/%s'%(catalog_name,id,image_id)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,
                        headers=headers,
                        params=params)

print response.status_code
pprint(response.json())

# Human friendly repsonse.

results = response.json()

print('[image url      ] %s'%(results['image_url']))

image_location = '%s?api_key=%s'%(urljoin(api_gateway_url,results['image_location']),
                                  props['X-Api-Key'])
print('[original image ] %s'%(image_location))

image_location = '%s&api_key=%s'%(urljoin(api_gateway_url,results['bounding_box']['image_location']),
                                  props['X-Api-Key'])
print('[bounding box   ] %s'%(image_location))

for color_info in results['dominant_colors']:
    print('[dominant colors] %s - %1.2f - %s - %s - %s - %s'%(color_info['hex'],
                                  color_info['fraction_pixels'],
                                  color_info['name'],
                                  color_info['entrylevel_name'],
                                  color_info['universal_name'],
                                  color_info['pantone_id']))

Sample json response

{
 "dominant_colors": [
  {
   "name": "dark coral",
   "pantone_rgb": [
    194,
    90,
    60
   ],
   "pantone_id": "pantone 18-1447 tcx orange rust",
   "hex": "#c56143",
   "universal_name": "red",
   "lab": [
    52.760181298097564,
    37.55416477816376,
    35.351008096609306
   ],
   "rgb": [
    197,
    97,
    67
   ],
   "hsv": [
    13.846153846153868,
    0.6598984771573604,
    0.7725490196078432
   ],
   "pantone_code": "18-1447 tcx",
   "fraction_pixels": 0.7691573737253264,
   "pantone_name": "orange rust",
   "entrylevel_name": "tomato"
  },
  {
   "name": "nude",
   "pantone_rgb": [
    241,
    206,
    179
   ],
   "pantone_id": "pantone 12-0913 tcx alesan",
   "hex": "#eecdb4",
   "universal_name": "white",
   "lab": [
    84.55409785378009,
    7.834123124968007,
    16.72944045045519
   ],
   "rgb": [
    238,
    205,
    180
   ],
   "hsv": [
    25.86206896551721,
    0.24369747899159655,
    0.9333333333333333
   ],
   "pantone_code": "12-0913 tcx",
   "fraction_pixels": 0.14824974655614526,
   "pantone_name": "alesan",
   "entrylevel_name": "peach"
  },
  {
   "name": "seal brown",
   "pantone_rgb": [
    67,
    57,
    55
   ],
   "pantone_id": "pantone 19-0910 tcx mulch",
   "hex": "#453a39",
   "universal_name": "black",
   "lab": [
    25.523637518334688,
    4.61600764818082,
    2.4026609351798234
   ],
   "rgb": [
    69,
    58,
    57
   ],
   "hsv": [
    5.0,
    0.17391304347826075,
    0.27058823529411763
   ],
   "pantone_code": "19-0910 tcx",
   "fraction_pixels": 0.08259287971852823,
   "pantone_name": "mulch",
   "entrylevel_name": "black"
  }
 ],
 "time_ms": "10.74",
 "bounding_box": {
  "image_location": "/v1/catalog/sample_catalog/images/SHRES16AWFSDR9346B_1.jpg?top_left_x=83&top_left_y=0&width=107&height=365",
  "top_left_x": 83,
  "top_left_y": 0,
  "height": 365,
  "width": 107,
  "score": 0.800896
 },
 "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Look_Medium.jpg",
 "image_location": "/v1/catalog/sample_catalog/images/SHRES16AWFSDR9346B_1.jpg"
}

Get the dominant colors for an image in the catalog.

End point

GET /v1/catalog/{catalog_name}/dominant_colors/{id}/{image_id}

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
id path (Required) The product id.
image_id path (Required) The image id.
fraction_pixels_threshold query Include only those colors whos fraction of pixels is greater than this number. 0.0

Response

Parameter Description
time_ms The time taken in milliseconds.
computed_on The time the dominant colors where computed.
dominant_colors A list of dominant colors. Each field in the list has the following fieldnames.
rgb The RGB values for the color.
hsv The HSV values for the color.
hex The hex code for the color.
universal_name The best matching universal color name. Berlin and Kay, in a classic study of worldwide color naming, postulated the existence of 11 universal basic color terms across languages. We have included two more colors(olive and yellow green) as per the ISCC-NBS system.
entrylevel_name The best matching entry level color name. A slightly larger curated set of color names which we call entry level. A random person should be able to recognize these color names.
name The best guess for the color name based on all the colors avaialable in our color taxonomy.
bounding_box The region in the image used to compute the dominant colors and corresponds to the the bounding box for the central detected person.
top_left_x The x co-ordinate of the top left corner of the bounding box.
top_left_y The y co-ordinate of the top left corner of the bounding box.
width The width of the bounding box.
height The height of the bounding box.
score The confidence score (between 0 and 1) that the bounding box contains a person.

Color Trends

Analyze and forecast temporal color trends.

Build color trend report

#------------------------------------------------------------------------------
# Start computing the color trend report.
# POST /v1/color_trends/{report_name}/trend_report
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

params = {}

# Pass the catalog names as a comma separated list of names.
catalog_names = []
catalog_names.append('vogue-autumn-winter-2014')
catalog_names.append('vogue-autumn-winter-2015')
catalog_names.append('vogue-autumn-winter-2016')
catalog_names.append('vogue-autumn-winter-2017')
params['catalog_names'] = ','.join(catalog_names)

# Optional parameters.
params['colors'] = 10
params['max_colors_per_image'] = 2

report_name = 'vogue-autumn-winter'

api_endpoint = '/v1/color_trends/%s/trend_report'%(report_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.post(url,headers=headers,params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "status": {
  "dominant_colors": {
   "vogue-autumn-winter-2017": {
    "num_of_products": "2",
    "num_of_images_ignored": "0",
    "num_of_images_missing_colors": "0",
    "num_of_images": "90",
    "num_of_images_processed": "90"
   },
   "vogue-autumn-winter-2016": {
    "num_of_products": "2",
    "num_of_images_ignored": "0",
    "num_of_images_missing_colors": "0",
    "num_of_images": "80",
    "num_of_images_processed": "80"
   },
   "vogue-autumn-winter-2015": {
    "num_of_products": "2",
    "num_of_images_ignored": "0",
    "num_of_images_missing_colors": "0",
    "num_of_images": "100",
    "num_of_images_processed": "100"
   },
   "vogue-autumn-winter-2014": {
    "num_of_products": "2",
    "num_of_images_ignored": "0",
    "num_of_images_missing_colors": "0",
    "num_of_images": "85",
    "num_of_images_processed": "85"
   }
  },
  "status": "done",
  "start_time": "2017-11-27 10:07:01.804707",
  "finish_time": "2017-11-27 10:07:09.043789"
 },
 "time_ms": "6.24"
}

Start computing the color trend report.

This API does color trend analysis and forecasting. The input is a time ordered list of catalogs. This first loads all the dominant colors for every image in the catalog and then clusters the colors. Then for each cluster is computes a popularity score for the cluster for every catalog. Once we have the poularity scores for a color over multiple time points we then apply a regression model to forecast the popularity score for the next year/time point.

End point

POST /v1/color_trends/{report_name}/trend_report

Request

Parameter Type Description Default
report_name path (Required) The report name. Every trend analysis is refered by a unique report name.
catalog_names query (Required) A time ordered list of catalog names. Pass the catalog names as a comma separated list of names, for example, catalog_names=vogue-autumn-winter-2014,vogue-autumn-winter-2015,vogue-autumn-winter-2016,vogue-autumn-winter-2017. Note that these catalog have to be ingested and the color search index has to be computed for each of the catalog. It is important to pass the catalog names in the right time order.
colors query The number of clusters to use in the analysis. The poularity sscore is computed for every cluster. 10
max_colors_per_image query The maximum number of dominant colors to use per image. all available colors
fraction_pixels_threshold query Include only those colors whos fraction of pixels is greater than this number. 0.0

Response

Parameter Description
time_ms The time taken in milliseconds.
status A json containing various info about the current status.
status The current status of the trend analysis. The status can be one of retrieving dominant colors,clustering,trend forecasting or done. The analysis is when the status becomes done.
start_time The time when the trend analysis started.
finish_time The time when the trend analysis finished.
dominant_colors Info about retrieving dominant colors.
num_of_products The number of products in the catalog.
num_of_images The total number of images in the catalog.
num_of_images_missing_colors The number of images for which there was no dominant color was found.
num_of_images_ignored The number of images that were ignored.
num_of_images_processed The total number of images processed.

Get status of color trend report

#------------------------------------------------------------------------------
# Get the status of the color trend report.
# GET /v1/color_trends/{report_name}/trend_report
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

report_name = 'vogue-autumn-winter'

api_endpoint = '/v1/color_trends/%s/trend_report'%(report_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,headers=headers)

print response.status_code
pprint(response.json())

Sample json response

{
 "status": {
  "dominant_colors": {
   "vogue-autumn-winter-2017": {
    "num_of_products": "2",
    "num_of_images_ignored": "0",
    "num_of_images_missing_colors": "0",
    "num_of_images": "90",
    "num_of_images_processed": "90"
   },
   "vogue-autumn-winter-2016": {
    "num_of_products": "2",
    "num_of_images_ignored": "0",
    "num_of_images_missing_colors": "0",
    "num_of_images": "80",
    "num_of_images_processed": "80"
   },
   "vogue-autumn-winter-2015": {
    "num_of_products": "2",
    "num_of_images_ignored": "0",
    "num_of_images_missing_colors": "0",
    "num_of_images": "100",
    "num_of_images_processed": "100"
   },
   "vogue-autumn-winter-2014": {
    "num_of_products": "2",
    "num_of_images_ignored": "0",
    "num_of_images_missing_colors": "0",
    "num_of_images": "85",
    "num_of_images_processed": "85"
   }
  },
  "status": "done",
  "start_time": "2017-11-27 10:07:01.804707",
  "finish_time": "2017-11-27 10:07:09.043789"
 },
 "time_ms": "6.24"
}

Get the status of the color trend report.

End point

GET /v1/color_trends/{report_name}/trend_report

Request

Parameter Type Description Default
report_name path (Required) The report name. Every trend analysis is refered by a unique report name.

Response

Parameter Description
time_ms The time taken in milliseconds.
status A json containing various info about the current status.
status The current status of the trend analysis. The status can be one of retrieving dominant colors,clustering,trend forecasting or done. The analysis is when the status becomes done.
start_time The time when the trend analysis started.
finish_time The time when the trend analysis finished.
dominant_colors Info about retrieving dominant colors.
num_of_products The number of products in the catalog.
num_of_images The total number of images in the catalog.
num_of_images_missing_colors The number of images for which there was no dominant color was found.
num_of_images_ignored The number of images that were ignored.
num_of_images_processed The total number of images processed.

Delete color trend report

#------------------------------------------------------------------------------
# Delete the color trend report.
# DELETE /v1/color_trends/{report_name}/trend_report
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

report_name = 'vogue-autumn-winter'

api_endpoint = '/v1/color_trends/%s/trend_report'%(report_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.delete(url,headers=headers)

print response.status_code
pprint(response.json())

Sample json response

{
 "deleted": true,
 "time_ms": "134.87",
 "report_name": "vogue-autumn-winter"
}

Delete the color trend report.

End point

DELETE /v1/color_trends/{report_name}/trend_report

Request

Parameter Type Description Default
report_name path (Required) The report name. Every trend analysis is refered by a unique report name.

Response

Parameter Description
time_ms The time taken in milliseconds.
report_name The report name.
deleted Returns true is the report was successfully deleted.
#------------------------------------------------------------------------------
# Get the popular colors.
# GET /v1/color_trends/{report_name}/popular_colors
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

params = {}
params['colors'] = 5
# Optional
#params['catalog_name'] = 'vogue-autumn-winter-2017'

report_name = 'vogue-autumn-winter'

api_endpoint = '/v1/color_trends/%s/popular_colors'%(report_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,headers=headers,params=params)

print response.status_code
pprint(response.json())

# Print the colors.
results = response.json()
years = ['2013','2014','2015','2016','2017']
for color_info in results['colors']:
    print('popularity [%s] [%+1.2f] trend [%s] [%+1.2f] [%s]'%(
                          ' '.join(['%1.2f'%(color_info['popularity_by_id']['%s-%s'%(report_name,year)]) for year in years]),
                          color_info['popularity_forecast']['mean'],
                          ' '.join(['%+1.2f'%(color_info['trend_by_id']['%s-%s'%(report_name,year)]) for year in years]),
                          color_info['trend_forecast']['mean'],
                          color_info['pantone_id']))

Sample json response

{
 "computed_on": "2018-04-08 08:23:29.263227",
 "time_ms": "3.98",
 "colors": [
  {
   "trend_forecast": {
    "mean": 0.11846037510176805
   },
   "pantone_name": "jet black",
   "name": "jet",
   "pantone_rgb": [
    45,
    44,
    47
   ],
   "pantone_id": "pantone 19-0303 tcx jet black",
   "trend_by_id": {
    "vogue-autumn-winter-2013": 0.0,
    "vogue-autumn-winter-2017": 0.27372356393630976,
    "vogue-autumn-winter-2016": 0.08555227333057681,
    "vogue-autumn-winter-2015": 0.10808528033524438,
    "vogue-autumn-winter-2014": -0.045649819903448
   },
   "popularity": 0.12474437627811862,
   "hex": "#2e2d30",
   "universal_name": "black",
   "popularity_by_id_predicted": {
    "vogue-autumn-winter-2013": 0.10106382816649939,
    "vogue-autumn-winter-2017": 0.17857142615067614,
    "vogue-autumn-winter-2016": 0.12121212398756362,
    "vogue-autumn-winter-2015": 0.12999999648153948,
    "vogue-autumn-winter-2014": 0.09183673705739197
   },
   "popularity_percentile": 90.0,
   "rgb": [
    46,
    45,
    48
   ],
   "n_instances": 122,
   "lab": [
    18.67502318692506,
    1.1641448868809912,
    -1.7731775401694017
   ],
   "pantone_code": "19-0303 tcx",
   "total_instances_by_id": {
    "vogue-autumn-winter-2013": 188,
    "vogue-autumn-winter-2017": 196,
    "vogue-autumn-winter-2016": 198,
    "vogue-autumn-winter-2015": 200,
    "vogue-autumn-winter-2014": 196
   },
   "hsv": [
    259.99999999999994,
    0.06249999999999989,
    0.18823529411764706
   ],
   "n_instances_by_id": {
    "vogue-autumn-winter-2013": 19,
    "vogue-autumn-winter-2017": 35,
    "vogue-autumn-winter-2016": 24,
    "vogue-autumn-winter-2015": 26,
    "vogue-autumn-winter-2014": 18
   },
   "entrylevel_name": "black",
   "popularity_by_id": {
    "vogue-autumn-winter-2013": 0.10106382978723404,
    "vogue-autumn-winter-2017": 0.17857142857142858,
    "vogue-autumn-winter-2016": 0.12121212121212122,
    "vogue-autumn-winter-2015": 0.13,
    "vogue-autumn-winter-2014": 0.09183673469387756
   },
   "popularity_forecast": {
    "confidence_interval_lower_limit": 0.030499034528666535,
    "confidence_interval_upper_limit": 0.3087030731262529,
    "mean": 0.1696010538274597
   }
  },
  {
   "trend_forecast": {
    "mean": 0.32502210212075666
   },
   "pantone_name": "deep well",
   "name": "raisin black",
   "pantone_rgb": [
    44,
    42,
    51
   ],
   "pantone_id": "pantone 19-3713 tcx deep well",
   "trend_by_id": {
    "vogue-autumn-winter-2013": 0.0,
    "vogue-autumn-winter-2017": 0.015566962791144334,
    "vogue-autumn-winter-2016": -0.33375267885934234,
    "vogue-autumn-winter-2015": -0.26977967317365265,
    "vogue-autumn-winter-2014": -0.22423467190267088
   },
   "popularity": 0.1114519427402863,
   "hex": "#22202a",
   "universal_name": "black",
   "popularity_by_id_predicted": {
    "vogue-autumn-winter-2013": 0.21276595355640066,
    "vogue-autumn-winter-2017": 0.09693877266310735,
    "vogue-autumn-winter-2016": 0.060606066963965866,
    "vogue-autumn-winter-2015": 0.07499999163851878,
    "vogue-autumn-winter-2014": 0.11734694598084383
   },
   "popularity_percentile": 85.0,
   "rgb": [
    34,
    32,
    42
   ],
   "n_instances": 109,
   "lab": [
    12.86179904012861,
    3.5801169702007196,
    -6.343380699850043
   ],
   "pantone_code": "19-3713 tcx",
   "total_instances_by_id": {
    "vogue-autumn-winter-2013": 188,
    "vogue-autumn-winter-2017": 196,
    "vogue-autumn-winter-2016": 198,
    "vogue-autumn-winter-2015": 200,
    "vogue-autumn-winter-2014": 196
   },
   "hsv": [
    252.0,
    0.23809523809523814,
    0.16470588235294117
   ],
   "n_instances_by_id": {
    "vogue-autumn-winter-2013": 40,
    "vogue-autumn-winter-2017": 19,
    "vogue-autumn-winter-2016": 12,
    "vogue-autumn-winter-2015": 15,
    "vogue-autumn-winter-2014": 23
   },
   "entrylevel_name": "black",
   "popularity_by_id": {
    "vogue-autumn-winter-2013": 0.2127659574468085,
    "vogue-autumn-winter-2017": 0.09693877551020408,
    "vogue-autumn-winter-2016": 0.06060606060606061,
    "vogue-autumn-winter-2015": 0.075,
    "vogue-autumn-winter-2014": 0.11734693877551021
   },
   "popularity_forecast": {
    "confidence_interval_lower_limit": 0.0614139235353279,
    "confidence_interval_upper_limit": 0.24248830328589702,
    "mean": 0.15195111341061246
   }
  },
  {
   "trend_forecast": {
    "mean": 0.27244798323564934
   },
   "pantone_name": "black ink",
   "name": "black olive",
   "pantone_rgb": [
    68,
    65,
    60
   ],
   "pantone_id": "pantone 19-0506 tcx black ink",
   "trend_by_id": {
    "vogue-autumn-winter-2013": 0.0,
    "vogue-autumn-winter-2017": 0.34844147476010096,
    "vogue-autumn-winter-2016": 0.6817749099763932,
    "vogue-autumn-winter-2015": 0.8257142812078491,
    "vogue-autumn-winter-2014": 1.1785714478460592
   },
   "popularity": 0.065439672801636,
   "hex": "#444340",
   "universal_name": "black",
   "popularity_by_id_predicted": {
    "vogue-autumn-winter-2013": 0.02127659559146082,
    "vogue-autumn-winter-2017": 0.10714285332584271,
    "vogue-autumn-winter-2016": 0.04545454898588769,
    "vogue-autumn-winter-2015": 0.0799999966233297,
    "vogue-autumn-winter-2014": 0.07142857173438694
   },
   "popularity_percentile": 75.0,
   "rgb": [
    68,
    67,
    64
   ],
   "n_instances": 64,
   "lab": [
    28.415459788429516,
    -0.22870650807427229,
    1.9645499625216334
   ],
   "pantone_code": "19-0506 tcx",
   "total_instances_by_id": {
    "vogue-autumn-winter-2013": 188,
    "vogue-autumn-winter-2017": 196,
    "vogue-autumn-winter-2016": 198,
    "vogue-autumn-winter-2015": 200,
    "vogue-autumn-winter-2014": 196
   },
   "hsv": [
    45.00000000000006,
    0.05882352941176472,
    0.26666666666666666
   ],
   "n_instances_by_id": {
    "vogue-autumn-winter-2013": 4,
    "vogue-autumn-winter-2017": 21,
    "vogue-autumn-winter-2016": 9,
    "vogue-autumn-winter-2015": 16,
    "vogue-autumn-winter-2014": 14
   },
   "entrylevel_name": "black",
   "popularity_by_id": {
    "vogue-autumn-winter-2013": 0.02127659574468085,
    "vogue-autumn-winter-2017": 0.10714285714285714,
    "vogue-autumn-winter-2016": 0.045454545454545456,
    "vogue-autumn-winter-2015": 0.08,
    "vogue-autumn-winter-2014": 0.07142857142857142
   },
   "popularity_forecast": {
    "confidence_interval_lower_limit": -0.0005011718754029948,
    "confidence_interval_upper_limit": 0.19164819507100214,
    "mean": 0.09557351159779957
   }
  },
  {
   "trend_forecast": {
    "mean": 0.5309714246051445
   },
   "pantone_name": "heron",
   "name": "gray blue",
   "pantone_rgb": [
    98,
    97,
    126
   ],
   "pantone_id": "pantone 18-3817 tcx heron",
   "trend_by_id": {
    "vogue-autumn-winter-2013": 0.0,
    "vogue-autumn-winter-2017": 0.25516862766198656,
    "vogue-autumn-winter-2016": 0.008004838367361827,
    "vogue-autumn-winter-2015": 0.004636694980282223,
    "vogue-autumn-winter-2014": 0.1394553051314291
   },
   "popularity": 0.019427402862985686,
   "hex": "#5d607d",
   "universal_name": "gray",
   "popularity_by_id_predicted": {
    "vogue-autumn-winter-2013": 0.015957453050017,
    "vogue-autumn-winter-2017": 0.030612222082882584,
    "vogue-autumn-winter-2016": 0.015151550242968215,
    "vogue-autumn-winter-2015": 0.01499998395269847,
    "vogue-autumn-winter-2014": 0.02040815601843815
   },
   "popularity_percentile": 35.0,
   "rgb": [
    93,
    96,
    125
   ],
   "n_instances": 19,
   "lab": [
    41.49038321061422,
    5.772538816200379,
    -16.61053151124028
   ],
   "pantone_code": "18-3817 tcx",
   "total_instances_by_id": {
    "vogue-autumn-winter-2013": 188,
    "vogue-autumn-winter-2017": 196,
    "vogue-autumn-winter-2016": 198,
    "vogue-autumn-winter-2015": 200,
    "vogue-autumn-winter-2014": 196
   },
   "hsv": [
    234.375,
    0.256,
    0.49019607843137253
   ],
   "n_instances_by_id": {
    "vogue-autumn-winter-2013": 3,
    "vogue-autumn-winter-2017": 6,
    "vogue-autumn-winter-2016": 3,
    "vogue-autumn-winter-2015": 3,
    "vogue-autumn-winter-2014": 4
   },
   "entrylevel_name": "gray",
   "popularity_by_id": {
    "vogue-autumn-winter-2013": 0.015957446808510637,
    "vogue-autumn-winter-2017": 0.030612244897959183,
    "vogue-autumn-winter-2016": 0.015151515151515152,
    "vogue-autumn-winter-2015": 0.015,
    "vogue-autumn-winter-2014": 0.02040816326530612
   },
   "popularity_forecast": {
    "confidence_interval_lower_limit": 0.03869663665993158,
    "confidence_interval_upper_limit": 0.05696091646598237,
    "mean": 0.047828776562956976
   }
  },
  {
   "trend_forecast": {
    "mean": 0.0970617321776512
   },
   "pantone_name": "white sand",
   "name": "timberwolf",
   "pantone_rgb": [
    219,
    213,
    209
   ],
   "pantone_id": "pantone 13-0002 tcx white sand",
   "trend_by_id": {
    "vogue-autumn-winter-2013": 0.0,
    "vogue-autumn-winter-2017": 0.20115535841989507,
    "vogue-autumn-winter-2016": 0.07030295267334408,
    "vogue-autumn-winter-2015": -0.16875410705247687,
    "vogue-autumn-winter-2014": -0.16146461244093568
   },
   "popularity": 0.07566462167689161,
   "hex": "#d7d1d0",
   "universal_name": "white",
   "popularity_by_id_predicted": {
    "vogue-autumn-winter-2013": 0.09042553119131298,
    "vogue-autumn-winter-2017": 0.09183673675117678,
    "vogue-autumn-winter-2016": 0.08585857644650922,
    "vogue-autumn-winter-2015": 0.050000010183979496,
    "vogue-autumn-winter-2014": 0.0612244844941708
   },
   "popularity_percentile": 80.0,
   "rgb": [
    215,
    209,
    208
   ],
   "n_instances": 74,
   "lab": [
    84.27837486243521,
    1.8817398220458137,
    1.2191511354760154
   ],
   "pantone_code": "13-0002 tcx",
   "total_instances_by_id": {
    "vogue-autumn-winter-2013": 188,
    "vogue-autumn-winter-2017": 196,
    "vogue-autumn-winter-2016": 198,
    "vogue-autumn-winter-2015": 200,
    "vogue-autumn-winter-2014": 196
   },
   "hsv": [
    8.571428571428555,
    0.032558139534883734,
    0.8431372549019608
   ],
   "n_instances_by_id": {
    "vogue-autumn-winter-2013": 17,
    "vogue-autumn-winter-2017": 18,
    "vogue-autumn-winter-2016": 17,
    "vogue-autumn-winter-2015": 10,
    "vogue-autumn-winter-2014": 12
   },
   "entrylevel_name": "silver",
   "popularity_by_id": {
    "vogue-autumn-winter-2013": 0.09042553191489362,
    "vogue-autumn-winter-2017": 0.09183673469387756,
    "vogue-autumn-winter-2016": 0.08585858585858586,
    "vogue-autumn-winter-2015": 0.05,
    "vogue-autumn-winter-2014": 0.061224489795918366
   },
   "popularity_forecast": {
    "confidence_interval_lower_limit": 0.0027438964207623234,
    "confidence_interval_upper_limit": 0.08989843677661184,
    "mean": 0.04632116659868708
   }
  }
 ]
}

Get the forecast for the popular colors for the next year.

End point

GET /v1/color_trends/{report_name}/popular_colors

Request

Parameter Type Description Default
report_name path (Required) The report name.
colors query The number of colors. 10
catalog_name query You can optionally specify the catalog name if you want the results from the previous years.

Response

Parameter Description
time_ms The time taken in milliseconds.
computed_on The time the trend analysis report where computed.
colors An ordered list of polular colors. Each field in the list has the following fieldnames.
rgb The RGB values for the color.
hsv The HSV values for the color.
lab The LAB values for the color.
hex The hex code for the color.
universal_name The best matching universal color name. Berlin and Kay, in a classic study of worldwide color naming, postulated the existence of 11 universal basic color terms across languages. We have included two more colors(olive and yellow green) as per the ISCC-NBS system.
entrylevel_name The best matching entry level color name. A slightly larger curated set of color names which we call entry level. A random person should be able to recognize these color names.
name The best guess for the color name based on all the colors avaialable in our color taxonomy.
popularity A score between 0 and 1 indicating the popularity of the color.
popularity_percentile The corresponding percentile score.
n_instances The number of colors in the cluster.
n_instances_by_id The number of colors in the cluster stratified by the catalog name.
total_instances_by_id The total number of colors stratified by the catalog name.
popularity_by_id The popularity score for the color stratified by the catalog name.
popularity_by_id_predicted The predicted popularity score for the color stratified by the catalog name.
popularity_forecast The popularity score forecast (mean and 95% confidence interval) for the color for the next season. The colors are sorted by this value.
trend_forecast The trend score forecast (mean) for the color for the next season.
#------------------------------------------------------------------------------
# Get the trending colors.
# GET /v1/color_trends/{report_name}/trending_colors
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

params = {}
params['colors'] = 5
# Optional
#params['catalog_name'] = 'vogue-autumn-winter-2017'

report_name = 'vogue-autumn-winter'

api_endpoint = '/v1/color_trends/%s/trending_colors'%(report_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,headers=headers,params=params)

print response.status_code
pprint(response.json())

# Print the colors.
results = response.json()
years = ['2013','2014','2015','2016','2017']
for color_info in results['colors']:
    print('popularity [%s] [%+1.2f] trend [%s] [%+1.2f] [%s]'%(
                          ' '.join(['%1.2f'%(color_info['popularity_by_id']['%s-%s'%(report_name,year)]) for year in years]),
                          color_info['popularity_forecast']['mean'],
                          ' '.join(['%+1.2f'%(color_info['trend_by_id']['%s-%s'%(report_name,year)]) for year in years]),
                          color_info['trend_forecast']['mean'],
                          color_info['pantone_id']))

Sample json response

{
 "computed_on": "2018-04-08 08:23:29.263227",
 "time_ms": "3.45",
 "colors": [
  {
   "trend_forecast": {
    "mean": 8.235715230566532
   },
   "pantone_name": "olivenite",
   "name": "aztec gold",
   "pantone_rgb": [
    193,
    166,
    92
   ],
   "pantone_id": "pantone 15-0732 tcx olivenite",
   "trend_by_id": {
    "vogue-autumn-winter-2013": 0.0,
    "vogue-autumn-winter-2017": 7.976730869261527,
    "vogue-autumn-winter-2016": 0.25904713834398163,
    "vogue-autumn-winter-2015": 0.5923803456031483,
    "vogue-autumn-winter-2014": 1.1785704702543323
   },
   "popularity": 0.017382413087934562,
   "hex": "#bc9f52",
   "universal_name": "olive",
   "popularity_by_id_predicted": {
    "vogue-autumn-winter-2013": 0.010638301716580001,
    "vogue-autumn-winter-2017": 0.02551019780659891,
    "vogue-autumn-winter-2016": 5.673337612199791e-09,
    "vogue-autumn-winter-2015": 0.01500000029600288,
    "vogue-autumn-winter-2014": 0.03571427823021432
   },
   "popularity_percentile": 27.500000000000004,
   "rgb": [
    188,
    159,
    82
   ],
   "n_instances": 17,
   "lab": [
    66.59479318367542,
    1.2071716907996466,
    43.61008842556798
   ],
   "pantone_code": "15-0732 tcx",
   "total_instances_by_id": {
    "vogue-autumn-winter-2013": 188,
    "vogue-autumn-winter-2017": 196,
    "vogue-autumn-winter-2016": 198,
    "vogue-autumn-winter-2015": 200,
    "vogue-autumn-winter-2014": 196
   },
   "hsv": [
    43.58490566037733,
    0.5638297872340425,
    0.7372549019607844
   ],
   "n_instances_by_id": {
    "vogue-autumn-winter-2013": 2,
    "vogue-autumn-winter-2017": 5,
    "vogue-autumn-winter-2016": 0,
    "vogue-autumn-winter-2015": 3,
    "vogue-autumn-winter-2014": 7
   },
   "entrylevel_name": "tan",
   "popularity_by_id": {
    "vogue-autumn-winter-2013": 0.010638297872340425,
    "vogue-autumn-winter-2017": 0.025510204081632654,
    "vogue-autumn-winter-2016": 0.0,
    "vogue-autumn-winter-2015": 0.015,
    "vogue-autumn-winter-2014": 0.03571428571428571
   },
   "popularity_forecast": {
    "confidence_interval_lower_limit": -0.0054111940580404486,
    "confidence_interval_upper_limit": 0.06648021884312591,
    "mean": 0.030534512392542727
   }
  },
  {
   "trend_forecast": {
    "mean": 7.571549001664395
   },
   "pantone_name": "carmine",
   "name": "carmine",
   "pantone_rgb": [
    188,
    72,
    105
   ],
   "pantone_id": "pantone 17-1831 tcx carmine",
   "trend_by_id": {
    "vogue-autumn-winter-2013": 0.0,
    "vogue-autumn-winter-2017": 8.218867318426964,
    "vogue-autumn-winter-2016": 8.084173058429286,
    "vogue-autumn-winter-2015": -0.33332935240964134,
    "vogue-autumn-winter-2014": -0.5000004190614799
   },
   "popularity": 0.0081799591002045,
   "hex": "#b94668",
   "universal_name": "purple",
   "popularity_by_id_predicted": {
    "vogue-autumn-winter-2013": 0.005319150011365242,
    "vogue-autumn-winter-2017": 0.010204085522693439,
    "vogue-autumn-winter-2016": 0.02525251555530907,
    "vogue-autumn-winter-2015": 8.322792285214708e-09,
    "vogue-autumn-winter-2014": -4.458101750498371e-09
   },
   "popularity_percentile": 10.0,
   "rgb": [
    185,
    70,
    104
   ],
   "n_instances": 8,
   "lab": [
    46.573551824894544,
    49.345973558034494,
    4.994866094189598
   ],
   "pantone_code": "17-1831 tcx",
   "total_instances_by_id": {
    "vogue-autumn-winter-2013": 188,
    "vogue-autumn-winter-2017": 196,
    "vogue-autumn-winter-2016": 198,
    "vogue-autumn-winter-2015": 200,
    "vogue-autumn-winter-2014": 196
   },
   "hsv": [
    342.2608695652174,
    0.6216216216216216,
    0.7254901960784313
   ],
   "n_instances_by_id": {
    "vogue-autumn-winter-2013": 1,
    "vogue-autumn-winter-2017": 2,
    "vogue-autumn-winter-2016": 5,
    "vogue-autumn-winter-2015": 0,
    "vogue-autumn-winter-2014": 0
   },
   "entrylevel_name": "maroon",
   "popularity_by_id": {
    "vogue-autumn-winter-2013": 0.005319148936170213,
    "vogue-autumn-winter-2017": 0.01020408163265306,
    "vogue-autumn-winter-2016": 0.025252525252525252,
    "vogue-autumn-winter-2015": 0.0,
    "vogue-autumn-winter-2014": 0.0
   },
   "popularity_forecast": {
    "confidence_interval_lower_limit": -0.049635410157543226,
    "confidence_interval_upper_limit": 0.030412093249694426,
    "mean": -0.0096116584539244
   }
  },
  {
   "trend_forecast": {
    "mean": 2.9002808043760666
   },
   "pantone_name": "burgundy",
   "name": "burgundy",
   "pantone_rgb": [
    100,
    49,
    62
   ],
   "pantone_id": "pantone 19-1617 tcx burgundy",
   "trend_by_id": {
    "vogue-autumn-winter-2013": 0.0,
    "vogue-autumn-winter-2017": -0.49456702511890355,
    "vogue-autumn-winter-2016": 1.1040734357100044,
    "vogue-autumn-winter-2015": 1.3893066120901132,
    "vogue-autumn-winter-2014": 1.8979602872913048
   },
   "popularity": 0.014314928425357873,
   "hex": "#5f323d",
   "universal_name": "purple",
   "popularity_by_id_predicted": {
    "vogue-autumn-winter-2013": 0.005319147493313,
    "vogue-autumn-winter-2017": -4.080331614253474e-09,
    "vogue-autumn-winter-2016": 0.005050514716681838,
    "vogue-autumn-winter-2015": 0.03499998777961907,
    "vogue-autumn-winter-2014": 0.025510208902419326
   },
   "popularity_percentile": 17.5,
   "rgb": [
    95,
    50,
    61
   ],
   "n_instances": 14,
   "lab": [
    26.880879480444015,
    21.737230131132435,
    2.138083288990311
   ],
   "pantone_code": "19-1617 tcx",
   "total_instances_by_id": {
    "vogue-autumn-winter-2013": 188,
    "vogue-autumn-winter-2017": 196,
    "vogue-autumn-winter-2016": 198,
    "vogue-autumn-winter-2015": 200,
    "vogue-autumn-winter-2014": 196
   },
   "hsv": [
    345.3333333333333,
    0.4736842105263158,
    0.37254901960784315
   ],
   "n_instances_by_id": {
    "vogue-autumn-winter-2013": 1,
    "vogue-autumn-winter-2017": 0,
    "vogue-autumn-winter-2016": 1,
    "vogue-autumn-winter-2015": 7,
    "vogue-autumn-winter-2014": 5
   },
   "entrylevel_name": "maroon",
   "popularity_by_id": {
    "vogue-autumn-winter-2013": 0.005319148936170213,
    "vogue-autumn-winter-2017": 0.0,
    "vogue-autumn-winter-2016": 0.005050505050505051,
    "vogue-autumn-winter-2015": 0.035,
    "vogue-autumn-winter-2014": 0.025510204081632654
   },
   "popularity_forecast": {
    "confidence_interval_lower_limit": -0.025658486147475734,
    "confidence_interval_upper_limit": 0.04677156348715779,
    "mean": 0.010556538669841027
   }
  },
  {
   "trend_forecast": {
    "mean": 1.8642376911307246
   },
   "pantone_name": "valiant poppy",
   "name": "firebrick",
   "pantone_rgb": [
    188,
    50,
    44
   ],
   "pantone_id": "pantone 18-1549 tcx valiant poppy",
   "trend_by_id": {
    "vogue-autumn-winter-2013": 0.0,
    "vogue-autumn-winter-2017": 3.693773482978249,
    "vogue-autumn-winter-2016": 2.010100475412465,
    "vogue-autumn-winter-2015": 1.3333322551535562,
    "vogue-autumn-winter-2014": -0.4999999533767581
   },
   "popularity": 0.022494887525562373,
   "hex": "#be1f24",
   "universal_name": "red",
   "popularity_by_id_predicted": {
    "vogue-autumn-winter-2013": 0.015957445073912335,
    "vogue-autumn-winter-2017": 0.07653060568321701,
    "vogue-autumn-winter-2016": 0.015151517728698292,
    "vogue-autumn-winter-2015": 0.004999998160189827,
    "vogue-autumn-winter-2014": 1.4879756417621442e-09
   },
   "popularity_percentile": 40.0,
   "rgb": [
    190,
    31,
    36
   ],
   "n_instances": 22,
   "lab": [
    41.30704144641319,
    60.19009061985351,
    39.52332046616106
   ],
   "pantone_code": "18-1549 tcx",
   "total_instances_by_id": {
    "vogue-autumn-winter-2013": 188,
    "vogue-autumn-winter-2017": 196,
    "vogue-autumn-winter-2016": 198,
    "vogue-autumn-winter-2015": 200,
    "vogue-autumn-winter-2014": 196
   },
   "hsv": [
    358.1132075471698,
    0.8368421052631578,
    0.7450980392156863
   ],
   "n_instances_by_id": {
    "vogue-autumn-winter-2013": 3,
    "vogue-autumn-winter-2017": 15,
    "vogue-autumn-winter-2016": 3,
    "vogue-autumn-winter-2015": 1,
    "vogue-autumn-winter-2014": 0
   },
   "entrylevel_name": "red",
   "popularity_by_id": {
    "vogue-autumn-winter-2013": 0.015957446808510637,
    "vogue-autumn-winter-2017": 0.07653061224489796,
    "vogue-autumn-winter-2016": 0.015151515151515152,
    "vogue-autumn-winter-2015": 0.005,
    "vogue-autumn-winter-2014": 0.0
   },
   "popularity_forecast": {
    "confidence_interval_lower_limit": -0.024902090520356926,
    "confidence_interval_upper_limit": 0.10317595574874246,
    "mean": 0.039136932614192765
   }
  },
  {
   "trend_forecast": {
    "mean": 0.7906371620551244
   },
   "pantone_name": "astral aura",
   "name": "grape",
   "pantone_rgb": [
    54,
    49,
    81
   ],
   "pantone_id": "pantone 19-3830 tcx astral aura",
   "trend_by_id": {
    "vogue-autumn-winter-2013": 0.0,
    "vogue-autumn-winter-2017": 0.668688540385415,
    "vogue-autumn-winter-2016": 0.20100251734269106,
    "vogue-autumn-winter-2015": 0.45016069962896715,
    "vogue-autumn-winter-2014": 0.818877437721917
   },
   "popularity": 0.03374233128834356,
   "hex": "#322e4b",
   "universal_name": "black",
   "popularity_by_id_predicted": {
    "vogue-autumn-winter-2013": 0.02127659660718742,
    "vogue-autumn-winter-2017": 0.0408163201213404,
    "vogue-autumn-winter-2016": 0.010101016968916778,
    "vogue-autumn-winter-2015": 0.03999999541935249,
    "vogue-autumn-winter-2014": 0.05612244643346036
   },
   "popularity_percentile": 55.00000000000001,
   "rgb": [
    50,
    46,
    75
   ],
   "n_instances": 33,
   "lab": [
    20.596319430718573,
    9.582459495460604,
    -17.306983424884383
   ],
   "pantone_code": "19-3830 tcx",
   "total_instances_by_id": {
    "vogue-autumn-winter-2013": 188,
    "vogue-autumn-winter-2017": 196,
    "vogue-autumn-winter-2016": 198,
    "vogue-autumn-winter-2015": 200,
    "vogue-autumn-winter-2014": 196
   },
   "hsv": [
    248.27586206896552,
    0.3866666666666667,
    0.29411764705882354
   ],
   "n_instances_by_id": {
    "vogue-autumn-winter-2013": 4,
    "vogue-autumn-winter-2017": 8,
    "vogue-autumn-winter-2016": 2,
    "vogue-autumn-winter-2015": 8,
    "vogue-autumn-winter-2014": 11
   },
   "entrylevel_name": "navy blue",
   "popularity_by_id": {
    "vogue-autumn-winter-2013": 0.02127659574468085,
    "vogue-autumn-winter-2017": 0.04081632653061224,
    "vogue-autumn-winter-2016": 0.010101010101010102,
    "vogue-autumn-winter-2015": 0.04,
    "vogue-autumn-winter-2014": 0.05612244897959184
   },
   "popularity_forecast": {
    "confidence_interval_lower_limit": -0.004410300375401743,
    "confidence_interval_upper_limit": 0.09245706928045698,
    "mean": 0.04402338445252762
   }
  }
 ]
}

Get the forecast for the trending colors for the next year.

This reflects the color which had the maximum increase in popularity over the past three years. These are the colors which may not be that popular but there is sharp increase in its popularity compared to the last few years.

End point

GET /v1/color_trends/{report_name}/trending_colors

Request

Parameter Type Description Default
report_name path (Required) The report name.
colors query The number of colors. 10
catalog_name query You can optionally specify the catalog name if you want the results from the previous years.

Response

Parameter Description
time_ms The time taken in milliseconds.
computed_on The time the trend analysis report where computed.
colors An ordered list of polular colors. Each field in the list has the following fieldnames.
rgb The RGB values for the color.
hsv The HSV values for the color.
lab The LAB values for the color.
hex The hex code for the color.
universal_name The best matching universal color name. Berlin and Kay, in a classic study of worldwide color naming, postulated the existence of 11 universal basic color terms across languages. We have included two more colors(olive and yellow green) as per the ISCC-NBS system.
entrylevel_name The best matching entry level color name. A slightly larger curated set of color names which we call entry level. A random person should be able to recognize these color names.
name The best guess for the color name based on all the colors avaialable in our color taxonomy.
popularity A score between 0 and 1 indicating the popularity of the color.
popularity_percentile The corresponding percentile score.
n_instances The number of colors in the cluster.
n_instances_by_id The number of colors in the cluster stratified by the catalog name.
total_instances_by_id The total number of colors stratified by the catalog name.
popularity_by_id The popularity score for the color stratified by the catalog name.
popularity_by_id_predicted The predicted popularity score for the color stratified by the catalog name.
popularity_forecast The popularity score forecast (mean and 95% confidence interval) for the color for the next season.
trend_forecast The trend score forecast (mean) for the color for the next season. The colors are sorted by this value.

Get trend report by RGB

#------------------------------------------------------------------------------
# Get the color trend graph by RGB value.
# GET /v1/color_trends/{report_name}/trend_graph
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

params = {}
params['r'] = 188
params['g'] = 89
params['b'] = 84

report_name = 'vogue-autumn-winter'

api_endpoint = '/v1/color_trends/%s/trend_graph'%(report_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,headers=headers,params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "computed_on": "2017-11-27 10:37:36.358990",
 "time_ms": "36.29",
 "distance": 4.14258845017703,
 "trend_graph": {
  "trend_forecast": {
   "mean": 18452119.817761216
  },
  "name": "indian red",
  "popularity": 0.01971830985915493,
  "hex": "#c46463",
  "universal_name": "red",
  "lab": [
   53.76430408872871,
   38.108463259306944,
   18.279605679684895
  ],
  "popularity_percentile": 10.0,
  "rgb": [
   196,
   100,
   99
  ],
  "hsv": [
   0.6185567010309114,
   0.4948979591836735,
   0.7686274509803922
  ],
  "n_instances_by_id": {
   "vogue-autumn-winter-2017": 5,
   "vogue-autumn-winter-2016": 0,
   "vogue-autumn-winter-2015": 8,
   "vogue-autumn-winter-2014": 1
  },
  "popularity_by_id_predicted": {
   "vogue-autumn-winter-2017": 0.02777777496324953,
   "vogue-autumn-winter-2016": 5.017991386996323e-10,
   "vogue-autumn-winter-2015": 0.03999999598475976,
   "vogue-autumn-winter-2014": 0.005882352647930724
  },
  "n_instances": 14,
  "total_instances_by_id": {
   "vogue-autumn-winter-2017": 180,
   "vogue-autumn-winter-2016": 160,
   "vogue-autumn-winter-2015": 200,
   "vogue-autumn-winter-2014": 170
  },
  "entrylevel_name": "tomato",
  "popularity_by_id": {
   "vogue-autumn-winter-2017": 0.027777777777777776,
   "vogue-autumn-winter-2016": 0.0,
   "vogue-autumn-winter-2015": 0.04,
   "vogue-autumn-winter-2014": 0.0058823529411764705
  },
  "popularity_forecast": {
   "confidence_interval_lower_limit": -0.05974450566166774,
   "confidence_interval_upper_limit": 0.06387994327947344,
   "mean": 0.0020677188089028493
  }
 }
}

Get the color trend graph by RGB value.

This retrieves the trend report for a particular color by RGB value.

End point

GET /v1/color_trends/{report_name}/trend_graph

Request

Parameter Type Description Default
r query (Required) The value for the red channel in the RGB color model (in the range 0 to 255).
g query (Required) The value for the green channel in the RGB color model (in the range 0 to 255).
b query (Required) The value for the blue channel in the RGB color model (in the range 0 to 255).

Response

Parameter Description
time_ms The time taken in milliseconds.
computed_on The time the trend analysis report where computed.
distance The distance between the RGB value and the closest cluster center in the trend analysis.
trend_graph Each field has the following fieldnames.
rgb The RGB values for the color.
hsv The HSV values for the color.
lab The LAB values for the color.
hex The hex code for the color.
universal_name The best matching universal color name. Berlin and Kay, in a classic study of worldwide color naming, postulated the existence of 11 universal basic color terms across languages. We have included two more colors(olive and yellow green) as per the ISCC-NBS system.
entrylevel_name The best matching entry level color name. A slightly larger curated set of color names which we call entry level. A random person should be able to recognize these color names.
name The best guess for the color name based on all the colors avaialable in our color taxonomy.
popularity A score between 0 and 1 indicating the popularity of the color.
popularity_percentile The corresponding percentile score.
n_instances The number of colors in the cluster.
n_instances_by_id The number of colors in the cluster stratified by the catalog name.
total_instances_by_id The total number of colors stratified by the catalog name.
popularity_by_id The popularity score for the color stratified by the catalog name.
popularity_by_id_predicted The predicted popularity score for the color stratified by the catalog name.
popularity_forecast The popularity score forecast (mean and 95% confidence interval) for the color for the next season.
trend_forecast The trend score forecast (mean) for the color for the next season. The colors are sorted by this value.

Print Search

A collection of APIs for enabling catalog search based on prints.

Build print search index

#------------------------------------------------------------------------------
# Build the print search index.
# POST /v1/catalog/{catalog_name}/print_search_index
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header.
headers = {'X-Api-Key': props['X-Api-Key']}

# Query paarameters.
params = {}
# Optional parameters.
params['print_count'] = 3
#params['image_max_dimension'] = 512
params['ignore_background'] = 'true'
params['model'] = 'person_fast'
params['fraction_boxes_threshold'] = 0.1
#params['ignore_images_without_person'] = 'true'

# Path paarameters.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/print_search_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.post(url,headers=headers,params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "status": {
  "status": "done",
  "finish_time": "2018-03-25 17:21:50.924603",
  "start_time": "2018-03-25 17:20:05.733959",
  "pid": "139",
  "print_search_index": {
   "num_of_images_missing_prints": "0",
   "num_of_images_indexed": "28",
   "num_of_images_ignored": "10"
  },
  "index_updated": "true",
  "print_computation": {
   "num_of_images_ignored": "10",
   "num_of_images_existing": "0",
   "num_of_images_error": "0",
   "num_of_images_processed": "28"
  },
  "num_of_products": "8",
  "num_of_images": "38"
 },
 "time_ms": "15.24"
}

Build the print search index.

Before you can start using the print search or dominant prints APIs the print search index has to be built. This API pre-computes the dominant prints for all the uploaded images in the catalog and then builds an index for fast nearest neighbor retrieval. A dominant print is a representative 64x64 print swatch that occurs most frequently in the image.

End point

POST /v1/catalog/{catalog_name}/print_search_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
print_count query The number of dominant prints to extract per image. 3
image_max_dimension query You can set this parameters to resize the image for faster computation of dominant prints. If your images are of very high resolution you can set this parameter to a smaller value (suggested values 256-512) for faster computation. For any image if max(image width,image height) > image_max_dimension resizes the image such that max(image width,image height) = image_max_dimension. no image resizing
ignore_background query By default we use the entire image to compute the dominant prints. If we set this parameter to true we internally use some algorithms to ignore the background and mainly focus on the person or apparel. false
model query The model to use to ignore the background. Currently we use person detecors to focus only on the person. The following options are supported person_fast (faster but slightly less accurate model), person_accurate (slower but more accurate model) and person_basic (a basic person detector using standard body proportions). person_fast
fraction_boxes_threshold query Include only those prints whos fraction of boxes is greater than this number. 0.0
ignore_images_without_person query If true ignore images where person is not detected. If false and person is not detected then defaults to ‘person_basic’ false

Response

Parameter Description
time_ms The time taken in milliseconds.
status A json containing various info about the current status of the index building process.
status The current status of the index building process. The status can be one of computing_dominant_prints,building_index,or done. The index is built when the status becomes done.
num_of_products The number of products in the catalog.
num_of_images The total number of images in the catalog.
start_time The time when the index building started.
finish_time The time when the index building finished.
print_computation Info about dominant print computation.
num_of_images_error The number of images for which there was some error in dominant print computation.
num_of_images_ignored The number of images that were ignored.
num_of_images_existing The number of images for which the dominant prints were already computed (in case of building a new index with new products added).
num_of_images_processed The total number of images for which the dominant prints were computed.
print_search_index Info about the index building.
num_of_images_missing_prints The number of images for which there was no dominant print was found.
num_of_images_ignored The number of images that were ignored.
num_of_images_indexed The total number of images finally indexed.

Get print search index status

#------------------------------------------------------------------------------
# Get the status of the print search index.
# GET /v1/catalog/{catalog_name}/print_search_index
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/print_search_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,headers=headers)

print response.status_code
pprint(response.json())

Sample json response

{
 "status": {
  "status": "computing_dominant_prints",
  "num_of_products": "8",
  "start_time": "2018-03-25 17:20:05.733959",
  "pid": "139",
  "print_search_index": {
   "num_of_images_missing_prints": "0",
   "num_of_images_indexed": "0",
   "num_of_images_ignored": "0"
  },
  "finish_time": "0",
  "print_computation": {
   "num_of_images_error": "0",
   "num_of_images_ignored": "1",
   "num_of_images_existing": "0",
   "num_of_images_processed": "5"
  },
  "num_of_images": "38"
 },
 "time_ms": "8.30"
}

Get the status of the print search index.

End point

GET /v1/catalog/{catalog_name}/print_search_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.

Response

Parameter Description
time_ms The time taken in milliseconds.
status A json containing various info about the current status of the index building process.
status The current status of the index building process. The status can be one of computing_dominant_prints,building_index,or done. The index is built when the status becomes done.
num_of_products The number of products in the catalog.
num_of_images The total number of images in the catalog.
start_time The time when the index building started.
finish_time The time when the index building finished.
print_computation Info about dominant print computation.
num_of_images_error The number of images for which there was some error in dominant print computation.
num_of_images_ignored The number of images that were ignored.
num_of_images_existing The number of images for which the dominant prints were already computed (in case of building a new index with new products added).
num_of_images_processed The total number of images for which the dominant prints were computed.
print_search_index Info about the index building.
num_of_images_missing_prints The number of images for which there was no dominant print was found.
num_of_images_ignored The number of images that were ignored.
num_of_images_indexed The total number of images finally indexed.

Delete the print search index

#------------------------------------------------------------------------------
# Delete the print search index.
# DELETE /v1/catalog/{catalog_name}/print_search_index
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/print_search_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.delete(url,headers=headers)

print response.status_code
pprint(response.json())

Sample json response

{
 "deleted": true,
 "time_ms": "8.88",
 "catalog_name": "sample_catalog"
}

Delete the print search index.

End point

DELETE /v1/catalog/{catalog_name}/print_search_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.

Response

Parameter Description
time_ms The time taken in milliseconds.
catalog_name The catalog name.
deleted This is true if the index was successfully deleted.
http://localhost:9080/v1/catalog/sample_catalog/print_search?max_number_of_results=3&image_id=1&id=SHRES16AWFSDR9346A&print_count=1&print_id=1&api_key=your_api_key
#------------------------------------------------------------------------------ 
# Get similar image/print swatches in the catalog for an existing image/print swatch.
# GET /v1/catalog/{catalog_name}/print_search
# params - id,image_id,print_id,print_count,max_number_of_results
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Parameters.
params = {}
params['id'] = 'SHRES16AWFSDR9346A' 
params['image_id'] = '1'
params['print_id'] = '1'
params['print_count'] = 1
params['max_number_of_results'] = 3

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/print_search'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,
                        headers=headers,
                        params=params)


print response.status_code
pprint(response.json())

Sample json response

{
 "time_ms": "17.92",
 "products": [
  {
   "distance": 0.0,
   "image_location": "/v1/catalog/sample_catalog/images/SHRES16AWFSDR9346A_1.jpg?top_left_x=97&top_left_y=169&width=64&height=64",
   "image_id": "1",
   "bounding_box": {
    "width": 64,
    "top_left_x": 97,
    "top_left_y": 169,
    "height": 64
   },
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346A54/Look_Medium.jpg",
   "print_id": "1",
   "id": "SHRES16AWFSDR9346A",
   "image_filename": "SHRES16AWFSDR9346A_1.jpg"
  },
  {
   "distance": 0.023897528648376465,
   "image_location": "/v1/catalog/sample_catalog/images/SHRES16AWFSDR9346B_4.jpg?top_left_x=129&top_left_y=205&width=54&height=54",
   "image_id": "4",
   "bounding_box": {
    "width": 54,
    "top_left_x": 129,
    "top_left_y": 205,
    "height": 54
   },
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Right_Medium.jpg",
   "print_id": "2",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_4.jpg"
  },
  {
   "distance": 0.024179430678486824,
   "image_location": "/v1/catalog/sample_catalog/images/SHRES16AWFSDR9346B_2.jpg?top_left_x=115&top_left_y=191&width=45&height=45",
   "image_id": "2",
   "bounding_box": {
    "width": 45,
    "top_left_x": 115,
    "top_left_y": 191,
    "height": 45
   },
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Left_Medium.jpg",
   "print_id": "2",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_2.jpg"
  }
 ]
}

Get similar image/print swatches in the catalog for an existing image/print swatch.

End point

GET /v1/catalog/{catalog_name}/print_search

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
id query (Required) The product id.
image_id query (Required) The image id.
print_id query The print id. Searches for print_count number of prints in the image.
print_count query The maximum number of dominant prints to search for in an image. 1
max_number_of_results query maximum number of results to return. 12

Response

Parameter Description
time_ms The time taken in milliseconds.
products A sorted list similar print images. Each item in the list has the following fields.
id The product id.
image_id The image id.
print_id The print id.
image_filename The image filename.
image_url The image url.
distance The euclidean distance between the print in the image to the print in the query.
image_location The resource location of the dominant print swatch.
bounding_box The bounding box of the dominant print in the image.
top_left_x The x co-ordinate of the top left corner of the bounding box.
top_left_y The y co-ordinate of the top left corner of the bounding box.
width The width of the bounding box.
height The height of the bounding box.
#------------------------------------------------------------------------------
# Get similar image/print swatches in the catalog for a user uploaded image.
# POST /v1/catalog/{catalog_name}/print_search
# params - print_count,image_max_dimension,max_number_of_results
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Parameters.
params = {}
params['print_count'] =  1
params['max_number_of_results'] = 3
#params['image_max_dimension'] = 512

headers['Content-Type'] = 'image/jpeg'

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/print_search'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.post(url,
                        headers=headers,
                        params=params,
                        data=open('test_image_1.jpeg','rb'))

print response.status_code
pprint(response.json())

Sample json response

{
 "time_ms": "245.13",
 "products": [
  {
   "distance": 0.3300967216491699,
   "image_location": "/v1/images/94571cf2-f376-4325-9305-c4973df05e38.jpe?top_left_x=116&top_left_y=272&width=64&height=64",
   "image_id": "5",
   "bounding_box": {
    "width": 64,
    "top_left_x": 116,
    "top_left_y": 272,
    "height": 64
   },
   "image_url": "http://images.abofcdn.com/catalog/images/2015/ABOFA15AMCWJG1044801/Front_Medium.jpg",
   "print_id": "3",
   "id": "ABOFA15AMCWJG10448",
   "image_filename": "ABOFA15AMCWJG10448_5.jpg"
  },
  {
   "distance": 0.33134496212005615,
   "image_location": "/v1/images/94571cf2-f376-4325-9305-c4973df05e38.jpe?top_left_x=118&top_left_y=264&width=64&height=64",
   "image_id": "2",
   "bounding_box": {
    "width": 64,
    "top_left_x": 118,
    "top_left_y": 264,
    "height": 64
   },
   "image_url": "http://images.abofcdn.com/catalog/images/2015/ABOFA15AMCWJG1044901/Front_Medium.jpg",
   "print_id": "1",
   "id": "ABOFA15AMCWJG10449",
   "image_filename": "ABOFA15AMCWJG10449_2.jpg"
  },
  {
   "distance": 0.3329866826534271,
   "image_location": "/v1/images/94571cf2-f376-4325-9305-c4973df05e38.jpe?top_left_x=136&top_left_y=272&width=64&height=64",
   "image_id": "1",
   "bounding_box": {
    "width": 64,
    "top_left_x": 136,
    "top_left_y": 272,
    "height": 64
   },
   "image_url": "http://images.abofcdn.com/catalog/images/2015/ABOFA15AMCWJG1044901/Right_Medium.jpg",
   "print_id": "2",
   "id": "ABOFA15AMCWJG10449",
   "image_filename": "ABOFA15AMCWJG10449_1.jpg"
  }
 ],
 "image_location": "/v1/images/94571cf2-f376-4325-9305-c4973df05e38.jpe"
}

Get similar image/print swatches in the catalog for a user uploaded image.

End point

POST /v1/catalog/{catalog_name}/print_search

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
data image/jpeg (Required) The image. The image can be in PNG, JPEG,
max_number_of_results query maximum number of results to return 12
print_count path The maximum number of dominant prints to search for in an image. 1
image_max_dimension query You can set this parameters to resize the image for faster computation of dominant prints. If your image is of high resolution you can set this parameter to a smaller value (suggested values 256-512) for faster computation. For any image if max(image width,image height) > image_max_dimension resizes the image such that max(image width,image height) = image_max_dimension. no image resizing

Response

Parameter Description
time_ms The time taken in milliseconds.
image_location The resource location of the uploaded image.
products A sorted list similar print images. Each item in the list has the following fields.
id The product id.
image_id The image id.
print_id The print id.
image_filename The image filename.
image_url The image url.
distance The euclidean distance between the print in the image to the print in the query.
image_location The resource location of the dominant print swatch.
bounding_box The bounding box of the dominant print in the image.
top_left_x The x co-ordinate of the top left corner of the bounding box.
top_left_y The y co-ordinate of the top left corner of the bounding box.
width The width of the bounding box.
height The height of the bounding box.

Dominant Prints

A collection of APIs for computing the dominant prints for an user uploaded image, the entire catalog, and any image in the catalog.

Get dominant prints for an image

#------------------------------------------------------------------------------
# Dominant prints for an image. 
# POST /v1/prints/dominant_prints
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header.
headers = {'X-Api-Key': props['X-Api-Key']}

params = {}
# Optional parameters.
params['count'] = 3
#params['image_max_dimension'] = 512
params['ignore_background'] = 'true'
params['model'] = 'person_fast'
#params['fraction_boxes_threshold'] = 0.3

api_endpoint = '/v1/prints/dominant_prints'

url = urljoin(api_gateway_url,api_endpoint)

# Three options to pass the image

# OPTION 1 : Directly post the image
headers['Content-Type'] = 'image/jpeg'
response = requests.post(url,
                         headers=headers,
                         params=params,
                         data=open('test_image_2.jpeg','rb'))

"""          
# OPTION 2 : Pass the image url
params['image_url'] = 'https://vg-images.condecdn.net/image/oDXPOxw65EZ/crop/405'
response = requests.post(url,
                         headers=headers,


# OPTION 3 : using multipart
image_filename = 'test_image_2.jpeg'
with open(image_filename,'rb') as images_file:
    response = requests.post(url,
                             headers=headers,
                             params=params,
                             files={'image': (image_filename,images_file,'image/jpeg')})   
""" 

print response.status_code
pprint(response.json())


# Human friendly repsonse.

results = response.json()

image_location = '%s?api_key=%s'%(urljoin(api_gateway_url,results['image_location']),
                                  props['X-Api-Key'])
print('[original image ] %s'%(image_location))

image_location = '%s&api_key=%s'%(urljoin(api_gateway_url,results['bounding_box']['image_location']),
                                  props['X-Api-Key'])
print('[bounding box   ] %s'%(image_location))

for print_info in results['dominant_prints']:
    print_swatch = '%s&api_key=%s'%(urljoin(api_gateway_url,print_info['image_location']),
                                    props['X-Api-Key'])
    print('[dominant prints] %1.2f %s'%(print_info['fraction_boxes'],print_swatch)) 

Sample json response


 "dominant_prints": [
  {
   "image_location": "/v1/images/2568a1e8-1993-40e0-9d5f-78c33666e876.jpe?top_left_x=256&top_left_y=402&width=64&height=64",
   "bounding_box": {
    "width": 64,
    "top_left_x": 256,
    "top_left_y": 402,
    "height": 64
   },
   "fraction_boxes": 0.388,
   "print_id": "2"
  },
  {
   "image_location": "/v1/images/2568a1e8-1993-40e0-9d5f-78c33666e876.jpe?top_left_x=239&top_left_y=372&width=64&height=64",
   "bounding_box": {
    "width": 64,
    "top_left_x": 239,
    "top_left_y": 372,
    "height": 64
   },
   "fraction_boxes": 0.332,
   "print_id": "1"
  },
  {
   "image_location": "/v1/images/2568a1e8-1993-40e0-9d5f-78c33666e876.jpe?top_left_x=225&top_left_y=210&width=64&height=64",
   "bounding_box": {
    "width": 64,
    "top_left_x": 225,
    "top_left_y": 210,
    "height": 64
   },
   "fraction_boxes": 0.28,
   "print_id": "3"
  }
 ],
 "time_ms": "2136.32",
 "bounding_box": {
  "image_location": "/v1/images/2568a1e8-1993-40e0-9d5f-78c33666e876.jpe?top_left_x=158&top_left_y=0&width=259&height=640",
  "top_left_x": 158,
  "top_left_y": 0,
  "height": 640,
  "width": 259,
  "score": 0.819546,
  "model": "person_fast"
 },
 "image_location": "/v1/images/2568a1e8-1993-40e0-9d5f-78c33666e876.jpe"
}

Get the dominant prints for an image.

End point

POST /v1/prints/dominant_prints

Request

Parameter Type Description Default
data image/jpeg (Required) The image. The image can be in PNG, JPEG, BMP, or GIF.
count query The number of dominant prints to extract per image. 3
image_max_dimension query You can set this parameters to resize the image for faster computation of dominant prints. If your images are of very high resolution you can set this parameter to a smaller value (suggested values 256-512) for faster computation. For any image if max(image width,image height) > image_max_dimension resizes the image such that max(image width,image height) = image_max_dimension. no image resizing
ignore_background query By default we use the entire image to compute the dominant prints. If we set this parameter to true we internally use some algorithms to ignore the background and mainly focus on the person or apparel. false
model query The model to use to ignore the background. Currently we use person detecors to focus only on the person. The following options are supported person_fast (faster but slightly less accurate model), person_accurate (slower but more accurate model) and person_basic (a basic person detector using standard body proportions). person_fast
fraction_boxes_threshold query Include only those prints whos fraction of boxes is greater than this number. 0.0

Instead of the posting the image data you can also pass an image url.

Parameter Type Description
image_url query (Required) The image url.

You can also pass the image using multipart/form-data with the fieldname image.

Response

Parameter Description
time_ms The time taken in milliseconds.
image_url The image url.
image_location The image location.
dominant_prints A list of dominant prints for the image sorted in the decreasing order of the fraction of boxes. Each field in the list has the following fieldnames.
bounding_box The bounding box of the print swatch.
top_left_x The x co-ordinate of the top left corner of the bounding box.
top_left_y The y co-ordinate of the top left corner of the bounding box.
width The width of the bounding box.
height The height of the bounding box.
fraction_boxes The fraction of swatches in the bounding box that can be attributed to this print.
print_id The print id.
image_location The image location of the print swatch.
bounding_box The region in the image used to compute the dominant prints and corresponds to the the bounding box for the central detected person. In case ignore_background is set to false this corresponds to the entire image.
top_left_x The x co-ordinate of the top left corner of the bounding box.
top_left_y The y co-ordinate of the top left corner of the bounding box.
width The width of the bounding box.
height The height of the bounding box.
score The confidence score (between 0 and 1) that the bounding box contains a person.
model The person detection model used.
image_location The image location of the bounding box.

Build dominant prints index

#------------------------------------------------------------------------------
# Build the dominant prints index.
# POST /v1/catalog/{catalog_name}/dominant_prints_index
# params - prints,max_prints_per_image,fraction_boxes_threshold
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

params = {}

# Optional parameters.
params['prints'] = 10
params['max_prints_per_image'] = 2
params['fraction_boxes_threshold'] = 0.1

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/dominant_prints_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.post(url,headers=headers,params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "status": {
  "dominant_prints": {
   "num_of_images_missing_prints": "0",
   "num_of_images_indexed": "28",
   "num_of_images_ignored": "10"
  },
  "status": "done",
  "num_of_products": "8",
  "results_updated": "true",
  "start_time": "2018-03-25 18:01:16.941760",
  "pid": "218",
  "finish_time": "2018-03-25 18:01:17.188224",
  "num_of_images": "38"
 },
 "time_ms": "2.31"
}

Build the dominant prints index.

This loads all the dominant prints for every image in the catalog and then clusters the prints to compute the dominant prints for the entire catalog. Before you can start querying for the dominant prints you need to call this API to start the clustering procedure.

End point

POST /v1/catalog/{catalog_name}/dominant_prints_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
prints query The number of dominant prints to compute. 10
max_prints_per_image query The maximum number of dominant prints to use per image. all available prints
fraction_boxes_threshold query Include only those prints whos fraction of boxes is greater than this number. 0.0

Response

Parameter Description
time_ms The time taken in milliseconds.
status A json containing various info about the current status of the index building process.
status The current status of the index building process. The status can be one of clustering or done. The index is built when the status becomes done.
num_of_products The number of products in the catalog.
num_of_images The total number of images in the catalog.
start_time The time when the index building started.
finish_time The time when the index building finished.
dominant_prints Info about dominant color.
num_of_images_missing_prints The number of images for which there was no dominant color was found.
num_of_images_ignored The number of images that were ignored.
num_of_images_indexed The total number of images finally indexed.

Get dominant prints index status

#------------------------------------------------------------------------------
# Get the status of the dominant prints index.
# GET /v1/catalog/{catalog_name}/dominant_prints_index
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/dominant_prints_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,headers=headers)

print response.status_code
pprint(response.json())

Sample json response

{
 "status": {
  "dominant_prints": {
   "num_of_images_missing_prints": "0",
   "num_of_images_indexed": "28",
   "num_of_images_ignored": "10"
  },
  "status": "done",
  "num_of_products": "8",
  "results_updated": "true",
  "start_time": "2018-03-25 18:01:16.941760",
  "pid": "218",
  "finish_time": "2018-03-25 18:01:17.188224",
  "num_of_images": "38"
 },
 "time_ms": "2.31"
}

Get the status of the dominant prints index.

End point

GET /v1/catalog/{catalog_name}/dominant_prints_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.

Response

Parameter Description
time_ms The time taken in milliseconds.
status A json containing various info about the current status of the index building process.
status The current status of the index building process. The status can be one of clustering or done. The index is built when the status becomes done.
num_of_products The number of products in the catalog.
num_of_images The total number of images in the catalog.
start_time The time when the index building started.
finish_time The time when the index building finished.
dominant_prints Info about dominant color.
num_of_images_missing_prints The number of images for which there was no dominant color was found.
num_of_images_ignored The number of images that were ignored.
num_of_images_indexed The total number of images finally indexed.

Delete the dominant prints index

#------------------------------------------------------------------------------
# Delete the dominant prints index.
# DELETE /v1/catalog/{catalog_name}/dominant_prints_index
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/dominant_prints_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.delete(url,headers=headers)

print response.status_code
pprint(response.json())

Sample json response

{
 "deleted": true,
 "time_ms": "8.88",
 "catalog_name": "sample_catalog"
}

Delete the dominant prints index.

End point

DELETE /v1/catalog/{catalog_name}/dominant_prints_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.

Response

Parameter Description
time_ms The time taken in milliseconds.
catalog_name The catalog name.
deleted This is true if the index was successfully deleted.

Get dominant prints for a product

#------------------------------------------------------------------------------
# Get the dominant prints for an image in the catalog.
# GET /v1/catalog/{catalog_name}/dominant_prints/{id}/{image_id}
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header.
headers = {'X-Api-Key': props['X-Api-Key']}

# Query parameters.
params = {}
# Optional parameters.
#params['fraction_boxes_threshold'] = 0.1

# Path parameters
catalog_name = props['catalog_name']
id ='SHRES16AWFSDR9346B'
image_id = '1'

api_endpoint = '/v1/catalog/%s/dominant_prints/%s/%s'%(catalog_name,id,image_id)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,
                        headers=headers,
                        params=params)

print response.status_code
pprint(response.json())

# Human friendly repsonse.

results = response.json()

print('[image url      ] %s'%(results['image_url']))

image_location = '%s?api_key=%s'%(urljoin(api_gateway_url,results['image_location']),
                                  props['X-Api-Key'])
print('[original image ] %s'%(image_location))

image_location = '%s&api_key=%s'%(urljoin(api_gateway_url,results['bounding_box']['image_location']),
                                  props['X-Api-Key'])
print('[bounding box   ] %s'%(image_location))

for print_info in results['dominant_prints']:
    print_swatch = '%s&api_key=%s'%(urljoin(api_gateway_url,print_info['image_location']),
                                    props['X-Api-Key'])
    print('[dominant prints] %1.2f %s'%(print_info['fraction_boxes'],print_swatch)) 

Sample json response

{
 "dominant_prints": [
  {
   "image_location": "/v1/catalog/sample_catalog/images/SHRES16AWFSDR9346B_1.jpg?top_left_x=104&top_left_y=136&width=64&height=64",
   "bounding_box": {
    "width": 64,
    "top_left_x": 104,
    "top_left_y": 136,
    "height": 64
   },
   "fraction_boxes": 0.528,
   "print_id": "3"
  },
  {
   "image_location": "/v1/catalog/sample_catalog/images/SHRES16AWFSDR9346B_1.jpg?top_left_x=104&top_left_y=194&width=64&height=64",
   "bounding_box": {
    "width": 64,
    "top_left_x": 104,
    "top_left_y": 194,
    "height": 64
   },
   "fraction_boxes": 0.26,
   "print_id": "1"
  },
  {
   "image_location": "/v1/catalog/sample_catalog/images/SHRES16AWFSDR9346B_1.jpg?top_left_x=104&top_left_y=243&width=64&height=64",
   "bounding_box": {
    "width": 64,
    "top_left_x": 104,
    "top_left_y": 243,
    "height": 64
   },
   "fraction_boxes": 0.212,
   "print_id": "2"
  }
 ],
 "time_ms": "2.71",
 "bounding_box": {
  "image_location": "/v1/catalog/sample_catalog/images/SHRES16AWFSDR9346B_1.jpg?top_left_x=83&top_left_y=0&width=107&height=365",
  "top_left_x": 83,
  "top_left_y": 0,
  "height": 365,
  "width": 107,
  "score": 0.800896
 },
 "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Look_Medium.jpg",
 "image_location": "/v1/catalog/sample_catalog/images/SHRES16AWFSDR9346B_1.jpg"
}

Get the dominant prints for an image in the catalog.

End point

GET /v1/catalog/{catalog_name}/dominant_prints/{id}/{image_id}

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
id path (Required) The product id.
image_id path (Required) The image id.
fraction_boxes_threshold query Include only those prints whos fraction of boxes is greater than this number. 0.0

Response

Parameter Description
time_ms The time taken in milliseconds.
image_url The image url.
image_location The image location.
dominant_prints A list of dominant prints for the image sorted in the decreasing order of the fraction of boxes. Each field in the list has the following fieldnames.
bounding_box The bounding box of the print swatch.
top_left_x The x co-ordinate of the top left corner of the bounding box.
top_left_y The y co-ordinate of the top left corner of the bounding box.
width The width of the bounding box.
height The height of the bounding box.
fraction_boxes The fraction of swatches in the bounding box that can be attributed to this print.
print_id The print id.
image_location The image location of the print swatch.
bounding_box The region in the image used to compute the dominant prints and corresponds to the the bounding box for the central detected person. In case ignore_background is set to false this corresponds to the entire image.
top_left_x The x co-ordinate of the top left corner of the bounding box.
top_left_y The y co-ordinate of the top left corner of the bounding box.
width The width of the bounding box.
height The height of the bounding box.
score The confidence score (between 0 and 1) that the bounding box contains a person.
model The person detection model used.
image_location The image location of the bounding box.

Get dominant prints for a catalog

#------------------------------------------------------------------------------
# Get the dominant prints for all images in the catalog.
# GET /v1/catalog/{catalog_name}/dominant_prints
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

params = {}
params['prints'] = 5

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/dominant_prints'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,headers=headers,params=params)

print response.status_code
pprint(response.json())

# Here is how you can serve the print swatches
results = response.json()
for print_info in results['dominant_prints']:
    print_swatch = '%s&api_key=%s'%(urljoin(api_gateway_url,print_info['image_location']),
                                    props['X-Api-Key'])
    print('[print swatch] %s'%(print_swatch)) 

Sample json response

{
 "computed_on": "2018-03-25 18:01:17.184551",
 "time_ms": "2.40",
 "dominant_prints": [
  {
   "image_location": "/v1/catalog/sample_catalog/images/ABOFA15AMCWJG10448_3.jpg?top_left_x=128&top_left_y=147&width=64&height=64",
   "popularity": 0.25,
   "image_id": "3",
   "bounding_box": {
    "width": 64,
    "top_left_x": 128,
    "top_left_y": 147,
    "height": 64
   },
   "n_instances": 14,
   "image_url": "http://images.abofcdn.com/catalog/images/2015/ABOFA15AMCWJG1044801/Left_Medium.jpg",
   "image_filename": "ABOFA15AMCWJG10448_3.jpg",
   "id": "ABOFA15AMCWJG10448",
   "print_id": "1"
  },
  {
   "image_location": "/v1/catalog/sample_catalog/images/SKLTS16AMCWSH8SP01_3.jpg?top_left_x=104&top_left_y=133&width=64&height=64",
   "popularity": 0.14285714285714285,
   "image_id": "3",
   "bounding_box": {
    "width": 64,
    "top_left_x": 104,
    "top_left_y": 133,
    "height": 64
   },
   "n_instances": 8,
   "image_url": "http://images.abofcdn.com/catalog/images/2016/SKLTS16AMCWSH8SP0150/Left_Medium.jpg",
   "image_filename": "SKLTS16AMCWSH8SP01_3.jpg",
   "id": "SKLTS16AMCWSH8SP01",
   "print_id": "2"
  },
  {
   "image_location": "/v1/catalog/sample_catalog/images/SKLTS16AMCWSH8SP01_5.jpg?top_left_x=136&top_left_y=198&width=64&height=64",
   "popularity": 0.10714285714285714,
   "image_id": "5",
   "bounding_box": {
    "width": 64,
    "top_left_x": 136,
    "top_left_y": 198,
    "height": 64
   },
   "n_instances": 6,
   "image_url": "http://images.abofcdn.com/catalog/images/2016/SKLTS16AMCWSH8SP0150/Right_Medium.jpg",
   "image_filename": "SKLTS16AMCWSH8SP01_5.jpg",
   "id": "SKLTS16AMCWSH8SP01",
   "print_id": "1"
  },
  {
   "image_location": "/v1/catalog/sample_catalog/images/SHRES16AWFSDR9346B_5.jpg?top_left_x=121&top_left_y=149&width=64&height=64",
   "popularity": 0.10714285714285714,
   "image_id": "5",
   "bounding_box": {
    "width": 64,
    "top_left_x": 121,
    "top_left_y": 149,
    "height": 64
   },
   "n_instances": 6,
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Front_Medium.jpg",
   "image_filename": "SHRES16AWFSDR9346B_5.jpg",
   "id": "SHRES16AWFSDR9346B",
   "print_id": "3"
  },
  {
   "image_location": "/v1/catalog/sample_catalog/images/SKLTS16AMCWSH8SH20_1.jpg?top_left_x=117&top_left_y=186&width=64&height=64",
   "popularity": 0.08928571428571429,
   "image_id": "1",
   "bounding_box": {
    "width": 64,
    "top_left_x": 117,
    "top_left_y": 186,
    "height": 64
   },
   "n_instances": 5,
   "image_url": "http://images.abofcdn.com/catalog/images/2016/SKLTS16AMCWSH8SH2005/Right_Medium.jpg",
   "image_filename": "SKLTS16AMCWSH8SH20_1.jpg",
   "id": "SKLTS16AMCWSH8SH20",
   "print_id": "1"
  }
 ]
}

Get the dominant prints for all images in the catalog.

The dominant prints is to be interpreted as a representative of the cluster of similar prints.

End point

GET /v1/catalog/{catalog_name}/dominant_prints

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
prints query The number of dominant prints to return. 10

Response

Parameter Description
time_ms The time taken in milliseconds.
image_url The image url.
image_location The image location.
dominant_prints A list of dominant prints for the catalog sorted in the decreasing order of popularity. Each field in the list has the following fieldnames.
id The product id.
image_id The image id.
print_id The print id.
image_url The image url.
image_filename The image filename.
image_location The image location of the print swatch.
popularity A score between 0 and 1 indicating the popularity of the print.
n_instances The number of prints in the cluster.
bounding_box The bounding box of the print swatch.
top_left_x The x co-ordinate of the top left corner of the bounding box.
top_left_y The y co-ordinate of the top left corner of the bounding box.
width The width of the bounding box.
height The height of the bounding box.

Looks Search

A collection of APIs for enabling catalog search based on looks.

Build look search index

#------------------------------------------------------------------------------
# Build the looks search index.
# POST /v1/catalog/{catalog_name}/looks_search_index
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header.
headers = {'X-Api-Key': props['X-Api-Key']}

# Query parameters.
params = {}
# Optional parameters.
#params['image_max_dimension'] = 512
params['ignore_background'] = 'true'
params['model'] = 'person_fast'
#params['ignore_images_without_person'] = 'true'

# Path paarameters.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/looks_search_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.post(url,headers=headers,params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "status": {
  "status": "computing_features",
  "looks_search_index": {
   "num_of_images_missing_features": "0",
   "num_of_images_indexed": "0",
   "num_of_images_ignored": "0"
  },
  "start_time": "2018-03-28 15:05:30.654530",
  "pid": "1229",
  "num_of_products": "8",
  "finish_time": "0",
  "num_of_images": "38",
  "feature_computation": {
   "num_of_images_error": "0",
   "num_of_images_ignored": "1",
   "num_of_images_existing": "0",
   "num_of_images_processed": "4"
  }
 },
 "time_ms": "8.29"
}

Build the looks search index.

Before you can start using the looks search or dominant looks APIs the looks search index has to be built. This API computes the features for all the uploaded images in the catalog and then builds an index for fast nearest neighbor retrieval.

End point

POST /v1/catalog/{catalog_name}/looks_search_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
image_max_dimension query You can set this parameters to resize the image for faster computation of dominant prints. If your images are of very high resolution you can set this parameter to a smaller value (suggested values 256-512) for faster computation. For any image if max(image width,image height) > image_max_dimension resizes the image such that max(image width,image height) = image_max_dimension. no image resizing
ignore_background query By default we use the entire image to compute the dominant prints. If we set this parameter to true we internally use some algorithms to ignore the background and mainly focus on the person or apparel. false
model query The model to use to ignore the background. Currently we use person detecors to focus only on the person. The following options are supported person_fast (faster but slightly less accurate model), person_accurate (slower but more accurate model) and person_basic (a basic person detector using standard body proportions). person_fast
ignore_images_without_person query If true ignore images where person is not detected. If false and person is not detected then defaults to using the entire image. false

Response

Parameter Description
time_ms The time taken in milliseconds.
status A json containing various info about the current status of the index building process.
status The current status of the index building process. The status can be one of computing_features,building_index,or done. The index is built when the status becomes done.
num_of_products The number of products in the catalog.
num_of_images The total number of images in the catalog.
start_time The time when the index building started.
finish_time The time when the index building finished.
feature_computation Info about feature computation.
num_of_images_error The number of images for which there was some error in features computation.
num_of_images_ignored The number of images that were ignored.
num_of_images_existing The number of images for which the features were already computed (in case of building a new index with new products added).
num_of_images_processed The total number of images for which the features were computed.
looks_search_index Info about the index building.
num_of_images_missing_feature The number of images for which there was no features.
num_of_images_ignored The number of images that were ignored.
num_of_images_indexed The total number of images finally indexed.

Get looks search index status

#------------------------------------------------------------------------------
# Get the status of the looks search index.
# GET /v1/catalog/{catalog_name}/looks_search_index
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/looks_search_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,headers=headers)

print response.status_code
pprint(response.json())

Sample json response

{
 "status": {
  "status": "done",
  "index_updated": "true",
  "looks_search_index": {
   "num_of_images_missing_features": "0",
   "num_of_images_indexed": "28",
   "num_of_images_ignored": "10"
  },
  "start_time": "2018-03-28 15:05:30.654530",
  "pid": "1229",
  "finish_time": "2018-03-28 15:06:37.109888",
  "num_of_products": "8",
  "num_of_images": "38",
  "feature_computation": {
   "num_of_images_error": "0",
   "num_of_images_ignored": "10",
   "num_of_images_existing": "0",
   "num_of_images_processed": "28"
  }
 },
 "time_ms": "8.54"
}

Get the status of the looks search index.

End point

GET /v1/catalog/{catalog_name}/looks_search_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.

Response

Parameter Description
time_ms The time taken in milliseconds.
status A json containing various info about the current status of the index building process.
status The current status of the index building process. The status can be one of computing_features,building_index,or done. The index is built when the status becomes done.
num_of_products The number of products in the catalog.
num_of_images The total number of images in the catalog.
start_time The time when the index building started.
finish_time The time when the index building finished.
feature_computation Info about feature computation.
num_of_images_error The number of images for which there was some error in features computation.
num_of_images_ignored The number of images that were ignored.
num_of_images_existing The number of images for which the features were already computed (in case of building a new index with new products added).
num_of_images_processed The total number of images for which the features were computed.
looks_search_index Info about the index building.
num_of_images_missing_feature The number of images for which there was no features.
num_of_images_ignored The number of images that were ignored.
num_of_images_indexed The total number of images finally indexed.

Delete the looks search index

#------------------------------------------------------------------------------
# Delete the looks search index.
# DELETE /v1/catalog/{catalog_name}/looks_search_index
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/looks_search_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.delete(url,headers=headers)

print response.status_code
pprint(response.json())

Sample json response

{
 "deleted": true,
 "time_ms": "8.88",
 "catalog_name": "sample_catalog"
}

Delete the looks search index.

End point

DELETE /v1/catalog/{catalog_name}/looks_search_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.

Response

Parameter Description
time_ms The time taken in milliseconds.
catalog_name The catalog name.
deleted This is true if the index was successfully deleted.

Looks Search by id

#------------------------------------------------------------------------------ 
# Get similar looks in the catalog for an existing image.
# GET /v1/catalog/{catalog_name}/looks_search
# params - id,image_id,max_number_of_results
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Parameters.
params = {}
params['id'] = 'SHRES16AWFSDR9346A' 
params['image_id'] = '1'
params['max_number_of_results'] = 5

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/looks_search'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,
                        headers=headers,
                        params=params)


print response.status_code
pprint(response.json())

# Human friendly repsonse.

results = response.json()

for info in results['products']:
    person_image = '%s&api_key=%s'%(urljoin(api_gateway_url,info['image_location']),
                                    props['X-Api-Key'])
    print('[%1.2f] %s'%(info['similarity'],person_image)) 

Sample json response

{
 "time_ms": "10.32",
 "products": [
  {
   "image_location": "/v1/catalog/sample_catalog/images/SHRES16AWFSDR9346A_1.jpg?top_left_x=68&top_left_y=0&width=119&height=323",
   "similarity": 1.0,
   "image_id": "1",
   "bounding_box": {
    "width": 119,
    "score": 0.701361,
    "top_left_x": 68,
    "top_left_y": 0,
    "height": 323
   },
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346A54/Look_Medium.jpg",
   "id": "SHRES16AWFSDR9346A",
   "image_filename": "SHRES16AWFSDR9346A_1.jpg"
  },
  {
   "image_location": "/v1/catalog/sample_catalog/images/SHRES16AWFSDR9346A_4.jpg?top_left_x=51&top_left_y=0&width=163&height=347",
   "similarity": 0.6284968256950378,
   "image_id": "4",
   "bounding_box": {
    "width": 163,
    "score": 0.702937,
    "top_left_x": 51,
    "top_left_y": 0,
    "height": 347
   },
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346A54/Front_Medium.jpg",
   "id": "SHRES16AWFSDR9346A",
   "image_filename": "SHRES16AWFSDR9346A_4.jpg"
  },
  {
   "image_location": "/v1/catalog/sample_catalog/images/SHRES16AWFSDR9346B_5.jpg?top_left_x=95&top_left_y=0&width=119&height=324",
   "similarity": 0.5597510933876038,
   "image_id": "5",
   "bounding_box": {
    "width": 119,
    "score": 0.629143,
    "top_left_x": 95,
    "top_left_y": 0,
    "height": 324
   },
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Front_Medium.jpg",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_5.jpg"
  }
 ]
}

Get similar looks in the catalog for an existing image.

End point

GET /v1/catalog/{catalog_name}/looks_search

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
id query (Required) The product id.
image_id query (Required) The image id.
max_number_of_results query maximum number of results to return. 12

Response

Parameter Description
time_ms The time taken in milliseconds.
products A sorted list similar images. Each item in the list has the following fields.
id The product id.
image_id The image id.
image_filename The image filename.
image_url The image url.
similariy The similarity score.
image_location The resource location of the bounding box for the detected person.
bounding_box The bounding box of the dominant person in the image.
top_left_x The x co-ordinate of the top left corner of the bounding box.
top_left_y The y co-ordinate of the top left corner of the bounding box.
width The width of the bounding box.
height The height of the bounding box.

Looks Search by image

#------------------------------------------------------------------------------
# Get similar looks in the catalog for a user uploaded image.
# POST /v1/catalog/{catalog_name}/looks_search
# params - max_number_of_results,ignore_background,model,image_max_dimension
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Parameters.
params = {}
params['max_number_of_results'] = 5
#params['image_max_dimension'] = 512
params['ignore_background'] = 'true'
params['model'] = 'person_fast'

headers['Content-Type'] = 'image/jpeg'

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/looks_search'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.post(url,
                        headers=headers,
                        params=params,
                        data=open('test_image_3.jpeg','rb'))

print response.status_code
pprint(response.json())

# Human friendly repsonse.

results = response.json()

image_location = '%s?api_key=%s'%(urljoin(api_gateway_url,results['image_location']),
                                  props['X-Api-Key'])
print('[original image ] %s'%(image_location))

image_location = '%s&api_key=%s'%(urljoin(api_gateway_url,results['bounding_box']['image_location']),
                                  props['X-Api-Key'])
print('[bounding box   ] %s'%(image_location))

for info in results['products']:
    person_image = '%s&api_key=%s'%(urljoin(api_gateway_url,info['image_location']),
                                    props['X-Api-Key'])
    print('[%1.2f] %s'%(info['similarity'],person_image)) 

Sample json response

{
 "time_ms": "2158.11",
 "bounding_box": {
  "image_location": "/v1/images/61e16e38-bb3e-4779-baf8-748491ca6162.jpe?top_left_x=177&top_left_y=27&width=170&height=541",
  "top_left_x": 177,
  "top_left_y": 27,
  "height": 541,
  "width": 170,
  "score": 0.889102
 },
 "products": [
  {
   "image_location": "/v1/catalog/sample_catalog/images/SHRES16AWFSDR9346A_5.jpg?top_left_x=54&top_left_y=0&width=154&height=343",
   "similarity": 0.41838812828063965,
   "image_id": "5",
   "bounding_box": {
    "width": 154,
    "score": 0.575364,
    "top_left_x": 54,
    "top_left_y": 0,
    "height": 343
   },
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346A54/Left_Medium.jpg",
   "id": "SHRES16AWFSDR9346A",
   "image_filename": "SHRES16AWFSDR9346A_5.jpg"
  },
  {
   "image_location": "/v1/catalog/sample_catalog/images/SHRES16AWFSDR9346B_2.jpg?top_left_x=101&top_left_y=0&width=74&height=303",
   "similarity": 0.404349684715271,
   "image_id": "2",
   "bounding_box": {
    "width": 74,
    "score": 0.307322,
    "top_left_x": 101,
    "top_left_y": 0,
    "height": 303
   },
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Left_Medium.jpg",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_2.jpg"
  },
  {
   "image_location": "/v1/catalog/sample_catalog/images/ABOFA15AMCWJG10448_5.jpg?top_left_x=0&top_left_y=0&width=313&height=417",
   "similarity": 0.40286576747894287,
   "image_id": "5",
   "bounding_box": {
    "width": 313,
    "score": 1.0,
    "top_left_x": 0,
    "top_left_y": 0,
    "height": 417
   },
   "image_url": "http://images.abofcdn.com/catalog/images/2015/ABOFA15AMCWJG1044801/Front_Medium.jpg",
   "id": "ABOFA15AMCWJG10448",
   "image_filename": "ABOFA15AMCWJG10448_5.jpg"
  }
 ],
 "image_location": "/v1/images/61e16e38-bb3e-4779-baf8-748491ca6162.jpe"
}

Get similar looks in the catalog for a user uploaded image.

End point

POST /v1/catalog/{catalog_name}/looks_search

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
data image/jpeg (Required) The image. The image can be in PNG, JPEG,
max_number_of_results query maximum number of results to return 12
print_count path The maximum number of dominant prints to search for in an image. 1
image_max_dimension query You can set this parameters to resize the image for faster computation of dominant prints. If your image is of high resolution you can set this parameter to a smaller value (suggested values 256-512) for faster computation. For any image if max(image width,image height) > image_max_dimension resizes the image such that max(image width,image height) = image_max_dimension. no image resizing
ignore_background query By default we use the entire image to compute the dominant prints. If we set this parameter to true we internally use some algorithms to ignore the background and mainly focus on the person or apparel. false
model query The model to use to ignore the background. Currently we use person detecors to focus only on the person. The following options are supported person_fast (faster but slightly less accurate model), person_accurate (slower but more accurate model) and person_basic (a basic person detector using standard body proportions). person_fast

Response

Parameter Description
time_ms The time taken in milliseconds.
image_location The image location.
products A sorted list similar images. Each item in the list has the following fields.
id The product id.
image_id The image id.
image_filename The image filename.
image_url The image url.
similarity The similarity score.
image_location The resource location of the bounding box for the detected person.
bounding_box The bounding box of the dominant person in the image.
top_left_x The x co-ordinate of the top left corner of the bounding box.
top_left_y The y co-ordinate of the top left corner of the bounding box.
width The width of the bounding box.
height The height of the bounding box.
bounding_box The bounding box for the detected person.
top_left_x The x co-ordinate of the top left corner of the bounding box.
top_left_y The y co-ordinate of the top left corner of the bounding box.
width The width of the bounding box.
height The height of the bounding box.
score The confidence score (between 0 and 1) that the bounding box contains a person.
image_location The image location of the bounding box.

Dominant Looks

A collection of APIs for computing the dominant looks for a catalog.

Build dominant looks index

#------------------------------------------------------------------------------
# Build the dominant looks index.
# POST /v1/catalog/{catalog_name}/dominant_looks_index
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

params = {}

# Optional parameters.
params['looks'] = 10

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/dominant_looks_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.post(url,headers=headers,params=params)

print response.status_code
pprint(response.json())

Sample json response

{
 "status": {
  "status": "done",
  "dominant_looks": {
   "num_of_images_missing_features": "0",
   "num_of_images_indexed": "28",
   "num_of_images_ignored": "10"
  },
  "num_of_products": "8",
  "results_updated": "true",
  "start_time": "2018-03-29 11:56:41.883208",
  "pid": "2067",
  "finish_time": "2018-03-29 11:56:42.170910",
  "num_of_images": "38"
 },
 "time_ms": "1.16"
}

Build the dominant looks index.

Before you can start querying for the dominant looks you need to call this API to start the clustering procedure.

End point

POST /v1/catalog/{catalog_name}/dominant_looks_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
looks query The number of dominant looks to compute. 10

Response

Parameter Description
time_ms The time taken in milliseconds.
status A json containing various info about the current status of the index building process.
status The current status of the index building process. The status can be one of clustering or done. The index is built when the status becomes done.
num_of_products The number of products in the catalog.
num_of_images The total number of images in the catalog.
start_time The time when the index building started.
finish_time The time when the index building finished.
dominant_looks Info about dominant looks.
num_of_images_missing_features The number of images for which there was no feature was found.
num_of_images_ignored The number of images that were ignored.
num_of_images_indexed The total number of images finally indexed.

Get dominant looks index status

#------------------------------------------------------------------------------
# Get the status of the dominant looks index.
# GET /v1/catalog/{catalog_name}/dominant_looks_index
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/dominant_looks_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,headers=headers)

print response.status_code
pprint(response.json())

Sample json response

{
 "status": {
  "status": "done",
  "dominant_looks": {
   "num_of_images_missing_features": "0",
   "num_of_images_indexed": "28",
   "num_of_images_ignored": "10"
  },
  "num_of_products": "8",
  "results_updated": "true",
  "start_time": "2018-03-29 11:56:41.883208",
  "pid": "2067",
  "finish_time": "2018-03-29 11:56:42.170910",
  "num_of_images": "38"
 },
 "time_ms": "2.45"
}

Get the status of the dominant looks index.

End point

GET /v1/catalog/{catalog_name}/dominant_looks_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.

Response

Parameter Description
time_ms The time taken in milliseconds.
status A json containing various info about the current status of the index building process.
status The current status of the index building process. The status can be one of clustering or done. The index is built when the status becomes done.
num_of_products The number of products in the catalog.
num_of_images The total number of images in the catalog.
start_time The time when the index building started.
finish_time The time when the index building finished.
dominant_looks Info about dominant looks.
num_of_images_missing_features The number of images for which there was no feature was found.
num_of_images_ignored The number of images that were ignored.
num_of_images_indexed The total number of images finally indexed.

Delete the dominant looks index

#------------------------------------------------------------------------------
# Delete the dominant looks index.
# DELETE /v1/catalog/{catalog_name}/dominant_looks_index
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/dominant_looks_index'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.delete(url,headers=headers)

print response.status_code
pprint(response.json())

Sample json response

{
 "deleted": true,
 "time_ms": "8.88",
 "catalog_name": "sample_catalog"
}

Delete the dominant looks index.

End point

DELETE /v1/catalog/{catalog_name}/dominant_looks_index

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.

Response

Parameter Description
time_ms The time taken in milliseconds.
catalog_name The catalog name.
deleted This is true if the index was successfully deleted.

Get dominant looks for a catalog

#------------------------------------------------------------------------------
# Get the dominant looks for all images in the catalog.
# GET /v1/catalog/{catalog_name}/dominant_looks
# params - looks
#------------------------------------------------------------------------------

import os
import json
import requests
from urlparse import urljoin
from pprint import pprint

from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
# Replace 'your_api_key' with your API key.
headers = {'X-Api-Key': props['X-Api-Key']}

params = {}
params['looks'] = 3

# Catalog name.
catalog_name = props['catalog_name']

api_endpoint = '/v1/catalog/%s/dominant_looks'%(catalog_name)

url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,headers=headers,params=params)

print response.status_code
pprint(response.json())

Sample json response


 "computed_on": "2018-03-29 11:56:42.162979",
 "time_ms": "2.24",
 "dominant_looks": [
  {
   "image_location": "/v1/catalog/sample_catalog/images/LPJNA16AMDMTE91662_2.jpg?top_left_x=57&top_left_y=0&width=197&height=351",
   "popularity": 0.14285714285714285,
   "image_id": "2",
   "bounding_box": {
    "width": 197,
    "score": 0.530316,
    "top_left_x": 57,
    "top_left_y": 0,
    "height": 351
   },
   "n_instances": 4,
   "image_url": "http://images.abofcdn.com/catalog/images/2016/LPJNA16AMDMTE9166200/Right_Medium.jpg",
   "id": "LPJNA16AMDMTE91662",
   "image_filename": "LPJNA16AMDMTE91662_2.jpg"
  },
  {
   "image_location": "/v1/catalog/sample_catalog/images/SHRES16AWFSDR9346B_4.jpg?top_left_x=111&top_left_y=0&width=91&height=326",
   "popularity": 0.14285714285714285,
   "image_id": "4",
   "bounding_box": {
    "width": 91,
    "score": 0.538281,
    "top_left_x": 111,
    "top_left_y": 0,
    "height": 326
   },
   "n_instances": 4,
   "image_url": "http://images.abofcdn.com/catalog/images/2015/SHRES16AWFSDR9346B18/Right_Medium.jpg",
   "id": "SHRES16AWFSDR9346B",
   "image_filename": "SHRES16AWFSDR9346B_4.jpg"
  },
  {
   "image_location": "/v1/catalog/sample_catalog/images/ABOFA15AMCWJG10449_4.jpg?top_left_x=119&top_left_y=0&width=114&height=360",
   "popularity": 0.14285714285714285,
   "image_id": "4",
   "bounding_box": {
    "width": 114,
    "score": 0.76403,
    "top_left_x": 119,
    "top_left_y": 0,
    "height": 360
   },
   "n_instances": 4,
   "image_url": "http://images.abofcdn.com/catalog/images/2015/ABOFA15AMCWJG1044901/Look_Medium.jpg",
   "id": "ABOFA15AMCWJG10449",
   "image_filename": "ABOFA15AMCWJG10449_4.jpg"
  }
 ]
}

Get the dominant looks for all images in the catalog.

The dominant looks is to be interpreted as a representative of the cluster of similar looks.

End point

GET /v1/catalog/{catalog_name}/dominant_looks

Request

Parameter Type Description Default
catalog_name path (Required) The catalog name.
looks query The number of dominant looks to return. 10

Response

Parameter Description
time_ms The time taken in milliseconds.
image_url The image url.
image_location The image location.
dominant_looks A list of dominant looks for the catalog sorted in the decreasing order of popularity. Each field in the list has the following fieldnames.
id The product id.
image_id The image id.
image_url The image url.
image_filename The image filename.
image_location The image location of the person in the image.
popularity A score between 0 and 1 indicating the popularity of the print.
n_instances The number of looks in the cluster.
bounding_box The bounding box of the person.
top_left_x The x co-ordinate of the top left corner of the bounding box.
top_left_y The y co-ordinate of the top left corner of the bounding box.
width The width of the bounding box.
height The height of the bounding box.

Complete the Look

Given a fashion apparel suggest another apparel/accessory that goes well with it. The API also returns a natural language style tip along with the products.

Some use cases for visual attributes include: - recommendation of apparels based on style rules - aids in curating fashion outfits by bloggers, designers

Complete the Look using meta data of the product of interest

Given a fashion apparel suggest another apparel/accessory that goes well with it using the meta data of the product


import os
import json
import requests
from urlparse import urljoin
from pprint import pprint
from props import *

# Replace this with the custom url generated for you.
api_gateway_url = props['api_gateway_url']

# Pass the api key into the header
headers = {'X-Api-Key': props['X-Api-Key']}

# Parameters.
params = {}
params['query_text'] = "red floral dress"
params['gender'] = "female"

api_endpoint = '/v1/complete_the_look/text/'
url = urljoin(api_gateway_url,api_endpoint)

response = requests.get(url,headers=headers,params=params)
print response.status_code
pprint(response.json())

Sample json response


{u'recommendation': [u'heels', u'sling bag', u'earrings'],
 u'style_tip': u'style this dress by teaming it with a pair of black heels and a sling bag and a pair of earrings and a sling bag. ',
 u'time_ms': 0.45203208923339844}

End point

`GET /v1/complete_the_look/text/

Request

Parameter Type Description Default
query_text query (Required) The query text
gender query gender for the query text

Response

Parameter Description
time_ms The time taken for generating the response in milliseconds.
style_tip The style tip for the query fashion item
recommendation List of fashion items which would go well with the query fashion item

Complete the Look using the image of the product of interest

Coming soon …

Errors

The Cogntive Fashion API uses the following error codes:

Error Code Meaning
400 Bad Request.
401 Unauthorized – Your API key is wrong
403 Forbidden
404 Not Found – The product is not in the catalog.
405 Method Not Allowed
406 Not Acceptable – You requested a format that isn’t json
500 Internal Server Error – We had a problem with our server. Try again later.
503 Service Unavailable – We’re temporarially offline for maintanance. Please try again later.