Productai

图片搜索服务

ProductAI平台为我们的企业客户提供,基于企业内独特数据的可定制化的AI服务。这些用于生成定制AI服务的数据,通过数据集的概念进行管理。目前平台支持2类数据集:图片集和商品集。对于搜索服务,数据集是一组数据的集合(等同于数据库中一张表的概念)。每一个搜索服务就是一个数据集上的索引。与传统数据库的类比,数据集等同于传统数据库的数据表,搜索服务等同于数据表上的一个索引。

图片集

图片集的每一笔数据是一张图片(等同于数据表的一笔记录)。每一张图片使用url作为唯一识别ID,不同的url意味着不同的数据,同一个url会被认定为同一张图片。每一个图片集创建时,会分配到一个唯一的ID,称为IMAGE_SET_ID

创建图片集

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.*;

// 设置API调用初始化参数
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);

// 调用API,获取调用结果
CreateDataSetResponse response = client.getResponse(request);
// 获取数据集ID
String image_set_id = response.getDataSetId();
// 获取返回的所有数据
//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);

// 创建Request,填入数据集名称和描述
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.cn/image_sets/_0000014

输入参数

参数名称类型说明必选限制
name字符串图片集名称最多16个unicode字符,超长的部分会被自动截断
description字符串图片集的描述信息最多128个unicode字符,超长的部分会被自动截断

输出结果

200 HTTP状态码
{
"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"
}
结果字段类型说明
created_at字符串创建UTC时间,精确到秒,格式为:年-月-日T小时:分钟:秒Z
creator_id整数创建者ID
description字符串图片集的描述信息
id字符串图片集唯一ID,后续操作都需要使用此ID完成
modified_at字符串最后修改UTC时间,精确到秒,格式为:年-月-日T小时:分钟:秒Z
n_downloaded整数图片集中下载完毕的图片数
n_failed整数图片集中下载失败的图片数
n_items整数图片集图片总数
name字符串图片集名称
request_id字符串本次调用的唯一ID,可以用于和ProductAI团队进行联调分析
status字符串目前图片集状态。没有任何图片被下载完毕,是not-downloaded。如果有部分图片被下载完毕,部分没有被下载完毕,是downloading。如果所有图片都被下载完毕,或者下载失败,是downloaded。
非200 HTTP状态码
{
"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"
}
结果字段类型说明
error_code整数表明细分错误代码
message字符串详细错误信息
request_id字符串本次调用的唯一ID,可以用于和ProductAI团队进行联调分析

错误信息

SDK/API使用http状态码来通知客户端本次调用成功和失败

http状态码error_code说明
200N/a图片集创建成功
4005004没有填写图片集名称
4033003用户可以创建的图片集个数是有上限的,超过了上限,就无法创建新的图片集,收到该错误代码。详情参见付费帐号和试用帐号有什么区别

获取所有图片集信息

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;

// 设置API调用初始化参数
IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

// 创建获取所有数据集request
IWebClient client = new DefaultProductAIClient(profile);
GetAllDataSetsRequest request = new GetAllDataSetsRequest();
request.setLanguage(LanguageType.Chinese);

// 调用API,获取调用结果
GetAllDataSetsResponse 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);

// 创建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.cn/get_image_sets/_0000014

输入参数

N/a

输出结果

200 HTTP状态码
{
"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"
},
...
]
}
结果字段类型说明
results数组客户当前存在的图片集列表,单个数组元素的字段同创建图片集输出结果
request_id字符串本次调用的唯一ID,可以用于和ProductAI团队进行联调分析

错误信息

SDK/API使用http状态码来通知客户端本次调用成功和失败

http状态码error_code说明
200N/a图片集信息获取成功

获取单个图片集信息

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.*;

// 设置API调用初始化参数
IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

// 设置数据集ID参数
IWebClient client = new DefaultProductAIClient(profile);
GetDataSetInfoRequest request = new GetDataSetInfoRequest(IMAGE_SET_ID);
request.setLanguage(LanguageType.Chinese);

// 调用API,获取调用结果
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);

// 创建Request,填入数据集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.cn/image_sets/_0000014/IMAGE_SET_ID

输入参数

N/a

输出结果

创建图片集输出结果

错误信息

SDK/API使用http状态码来通知客户端本次调用成功和失败

