ViSearch 1.5.1

ViSearch 1.5.1

测试已测试
Lang语言 Obj-CObjective C
许可证 MIT
发布最后发布2021年4月

“Yaoxuan”ShaohuanYuluNgo HungNgo Hung维护。



ViSearch 1.5.1

  • Yaoxuan,Yulu 和 Hung

ViSearch iOS SDK 和 Demo 源代码

Build Status


## 目录

  1. 概述
  2. 设置
  3. 初始化
  4. 解决方案 API
  5. 搜索结果
  6. 高级搜索参数
  7. 事件跟踪

1. 概述

ViSearch 是一个提供精确、可靠和可扩展的图像搜索的 API。ViSearch API 为开发者提供了两个服务(数据 API 和搜索 API),以让他们能够高效地准备图像数据库并进行图像搜索。ViSearch API 可以轻松集成到您的 Web 和移动应用程序中。有关更详细的信息,请参阅 ViSearch API 文档

ViSearch iOS SDK是一个开源软件,用于方便地将ViSearch搜索API集成到您的iOS应用程序中。它提供基于ViSearch解决方案API的四种搜索方法 - 查找相似、你可能还会喜欢、按图像搜索和按颜色搜索。有关源代码和参考资料,请访问Github仓库

当前稳定版本:1.5.0

支持的iOS版本:iOS 7.x及以上

2. 设置

2.1 运行示例

示例应用程序的源代码与SDK一起提供(示例)。您只需在XCode中打开ViSearchExample项目并运行示例即可。

screenshot

在运行之前,您应该将访问密钥和密钥对更改为您自己的密钥对。

@implementation HomeViewController {
    NSMutableArray *rectangles;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    rectangles = [[NSMutableArray alloc] init];
    self.generalService = [GeneralServices sharedInstance];

    //TODO: insert your own application keys
    NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
    
    // new way of authenticate. only need app key
    [dict setValue:@"YOUR_APP_KEY" forKey:@"app_key"];
    
    // old way of authentication which need access and secret key
//    [dict setValue:@"YOUR_ACCESS_KEY" forKey:@"access_key"];
//    [dict setValue:@"YOUR_SECRET_KEY" forKey:@"secret_key"];
    
    [[CoreDataModel sharedInstance] insertApplication:dict];
}

您可以使用我们的示例应用程序来探索我们是如何使用ViSearch SDK构建酷炫的图像搜索功能的。

ios_demo

2.2 设置Xcode项目

在Xcode中,转到文件&大于;新建&大于;项目选择单视图应用程序。

screenshot

为您的项目输入一个名称并按下一步,这里我们使用“示例”作为项目名称。

screenshot

2.3 导入ViSearch SDK

2.3.1 使用CocoaPods

首先,您需要安装CocoaPods Ruby宝石

[sudo] gem install cocoapods
pod setup

然后转到您的项目目录以创建空的Podfile

cd /path/to/Demo
pod init

按以下方式编辑Podfile

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '7.0'
...
pod 'ViSearch', '~>1.3.1'
...

安装ViSearch SDK

pod install

应该创建一个Demo.xcworkspace项目。

2.3.2 使用手动方法

您还可以直接下载 iOS ViSearch SDK。使用时,请解压并将其中的 ViSearch SDK 文件夹拖动到 Demo 项目的文件文件夹中。

screenshot

然后将它添加到您的项目中

screenshot

2.4 添加隐私使用说明

iOS 10 现在要求使用户权限来访问相机和照片库。如果您的应用程序需要这些访问,请在 Info.plist 中添加 NSCameraUsageDescription,NSPhotoLibraryUsageDescription 的描述。更多详细信息请参阅这里

3. 初始化

ViSearch 必须 使用 appKeyaccessKey/secretKey初始化 后才能使用。

#import <ViSearch/VisearchAPI.h>
...
// using default ViSearch client. The client, by default,
// connects to Visenze's server

