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.
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
- A product goes out-of-stock and you can just change the
out_of_stock
field in the product json toyes
to reflect this change. - There is a sale for the product and and you can update the
sale_price
andsale_percentage
fields. - The product image has changes and you can update the
image_url
.
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
friendly_name
- A friendly name for display purposes.hero_image_url
- The url of the hero image.description
- A brief description.
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
#------------------------------------------------------------------------------
# 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:
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.
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.
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 usevisual_search_category
(for visual search) andvisual_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 thecategory
while thevisual_search_category
could bewomen 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 bothtops
andblouses
.
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. |
Visual Search
#------------------------------------------------------------------------------
# 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:
- Show me some black graphic print cotton tees under 1k in small size on sale.
- Can you show me some red dresses for my girlfriend for around 100 dollars ?
- Show me some red mandarin collar shirts.
- Show me some edgy longline tees for a party tonight.
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:
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.
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.’).
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.
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’.
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.
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.
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.
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.
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
#------------------------------------------------------------------------------
# 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:
- Auto-attribution of catalog images.
- Catalog enrichment for a better text search.
- Post-filtering of visual search results.
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:
- universal 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 A slightly larger curated set of color names which we call entry level. A random person should be able to recognize these color names.
- full The full set of colors available in our color taxonomy including more esoteric color terms.
- pantone The pantone color terms for fashion.
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. |
Forecast popular colors
#------------------------------------------------------------------------------
# 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. |
Forecast trending colors
#------------------------------------------------------------------------------
# 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. |
Print Search by id
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. |
Print Search by image
#------------------------------------------------------------------------------
# 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. |