http状态码error_code说明
200N/a图片集信息获取成功
4031002试图获取一个不属于自己的图片集信息
4042001图片集不存在

修改图片集名称和描述

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.update_image_set(name=NEW_NAME)

# 修改数据集的描述
resp = api.update_image_set(description=NEW_DESC)

# 修改数据集的名称和描述
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.*;

// 设置API调用初始化参数
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);
UpdateDataSetRequest request = new UpdateDataSetRequest(IMAGE_SET_ID, SET_NAME, SET_DESC);
request.setLanguage(LanguageType.Chinese);

// 调用API,获取调用结果
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);

// 设置数据集ID,及新的名称和描述
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.cn/image_sets/_0000014/IMAGE_SET_ID

输入参数

创建图片集输入参数

输出结果

创建图片集输出结果

错误信息

SDK/API使用http状态码来通知客户端本次调用成功和失败

http状态码error_code说明
200N/a图片集修改成功
4005004不能使用空字符串做为图片集名称
4031002试图修改一个不属于自己的图片集
4042001图片集不存在

删除图片集

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.*;

// 设置API调用初始化参数
IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

// 设置数据集ID参数
IWebClient client = new DefaultProductAIClient(profile);
DeleteDataSetRequest request = new DeleteDataSetRequest(IMAGE_SET_ID);
request.setLanguage(LanguageType.Chinese);

// 调用API,获取调用结果
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);

// 设置数据集ID来创建删除数据集的请求
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.cn/image_sets/_0000014/IMAGE_SET_ID

输入参数

N/a

输出结果

N/a

错误信息

SDK/API使用http状态码来通知客户端本次调用成功和失败

http状态码error_code说明
204N/a图片集删除成功
4031002试图删除一个不属于自己的图片集
4033001有依赖于该图片集的搜索服务依旧存在,则不能删除该图片集
4042001图片集不存在

图片管理

向图片集上传单张图片

图片数据可以包含三个字段:

  • url,上传图片的链接.目前图片使用该字段作为唯一ID.不同的url意味着不同的图片数据.
  • metadata,与图片相关的文本信息,会与图片一起作为结果返回.
  • tags,与图片相关的标签信息,会与图片一起被搜索,并可用于tag filter.多个tags之间需要用 |进行分隔.

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=200 ['cartoon','square']);
import java.util.ArrayList;
import cn.productai.api.core.*;
import cn.productai.api.core.enums.*;
import cn.productai.api.pai.entity.dataset.*;

// 设置API调用初始化参数
IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

// 设置url、meta、tags参数
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);

// 调用API,获取调用结果
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);

// 创建一个添加一条数据的请求。需要填入数据集ID和图片url,tags和metaId为optional选项
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.cn/image_sets/_0000014/IMAGE_SET_ID

输入参数

参数名称类型说明必选限制
url字符串上传图片URL最多512个unicode字符,超长会导致报错
meta字符串图片的描述信息最多512个unicode字符,超长会导致报错
tags字符串图片的标签信息会和图片数据一起进行索引。用于用户主动发起的图片加标签过滤的请求。字符串中允许包含多个标签,标签之间以"|"作为分隔,例:上衣|短袖|POLO衫。若此参数含有非ASCII字符集内的内容,请使用UTF-8编码。

输出结果

创建图片集输出结果

错误信息

SDK/API使用http状态码来通知客户端本次调用成功和失败

http状态码error_code说明
200N/a数据上传成功
4005001url超过512个unicode字符,或者url为空,或者meta参数超过512个字符
4031002试图向一个不属于自己的图片集提交数据
4042001图片集不存在
5004001url无法下载成功

向图片集批量上传图片

推荐用户使用csv文件来准备图片数据,然后上传。csv文件中每行为1张图片数据.每行3列.各列依次为图片URL,图片metadata(可选),tags(可选)。请参见csv文件创建示例。向图片集中批量上传图片示例:

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.*;

// 设置API调用初始化参数
IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

// 设置数据集ID和csv文件参数
IWebClient client = new DefaultProductAIClient(profile);
DataSetBatchAddRequest request = new DataSetBatchAddRequest(IMAGE_SET_ID);
request.setCsvFile(new File("added.csv"));
request.setLanguage(LanguageType.Chinese);

// 调用API,获取调用结果
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);

