productAI

Search

Image search is a key feature of ProductAI. It helps customers to build index on their image set, to achieve photo&buy, product management, product association functions.

Image Set

The basic concept in ProductAI is Image Set (to analogy with data table in traditional relational database). Every search service is an index on image set. Compared with the traditional database, Image Set equals to the data table of the traditional database, and search service equals to an index on the data table.

ProductAI only supports image data type by now. Each image in image set (to analogy with data record in data table). Every image uses url as an unique id. The different url means the different data. If 2 records have the same url will be treated as the single record.

When a new image set is created, an unique id is assigned, called IMAGE_SET_ID.

Create Image Set

Python

PHP

Java

C#

cURL

from productai import Client

cli = Client(ACCESS_KEY_ID, SECRET_KEY)
api = cli.get_image_set_creating_api()
resp = api.create_image_set(name=SET_NAME, description=SET_DESC)

if resp.status_code == 200:
import json
image_set = json.loads(resp.content)
image_set_id = image_set['id']
use ProductAI;

$product_ai = new ProductAI\API($access_key_id=ACCESS_KEY_ID, $secret_key=SECRET_KEY);
$result = $product_ai->createImageSet($name=SET_NAME, $description=SET_DESC);
$image_set_id = $result['id'];
import cn.productai.api.core.*;
import cn.productai.api.core.enums.*;
import cn.productai.api.pai.entity.dataset.*;

IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

IWebClient client = new DefaultProductAIClient(profile);
CreateDataSetRequest request = new CreateDataSetRequest(SET_NAME, SET_DESC);
request.setLanguage(LanguageType.Chinese);

CreateDataSetResponse response = client.getResponse(request);

String image_set_id = response.getDataSetId();
// return all the fields as JSON
String json = response.getResponseJsonString();
using MalongTech.ProductAI.Core;
using MalongTech.ProductAI.API.Entity;

IProfile profile = new DefaultProfile
{
Version="1",
AccessKeyId=ACCESS_KEY_ID,
SecretKey=SECRET_KEY
};
var client = new DefaultProductAIClient(profile);

// Create request with image set name and description
var request = new CreateDataSetRequest
{
Name=SET_NAME,
Description=SET_DESC
};

var response = client.GetResponse(request);
var dataSetId = response.DataSetId;
curl -X POST \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
-H 'Content-Type: application/json' \
-d '{"name": "NAME", "description": "DESC"}' \
https://api.productai.com/image_sets/_0000014

Request

ArgumentTypeDescriptionRequiredLimitation
nameStringimage set nameYesMaximum 16 unicode characters,the extra characters are truncated
descriptionStringimage set descriptionYesMaximum 128 unicode characters,the extra characters are truncated

Response

200 HTTP Status Code
{
"created_at": "2017-12-13T08:40:51Z",
"creator_id": 2031,
"description": "yyy",
"id": "l5qwws5f",
"modified_at": "2017-12-13T08:40:51Z",
"n_downloaded": 0,
"n_failed": 0,
"n_items": 0,
"name": "xxx",
"request_id": "53361e08-dfe1-11e7-a97c-664c03c7cfbb",
"status": "not-downloaded"
}
FieldTypeDescription
created_atStringCreated UTC datetime, the format is: %Y-%m-%dT%H:%M:%SZ
creator_idIntegerCreator ID
descriptionStringImage set description
idStringUnique ID, all the image set related APIs will use this ID to identify a image set.
modified_atStringLast modified UTC datetime,the format is: %Y-%m-%dT%H:%M:%SZ
n_downloadedIntegerThe count of successful downloaded image
n_failedIntegerThe count of failed downloaded image
n_itemsIntegerThe total non-deleted image count
nameStringImage set name
request_idStringThe unique ID of this request, it can be used in product issue debugging with ProductAI support team
statusStringThe status of image set. If no any image is downloaded, the value is not-downloaded. If some of images are downloaded successfully, but the other haven’t been downloaded yet, the value of this field is downloading. If all the images were download successfully or failed, the value is downloaded
Non-200 HTTP Status Code
{
"error_code": 5001,
"message": "lineno 1 : `` should be a valid image URL less than or equal to 512 characters in length",
"request_id": "810c0180-e00e-11e7-9a0f-b217471bc47d"
}
FieldTypeDescription
error_codeIntegerDetailed error code
messageStringDetailed error message
request_idStringThe unique ID of this request, it can be used in product issue debugging with ProductAI support team

Error Code

SDK/API notifies the client about whether the request success or fails via HTTP status code

HTTP Status Codeerror_codeDescription
200N/aImage set creation successfully
4005004Missing image set name
4033003The total count of image sets for single account has an upper bound. Once user created too many image sets more than the limitation, he will receive this error code. More information, please read What is the difference between paid account and trial account?

List Image Sets

Python

PHP

Java

C#

cURL

from productai import Client

cli = Client(ACCESS_KEY_ID, SECRET_KEY)
api = cli.get_image_set_api()
resp = api.get_image_sets()
use ProductAI;

$product_ai = new ProductAI\API($access_key_id=ACCESS_KEY_ID, $secret_key=SECRET_KEY);
$result = $product_ai->getImageSets();
import cn.productai.api.core.*;
import cn.productai.api.core.enums.*;
import cn.productai.api.pai.entity.dataset.GetAllDataSetsRequest;
import cn.productai.api.pai.entity.dataset.GetAllDataSetsResponse;

IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

IWebClient client = new DefaultProductAIClient(profile);
GetAllDataSetsRequest request = new GetAllDataSetsRequest();
request.setLanguage(LanguageType.Chinese);

GetAllDataSetsResponse response = client.getResponse(request);

// return all the fields as JSON
//String json = response.getResponseJsonString();
using MalongTech.ProductAI.Core;
using MalongTech.ProductAI.API.Entity;

IProfile profile = new DefaultProfile
{
Version="1",
AccessKeyId=ACCESS_KEY_ID,
SecretKey=SECRET_KEY
};
var client = new DefaultProductAIClient(profile);

// Create request
var request = new GetAllDataSetsRequest;

var response = client.GetResponse(request);
curl -X GET \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
https://api.productai.com/get_image_sets/_0000014

Request

N/a

Response

200 HTTP Status Code
200 {
"request_id": "a05da544-0f9c-11e8-8f9b-0242ac120103",
"results": [
{
"created_at": "2018-02-06T12:32:22Z",
"creator_id": ...,
"description": "...",
"id": "37coud1d",
"modified_at": "2018-02-07T01:53:12Z",
"n_downloaded": 319,
"n_failed": 0,
"n_items": 319,
"name": "...",
"status": "downloaded"
},
...
]
}
FieldTypeDescription
resultsArrayAll the existing image sets, the fields of single item in array is same as Create Image Set Response
request_idStringThe unique ID of this request, it can be used in product issue debugging with ProductAI support team

Error Code

SDK/API notifies the client about whether the request success or fails via HTTP status code

HTTP Status Codeerror_codeDescription
200N/aList image sets successfully

Fetch Image Set

Python

PHP

Java

C#

cURL

from productai import Client

cli = Client(ACCESS_KEY_ID, SECRET_KEY)
api = cli.get_image_set_api(IMAGE_SET_ID)
resp = api.get_image_set()
use ProductAI;

$product_ai = new ProductAI\API($access_key_id=ACCESS_KEY_ID, $secret_key=SECRET_KEY);
$result = $product_ai->getImageset($set_id=IMAGE_SET_ID);
import cn.productai.api.core.*;
import cn.productai.api.core.enums.*;
import cn.productai.api.pai.entity.dataset.*;

IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

// Create a request with a IMAGE_SET_ID
IWebClient client = new DefaultProductAIClient(profile);
GetDataSetInfoRequest request = new GetDataSetInfoRequest(IMAGE_SET_ID);
request.setLanguage(LanguageType.Chinese);

// Parse the result from response
GetDataSetInfoResponse response = client.getResponse(request);
String json = response.getResponseJsonString();
using MalongTech.ProductAI.Core;
using MalongTech.ProductAI.API.Entity;

IProfile profile = new DefaultProfile
{
Version = "1",
AccessKeyId = ACCESS_KEY_ID,
SecretKey = SECRET_KEY
};
var client = new DefaultProductAIClient(profile);

// Create a request with IMAGE_SET_ID
var request = new GetDataSetInfoRequest
{
DataSetId = IMAGE_SET_ID
};

var response = client.GetResponse(request);
curl -X GET \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
https://api.productai.com/image_sets/_0000014/IMAGE_SET_ID

Request

N/a

Response

Same as Create Image Set Response

Error Code

SDK/API notifies the client about whether the request success or fails via HTTP status code

HTTP Status Codeerror_codeDescription
200N/aFetch image set successfully
4031002Authentication failed
4042001Image set doesn’t exist

Modify Image Set

Python

PHP

Java

C#

cURL

from productai import Client

cli = Client(ACCESS_KEY_ID, SECRET_KEY)
api = cli.get_image_set_api(IMAGE_SET_ID)

# Modify the name of image set
resp = api.update_image_set(name=NEW_NAME)

# Modify the description of image set
resp = api.update_image_set(description=NEW_DESC)

# Modify both
resp = api.update_image_set(name=NEW_NAME, description=NEW_DESC)
use ProductAI;

$product_ai = new ProductAI\API($access_key_id=ACCESS_KEY_ID, $secret_key=SECRET_KEY);
$result = $product_ai->updateImageSetNameDesc($set_id=IMAGE_SET_ID, $name=NEW_NAME, $description=NEW_DESC);
import cn.productai.api.core.*;
import cn.productai.api.core.enums.*;
import cn.productai.api.pai.entity.dataset.*;

IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

// Set image set name and description
IWebClient client = new DefaultProductAIClient(profile);
UpdateDataSetRequest request = new UpdateDataSetRequest(IMAGE_SET_ID, SET_NAME, SET_DESC);
request.setLanguage(LanguageType.Chinese);

// Parse the response
UpdateDataSetResponse response = client.getResponse(request);
String json = response.getResponseJsonString();
using MalongTech.ProductAI.Core;
using MalongTech.ProductAI.API.Entity;

IProfile profile = new DefaultProfile
{
Version = "1",
AccessKeyId = ACCESS_KEY_ID,
SecretKey = SECRET_KEY
};
var client = new DefaultProductAIClient(profile);

// Create a request with new name and new description
var request = new UpdateDataSetRequest
{
Name = SET_NAME,
Description = SET_DESC,
DataSetId = IMAGE_SET_ID,
};
var response = client.GetResponse(request);
curl -X PUT \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
-H 'Content-Type: application/json' \
-d '{"name": "NEW_NAME", "description": "NEW_DESC"}' \
https://api.productai.com/image_sets/_0000014/IMAGE_SET_ID

Request

Same as Create Image Set Request

Response

Same as Create Image Set Response

Error Code

SDK/API notifies the client about whether the request success or fails via HTTP status code

HTTP Status Codeerror_codeDescription
200N/aModify image set successfully
4005004Empty image set name is disallowed
4031002Authentication failed
4042001Image set doesn’t exist

Delete Image Set

Python

PHP

Java

C#

cURL

from productai import Client

cli = Client(ACCESS_KEY_ID, SECRET_KEY)
api = cli.get_image_set_api(IMAGE_SET_ID)

resp = api.delete_image_set()
use ProductAI;

$product_ai = new ProductAI\API($access_key_id=ACCESS_KEY_ID, $secret_key=SECRET_KEY);
$result = $product_ai->removeImageSet($set_id=IMAGE_SET_ID);
import cn.productai.api.core.*;
import cn.productai.api.core.enums.*;
import cn.productai.api.pai.entity.dataset.*;

IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

IWebClient client = new DefaultProductAIClient(profile);
DeleteDataSetRequest request = new DeleteDataSetRequest(IMAGE_SET_ID);
request.setLanguage(LanguageType.Chinese);

DeleteDataSetResponse response = client.getResponse(request);
String json = response.getResponseJsonString();
using MalongTech.ProductAI.Core;
using MalongTech.ProductAI.API.Entity;

IProfile profile = new DefaultProfile
{
Version = "1",
AccessKeyId = ACCESS_KEY_ID,
SecretKey = SECRET_KEY
};
var client = new DefaultProductAIClient(profile);

var request = new DeleteDataSetRequest
{
DataSetId = IMAGE_SET_ID
};
var response = client.GetResponse(request);
curl -X POST \
-H 'x-ca-accesskeyid:ACCESS_KEY_ID' \
https://api.productai.com/image_sets/_0000014/IMAGE_SET_ID

Request

N/a

Response

N/a

Error Code

SDK/API notifies the client about whether the request success or fails via HTTP status code

HTTP Status Codeerror_codeDescription
204N/aDelete image set successfully
4031002Authentication failed
4033001Can’t delete image set because some running services depend on it.
4042001Image set doesn’t exist

Data

There are 3 fields can be included in a image data:

  • url,Url of uploading image, currently this url is used as the unique ID, that means different url indicates different image data.
  • metadata,information about the image, it is returned in response along with image
  • tags,tags for the image, it is searched with image and can be used in tag filter. Note that multiple tags should be delimited by |

Add Single Data to Image Set

Python

PHP

Java

C#

cURL

from productai import Client

cli = Client(ACCESS_KEY_ID, SECRET_KEY)
api = cli.get_image_set_api(IMAGE_SET_ID)
api.add_image(url, meta, tags='cartoon|square')
use ProductAI;

$product_ai = new ProductAI\API($access_key_id=ACCESS_KEY_ID, $secret_key=SECRET_KEY);
$result = $product_ai->addImageToSet($set_id=IMAGE_SET_ID, $image_url='http://yyyy', $meta="metadata" , $tags=['cartoon','square']);
import java.util.ArrayList;
import cn.productai.api.core.*;
import cn.productai.api.core.enums.*;
import cn.productai.api.pai.entity.dataset.*;

IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

IWebClient client = new DefaultProductAIClient(profile);

ArrayList<String> tagList = new ArrayList<String>();
tagList.add("cartoon");
tagList.add("square");

DataSetSingleAddByImageUrlRequest request = new DataSetSingleAddByImageUrlRequest(IMAGE_SET_ID, tagList, "metadata");
request.imageUrl = "http://yyyy";
request.setLanguage(LanguageType.Chinese);

DataSetBaseResponse response = client.getResponse(request);
String json = response.getResponseJsonString();
using MalongTech.ProductAI.Core;
using MalongTech.ProductAI.API.Entity;

IProfile profile = new DefaultProfile
{
Version = "1",
AccessKeyId = ACCESS_KEY_ID,
SecretKey = SECRET_KEY
};
var client = new DefaultProductAIClient(profile);

// Create a request to add an image with url, tags, and metadata. tags and metadata are optional fields.
var request = new DataSetSingleAddByImageUrlRequest(IMAGE_SET_ID, "http://yyyy",tags=new List<String>() {"cartoon", "square"}, metaId="metadata");
var response = client.GetResponse(request);
curl -X POST \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
-d 'image_url=http://yyyy&meta=metadata&tags=cartoon|square' \
https://api.productai.com/image_sets/_0000014/IMAGE_SET_ID