// 1. new way of init ViSearch client with only app key
static NSString * const appKey = @"your_app_key";


[ViSearchAPI setupAppKey:appKey];
ViSearchClient *client = [ViSearch defaultClient];


// 2. OR old way of init ViSearch client with access and secret key
static NSString * const accessKey = @"your_access_key";
static NSString * const privateKey = @"your_secret_key";

[ViSearchAPI setupAccessKey:accessKey andSecretKey:secretKey];
ViSearchClient *client = [ViSearch defaultClient];
client.isAppKeyEnabled = NO;
...


// OR using customized client, which connects to your own server
static NSString * const privateKey = @"your_url";
ViSearchClient *client = [[ViSearchClient alloc] initWithBaseUrl:url
	appKey:appKey];
...

如果您连接到的是除默认端点 (https://visearch.visenze.com) 之外的其他端点,请以这种方式初始化 ViSearch 客户端。

static NSString * const privateKey = @"your_url";
ViSearchClient *client = [[ViSearchClient alloc] initWithBaseUrl:url
	appKey:appKey];

4. 解决方案 API

4.1 视觉相似推荐

GET /search

视觉相似推荐 解决方案用于在图像数据库中搜索由索引图像的唯一标识符 (im_name) 给定的视觉相似图像。

#import <ViSearch/VisearchAPI.h>
...
SearchParams *searchParams = [[SearchParams alloc] init];
searchParams.imName = @"imName-example";

[[ViSearchAPI defaultClient]
	searchWithImageId:searchParams
	success:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
	// Do something when request succeeds
	} failure:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
	// Do something when request fails
	}];
...

4.2 通过图片搜索

POST /uploadsearch

通过图片搜索解决方案用于通过上传图片或提供图片URL搜索相似图片。Image类用于执行图片编码和缩放。您应该构造Image对象并将其传递给UploadSearchParams以启动搜索。

  • 使用UIImage
#import <ViSearch/VisearchAPI.h>
...
UIImage *image = [UIImage imageNamed:@"example.jpg"];

UploadSearchParams *uploadSearchParams = [[UploadSearchParams alloc] init];
uploadSearchParams.imageFile = image

[[ViSearchAPI defaultClient]
	searchWithImageData:uploadSearchParams
	success:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
	// Do something when request succeeds
    } failure:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
	// Do something when request fails
    }];
  • 或者,您可以直接将图片URL传递给uploadSearchParams以启动搜索
#import <ViSearch/VisearchAPI.h>
...
UploadSearchParams *uploadSearchParams = [[UploadSearchParams alloc] init];
uploadSearchParams.imageUrl = @"http://example.com/example.jpg";

[[ViSearchAPI defaultClient]
	searchWithImageUrl:uploadSearchParams
	success:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
	// Do something when request succeeds
    } failure:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
	// Do something when request fails
    }];
...
  • 上传图片后,您将从搜索结果中收到im_id属性。如果您想再次搜索相同的图片,可以通过指定params中的im_id来节省带宽。
#import <ViSearch/VisearchAPI.h>
...
UploadSearchParams *uploadSearchParams = [[UploadSearchParams alloc] init];
uploadSearchParams.imId = visearchResult.imId;

[[ViSearchAPI defaultClient]
	searchWithImage:uploadSearchParams
	success:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
	// Do something when request succeeds
    } failure:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
	// Do something when request fails
    }];
...

4.2.1 选择框

如果您希望搜索的对象仅占您图像的一小部分,或者同一图像中存在其他无关对象,搜索结果可能不准确。使用Box参数可以精炼图像搜索区域以提高准确性。坐标是根据上传的图像原始大小设置的。注意:坐标系统使用像素为单位而不是点。

// create the box to refine the area on the searching image
// Box(x1, y1, x2, y2) where (0,0) is the top-left corner
// of the image, (x1, y1) is the top-left corner of the box,
// and (x2, y2) is the bottom-right corner of the box.
...
UploadSearchParams *uploadSearchParams = [[UploadSearchParams alloc] init];