// 通过csv文件批量上传数据
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.cn/image_sets/_0000014/IMAGE_SET_ID

该API服务也支持tar.gz压缩格式。可以通过如下命令将csv文件压缩为tar.gz文件

tar zcvf added.tar.gz added.csv

输入参数

参数名称类型说明必选限制
f文件csv文件内容,csv文件格式请参看csv文件创建示例小于50MB

输出结果

创建图片集输出结果

错误信息

SDK/API使用http状态码来通知客户端本次调用成功和失败

http状态码error_code说明
200N/a数据提交成功
4005001不合法的csv文件,如:包含超过三列,第一列不是一个合法的URL
4031002试图向一个不属于自己的图片集提交数据
4042001图片集不存在

从图片集中批量删除图片

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.*;

// 设置API调用初始化参数
IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

// 设置数据集ID和csv文件参数
IWebClient client = new DefaultProductAIClient(profile);
DataSetBatchDeleteRequest request = new DataSetBatchDeleteRequest(IMAGE_SET_ID);
request.setCsvFile(new File("deleted.csv"));
request.setLanguage(LanguageType.Chinese);

// 调用API,获取调用结果
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.cn/image_sets/_0000014/IMAGE_SET_ID

输入参数

参数名称类型说明必选限制
f文件csv文件内容,csv文件格式请参看csv文件创建示例。删除只需要使用URL作为唯一识别,所以该csv文件可以只包含一列,即URL列小于50MB

输出结果

创建图片集输出结果

错误信息

SDK/API使用http状态码来通知客户端本次调用成功和失败

http状态码error_code说明
200N/a数据提交成功
4005001不合法的csv文件,如:包含超过三列,第一列不是一个合法的URL
4031002试图向一个不属于自己的图片集提交数据
4042001图片集不存在

批量更新图片属性

请使用向图片集批量上传图片所介绍的方法完成更新图片集中图片的metadata和tags信息。ProductAI以图搜图功能使用URL作为每张图片的唯一识别ID。上传数据时,如果某个URL已经在数据库中,则该URL不会重新插入和下载。同时新上传数据中该URL对应的metadata和tags会覆盖数据库中已有的信息,完成更新操作。

服务管理

创建搜索服务

有了图片集,选择一个合适的场景,就可以创建一个图片搜索服务。

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')

# 获取服务ID
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.*;

// 设置API调用初始化参数
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);

// 调用API,获取调用结果
CreateSearchServiceResponse response = client.getResponse(request);
// 获取服务ID
String service_id = response.getServiceId();
// 获取返回的所有数据
//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);

// 使用数据集ID,名称及服务场景来创建一个新服务
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.cn/image_sets/_0000014/IMAGE_SET_ID/services

输入参数

参数名称类型说明必选限制
name字符串服务名称必选32个字符,超过部分会被截断
scenario字符串场景类别必选必须是场景列表中定义的场景之一

输出结果

200 HTTP状态码
{
"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
}
结果字段类型说明
created_at字符串创建UTC时间,精确到秒,格式为:年-月-日T小时:分钟:秒Z
creator_id整数创建者ID
id字符串搜索服务唯一ID,后续操作都需要基于此ID进行
image_set_id字符串搜索服务基于的数据集ID
indexed_ratio浮点数索引完成率 = 索引的图片数 / 下完成的图片数
last_indexed_time字符串搜索服务最后一次索引部署时间
last_updated_at字符串最后修改UTC时间,精确到秒,格式为:年-月-日T小时:分钟:秒Z
n_indexed整数当前搜索服务线上索引量
name字符串搜索服务名称
request_id字符串本次调用的唯一ID,可以用于和ProductAI团队进行联调分析
status字符串目前搜索服务状态只有running一种
status_duration整数N/a
type整数N/a
非200 HTTP状态码
{
"error_code": 5003,
"message": "Scenarios Not Supported",
"request_id": "a0393714-e331-11e7-9a0f-b217471bc47d"
}
结果字段类型说明
error_code整数表明细分错误代码
message字符串详细错误信息
request_id字符串本次调用的唯一ID,可以用于和ProductAI团队进行联调分析

错误信息

SDK/API使用http状态码来通知客户端本次调用成功和失败