Request

ArgumentTypeDescriptionRequiredLimitation
urlStringURL for uploading imageYesMaximum 512 unicode characters, will raise an error if length exceeds this limit
metaStringData descriptionNoMaximum 512 unicode characters, will raise an error if length exceeds this limit
tagsStringData tagsNoTags are indexed along with image data, and are used in filtering requests initiated by user. Note that this field can contain multiple tags, they should be delimited with ‘|’, For example: coat|tshirt|POLO. Please use utf-8 encoding for non-ascii characters

Response

Same as Create Image Set Response

Error Code

SDK/API notifies the client about whether the request success or fails via HTTP status code

HTTP Status Codeerror_codeDescription
200N/aUpload data successfully
4005001Url contains more than 512 unicode characters, or Url is empty, or meta field contains more than 512 unicode characters
4031002Authentication failed
4042001Image set doesn’t exist
5004001Can’t download the image from url.

Add Multiple Data to Image Set

It is recommended to use csv file to prepare image data, and then upload the csv file. Note that each line in the csv file should contain one image data. The format should follow this pattern: each line contains 3 columns, that is image Url, image metadata(optional), tags(optional). For details, please refer to csv file example. Example of batch uploading images to image set:

Python

PHP

Java

C#

cURL

from productai import Client

cli = Client(ACCESS_KEY_ID, SECRET_KEY)
api = cli.get_image_set_api(IMAGE_SET_ID)
with open('added.csv') as f:
api.add_images_in_bulk(f)
use ProductAI;
$product_ai = new ProductAI\API($access_key_id=ACCESS_KEY_ID, $secret_key=SECRET_KEY);
$result = $product_ai->addImagesToSet($set_id=IMAGE_SET_ID, $filename = 'added.csv');
import java.io.File;
import cn.productai.api.core.*;
import cn.productai.api.core.enums.*;
import cn.productai.api.pai.entity.dataset.*;

IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

IWebClient client = new DefaultProductAIClient(profile);
DataSetBatchAddRequest request = new DataSetBatchAddRequest(IMAGE_SET_ID);
request.setCsvFile(new File("added.csv"));
request.setLanguage(LanguageType.Chinese);

DataSetBaseResponse response = client.getResponse(request);
String json=response.getResponseJsonString();
using MalongTech.ProductAI.Core;
using MalongTech.ProductAI.API.Entity;

IProfile profile = new DefaultProfile
{
Version = "1",
AccessKeyId = ACCESS_KEY_ID,
SecretKey = SECRET_KEY
};
var client = new DefaultProductAIClient(profile);

var request = new DataSetBatchAddRequest(IMAGE_SET_ID)
{
CsvFile = new System.IO.FileInfo(@"added.csv")
};
var response = client.GetResponse(request);
curl -X POST \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
-F "urls_to_add=@add.csv" \
https://api.productai.com/image_sets/_0000014/IMAGE_SET_ID

This API service also supports tar.gz compressed file. You can create compressed file by following command

tar zcvf added.tar.gz added.csv

Request

ArgumentTypeDescriptionRequiredLimitation
fFilecsv file content, for csv file format please refer to csv file exampleYesshould be smaller than 50MB

Response

Same as Create Image Set Response

Error Code

SDK/API notifies the client about whether the request success or fails via HTTP status code

HTTP Status Codeerror_codeDescription
200N/aSuccess
4005001Invalid csv file, for example: contains more than 3 columns in one line, the first column is not a valid url
4031002Authentication failed
4042001Image set doesn’t exist

Delete Multiple Data from Image Set

Python

PHP

Java

C#

cURL

from productai import Client

cli = Client(ACCESS_KEY_ID, SECRET_KEY)
api = cli.get_image_set_api(IMAGE_SET_ID)
with open('deleted.csv') as f:
api.delete_images_in_bulk(f)
use ProductAI;

$product_ai = new ProductAI\API($access_key_id=ACCESS_KEY_ID, $secret_key=SECRET_KEY);
$result = $product_ai->removeImagesFromSet($set_id=IMAGE_SET_ID, $filename = 'deleted.csv');
import java.io.File;
import cn.productai.api.core.*;
import cn.productai.api.core.enums.*;
import cn.productai.api.pai.entity.dataset.*;

IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

IWebClient client = new DefaultProductAIClient(profile);
DataSetBatchDeleteRequest request = new DataSetBatchDeleteRequest(IMAGE_SET_ID);
request.setCsvFile(new File("deleted.csv"));
request.setLanguage(LanguageType.Chinese);

DataSetBaseResponse response = client.getResponse(request);
String json = response.getResponseJsonString();
using MalongTech.ProductAI.Core;
using MalongTech.ProductAI.API.Entity;

IProfile profile = new DefaultProfile
{
Version = "1",
AccessKeyId = ACCESS_KEY_ID,
SecretKey = SECRET_KEY
};
var client = new DefaultProductAIClient(profile);

var request = new DataSetBatchDeleteRequest(IMAGE_SET_ID)
{
CsvFile = new System.IO.FileInfo(@"deleted.csv")
};
var response = client.GetResponse(request);
curl -X POST \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
-F "urls_to_delete=@deleted.csv" \
https://api.productai.com/image_sets/_0000014/IMAGE_SET_ID

Request

ArgumentTypeDescriptionRequiredLimitation
fFilecsv file content, for csv file format please refer to csv file example. Note that only URL, which is the unique ID for an image, is required when deleting an imageYesshould be smaller than 50MB

Response

Same as Create Image Set Response

Error Code

SDK/API notifies the client about whether the request success or fails via HTTP status code

HTTP Status Codeerror_codeDescription
200N/aSuccess
4005001Invalid csv file, for example: contains more than 3 columns in one line, the first column is not a valid url
4031002Authentication failed
4042001Image set doesn’t exist

Update Multiple Data in Image Set

Please use the method introduced in Batch uploading to update metadata and tags information in image data set. ProductAI image search service uses URL as unique ID for every image. When uploading data, ProductAI will not re-download or re-insert the image if its URL already exists in data set. Note that metadata and tags will be updated if they are provided in uploaded data.

Scenario

Image search service uses different model for different scenario, for example: you can expect a model trained on furnitures to gain a good performance if you use this model on furniture scenario, but it is highly possible to see a bad performance in a fashion clothes scenario. To analogy with traditional relational database, a scenario can be recognized as a index of data table

The most important parameter for search service creation is scenario. According to your data characters (e.g. UGC or PGC (Professional Generated Content), furniture or apparel), choose an appropriate scenario model.

Supported Scenarios

Currently supported scenarios on ProductAI:

Scenario nameScenario ID(Used as parameter by SDK/API to initiate scenario)Current versionDescription
Fashionfashion_v5_5v5.5For fashion image search scenario which uses PGC (Professional Generated Content) and UGC data as traning set, it fits in fashion image search product management systems. Reference: 19 Fashion Tags
Shoeshoe_v1v1.0For shoe image search scenario which uses PGC (Professional Generated Content) and UGC data as training set. Suitable for shoe e-commerce search products and product management systems
Furniturefurniture_v6v6.0For furniture image search scenario which uses PGC (Professional Generated Content) and UGC data as traning set, it fits in furniture image search product management systems
Winewine_v2_1v2.1For wine image search scenario which uses UGC data as traning set, it fits in wine image search product management systems
Materialmaterialv1.0For material image search scenario which uses PGC (Professional Generated Content) and UGC data as traning set, it fits in material(especially on patterns) image search product management systems. For best results please use flat material images when creating dataset. Our models are optimized for flat material images. See the Reference 2
Generalgeneralv1.0For general image search scenario which uses PGC (Professional Generated Content) data as traning set, it fits in general image search systems
Ecommerce Productecom_product_v1v1.1For e-commerce product image search scenario which uses PGC (Professional Generated Content) data as traning set, it can be used to search similar product