Box *box = [[Box alloc]initWithX1:0 y1:0 x2:100 y2:100];
uploadSearchParams.box = box;

// start searching
...

4.2.2 缩放设置

在上传搜索期间,您可能会注意到随着图像文件大小的增加,搜索延迟也随之增加。这是由于在网络中将您的图像传输到ViSearch服务器所花费的时间增加,以及在ViSearch中处理大型图像文件所需的时间增加。

为了减少上传搜索延迟,默认情况下,uploadSearch方法会复制您的图像文件,并将大小调整到512x512像素,如果原始尺寸之一超过512像素。这是降低搜索延迟的最佳尺寸,同时不会牺牲通用用例的搜索准确性。

// by default, the max width of the image is set to 512px, quality is 0.97
UploadSearchParams *uploadSearchParams = [[UploadSearchParams alloc] init];
// or you can explicitly set a param's settings
uploadSearchParams.settings = [ImageSettings defaultSettings];

如果您的图像包含如织物图案和纹理之类的细小细节,您可以为搜索提供更大尺寸的图像以获得更好的搜索结果

// by default, the max width of the image is set to 512px, quality is 0.97
UploadSearchParams *uploadSearchParams = [[UploadSearchParams alloc] init];
// set the image with high quality settings.
// Max width is 1024px, and the quality is 0.985. Note: Quality with 1.0 take hugespace
uploadSearchParams.settings = [ImageSettings highqualitySettings];

或者,提供自定义的缩放设置。为了有效利用移动设备上的内存和网络带宽,最大尺寸设置为1024 x 1024。任何超出限制的图像都将被缩放至该限制。

//resize the image to 800 by 800 area using jpeg 0.9 quality
uploadSearchParams.settings = [[ImageSettings alloc]
	initWithSize:CGSizeMake(800, 800) Quality:0.9];

4.3 通过颜色搜索

GET /colorsearch

通过颜色搜索方案通过提供颜色代码来搜索具有相似颜色的图片。颜色代码应为十六进制格式,并以字符串形式传递给ColorSearchParams

#import <ViSearch/VisearchAPI.h>
...
ColorSearchParams *colorSearchParams = [[ColorSearchParams alloc] init];
colorSearchParams.color = @"012ACF";

[[ViSearchAPI defaultClient]
	searchWithColor:colorSearchParams
	success:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
    // Do something when request succeeds   
    } failure:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
    // Do something when request fails
    }];
...

4.4 多产品搜索

POST /discoversearch

多产品搜索解决方案通过上传图片或提供图片 URL,类似于通过图片搜索来搜索类似图片。多产品搜索能够检测图像中的所有对象,并一次性返回每个对象的相似图像。

  • 使用UIImage
#import <ViSearch/VisearchAPI.h>
...
UIImage *image = [UIImage imageNamed:@"example.jpg"];

UploadSearchParams *uploadSearchParams = [[UploadSearchParams alloc] init];
uploadSearchParams.imageFile = image

[[ViSearchAPI defaultClient]
	discoverSearchWithImageData:uploadSearchParams
	success:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
	// Do something when request succeeds
    } failure:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
	// Do something when request fails
    }];
  • 或者,您可以直接将图片URL传递给uploadSearchParams以启动搜索
#import <ViSearch/VisearchAPI.h>
...
UploadSearchParams *uploadSearchParams = [[UploadSearchParams alloc] init];
uploadSearchParams.imageUrl = @"http://example.com/example.jpg";

[[ViSearchAPI defaultClient]
	discoverSearchWithImageUrl:uploadSearchParams
	success:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
	// Do something when request succeeds
    } failure:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
	// Do something when request fails
    }];
...
  • 上传图片后,您将从搜索结果中收到im_id属性。如果您想再次搜索相同的图片,可以通过指定params中的im_id来节省带宽。