http状态码error_code说明
200N/a查询成功
4005003scenario中指定的场景不存在
4033004创建服务数超过上限,请参见帐号限制
4093002每个scenario,在同一个数据集上只能创建一个。试图创建第二个服务出错

获取所有服务信息

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;

// 设置API调用初始化参数
IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

// 创建获取所有搜索服务request
IWebClient client = new DefaultProductAIClient(profile);
GetAllServicesRequest request = new GetAllServicesRequest();
request.setLanguage(LanguageType.Chinese);

// 调用API,获取调用结果
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);

// 创建Request
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.cn/customer_services/_0000172

输入参数

N/a

输出结果

200 HTTP状态码
{
"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
},
...
]
}
结果字段类型说明
results数组客户所有running的服务列表,单个数组元素的字段同创建搜索服务输出结果
request_id字符串本次调用的唯一ID,可以用于和ProductAI团队进行联调分析

错误信息

SDK/API使用http状态码来通知客户端本次调用成功和失败

http状态码error_code说明
200N/a查询成功

获取搜索服务信息

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.*;

// 设置API调用初始化参数
IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

// 设置服务ID
IWebClient client = new DefaultProductAIClient(profile);
GetServiceInfoRequest request = new GetServiceInfoRequest(SERVICE_ID);
request.setLanguage(LanguageType.Chinese);

// 调用API,获取调用结果
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.cn/customer_services/_0000172/SERVICE_ID

输入参数

N/a

输出结果

创建搜索服务输出结果

错误信息

SDK/API使用http状态码来通知客户端本次调用成功和失败

http状态码error_code说明
200N/a查询成功
4031003试图获取他人帐号下的服务
4042002服务不存在

更新搜索服务信息

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.*;

// 设置API调用初始化参数
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);

// 调用API,获取调用结果
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.cn/customer_services/_0000172/SERVICE_ID

输入参数

参数名称类型说明必选限制
name字符串服务名称必选32个字符,超过部分会被截断

输出结果

创建搜索服务输出结果

错误信息

SDK/API使用http状态码来通知客户端本次调用成功和失败

http状态码error_code说明
200N/a修改成功
4031003试图修改他人帐号下的服务
4042002服务不存在

删除搜索服务

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.*;

// 设置API调用初始化参数
IProfile profile = new DefaultProfile();
profile.setAccessKeyId(ACCESS_KEY_ID);
profile.setSecretKey(SECRET_KEY);
profile.setVersion("1");
profile.setGlobalLanguage(LanguageType.Chinese);

// 设置服务ID
IWebClient client = new DefaultProductAIClient(profile);
DeleteServiceRequest request = new DeleteServiceRequest(SERVICE_ID);
request.setLanguage(LanguageType.Chinese);

// 调用API,获取调用结果
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.cn/customer_services/_0000172/SERVICE_ID

输入参数

N/a

输出结果

N/a

错误信息

SDK/API使用http状态码来通知客户端本次调用成功和失败

http状态码error_code说明
204N/a删除成功
4031003试图修改他人帐号下的服务
4042002服务不存在

图片搜索

Python

PHP

Java

C#

cURL

from productai import Client

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

# 用图片URL查询
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)

# 指定查询结果数量上限,默认为 20
# 指定查询结果必须有MALE和SHOES标签
resp = api.query('http://yyyy', count=2, tags=['MALE', 'SHOES'])

# 也可以按如下方式创建标签搜索,"|"等价于"and"操作符
resp = api.query('http://yyyy', count=2, tags='MALE|SHOES')

# 或者使用复杂标签搜索
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);

// 用图片URL查询
$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')

// 指定查询结果数量上限,默认为 20
// 指定查询结果必须有MALE和SHOES标签
$result = $product_ai->searchImage($service_type='search', $service_id=SERVICE_ID, $image='http://yyyy',$count=2, $tags=['MALE', 'SHOES'])

// 也可以按如下方式创建标签搜索,"|"等价于"and"操作符
$result = $product_ai->searchImage($service_type='search', $service_id=SERVICE_ID, $image = '@zzzz.jpg',$tags='MALE|SHOES')

// 或者使用复杂标签搜索
$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);

// 复杂Tag查询示例
// 指定查询结果必须有MALE和SHOES标签
ISearchTag andTag = new AndTag();
andTag.Add("MALE");
andTag.Add("SHOES");