Reference 1:PGC (Professional Generated Content), UGC

Reference 2:Examples of fabric pictures

SupportNonsupport
FlatRolled

Search Service

Create Search Service

With dataset, and by choosing a suitable scenario, you can create a search service. And then users can query this search service right after this service is created. But please note that at this initial stage only a few images can be fetched because the indexing process is just started. The whole indexing stage will finish after a certain time frame. The total time cost depends on image data size, scenario model complexity and infrastructure resources used on this service which is scheduled by ProductAI. Please contact our account manager if you need a priority indexing service.

Python

PHP

Java

C#

cURL

from productai import Client

cli = Client(ACCESS_KEY_ID, SECRET_KEY)

api = cli.get_image_set_api(IMAGE_SET_ID)

resp = api.create_service(name='NAME', scenario='fashion_v5_5')

import json
service = json.loads(resp.content)
service_id = service['id']
use ProductAI;

$product_ai = new ProductAI\API($access_key_id=ACCESS_KEY_ID, $secret_key=SECRET_KEY);
$result = $product_ai->createService($image_set_id=IMAGE_SET_ID, $name='NAME', $scenario='fashion_v5_5');
$service_id = $result['id']
import cn.productai.api.core.*;
import cn.productai.api.core.enums.*;
import cn.productai.api.pai.entity.service.*;

IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

IWebClient client = new DefaultProductAIClient(profile);
CreateSearchServiceRequest request = new CreateSearchServiceRequest(IMAGE_SET_ID, "NAME", "fashion_v5_5");
request.setLanguage(LanguageType.Chinese);

CreateSearchServiceResponse response = client.getResponse(request);

String service_id = response.getServiceId();
// Parse the response
//String json = response.getResponseJsonString();
using MalongTech.ProductAI.Core;
using MalongTech.ProductAI.API.Entity;

IProfile profile = new DefaultProfile
{
Version = "1",
AccessKeyId = ACCESS_KEY_ID,
SecretKey = SECRET_KEY
};
var client = new DefaultProductAIClient(profile);

var request = new CreateSearchServiceRequest(IMAGE_SET_ID, "NAME", "fashion_v5_5");
var response = client.GetResponse(request);
var serviceId = response.ServiceId;
curl -X POST \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
-H 'Content-Type: application/json' \
-d '{"name": "NAME", "scenario": "fashion_v5_5"}' \
https://api.productai.com/image_sets/_0000014/IMAGE_SET_ID/services

Request

ArgumentTypeDescriptionRequiredLimitation
nameStringService NameRequired32 unicode characters, the extra characters are truncated
scenarioStringScenario TypeRequiredMust be one of Supported Scenarios

Response

200 HTTP Status Code
{
"created_at": "2017-12-17T13:49:56Z",
"creator_id": 2031,
"id": "790jvquc",
"image_set_id": "0mspcj1m",
"indexed_ratio": 0,
"last_indexed_time": null,
"last_updated_at": null,
"n_indexed": 0,
"name": "xxx",
"request_id": "298f4aea-e331-11e7-a97c-664c03c7cfbb",
"scenario": "fashion_v5_4",
"status": "running",
"status_duration": 0
}
FieldTypeDescription
created_atStringCreated UTC datetime, the format is: %Y-%m-%dT%H:%M:%SZ
creator_idIntegerCreator ID
idStringUnique ID of search service, all following operations are depending on this ID
image_set_idStringdataset ID which is used for current service
indexed_ratioFloatration = indexed image amount / downloaded image amount
last_indexed_timeStringlast index deployed time for this service
last_updated_atStringlast modified UTC time, to seconds, the format is: %Y-%m-%dT%H:%M:%SZ
n_indexedIntegercurrently indexed amount
nameStringsearch service name
request_idStringThe unique ID of this request, it can be used in product issue debugging with ProductAI support team
statusStringonly one status running right now
status_durationIntegerN/a
typeIntegerN/a
Non-200 HTTP Status Code
{
"error_code": 5003,
"message": "Scenarios Not Supported",
"request_id": "a0393714-e331-11e7-9a0f-b217471bc47d"
}
FieldTypeDescription
error_codeIntegerdetailed error code
messageStringdetailed error message
request_idStringThe unique ID of this request, it can be used in product issue debugging with ProductAI support team

Error Code

SDK/API notifies the client about whether the request success or fails via HTTP status code

HTTP Status Codeerror_codeDescription
200N/aSuccess
4005003specified scenario does not exist
4033004Created service amount exceeded account limit, please refer to account limitations
4093002Only one scenario can be created upon one image set, server will return an error if user try to create another service upon the same image dataset

List Search Services

Python

PHP

Java

C#

cURL

from productai import Client

cli = Client(ACCESS_KEY_ID, SECRET_KEY)
api = cli.get_customer_service_api()
resp = api.get_services()
use ProductAI;

$product_ai = new ProductAI\API($access_key_id=ACCESS_KEY_ID, $secret_key=SECRET_KEY);
$result = $product_ai->getServices();
import cn.productai.api.core.*;
import cn.productai.api.core.enums.*;
import cn.productai.api.pai.entity.service.GetAllServicesRequest;
import cn.productai.api.pai.entity.service.GetAllServicesResponse;

IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

IWebClient client = new DefaultProductAIClient(profile);
GetAllServicesRequest request = new GetAllServicesRequest();
request.setLanguage(LanguageType.Chinese);

GetAllServicesResponse response = client.getResponse(request);
String json = response.getResponseJsonString();
using MalongTech.ProductAI.Core;
using MalongTech.ProductAI.API.Entity;

IProfile profile = new DefaultProfile
{
Version="1",
AccessKeyId=ACCESS_KEY_ID,
SecretKey=SECRET_KEY
};
var client = new DefaultProductAIClient(profile);

var request = new GetAllServicesRequest();
var response = client.GetResponse(request);
curl -X GET \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
https://api.productai.com/customer_services/_0000172

Request

N/a

Response

200 HTTP Status Code
{
"request_id": "a06e3800-0f9c-11e8-8f9b-0242ac120103",
"results": [
{
"created_at": "2018-02-06T12:49:49Z",
"creator_id": ...,
"id": "...",
"image_set_id": "...",
"indexed_ratio": 1.0,
"last_indexed_time": "2018-02-08T07:01:49Z",
"last_updated_at": "2018-02-08T06:53:53Z",
"n_indexed": 319,
"name": "...",
"scenario": "furniture_v6",
"status": "running",
"status_duration": 0,
"type": 1
},
...
]
}
FieldTypeDescription
resultsArrayList all the customer’s running services,the field of single service is same as Create Search Service Response
request_idStringThe unique ID of this request, it can be used in product issue debugging with ProductAI support team

Error Code

SDK/API notifies the client about whether the request success or fails via HTTP status code

HTTP Status Codeerror_codeDescription
200N/aSuccess

Fetch Search Service

Python

PHP

Java

C#

cURL

from productai import Client

cli = Client(ACCESS_KEY_ID, SECRET_KEY)
api = cli.get_customer_service_api(SERVICE_ID)
resp = api.get_service()