#import <ViSearch/VisearchAPI.h>
...
UploadSearchParams *uploadSearchParams = [[UploadSearchParams alloc] init];
uploadSearchParams.imId = visearchResult.imId;

[[ViSearchAPI defaultClient]
	discoverSearchWithImage:uploadSearchParams
	success:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
	// Do something when request succeeds
    } failure:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
	// Do something when request fails
    }];
...

5. 搜索结果

搜索请求成功后,将结果列表以ViSearchResult的形式传递给回调函数。您可以使用以下属性来完成自己的目的。

名称 类型 描述
成功 BOOL 请求是否由服务器成功处理。
注意:发送给服务器的无效参数也可能使此属性为false
错误 ViSearchError 除了由网络条件引起的错误外,还显示了由于发送给服务器的无效参数引起的错误。
内容 NSDictionary 从服务器返回的完整 JSON 数据。(此属性可能在将来被弃用)
imageResultsArray NSArray 从服务器返回的图像结果列表。
reqId NSString 一个请求 ID,可用于跟踪。更多详情请参阅第 7 节
imId NSString 结果中返回的图像 ID,代表刚刚上传的图像。可以再次使用它来进行相同图像的上传搜索。更多详情请参阅通过图片搜索

鼓励使用imageResultsArray,因为强内容属性可能在将来被弃用。每个图像结果都采用ImageResult的形式。您可以使用以下ImageResult的属性来完成自己的目的。

名称 类型 描述
im_name NSString 图像的标识名称。
url NSString 图像 URL。
分数 CGFloat 介于 0.0 到 1.0 之间的浮点值。请参阅第 6.3 节结果分数
metadataDictionary NSDictionary 从服务器返回的其他元数据。请参阅第 6.1 节检索元数据
// This is an example of image url search.
// The process of handling results by other kinds of search is similar.
[[ViSearchAPI defaultClient]
	searchWithImageUrl:uploadSearchParams
	success:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
		// Iterate all returned results
		for (ImageResult *result in data.imageResultsArray) {
			NSLog("%@", result.url);//log result's image url.
			//Do something here
		}
    } failure:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
		NSLog("%@", data.error.message);//log network and server error message
    }];

您可以通过提供分页参数来控制图像搜索结果的分页。通过配置基本搜索参数 BaseSearchParams 实现。由于结果以每页图像列表的格式返回,请使用 setLimit 设置每页的结果数量,使用 setPage 表示页码。

名称 类型 描述
整数 指定结果页码的可选参数。结果的第一页为1。默认为1。
limit 整数 指定每页结果数量的可选参数。默认为10。
// For example, when the server side has 60 items, the search operation will return
// the first 30 items with page = 1 and limit = 30. By changing the page to 2,
// the search will return the last 30 items.
...
SearchParams *searchParams = [[SearchParams alloc] init];
searchParams.page = 2;
searchParams.limit = 30;

// start searching
...

6. 高级搜索参数

6.1 获取元数据

要获取搜索结果的元数据,请将元数据键的列表作为基本搜索属性中的 fl(字段列表)提供

SearchParams *searchParams = [[SearchParams alloc] init];
searchParams.fl = @[@"price",@"brand",@"im_url"];

要获取所有图像结果的所有元数据,指定 get_all_fl 参数并将其设置为 true

SearchParams *searchParams = [[SearchParams alloc] init];
searchParams.getAllFl = true;

在结果回调中,您可以读取元数据

success:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
	// Iterate all returned results
	for (ImageResult *result in data.imageResultsArray) {
		NSLog("%@", result.metadataDictionary);//log result's metadata.
		NSLog("%@", [result.metadataDictionary
			objectForKey;@"price"]);//log price in metadata
		//Do something here
	}
}

从 ViSearch 中只能检索类型为字符串、int 和 float 的元数据。不支持检索文本类型的元数据。

6.2 过滤结果

要基于元数据值过滤搜索结果,请提供一个映射,表示元数据键到过滤值的 fq(过滤查询)属性