// 指定查询结果或有"TMALL"标签
ISearchTag orTag = new OrTag();
orTag.Add("TMALL");
andTag.Add(orTag);

// 添加标签到request
ITag searchTag = new SearchTag();
searchTag.setTag(andTag);

// 用图片URL查询
ImageSearchByImageUrlRequest request = new ImageSearchByImageUrlRequest(SERVICE_ID);
request.setUrl("http://yyyy");

// 上传本地文件查询
ImageSearchByImageFileRequest request = new ImageSearchByImageFileRequest(SERVICE_ID);
request.setImageFile(new File("zzzz.jpg"));

// 指定查询结果数量上限,默认为 20
request.setCount(2);
request.setSearchTag(searchTag);
request.setLanguage(LanguageType.Chinese);

// 发起API调用, 获取结果
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
};

// 使用URL进行搜索
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);
# 使用URL作为参数调用API
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.cn/search/SERVICE_ID

# 或者使用本地文件作为参数调用API
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.cn/search/SERVICE_ID

输入参数

参数名称类型说明必选限制
search文件Query图片文件内容与url参数二选一
url字符串Query图片的链接与search参数二选一
count整数指定返回搜索结果数量默认数量20,取值范围1-3000,不能超过3000
tags字符串数据集的标签信息作为搜索结果筛选条件用的关键字标签。所用标签,为用户添加或更新数据时提交,非自动生成。简单标签使用方法:可以含多个标签,标签之间以“|”分隔。当用户同时输入多个标签时,仅返回同时含有全部给定标签的结果。例:上衣|短袖|POLO 衫。若此参数含有非 ASCII字符集内的内容,请使用 UTF-8 编码。复杂嵌套使用方法:tags参数里是一个查询对象。主要是两种形式,{“or”:[一个或多个子查询]}和{“and”:[一个或多个子查询]}。一个复杂的查询例子tags={“and”:[“上衣”,{“or”:[“蓝色”,”休闲”]}]}。请参见tags使用
loc字符串图片中的搜索范围图片标框的位置信息,格式为”x-y-w-h”。其中x,y,w,h 四个子参数的含义为:以待检测图片左上角位置为坐标(0,0),右下角位置为(1,1),x 为所框选框体左上角横坐标与图片宽度的比值,y 为所框选框体左上角纵坐标与图片高度的比值,w 为所框选框体宽与图片宽度的比值,h为所框选框体高与图片高度的比值。请参见loc使用

输出结果