import json
service = json.loads(resp.content)
service_id = service['id']
service_status = service['status']
use ProductAI;
$product_ai = new ProductAI\API($access_key_id=ACCESS_KEY_ID, $secret_key=SECRET_KEY);
$result = $product_ai->getService($service_id=SERVICE_ID);
import cn.productai.api.core.*;
import cn.productai.api.core.enums.*;
import cn.productai.api.pai.entity.service.*;

IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

IWebClient client = new DefaultProductAIClient(profile);
GetServiceInfoRequest request = new GetServiceInfoRequest(SERVICE_ID);
request.setLanguage(LanguageType.Chinese);

GetServiceInfoResponse response = client.getResponse(request);
String json = response.getResponseJsonString();
using MalongTech.ProductAI.Core;
using MalongTech.ProductAI.API.Entity;

IProfile profile = new DefaultProfile
{
Version = "1",
AccessKeyId = ACCESS_KEY_ID,
SecretKey = SECRET_KEY
};
var client = new DefaultProductAIClient(profile);

var request = new GetServiceInfoRequest
{
ServiceId = SERVICE_ID
};
var response = client.GetResponse(request);
curl -X GET \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
https://api.productai.com/customer_services/_0000172/SERVICE_ID

Request

N/a

Response

Same as Create Search Service Response

Error Code

SDK/API notifies the client about whether the request success or fails via HTTP status code

HTTP Status Codeerror_codeDescription
200N/aSuccess
4031003Authentication failed
4042002Service does not exist

Modify Search Service

Python

PHP

Java

C#

cURL

from productai import Client

cli = Client(ACCESS_KEY_ID, SECRET_KEY)
api = cli.get_customer_service_api(SERVICE_ID)
api.update_service(name='NEW_NAME')
use ProductAI;

$product_ai = new ProductAI\API($access_key_id=ACCESS_KEY_ID, $secret_key=SECRET_KEY);
$result = $product_ai->updateServiceName($service_id=SERVICE_ID, $name='NEW_NAME');
import cn.productai.api.core.*;
import cn.productai.api.core.enums.*;
import cn.productai.api.pai.entity.service.*;

IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

IWebClient client = new DefaultProductAIClient(profile);
UpdateServiceRequest request = new UpdateServiceRequest(SERVICE_ID, "NEW_NAME");
request.setLanguage(LanguageType.Chinese);

UpdateServiceResponse response = client.getResponse(request);
String json = response.getResponseJsonString();
using MalongTech.ProductAI.Core;
using MalongTech.ProductAI.API.Entity;

IProfile profile = new DefaultProfile
{
Version = "1",
AccessKeyId = ACCESS_KEY_ID,
SecretKey = SECRET_KEY
};
var client = new DefaultProductAIClient(profile);

var request = new UpdateServiceRequest
{
Name = "NEW_NAME",
ServiceId = SERVICE_ID
};
var response = client.GetResponse(request);
curl -X PUT \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
-H 'Content-Type: application/json' \
-d '{"name": "NEW_NAME"}' \
https://api.productai.com/customer_services/_0000172/SERVICE_ID

Request

ArgumentTypeDescriptionRequiredLimitation
nameStringService nameRequired32 characters, will be truncated if length is over 32

Response

Same as Create Search Service Response

Error Code

SDK/API notifies the client about whether the request success or fails via HTTP status code

HTTP Status Codeerror_codeDescription
200N/aSuccess
4031003Authentication failed
4042002Service does not exist

Delete Search Service

Python

PHP

Java

C#

cURL

from productai import Client

cli = Client(ACCESS_KEY_ID, SECRET_KEY)
api = cli.get_customer_service_api(SERVICE_ID)
api.delete_service()
use ProductAI;

$product_ai = new ProductAI\API($access_key_id=ACCESS_KEY_ID, $secret_key=SECRET_KEY);
$result = $product_ai->removeService($service_id=SERVICE_ID);
import cn.productai.api.core.*;
import cn.productai.api.core.enums.*;
import cn.productai.api.pai.entity.service.*;

IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

IWebClient client = new DefaultProductAIClient(profile);
DeleteServiceRequest request = new DeleteServiceRequest(SERVICE_ID);
request.setLanguage(LanguageType.Chinese);

DeleteServiceResponse response = client.getResponse(request);
String json = response.getResponseJsonString();
using MalongTech.ProductAI.Core;
using MalongTech.ProductAI.API.Entity;

IProfile profile = new DefaultProfile
{
Version = "1",
AccessKeyId = ACCESS_KEY_ID,
SecretKey = SECRET_KEY
};
var client = new DefaultProductAIClient(profile);

var request = new DeleteServiceRequest
{
ServiceId = SERVICE_ID
};
var response = client.GetResponse(request);
curl -X DELETE \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
https://api.productai.com/customer_services/_0000172/SERVICE_ID

Request

N/a

Response

N/a

Error Code

SDK/API notifies the client about whether the request success or fails via HTTP status code

HTTP Status Codeerror_codeDescription
204N/aSuccess
4031003Authentication failed
4042002Service does not exist

Python

PHP

Java

C#

cURL

from productai import Client

cli = Client(ACCESS_KEY_ID, SECRET_KEY)
api = cli.get_image_search_api(SERVICE_ID)

resp = api.query(image='http://yyyy', loc='0.1-0.1-0.8-0.7')

with open("fashion.jpg", mode='rb') as search:
resp = api.query(search)

# Indicate query result should contain MALE and SHOES tag
resp = api.query('http://yyyy', count=2, tags=['MALE', 'SHOES'])

# Or set the condition in following way, "|" equals to "and" operator
resp = api.query('http://yyyy', count=2, tags='MALE|SHOES')

# Or use a comprehansive search condition
resp = api.query('http://yyyy', count=2, tags={'and': ['MALE', 'SHOES', {'or': ['TMALL', 'TAOBAO']}]})
use ProductAI;

$product_ai = new ProductAI\API($access_key_id=ACCESS_KEY_ID, $secret_key=SECRET_KEY);

$result = $product_ai->searchImage($service_type='search', $service_id=SERVICE_ID, $image='http://yyyy',loc=[0, 0.1, 0.4, 0.5])

$result = $product_ai->searchImage($service_type='search', $service_id=SERVICE_ID, $image = '@zzzz.jpg')

// Indicate query result should contain MALE and SHOES tag
$result = $product_ai->searchImage($service_type='search', $service_id=SERVICE_ID, $image='http://yyyy',$count=2, $tags=['MALE', 'SHOES'])

// Or set the condition in following way, "|" equals to "and" operator
$result = $product_ai->searchImage($service_type='search', $service_id=SERVICE_ID, $image = '@zzzz.jpg',$tags='MALE|SHOES')

// Or use a comprehansive search condition
$result = $product_ai->searchImage($service_type='search', $service_id=SERVICE_ID, $image = '@zzzz.jpg',tags='{"and":["123",{"or":["456","789"]}]}'
import java.io.File;
import cn.productai.api.core.*;
import cn.productai.api.core.enums.*;
import cn.productai.api.pai.entity.search.*;

IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);
IWebClient client = new DefaultProductAIClient(profile);

// Indicate query result should contain MALE and SHOES tag
ISearchTag andTag = new AndTag();
andTag.Add("MALE");
andTag.Add("SHOES");

// Condition OR, with a TMALL tag
ISearchTag orTag = new OrTag();
orTag.Add("TMALL");
andTag.Add(orTag);

ITag searchTag = new SearchTag();
searchTag.setTag(andTag);

ImageSearchByImageUrlRequest request = new ImageSearchByImageUrlRequest(SERVICE_ID);
request.setUrl("http://yyyy");