...
UploadSearchParams *uploadSearchParams = [[UploadSearchParams alloc] init];

// the type of "count" on db schema is int,
// so we can specify the value range, or do a value match
[uploadSearchParams.fq setObject:@"0, 199" forKey:@"count"];
[uploadSearchParams.fq setObject:@"199" forKey:@"count"];

// the type of "price" on db schema is float,
// so we can specify the value range, or do a value match
[uploadSearchParams.fq setObject:@"0.0, 199.0" forKey:@"price"];
[uploadSearchParams.fq setObject:@"15.0" forKey:@"price"];

// the type of "description" on db schema is string, so we can do a string match.
[uploadSearchParams.fq setObject:@"description" forKey:@"wooden"];

// start searching
...

以下表中列出了每种元数据类型的查询语法

类型 FQ
字符串 元数据值必须与查询值完全匹配,例如:"Vintage Wingtips" 不会匹配 "vintage wingtips" 或 "vintage"
文本 元数据值将使用全文搜索引擎进行索引,并支持模糊文本匹配,例如:"A pair of high quality leather wingtips" 会匹配短语中的任何单词
int 元数据值可以是以下之一
  • 与查询值完全匹配
  • 与范围查询 minValue,maxValue 匹配,例如:int 值 1, 99,和 199 会匹配范围查询 0,199 但不会匹配范围查询 200,300
float 元数据值可以是以下之一
  • 与查询值完全匹配
  • 与范围查询 minValue,maxValue 匹配,例如:float 值 1.0,99.99,和 199.99 会匹配范围查询 0.0,199.99 但不会匹配范围查询 200.0,300.0

6.3 结果得分

ViSearch图片搜索结果按照降序排列,即从最高分到最低分,分数范围从1.0到0.0。默认情况下,不会返回每个结果的得分。您可以通过启用分数参数来检索每个图像结果的得分

...
UploadSearchParams *uploadSearchParams = [[UploadSearchParams alloc] init];
uploadSearchParams.score = YES; // result will include score for every image

// start searching
...

如果您需要从最低得分到最高得分限制搜索结果,请指定score_min和/或score_max参数

...
UploadSearchParams *uploadSearchParams = [[UploadSearchParams alloc] init];
uploadSearchParams.score = YES; // result will include score for every image
uplaodSearchParams.scoreMin = 0.3; // the minimum score is 0.3  
uplaodSearchParams.scoreMax = 0.8; // the maximum score is 0.8

// start searching. Every image result will have a score within [0.3, 0.8].
...

6.4 自动对象识别(Beta版)

通过自动对象识别,ViSearch /uploadsearch API能够智能地检测查询图像中的对象,并为搜索建议最佳匹配的产品类型。

您可以在上传搜索中开启此功能,通过设置API参数“detection=all”。目前,我们能够检测各种类型的时尚商品,包括《上衣》、《连衣裙》、《下装》、《鞋子》、《包袋》、《手表》和《印度民族服饰》。随着我们探索其他类别,该列表将持续扩展。

注意:此功能目前仅适用于时尚应用程序类型。您需确保在ViSenze仪表板上将您的应用程序类型配置为“时尚”(ViSenze仪表板)。

params.detection = @"all";

您可以使用Box参数限制图像区域[x1, y1, x2, y2]作为您图像中搜索的部分。当您输入宽度为0、高度为0的框,例如“box”:[574,224,574,224]。我们将将其视为一个点,并在当前位置进行对象检测。

您还可以通过配置检测参数为特定产品类型作为“detection={type}”,从上传的查询图像中识别特定类型的对象。我们的API将在该产品类型内执行搜索。

示例请求检测上传图像中的包袋

params.detection = @"bag";

检测到的产品类型及其匹配分数和检测对象区域框列表在product_types中。查询图像中的多个对象可以根据分数从高到低排序。我们的API支持的完整产品类型列表也将返回在product_types_list中。

6.5 索引过滤