200 HTTP状态码
{
"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字段为一个数组,包含全部搜索结果,详解参见Results字段详解

时间相关字段说明

结果字段类型说明
detect_time字符串检测服务时间消耗,单位为秒
download_time字符串图片下载时间消耗,单位为秒
preprocess_time字符串图片搜索前,预处理时间消耗,单位为秒
searchtime字符串搜索时间消耗,单位为秒
time字符串服务器端全部时间消耗,单位为秒

检测器相关字段说明

结果字段类型说明
detect_time字符串检测服务时间消耗,单位为秒
detection_score浮点数检测服务返回的置信度
loc数组检测服务返回,图中最有可能的搜索目标物体,四个数值依次为x, y, w, h
type数组检测服务返回,图中最有可能的物体类别

其他相关字段说明

结果字段类型说明
ds字符串将废弃,请勿使用
is_err整数将废弃,请勿使用
most_common_tags数组详细使用,请参见ret_img_tags使用
request_id字符串本次请求的唯一识别ID,用于和ProductAI平台进行联调诊断
ver字符串索引版本号

Results字段详解

{
"metadata": "131",
"score": 0.5732779921465632,
"url": "http://xxx/131/ab505d2fd40e17f64397c796adfb6a8b.jpg",
"tags": [
"FEMALE",
"FOREVER21",
"ONE-PIECE"
]
}
结果字段类型说明
url字符串搜索结果图片对应的链接地址
score浮点数与Query图片的相似度
metadata字符串为被搜索出来的图片索引时上传的metadata。详情参见metadata使用
tags数组包含被搜索图片上传时,包含的tags数据。详情参见ret_img_tags使用
非200 HTTP状态码
{
"error_code": 1004,
"message": "Image Downloading Not Found",
"request_id": "eccff8dc-b86c-11e7-ab03-b66791ba711f"
}
结果字段类型说明
error_code整数表明细分错误代码
message字符串详细错误信息
request_id字符串本次调用的唯一ID,可以用于和ProductAI团队进行联调分析

错误信息

SDK/API使用http状态码来通知客户端本次调用成功和失败

http状态码error_code说明
200N/a查询成功
4005001不合法的csv文件,如:包含超过三列,第一列不是一个合法的URL
4031002试图向一个不属于自己的数据集提交数据
4042001数据集不存在
429N/a调用超过并发限制,请参看并发限制错误

最佳实践

metadata使用

数据集中的任何一张图片都可以有一个metadata信息。信息可以是不包含逗号的任意字符串。当该张图片被搜索出来时,该metadata信息会被一并返回给客户。metadata最多512个unicode字符,超长会导致报错。

建议使用方案

  1. 图片对应产品的产品ID,用户搜索出该图片后,可以使用metadata作为ID,在自己的数据中搜索获取产品详细信息。
  2. 图片对应产品链接,用户搜索出该图片后,可以使用metadata作为链接进行跳转。
  3. 图片对应产品的详细信息(可以使用json格式包装),用户搜索出该图片后,可以使用metadata解析出产品详情,避免进一步查询数据库造成的调用开销。

tags使用

数据集中任何一张图片都可以有一组tags。多个tags之间需要使用 | 进行分割,并且每一个tag中都不能包含逗号。搜索服务会将每一个tag和其对应的图片一起索引。当用户进行搜索时,除了提交Query图片外,也可以通过传入tags,限制本次搜索只在包含这些tags的图片中完成。我们称这样的搜索为 tag filtertag filter可以使得搜索更准确,搜索速度也会更加迅速。

建议使用方案

  1. 搜索时,服务会对查询提交的图片进行物品检测,随后仅针对图像尺寸占比最大的物品进行匹配搜索。所以强烈建议使用tag时,查询图片中仅包含一种物品;或设置loc参数限定tag过滤的物品。
  2. 将图片对应的类别放入tags中进行索引。搜索时,传入类别信息作为搜索tag,从而限制搜索只在同样类别中的商品搜索,从而使得搜索更准确。
  3. 将图片对应的用户ID放入tags中进行索引。搜索时,传入用户ID作为搜索tag,从而限制搜索只能在当前用户的图集中完成。实现个人相册功能。

tag搜索语法

目前支持三种语法:

  • 将一组tags作为数组传入SDK。该语法会限制搜索应在同时包含MALE和SHOES两个tags的图片子集中完成。

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");

// 添加标签到request
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
};

// 使用URL进行搜索
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.cn/search/SERVICE_ID
  • 将一组tags使用|拼接成字符串传入SDK。该语法会限制搜索应在同时包含MALE和SHOES两个tags的图片子集中完成。

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";
// 暂不支持这种方式使用tags
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.cn/search/SERVICE_ID
  • 支持简单andor组成的表达式树。如下图会限制搜索在,同时包含MALE,SHOES,TMALL的图片子集,或者同时包含MALE,SHOES, TAOBAO的图片子集中完成

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
};

// 使用URL进行搜索
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.cn/search/SERVICE_ID

loc使用

Python

PHP

Java

C#

cURL

# loc参数使用相对位置,格式x-y-w-h,每一个值都是大于0,小于1的浮点数
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.cn/search/SERVICE_ID

图片标框的位置信息,格式为”x-y-w-h”。其中x,y,w,h 四个子参数的含义为:以待检测图片左上角位置为坐标(0,0),右下角位置为(1,1),x 为所框选框体左上角横坐标与图片宽度的比值,y 为所框选框体左上角纵坐标与图片高度的比值,w 为所框选框体宽与图片宽度的比值,h为所框选框体高与图片高度的比值。

用户直接使用loc参数实现两个功能:

  1. 可以限制搜索区域在loc定义的图片区域内完成,从而减少图片中背景物体对搜索的干扰。
  2. 如果图片中包含多个物体,可以通过loc指定搜索其中的哪个物体
Query图片区域搜索结果
示例图1红色大衣示例图2
示例图3黑色女包示例图4

分页

目前搜索服务支持分页功能。最多支持通过分页获取3000条记录。

注:当获取超过3000条以上的记录时,服务返回空结果。

Python

PHP

Java

C#

# 只请求返回10条结果
api.query('http://yyyy', count=10)