ImageSearchByImageFileRequest request = new ImageSearchByImageFileRequest(SERVICE_ID);
request.setImageFile(new File("zzzz.jpg"));

request.setCount(2);
request.setSearchTag(searchTag);
request.setLanguage(LanguageType.Chinese);

ImageSearchResponse response = client.getResponse(request);
String json = response.getResponseJsonString();
using MalongTech.ProductAI.Core;
using MalongTech.ProductAI.API.Entity;

IProfile profile = new DefaultProfile
{
Version = "1",
AccessKeyId = ACCESS_KEY_ID,
SecretKey = SECRET_KEY
};
var client = new DefaultProductAIClient(profile);

ISearchTag andTag = new AndTag();
andTag.Add(new List<string> { "MALE", "SHOES" });

ISearchTag orTag = new OrTag();
orTag.Add("TMALL");
andTag.Add(orTag);

ITag searchTag = new SearchTag
{
Tag = andTag
};

var request = new ImageSearchByImageUrlRequest(SERVICE_ID)
{
Url = "http://yyyy",
SearchTag = searchTag
};
request.Options.Add("count", "1");

var request = new ImageSearchByImageFileRequest("k7h9fail")
{
ImageFile = new System.IO.FileInfo(@"zzzz.jpg"),
SearchTag = searchTag
};

var response = client.GetResponse(request);
# Request service by URL
curl -X POST \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
-H 'Content-Type: application/json' \
-d '{"url":"http://yyyy","count":"2","tags":{"and":["123",{"or":["456","789"]}]}}' \
https://api.productai.com/search/SERVICE_ID

# Request service by local file
curl -X POST \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
-F "search=@zzzz.jpg" \
-F "count=2" \
-F 'tags={"and":["123",{"or":["456","789"]}]}' \
https://api.productai.com/search/SERVICE_ID

Request

ArgumentTypeDescriptionRequiredLimitation
searchFileImage content for queryYesShould fill this field or url
urlStringImage url for queryYesShould fill this field or search
countIntegerSpecify result countNo10 by default, the value range is [1-3000], but should no more than 3000
tagsStringData tagsNoTags can be used as filtering condition of search result. These tags are specified by user when uploading/updating data, they are not generated automatically. A simple way to leverage these tags: when use multiple tags, please delimit with “|”. Service will return result which contains all the tags specified in the condition. For example, coat|tshirt|POLO. Please use utf-8 encoding for non-ascii characters. For complex condition: 1), {“or”, [one or more sub-conditions]}, {“and”: [one or more sub-conditions]}. For example: tags={“and”:[“coat”,{“or”:[“blue”,”leisure”]}]}. Please refer to usage of tags
locStringSearch area within a imageNoBounding box info, format is ”x-y-w-h”。x,y,w,h means:mark top left corner of image as (0,0), right bottom corner as (1,1), x is bounding-box-left-position/image-width , y is bounding-box-top-position/image-height, w is bounding-box-width/image-width, h is bounding-box-height/image-height, for details please refer to loc usage

Response

200 HTTP Status Code
{
"detect_time": "0.000",
"detection_score": null,
"download_time": "0.004",
"ds": "70awubt0",
"is_err": 0,
"loc": [
0,
0,
1080,
1920
],
"most_common_tags": [],
"preprocess_time": "0.005",
"request_id": "d2605570-e33a-11e7-9a73-92019f9dce87",
"results": [
...
],
"searchtime": "0.307",
"time": "0.324",
"type": [
"Jumpsuit-romper",
"beidaiku",
"leisure-pants",
"flat-sandals",
"bodycon-dress",
"Culotte-pants"
],
"ver": "20171113-135702"
}

results field is an arrary, it contains all the search results, for details please refer to Results details

Fields relate to time

FieldTypeDescription
detect_timeStringTime cost of detection, seconds
download_timeStringTime cost of image downloading, seconds
preprocess_timeStringTime cost of preprocessing, seconds
searchtimeStringTime cost of search, seconds
timeStringTotal time cost on server side, seconds

Fields relate to detector

FieldTypeDescription
detect_timeStringTime cost of detection, seconds
detection_scoreFloatConfidence score returned by detection service
locArrayReturned from detection service, object detected with highest score, values are x, y, w, h
typeArrayReturned from detection service, category of detected object

Other fields

FieldTypeDescription
dsStringdeprecated, please do not use
is_errIntegerdeprecated, please do not use
most_common_tagsArrayFor details please refer to ret_img_tags
request_idStringUnique ID of this API call, can be used in issue debugging with ProductAI support team
verStringindex version number

Results details

{
"metadata": "131",
"score": 0.5732779921465632,
"url": "http://xxx/131/ab505d2fd40e17f64397c796adfb6a8b.jpg",
"tags": [
"FEMALE",
"FOREVER21",
"ONE-PIECE"
]
}
FieldTypeDescription
urlStringUrl of result image
scoreFloatSimilarity score with query image
metadataStringMetadata of result image, please refer to metadata
tagsArrayTags of result image, please refer to ret_img_tags
Non-200 HTTP Status Code
{
"error_code": 1004,
"message": "Image Downloading Not Found",
"request_id": "eccff8dc-b86c-11e7-ab03-b66791ba711f"
}
FieldTypeDescription
error_codeIntegerThe detail error type
messageStringThe detail error message
request_idStringThe unique ID of this request, it can be used in product issue debugging with ProductAI support team

Error Code

SDK/API notifies the client about whether the request success or fails via HTTP status code

HTTP Status Codeerror_codeDescription
200N/aSuccess
4005001Invalid csv file, for example: contains more than 3 columns in one line, the first column is not a valid url
4031002Authentication failed
4042001Image set doesn’t exist
429N/aExceeds concurrency limits, please refer to concurrency limits

Duplication Scenarios

Accurate matching is a special image search scenario. It filters and re-orders the images after the normal image search model, in order to return the most accurate matching result with query image. It supports 2 scenarios currently Precise Creative Picture MatchingPrecise Ecommerce Product Image Matching

Since matching service is also a use case of image search, all the operations of search service can be used on matching service

Precise Creative Picture Matching

This service builds index for creative photos, art designs, paintings and movie pictures. User is able to find images that exactly the same or with a certain range of modifications (such as waterprint, add image effect filter, etc) compared to query image. This service can be used in IP protection of creative images or products, video content search, etc.

Query ImageSearch Result: water print, rotation, clipping, scaling, mirroring, color space shifting, etc
SampleImage1SampleImage2

Create a Precise Creative Picture Matching service

Python

PHP

Java

C#

cURL

from productai import Client

cli = Client(ACCESS_KEY_ID, SECRET_KEY)

api = cli.get_image_set_api(IMAGE_SET_ID)

resp = api.create_service(name='NAME', scenario='dedupe_tuku_v2')
use ProductAI;

$product_ai = new ProductAI\API($access_key_id=ACCESS_KEY_ID, $secret_key=SECRET_KEY);
$result = $product_ai->createService($image_set_id = IMAGE_SET_ID, $name = 'NAME', $scenario = 'dedupe_tuku_v2');
import cn.productai.api.core.*;
import cn.productai.api.core.enums.*;
import cn.productai.api.pai.entity.service.*;

IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

IWebClient client = new DefaultProductAIClient(profile);
CreateSearchServiceRequest request = new CreateSearchServiceRequest(IMAGE_SET_ID, "NAME", "dedupe_tuku_v2");
request.setLanguage(LanguageType.Chinese);