您可以通过发送要启用索引过滤的字段列表来获取索引结果。以下是对请求的限制

  • 在ViSenze仪表板上,需要将面域字段标记为可搜索。文本字段不支持作为面域字段,即使它是可搜索的。系统将返回数值字段的值范围,包括最小值和最大值。

  • 只返回当前搜索结果中存在的面域值。例如,如果您的搜索结果包含10个独特品牌,则面域过滤器将返回这10个品牌的值。

  • 面域值列表将按项目数量降序排序。当值设置为全部(面域 = *)时,所有可搜索的字段都将用作面域字段。

名称 类型 描述
面域 数组 启用分面所需字段列表。
面域限制 整型 返回面域值的数量限制。仅适用于非数值字段。
显示面域计数 布尔型 响应中显示面域计数选项。
searchParams.facets = @[@"brand" , @"price"];
searchParams.facetShowCount = YES;
searchParams.facetsLimit = 10;

// view facet results
ViSearchResult.facets

7. 事件跟踪

为了提高搜索性能和获取有用的数据见解,建议发送与我们的视觉搜索结果的用户交互(操作)。我们的跟踪SDK(Swift)位于https://github.com/visenze/visenze-tracking-swift

7.1 设置跟踪

您可以通过登录ViSenze仪表板使用跟踪ID(代码)初始化ViSenze跟踪器。跟踪器有两个不同的端点(一个用于中国,另一个用于世界其他地区)。如果SDK打算在中国以外使用,请设置forCn参数为false。

import ViSenzeAnalytics
...


let tracker = ViSenzeAnalytics.sharedInstance.newTracker(code: "your-code", forCn: false)

7.2 发送事件

目前我们支持以下事件动作:clickviewproduct_clickproduct_viewadd_to_carttransactionaction参数可以是任意字符串,可以发送自定义事件。

要发送事件,首先从搜索结果回调中检索搜索查询ID。


success:^(NSInteger statusCode, ViSearchResult *data, NSError *error) {
		NSString* queryId = [data reqId];

然后可以按如下方式发送事件:

# send product click
let productClickEvent = VaEvent.newProductClickEvent(queryId: "ViSearch reqid in API response", pid: "product ID", imgUrl: "product image URL", pos: 3)
tracker.sendEvent(productClickEvent) { (eventResponse, networkError) in
   
}

# send product impression
let impressionEvent = VaEvent.newProductImpressionEvent(queryId: "ViSearch reqid in API response", pid: "product ID", imgUrl: "product image URL", pos: 3)
tracker.sendEvent(impressionEvent)

# send Transaction event e.g order purchase of $300
let transEvent = VaEvent.newTransactionEvent(queryId: "xxx", transactionId:"your trans id", value: 300)
tracker.sendEvent(transEvent)

# send Add to Cart Event
let add2Cart = VaEvent.newAdd2CartEvent(queryId: "ViSearch reqid in API response", pid: "product ID", imgUrl: "product image URL", pos: 3)
tracker.sendEvent(add2Cart)
 

最后通过跟踪器发送事件。

tracker.sendEvent(event);

以下是各种参数的简要描述

字段 描述 必填
queryId 搜索请求的请求ID。此reqid可以从搜索响应处理程序中获得:ViSearchResult .reqId
action 事件动作。目前我们支持以下事件动作:clickviewproduct_clickproduct_viewadd_to_carttransaction
pid 产品ID(通常这是 im_name)对于此产品。可以通过 ImageResult.im_name 获取。 用于产品查看、点击和添加到购物车事件。
imgUrl 图像URL(通常这是 im_url)对于此产品。可以通过 ImageResult.url 获取。 用于产品查看、点击和添加到购物车事件。
pos 产品在搜索结果中的位置,例如点击位置/查看位置。请注意,从1开始,而不是0。 用于产品查看、点击和添加到购物车事件。
transactionId 事务ID 用于事务事件。
value 交易价值,例如订单价值。 用于事务事件。