# 每页5条结果,请求第1页
api.query('http://yyyy', page=0, count=5)

# 每页5条结果,请求第2页
api.query('http://yyyy', page=1, count=5)
# 只请求返回10条结果
$result = $product_ai->searchImage($service_type='search', $service_id=SERVICE_ID, $url='http://yyyy', loc=[0,0.1,0.4,0.5], $count=10)

# 每页5条结果,请求第1页
$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)

# 每页5条结果,请求第2页
$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)
// 获取请求对象
ImageSearchByImageUrlRequest request = new ImageSearchByImageUrlRequest(SERVICE_ID);
request.setUrl("http://yyyy");

// 每页5条结果
request.setCount(5)

// 请求第1页
request.getOptions().put("page", "0");

// 或者请求第2页
request.getOptions().put("page", "1");

// 发起API调用, 获取结果
ImageSearchResponse response = client.getResponse(request);
String json = response.getResponseJsonString();
// 获取请求对象
var request = new ImageSearchByImageUrlRequest(SERVICE_ID)
{
Url = "http://yyyy",
};

// 每页5条结果
request.Options.Add("count", "5");

// 请求第1页
request.Options.Add("page", "0");

// 或者请求第2页
request.Options.Add("page", "1");

var response = client.GetResponse(request);

ret_img_tags使用

当用户上传图片时,给每张图片指定了tags信息。则在搜索时,可以指定参数ret_img_tags=1,从而返回每一张图对应的tags,并且搜索服务会将结果中出现次数最多的tags放到most_common_tags结果字段中。

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.cn/search/SERVICE_ID

返回结果中:

  • results数组中的每条结果都会包含一个字段tags,即该条结果上传时,一起提交的tags信息。
  • most_common_tags数组中包含一组tags,即统计所有返回结果的所有tags,汇总出现次数最多的tags及其次数。

使用建议:

  • 可用于判定图片中可能包含的物体。下例中ONE-PIECE出现了19次,FEMALE出现了18次。所以搜索图片中包含FEMALE和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"
}

电商商品PGC图搜索

电商网站商品图片都有如下特点:

  • 每款商品都会有多张图片展示商品
  • 每张图片展示商品的某个角度,或者某个细节,或者某种颜色有差别的同款
  • 图片均为PGC图片(即背景干净的商品图,或者专业摄影师拍摄的街拍图)

当电商网站需要在后台商品管理系统,完成如下功能时:

  • 确认商品是否在数据库中
  • 同款查找
  • 商品去重
  • 商品关联

可使用此处描述的方案来提升搜索精准度。该方案如下:

  • 创建搜索服务, 设置 scenario=”ecom_product_v1” (Console中选择场景名称为"电子商务PGC商品图片搜索 v1.1")
  • 每款商品多张图(不同角度,不同细节,不同颜色)均上传到ProductAI系统的数据集中
  • 上传时,请给每张图都附带metadata信息,信息为图所展示的商品ID
  • 调用时,使用如下代码(仅用Python展示业务逻辑,故未提供其他语言示例代码)

Python

from productai import Client

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

# 此处count值依赖于:
# - 索引中每一款产品有多少相似产品,如果相似产品越多且用户希望得到尽可能多的相似产品,则count值可以加大
# - 用户是偏好更准确的结果,还是偏好更多的结果(允许一定的错误结果);如果为后者,则count值可以加大
resp = api.query('http://yyyy', count=6)

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

statistics_counter = {}
for x in obj.get('results'):
# 每一张图都将对应的产品id(pid)存储到metadata字段中
pid = x.get('metadata')
statistics_counter.setdefault(pid, [x.get('url'), 0, 0])
# 统计每一款产品在搜索结果中出现的次数
statistics_counter[pid][1] += 1
# 统计每一款产品在搜索结果中rank score的总和
statistics_counter[pid][2] += x.get('score')

# 只保留在结果中出现过一次以上的商品,以提升准确度
statistics_counter = [x for x in statistics_counter.items() if x[1][1] > 1]

# 根据每一款产品平均rank score(即rank score之和除以出现总次数)进行倒排
results = sorted(statistics_counter, key = lambda x: x[1][2] / x[1][1], reverse = True)

# 可以只取top1的结果,来进一步提升准确度
results = results[:1]