相同图片搜索
更新时间:2023-02-08
接口格式说明
变量类型定义
类型 | 定义 |
---|---|
string | 普通的字符串,可能会有长度要求,具体参见接口说明中的备注 |
uint32 | 整形数字,最大取值为4字节int。自然数 |
int64 | 整形数字,最大取值为8字节int。允许负数 |
json | 无论是request还是response中某个字段定义为json,那么它其实是一个json格式的字符串,需要二次解析 |
list | 与字符串的索引一样,列表索引从0开始。列表可以进行截取、根据索引读取 |
float | 浮点型 |
bytes | bytes以字节序列的形式(二进制形式)来存储数据(文本、图片、音频等) |
接口调用说明
调用接口的地址示例:[192.168.0.1]:8120/GeneralClassifyService/classify, 示例中的ip[192.168.0.1]需要替换为用户自己服务器的ip,示例中的端口8120需根据所调用接口进行替换:
- 特征接口默认端口8120
- 检索接口默认端口8025
- 底库管理默认端口8103
一、相同图片搜索-特征接口
调用接口的地址示例:[192.168.0.1]:8120/GeneralClassifyService/classify, 示例中的ip[192.168.0.1]需要替换为用户自己服务器的ip
参数说明
参数 | 值类型 | 取值示例 | 备注 |
---|---|---|---|
logid | uint32 | 100 | 后台标记不同请求的日志,每个请求对 应不同logid,logid取值范围为32位无符 号整数。 |
format | string | "json" | 当值为“json”时,传入参数中img和feature_data为base64编码,建议使用格式 |
from | string | "test-python-tom" | 必填 方便as确认请求来源 |
cmdid | string | "123" | |
data | string | [pb base64编码] | 上传的后端服务访问输入参数 |
注:data[pb base64编码]格式如下(重点修改):(如需使用自定义库,自定义库 APPID 请写死为"same")
请求参数
参数名称 | 请求关键字 | 参数类型 | 参数取值示例 | 参数说明 |
---|---|---|---|---|
featureids | featureids | string | "" | 必填,指定服务输出特征结果 |
image | image | string | 图像的二进制数据 | 必选,上传的查询图片 |
appid | appid | string | "same" | |
sub_lib | sub_lib | string | "1" | 可选,与appid拼接成完整的 appid |
请求代码示例
特征服务,一般不开放接口
same_private_example.py
#!/usr/bin/env python
#coding:utf-8
import os
import os.path
import json
import sys
import urllib
import urllib2
import base64
from proto import imgfeature_pb2
import logging
import time
import subprocess
import random
logger = logging.getLogger()
class CalFeatureError(Exception):
"""when call remote server error"""
pass
def calfeature_idlapi_remote(serverurl, imagedata, infos, logid=0):
""" cropmethod will pass to server as alignflag parameter"""
def _createprotobufdata(imagestr, info):
"""create protobuf from image and info"""
proto_data = imgfeature_pb2.FeatureRequest()
proto_data.image = imagestr
proto_data.query_sign = '0,0'
def addinfo(key, value):
"""add info to proto"""
infoele = proto_data.info.texts.add()
infoele.key = key
infoele.value = value
if info is not None:
for key, value in info.iteritems():
addinfo(key, value)
data = proto_data.SerializeToString()
return data
protodata = _createprotobufdata(imagedata, infos)
protodata = base64.b64encode(protodata)
req_json = {
'appid': "123456",
'logid': logid,
'format': 'json',
'from': 'test-python',
'cmdid': '123',
'clientip': '0.0.0.0',
'data': protodata,
}
conn = urllib2.urlopen(serverurl, data=json.dumps(req_json))
resultjson = conn.read()
result = json.loads(resultjson)
if result['err_no'] != 0:
errorinfo = '%s:%s' % (result['err_no'], result['err_msg'])
logger.warn('got error from server:%s', errorinfo)
raise CalFeatureError(errorinfo)
res_data = result['result'].decode('base64')
proto_result = imgfeature_pb2.FeatureResponse()
proto_result.ParseFromString(res_data)
features = {fea.fea_id: fea.fea_data for fea in proto_result.features}
return features
def calfeature_remote(filename, feaaddr, featureids=''):
import urllib2
feaserverurl = 'http://%s/GeneralClassifyService/classify' % (feaaddr)
param = {"detect": "1", "usedb": "0"}
imagedata = open(filename, 'rb').read()
start = time.time()
features = calfeature_idlapi_remote(feaserverurl, imagedata, params)
print "time cost: %.2f ms" % ((time.time() - start)*1000)
for feaname in features:
print "-------------"*5
print feaname, features[feaname], len(features[feaname])
def main():
img_path = 'query.jpg'
calfeature_remote(img_path,'127.0.0.1:8120','')
pass
if __name__ == '__main__':
if len(sys.argv)>1 :
func = getattr(sys.modules[__name__], sys.argv[1])
func(*sys.argv[2:])
else:
print >> sys.stderr,'tools.py command'
二、相同图片搜索-入库/更新/检索/删除接口
调用接口的地址示例:[192.168.0.1]:8025/GeneralClassifyService/classify, 示例中的ip[192.168.0.1]需要替换为用户自己服务器的ip
请求参数
参数名称 | 参数类型 | 是否必填 | 参数说明 |
---|---|---|---|
logid | uint64 | 否 | 日志号,可不传 |
format | string | 否 | 当值为“json”时,传入参数中img和 feature_data为base64编码,建议使用格式 |
from | string | 是 | 必填 方便as确认请求来源 |
appid | string | 是 | 必填用户名same_1/same_2(上面设置的用户id,id不能带逗号) |
image | bytes | 否 | 图片二进制,当format为json时,需进 行base64编码。如果请求是传图,as会 通过图片计算contsign值 |
pn | unit32 | 否 | 返回结果开始位置,检索search时可用 |
rn | unit32 | 否 | 返回结果取多少条,检索search时可用 |
consign | ContSign | 否 | ContSign {uint32 sign1, uint32 sign2} 。如果同时传了image信息,as会以图片计算出的contsign值为准。 |
consigns | repeated ContSign | 否 | 删除一组数据时使用,进行删除操作时,以contsigns数据为准,当contsigns中无数据才会删除contsign对应的数据 |
image | bytes | 否 | 图片二进制,当format为json时,需进 行base64编码。如果请求是传图,as会 通过图片计算contsign值 |
features | repeated FeatureData | add必填 | add时features中必须要传入brief信息 :fea_id:1000, 在fea_data中传入当前add的图片的简要说明,search时会返回该参数)fea_id:999, 固定传入一个struct,struct值参考示例代码update时features只需要传入feaid=1000的需要更新的信息即可 |
入库/更新/检索/删除 请求示例
same_private_example_add_remove.py:
#coding:utf-8
import urllib2
import base64
import json
import os
import sys
import logging
logger = logging.getLogger()
AS_SERVER = 'http://10.255.140.17:8025'
ADD_IMG = 'query.jpg'
APPID='test'
def rts_as_add(filename=ADD_IMG, appid=APPID):
params = {
"appid": appid,
"format": "json",
"from": "from_xx",
"logid": 666,
"brief": "brief",
"image": base64.b64encode(open(filename,'rb').read()),
"features": [{"fea_id":1000, "fea_data" : base64.b64encode("addtest")}, {"fea_id":999, "fea_data": base64.b64encode(struct.pack('II', 0, 4))}]
}
conn = urllib2.urlopen(AS_SERVER+'/RTSAsService/add', data=json.dumps(params)).read()
print conn
def rts_as_update(filename=IMG, appid=APPID):
params = {
"appid": appid,
"format": "json",
"from": "from_xx",
"logid": 666,
"image": base64.b64encode(open(filename,'rb').read()),
"features": [{"fea_id":1000, "fea_data" : base64.b64encode("addtest")}]
}
conn = urllib2.urlopen(AS_SERVER+'/RTSAsService/update', data=json.dumps(params)).read()
print conn
def rts_as_search(filename=IMG, appid=APPID):
params = {
"appid": appid,
"image": base64.b64encode(open(filename,'rb').read()),
"format": "json",
"from": "from_yyy",
"logid": 44,
}
conn = urllib2.urlopen(AS_SERVER+'/RTSAsService/search', data=json.dumps(params)).read()
print conn
def rts_as_delete(contsign, appid=APPID):
sign1, sign2 = map(int,contsign.split(','))
params = {
"appid": appid,
"format": "json",
"from": "from_xx",
"logid": 666,
#"image": base64.b64encode(open('1.jpg','rb').read()),
"contsign" : {'sign1':sign1,"sign2":sign2},
}
conn = urllib2.urlopen(AS_SERVER+'/RTSAsService/remove', data=json.dumps(params)).read()
print conn
def rts_as_snapshot(appid=APPID):
params = {
"appid": appid,
"from": "from_xx",
"logid": 666,
}
conn = urllib2.urlopen(AS_SERVER+'/RTSAsService/snapshot', data=json.dumps(params)).read()
print conn;
def signup(appid=APPID):
params = {
"appid": appid,
"from": "from_xx",
"logid": 666,
}
conn = urllib2.urlopen(AS_SERVER+'/RTSAsService/signup', data=json.dumps(params)).read()
print conn;
if __name__ == '__main__':
if len(sys.argv) > 1:
func = getattr(sys.modules[__name__], sys.argv[1])
func(*sys.argv[2:])
else:
print >> sys.stderr, 'api.py {rts_as_add,rts_as_search,rts_as_delete}'
返回参数
参数名称 | 参数类型 | 参数说明 |
---|---|---|
err_no | int32 | 错误码,详见下方错误码列表信息 |
err_msg | string | 错误信息,详见下方错误码列表信息 |
data_items | ResultItem | search的返回结果 |
features | FeatureData | 分类检索的返回结果 |
has_more | unit32 | 除了返回的检索结果外是否还有更多的结果 |
index_capacity | int32 | 使用snapshot接口(查询用户的基本信息和用户已插入数据量等信息)的返回参数,表示当前数据库可支持的总容量 |
index_size | int32 | 使用snapshot接口(查询用户的基本信息和用户已插入数据量等信息)的返回参数,表示已使用容量 |
返回示例
接口 | 正确返回示例 | 错误返回示例 |
---|---|---|
add入库 | {"err_no":0,"err_msg":"OK"} | {"err_no":101,"err_msg":"duplicated add","data_items":[{"contsign":{"sign1":1143248165,"sign2":1517467661},"features":[{"fea_id":1000,"fea_data":"eWFoYWhh"}]}]} |
update更新 | {"err_no":0,"err_msg":"OK"} | |
search检索 | {"err_no":0,"err_msg":"OK","data_items":[{"contsign":{"sign1":1143248165,"sign2":1517467661},"score":1.0000001192092896,"features":[{"fea_id":1000,"fea_data":"dXBkYXRl"}]},{"contsign":{"sign1":2904947031,"sign2":1496948683},"score":0.33452537655830386,"features":[{"fea_id":1000,"fea_data":"dHVkb3UxMTEx"}]}],"has_more":0} | |
delete删除 | {"err_no":0,"err_msg":"OK"} | |
snapshot查询 | {"err_no":0,"err_msg":"OK","snapshot":{"tag":0,"index_size":1,"index_capacity":0,"queue_size":0}} | |
signup增加注册用户 | "err_no":0,"err_msg":"OK"} | {"err_no":0,"err_msg":"OK"} |
错误码
错误码 | 错误信息 |
---|---|
-1 | 服务初始化失败 |
0 | ok |
1 | 请求参数不合法 |
2 | feature服务超时 |
3 | bs服务超时 |
4 | meta服务超时 |
5 | 无效的feature服务 |
6 | 无效的bs服务 |
7 | 无效的meta服务 |
8 | 提取feature失败 |
9 | 请求bs失败 |
10 | 获取meta信息失败 |
11 | 服务内部错误 |
12 | 鉴权失败 |
99 | 服务忙 |
100 | 由于用户输入原因提取特征失败(1003,1004,1005,101003,216200(空图)216201(解码/图像格式错误)216202(图像尺寸错误)) |
101 | 重复add |
102 | 更新不在table中的数据 |
103 | 用户未注册 |
104 | 用户已存在 |