CreateSearchServiceResponse response = client.getResponse(request);
String json = response.getResponseJsonString();
using MalongTech.ProductAI.Core;
using MalongTech.ProductAI.API.Entity;

IProfile profile = new DefaultProfile
{
Version = "1",
AccessKeyId = ACCESS_KEY_ID,
SecretKey = SECRET_KEY
};
var client = new DefaultProductAIClient(profile);

var request = new CreateSearchServiceRequest(IMAGE_SET_ID, "NAME", "dedupe_tuku_v2");
var response = client.GetResponse(request);
var serviceId = response.ServiceId;
curl -X POST \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
-H 'Content-Type: application/json' \
-d '{"name": "NAME", "scenario": "dedupe_tuku_v2"}' \
https://api.productai.com/image_sets/_0000014/IMAGE_SET_ID/services

Precise E-Commerce Image Matching

This service indexes product images, user is able to find images that exactly the same or with a certain range of modifications (such as waterprint, add image effect filter, etc) compared to query image. This service can be used in product price comparing, relative searching, de-duplication, etc.

Query ImageSearch Result (even with some modifications, such as water print)
SampleImage1SampleImage2
Query ImageSearch result, with some pose difference
SampleImage1SampleImage2

Create a Precise E-commerce matching service

Python

PHP

Java

C#

cURL

from productai import Client

cli = Client(ACCESS_KEY_ID, SECRET_KEY)

api = cli.get_image_set_api(IMAGE_SET_ID)

resp = api.create_service(name='NAME', scenario='dedupe_v2')
use ProductAI;

$product_ai = new ProductAI\API($access_key_id=ACCESS_KEY_ID, $secret_key=SECRET_KEY);
$result = $product_ai->createService($image_set_id = IMAGE_SET_ID, $name = 'NAME', $scenario = 'dedupe_v2');
import cn.productai.api.core.*;
import cn.productai.api.core.enums.*;
import cn.productai.api.pai.entity.service.*;

IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

IWebClient client = new DefaultProductAIClient(profile);
CreateSearchServiceRequest request = new CreateSearchServ(IMAGE_SET_ID, "NAME", "dedupe_v2");
request.setLanguage(LanguageType.Chinese);

CreateSearchServiceResponse response = client.getResponse(request);
String json = response.getResponseJsonString();
using MalongTech.ProductAI.Core;
using MalongTech.ProductAI.API.Entity;

IProfile profile = new DefaultProfile
{
Version = "1",
AccessKeyId = ACCESS_KEY_ID,
SecretKey = SECRET_KEY
};
var client = new DefaultProductAIClient(profile);

var request = new CreateSearchServiceRequest(IMAGE_SET_ID, "NAME", "dedupe_v2");
var response = client.GetResponse(request);
var serviceId = response.ServiceId;
curl -X POST \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
-H 'Content-Type: application/json' \
-d '{"name": "NAME", "scenario": "dedupe_v2"}' \
https://api.productai.com/image_sets/_0000014/IMAGE_SET_ID/services

Advanced

Metadata

Any image in the imageset can have a metadata. Metadata can be any string without comma. This metadata will be returned to user along with image in the search result. Note that metadata is of maximum 512 unicode characters, will raise an error if length exceeds this limit.

  1. Image with product ID: set metadata as ID, query image to get ID, and then fetch detailed product information by this ID in your own database
  2. Image with product link: set metadata to contain url info, query image to get url and then navigate to this link
  3. Image with product details: set metadata to contain detailed product info (for example, a json object), query image to get detailed info to avoid time cost for fetching product details

Tags

Any image can contain a set of tags, multiple tags should be delimited with |, a tag must not contain comma. Search service will index tag along with image, user can use tags as search condition along with query image. We call this search as tag filtertag filter make the searching more accurate and more faster

  1. Since service search the only main object detected in query image, it is strongly recommended to use tags when query image including only one object. Or with loc parameter to specify the object wanting to search.
  2. Image category in tags: so that user can limit the result category
  3. Image related user ID in tags: so that user can limit the search only across some certain users, in order to implement scenarios such as personal photo albumns

Tag Syntax

Currently support 3 types

  • Pass tags as array with SDK

Python

PHP

Java

C#

cURL

api.query("http://yyyy", tags=['MALE', 'SHOES'])
$result = $product_ai->searchImage($service_type='search', $service_id=SERVICE_ID, $image='http://yyyy', $tags=['MALE', 'SHOES'])
ISearchTag andTag = new AndTag();
andTag.Add("MALE");
andTag.Add("SHOES");

ITag searchTag = new SearchTag();
searchTag.setTag(andTag);

ImageSearchByImageUrlRequest request = new ImageSearchByImageUrlRequest(SERVICE_ID);
request.setUrl("http://yyyy");
request.setSearchTag(searchTag);
ISearchTag andTag = new AndTag();
andTag.Add(new List<string> { "MALE", "SHOES" });

ITag searchTag = new SearchTag
{
Tag = andTag
};

var request = new ImageSearchByImageUrlRequest(SERVICE_ID);
request.Url = 'http://yyyy';
request.SearchTag = searchTag;
curl -X POST \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
-H 'Content-Type: application/json' \
-d '{"url":"http://yyyy","tags":{"and":["MALE","SHOES"]}}' \
https://api.productai.com/search/SERVICE_ID
  • Join a set of tags with delimiter “|”

Python

PHP

Java

C#

cURL

api.query(image_url, tags='MALE|SHOES')
$result = $product_ai->searchImage($service_type='search', $service_id=SERVICE_ID, $image='http://yyyy', $tags='MALE|SHOES')
ImageSearchByImageUrlRequest request = new ImageSearchByImageUrlRequest(SERVICE_ID);
request.setUrl("http://yyyy");
request.tags="MALE|SHOES";
// Not supported at this moment
curl -X POST \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
-H 'Content-Type: application/json' \
-d '{"url":"http://yyyy","tags":"MALE|SHOES"}' \
https://api.productai.com/search/SERVICE_ID
  • Supoort expression tree consists with and and or

Python

PHP

Java

C#

cURL

api.query(image_url, tags={'and': ['MALE', 'SHOES', {'or': ['TMALL', 'TAOBAO']}]})
$result = $product_ai->searchImage($service_type='search', $service_id=SERVICE_ID, $image='http://yyyy', tags='{"and":["MALE", "SHOES",{"or":["TMALL","TAOBAO"]}]}'
ISearchTag orTag = new OrTag();
orTag.Add("TMALL");
orTag.Add("TAOBAO");

ISearchTag andTag = new AndTag();
andTag.Add("MALE");
andTag.Add("SHOES");
andTag.Add(orTag);

ITag searchTag = new SearchTag();
searchTag.setTag(andTag);

ImageSearchByImageUrlRequest request = new ImageSearchByImageUrlRequest(SERVICE_ID);
request.setUrl('http://yyyy');
request.setSearchTag(searchTag);
ISearchTag orTag = new OrTag();
orTag.Add("TMALL");
orTag.Add("TAOBAO");

ISearchTag andTag = new AndTag();
andTag.Add(new List<string> { "MALE", "SHOES" });
andTag.Add(orTag);

ITag searchTag = new SearchTag
{
Tag = andTag
};

var request = new ImageSearchByImageUrlRequest(SERVICE_ID);
request.Url = "http://yyyy";
request.SearchTag = searchTag;
curl -X POST \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
-H 'Content-Type: application/json' \
-d '{"url":"http://yyyy","tags":{"and":["MALE","SHOES",{"or":["TMALL","TAOBAO"]}]}}' \
https://api.productai.com/search/SERVICE_ID

loc

Python

PHP

Java

C#

cURL

resp = api.query("http://yyyy", loc = '0.1-0.1-0.8-0.7')
$result = $product_ai->searchImage($service_type='search', $service_id=SERVICE_ID, $image='http://yyyy', $loc = [0.1,0.1,0.8,0.7]
ImageSearchByImageUrlRequest request = new ImageSearchByImageUrlRequest(SERVICE_ID);
request.setUrl('http://yyyy');
request.setLoc('0.1-0.1-0.8-0.7');
var request = new ImageSearchByImageUrlRequest(SERVICE_ID);
request.Url = "http://yyyy";
request.Loc = '0.1-0.1-0.8-0.7';
curl -X POST \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
-H 'Content-Type: application/json' \
-d '{"url":"http://yyyy","loc":"0.1-0.1-0.8-0.7"}' \
https://api.productai.com/search/SERVICE_ID

Bounding box info, format is ”x-y-w-h”. x,y,w,h means:

  • mark top left corner of image as (0,0)
  • right bottom corner as (1,1)
  • x is bounding-box-left-position/image-width
  • y is bounding-box-top-position/image-height
  • w is bounding-box-width/image-width
  • h is bounding-box-height/image-height

2 common usage of loc:

  1. Limit the search area to be the bounding box, to reduce background inference
  2. Use loc to specify which object in the image should be searched
QuerySearch RegionSearch Result
Sample 1red coatSample 2
Sample 3black bagSample 4

Paging

Search supports paging feature, which returns up to 3000 results.

Note: when more than 3,000 results are requested, the service returns an empty response.

Python

PHP

Java

C#


# request top 10 results
api.query('http://yyyy', count=10)

# request the first page with 5 results per one page
api.query('http://yyyy', page=0, count=5)

# request the second page with 5 results per one page
api.query('http://yyyy', page=1, count=5)
# request top 10 results
$result = $product_ai->searchImage($service_type='search', $service_id=SERVICE_ID, $url='http://yyyy', loc=[0,0.1,0.4,0.5], $count=10)

// request the 1st page with 5 results per page
$result = $product_ai->searchImage($service_type='search', $service_id=SERVICE_ID, $url='http://yyyy', loc=[0,0.1,0.4,0.5], $count=5, page=0)

// request the 2nd page with 5 results per page
$result = $product_ai->searchImage($service_type='search', $service_id=SERVICE_ID, $url='http://yyyy', loc=[0,0.1,0.4,0.5], $count=5, page=1)
// by default, we have 10 results
ImageSearchByImageUrlRequest request = new ImageSearchByImageUrlRequest(SERVICE_ID);
request.setUrl("http://yyyy");

// request top 5 results
request.setCount(5)

// request the 1st page with 5 results per page
request.getOptions().put("page", "0");

// request the 2nd page with 5 results per page
request.getOptions().put("page", "1");

ImageSearchResponse response = client.getResponse(request);
String json = response.getResponseJsonString();
// by default, we have 10 results
var request = new ImageSearchByImageUrlRequest(SERVICE_ID)
{
Url = "http://yyyy",
};

// request top 5 results
request.Options.Add("count", "5");

// request the 1st page with 5 results per page
request.Options.Add("page", "0");

// request the 2nd page with 5 results per page
request.Options.Add("page", "1");

var response = client.GetResponse(request);

ret_img_tags

When parameter ret_img_tags is set to 1, service will return tags (which is submitted with image in csv file) along with image, and the tag with most occurrence will be stored in most_common_tags result field as well.

Python

PHP

Java

C#

cURL

api.query('http://yyyy', ret_img_tags=1)
$result = $product_ai->generalRequest($service_type='search', $service_id=SERVICE_ID, $image='http://yyyy', $args=['ret_img_tags' => 1], $json=false);
ImageSearchByImageUrlRequest request = new ImageSearchByImageUrlRequest(SERVICE_ID);
request.setUrl('http://yyyy');
request.getOptions().put('ret_img_tags', '1');
var request = new ImageSearchByImageUrlRequest(SERVICE_ID);
request.Url = "http://yyyy";
request.Options.Add('ret_img_tags', '1');
curl -X POST \
-H 'x-ca-version: 1.0' \
-H 'x-ca-accesskeyid: ACCESS_KEY_ID' \
-H 'Content-Type: application/json' \
-d '{"url":"http://yyyy","ret_img_tags":"1"}' \
https://api.productai.com/search/SERVICE_ID

In the response:

  • Each item in results contains a corresponding tags field
  • most_common_tags indicates a collection of tags, which have the most occurrences and their occurrence count

Recommended usage:

  • Can be used to infer possible objects in the image. As in following example, ONE-PIECE presents 19 times,FEMALE presents 18 times, so that it is highly possible that query image contains FEMALE and ONE-PIECE
{
"detect_time": "1.093",
"detection_score": 0.9705721139907837,
"download_time": "0.000",
"ds": "u70rgsx2",
"is_err": 0,
"loc": [
438,
301,
1015,
1691
],
"most_common_tags": [
[
"ONE-PIECE",
19
],
[
"FEMALE",
18
],
...
],
"preprocess_time": "0.005",
"request_id": "754e5fd8-e3a5-11e7-a97c-664c03c7cfbb",
"results": [
{
"metadata": "",
"score": 0.7404570709058489,
"tags": [
"FEMALE",
"FOREVER21",
"ONE-PIECE",
"JUMPSUIT-ROMPER",
"TOP",
"TANK-STRAP-TOPS",
"FLAT-SANDALS",
"SHOES"
],
"url": "https://oss-downloader.productai.cn/mQxMzhiMzJiYjU1M2RlYThmMmYuanBn.jpg"
},
...
],
"searchtime": "0.323",
"time": "1.429",
"type": [
"Jumpsuit-romper",
"beidaiku",
"leisure-pants",
"flat-sandals",
"bodycon-dress",
"Culotte-pants"
],
"ver": "20170730-184346"
}

Common features on E-commerce product images:

  • multiple images for one product
  • each image presents a certain aspect or a certain detail, or model in different color
  • images are PGC (Professional generated content, well shooted product picture with clean background, or street photo by professional photographers)

Some common scenarios:

  • to determine if a product exists in database
  • search for same model
  • deduplicate
  • product relations

Solution for improve precision:

  • Create Search Service, set scenario=”ecom_product_v1” (In Console, choose scenario “E-commerce product image search v1.1”)
  • Upload multiple images for a certain product (with different aspects, details, or color)
  • Set image metadata to be product ID
  • Call service with code similar to following

Python

from productai import Client

cli = Client(ACCESS_KEY_ID, SECRET_KEY)
api = cli.get_image_search_api(SERVICE_ID)

resp = api.query('http://yyyy', count=6)

import json
obj = json.loads(resp1.content)

statistics_counter = {}
for x in obj.get('results'):
pid = x.get('metadata')
statistics_counter.setdefault(pid, [x.get('url'), 0, 0])
# calculate product occurrence in result
statistics_counter[pid][1] += 1
# calculate total score for each product in the result
statistics_counter[pid][2] += x.get('score')

# only keep product which occurs more than 1 time
statistics_counter = [x for x in statistics_counter.items() if x[1][1] > 1]

# order products with average score in descending
results = sorted(statistics_counter, key = lambda x: x[1][2] / x[1][1], reverse = True)

# we can only fetch top 1 result for most precise result
results = results[:1]

More

19 Fashion Tags

Tags
DressSkirtSuspenderSwim-SuitTopCoatJacketShoe
ShortPantBagJewelryGlassWatchBeltScarf
GloveCapNon-fashion

See: Supported Scenarios