开放能力
开发平台
行业应用
生态合作
开发与教学
资讯 社区 控制台
技术能力
语音技术
文字识别
人脸与人体
图像技术
语言与知识
视频技术
AR与VR
数据智能
场景方案
部署方案
行业应用
智能教育
智能医疗
智能零售
智能工业
企业服务
智能政务
信息服务
智能园区

iOS_SDK

简介

本文档描述货架拼接iOS SDK如何使用。

系统支持

系统:iOS 9.0 以上

硬件:armv7 arm64 (Starndard architectures)(暂不支持模拟器)

Release Notes

时间 版本 说明
2021.12.22 4.1.0 新增手机端实时拼接模糊图像检测功能
2021.10.20 4.0.0 新增手机端实时拼接功能
2021.03.09 3.0.1 新增光线和手机方向检测功能
2020.12.30 3.0.0 新增支持拍摄图片,云端拼接功能
2020.11.12 2.0.0 新增支持排面统计占比
2019.08.30 1.0.0 支持拍摄视频,端上抽帧,云端拼接

集成指南

库依赖

SDK依赖以下静态库/动态库,需正确集成至项目中并配置Framework Search Paths / Header Search Paths / Library Search Paths:

  • opencv2.framework:OpenCV V4.5.2,必须引入
  • libmontage_algo.a:手机端实时拼接功能库,可选引入,集成时请一并拷贝头文件目录montage_algo至项目合适路径
  • libEasyDL.a:模糊图像检测引擎库,可选引入,集成时请一并拷贝头文件目录EasyDL至项目合适路径
  • libpaddle_api_full_bundled.a:模糊图像检测引擎库,可选引入,集成时请一并拷贝头文件目录paddlelite至项目合适路径

libEasyDL.a 和 libpaddle_api_full_bundled.a 需同时引入才可支持模糊图像检测

集成摄像头相关逻辑

UI部分包括摄像头代码均开源,可参考以下文件,用户拷贝相关代码至项目中即可,并修改相应文件名以避免符号冲突:

  • easydl-stitch-ios/ViewController/ImagePickerViewController:云端拼接拍照逻辑,重合度算法开源
  • easydl-stitch-ios/ViewController/MBStitchCameraViewController:手机端实时拼接拍照逻辑,拼接等相关算法依赖 libmontage_algo.a
  • easydl-stitch-ios/ViewController/VideoStitchViewController#startUIImagePicker():云端拼接视频逻辑入口,参考该方法内对系统UIImagePickerController的使用

拍照拼接参数配置

// easydl-stitch-ios/EasyDLStitch/EasyDLStitchParams.h

#define kThreshold 75 // 判断重合的阈值,0~100之间
#define kStrategy "phash" // 重合算法,类型:["ahash","phash","dhash"]
#define kThetaZ 60 // 手机倾斜Z轴角度阈值
#define kThetaXY 20 // 手机倾斜XY轴角度阈值
#define kOverLapControl true // 是否与遮罩重合才可以拍照
#define kOrientationControl true // 是否手机持握方向符合要求才可以拍照
#define kSkipFrames 3 // 跳过视频帧比对的数量,比如3为每3帧比对一次
#define kBrightnessLow -3 // 光线强度阈值,-99~99之间
#define kBrightnessHigh 5 // 光线强度阈值,-99~99之间
#define kBrightnessControl false // 是否光线符合要求才可以拍照

参数说明:

  • 获取重合度有"ahash","phash","dhash"三种算法,返回0~100之间的数值,越大表示重合度越高。不同算法返回的数值有区别,需相应调整阈值
  • 手机倾斜XY轴指左右倾斜,Z轴是前后倾斜,当倾斜角度过大会影响拼接效果
  • 设置只有手机倾斜角度、待拍摄图片与上一张图片重合度、环境光线亮度等条件符合要求才拍摄图片,保证拍摄效果
  • 相机默认为每秒30帧,修改kSkipFrames的值调节做重合度对比的速度,避免卡顿或拍摄状态切换过快

视频拼接参数配置

体验APP中对视频截取帧的频率为1秒1帧,由于每个视频的帧数不能大于60,所以体验APP不能拼接长度大于60s的视频。开发者可根据实际情况调整截帧的频率,并相应限制视频长度。调整频率方法:

// easydl-stitch-ios/ViewController/StitchViewController.m

static int frameInterval = 1;//截帧间隔(秒)

并在合适的地方提示视频长度限制:

UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:@"选择对象(视频长度不能超过60s)" message:nil preferredStyle:UIAlertControllerStyleActionSheet];

SDK工程结构

EasyDL-Image-Stitching-iOS
|- LIB
    |- include
        |- montage_algo/ // 手机端实时拼接功能库头文件
        |- EasyDL/       // 手机端实时拼接模糊图像检测引擎头文件
        |- paddlelite/   // 手机端实时拼接模糊图像检测引擎头文件
    |- libs
        |- opencv2.framework 		        // OpenCV库
        |- libmontage_algo.a 		        // 手机端实时拼接功能库
        |- libEasyDL.a                  // 手机端实时拼接模糊图像检测引擎
        |- libpaddle_api_full_bundled.a // 手机端实时拼接模糊图像检测引擎
|- EasyDLStitch
    |- images/              // 资源文件
    |- easydl-stitch-ios/   // Demo工程文件
    |- RES/
        |- conf.json       // API配置文件
        |- fuzzy_model/    // 模糊图像检测模型

SDK调用流程

获取鉴权

  1. 进入EasyDL零售版的百度智能云控制台应用列表页面,如下图所示:

1.png

  1. 如果还未创建应用,请点击「创建应用」按钮进行创建。创建应用后,参考鉴权参考文档,使用API Key(AK)和Secret Key(SK)获取access_token

下载SDK包后,填写ak、sk等信息。在RES/conf.json相应位置填入:

{
  "ak": "Mz0zhObvEZ6lnG1K3renXXXX", // API Key的值

  "sk": "188fRHYvLPmlPrNCDpBnkhL3ydXXXXX", // Secret Key的值

  "apiUrl": "https://aip.baidubce.com/rpc/2.0/ai_custom_retail/v1/detection/XXXX"  // 定制商品检测服务API
}

云端非实时拼接调用流程

  1. 创建任务:开始拼接整个流程
  2. 加货架图:上传图片
  3. 开始任务:启动货架拼接离线任务
  4. 查询任务:查询拼接任务的状态和结果

其他:

  1. 取消任务:取消正在进行或者等待的任务
  2. 任务列表:查询所有状态的任务列表
  3. 终止任务:终止正在进行或者等待的任务

调用API

云端拼接API的调用逻辑已封装在EasyDLStitchApiService文件中,以下为SDK调用货架拼接API的方法说明。货架拼接API接口的返回值及其他信息参见文档货架拼接API调用方法

创建拼接任务
- (void)createSpliceTaskWithConfig:(NSDictionary *)config successHandler:(SuccessBlock)successHandler failHandler:(FailureBlock)failHandler;

其中config为参数,后面两个回调block。参数取值及描述:

参数名称 是否必需 参数类型 描述 参数值限制
api_url string 商品检测服务的url
row_image_nums array[number] 各行待拼接货架图片的数量,array长度为货架图片的行数,array[i]为第i行的货架图片数量 行数不大于3,行内图片数量不大于60
detection_threshold float 商品检测服务的阈值 默认值为商品检测服务的阈值,取值范围[0,1]
nms_iou_threshold float 检测框矫准去重的阈值 默认值为0.45, 取值范围[0.2,0.8]
上传图片
- (void)uploadImageWithConfig:(NSDictionary *)config successHandler:(SuccessBlock)successHandler failHandler:(FailureBlock)failHandler;

其中config为参数,后面两个回调block。参数取值及描述:

参数名称 是否必需 参数类型 描述 参数值限制
task_id string 货架拼接任务id
row number 图片对应行的index 取值从0开始,需小于创建任务参数row_image_nums的长度
column number 图片在行内所在的index 取值从0开始,需小于创建任务参数row_image_nums[row]的取值
image string 上传图片的base64编码
启动拼接任务
-(void)startSpliceTaskWithConfig:(NSDictionary *)config successHandler:(SuccessBlock)successHandler failHandler:(FailureBlock)failHandler;

其中config为参数,后面两个回调block。参数取值及描述:

参数名称 是否必需 参数类型 描述 参数值限制
task_id string 货架拼接任务id
查询任务状态
-(void)queryTaskResultWithConfig:(NSDictionary *)config successHandler:(SuccessBlock)successHandler failHandler:(FailureBlock)failHandler;

其中config为参数,后面两个回调block。参数取值及描述:

参数名称 是否必需 参数类型 描述 参数值限制
task_id string 货架拼接任务id
查询任务列表
-(void)listTaskWithConfig:(NSDictionary *)config successHandler:(SuccessBlock)successHandler failHandler:(FailureBlock)failHandler;

其中config为参数,后面两个回调block。参数取值及描述:

参数名称 是否必需 参数类型 描述 参数值限制
task_ids array[string] 只返回指定id的任务信息
begin_time number 只返回begin_time以后创建的任务信息 时间戳
end_time number 只返回end_time之前创建的任务信息 时间戳
终止任务
-(void)terminateTaskWithConfig:(NSDictionary *)config successHandler:(SuccessBlock)successHandler failHandler:(FailureBlock)failHandler;

其中config为参数,后面两个回调block。参数取值及描述:

参数名称 是否必需 参数类型 描述 参数值限制
task_id string 货架拼接任务id

手机端实时拼接调用流程

  1. 准备目录
  2. 对比图片:新图片(now)在参与实时拼接前需先与上一张参与拼接的图片(last)进行对比,如果now与last的对比特征合法则可以成功拼接,否则无法得到理想实时拼接结果
  3. 实时拼接:SDK会寻找now.jpg并进行实时拼接得到新拼接结果
  4. 上传云端,得到结果

其他:

  1. 撤销拼接:撤销最后一次拼接结果

SDK的调用

手机端实时拼接的调用逻辑已封装在EasyDLMBStitchApiService文件中,包括商品检测API以及拼接算法的调用,以下为SDK调用的方法说明。

准备目录

实时拼接过程中产生的文件需保存在本地,首先初始化准备保存的目录。单个拼接任务的保存目录不可发生变化。

- (void)prepare;

// 调用示例
[[EasyDLMBStitchApiService sharedService] prepare];
对比图片
- (void)compareImage:(UIImage *)image firstFrame:(BOOL)isFirstFrame completionHandler:(CompletionHandler)completionHandler;

// 调用示例
[[EasyDLMBStitchApiService sharedService] compareImage:image firstFrame:_firstFrameCompare completionHandler:^(id responseObject, NSError *error) {
    if (error) {
        NSLog(@"%@", error.localizedDescription);
    } else {
      	// 回调结果
        CompareResult *compareResult = responseObject;
      	// do something
    }
}];

参数说明:

  • image:当前要参与对比的图片
  • isFirstFrame:是否是第一帧

    • 第一帧的定义取决于上一张参与拼接的图片(last)是否已经被对比过。假设有图片A和B,先用A与last对比,且last是初次被对比,此时isFirstFrame应为true,再用B与last对比,此时isFirstFrame应为false
  • completionHandler:异步回调,在主线程
CompareResult
// montage_algo/EasyDLStitchAlgo.h

// 当前图片相对上一张参与拼接的图片的方位
@property(nonatomic) ImageDirection direction;
/**
 * 是否需要判断方向,如当拍摄完图片过近时,direction可能由于两图过于相似而不可靠,这种情况不需要判断方向,即该值=false
 * 一般direction不可靠时,该值=false
 * 对比的两张图是第一次对比时,该值=false
 * 当该值=true时,请在调用实时拼接API前确认方法是否合法,否则可能导致拼接失败
 */
@property(nonatomic, getter = needCheckDirection) BOOL checkDirection;
// 对比结果中的方位是否合法,非法的方位将无法完成拼接
@property(nonatomic) BOOL directionValid;
// 两张图片重叠部分的点位
@property(nonatomic, retain) NSArray<NSValue *> *points;
// 两张图片重叠状态
@property(nonatomic) OverlapStatus overlapStatus;
// 最后一次参与拼接的图片序号,从1开始
@property(nonatomic) int lastImgIndex;
对比结果的合法性判断参考
switch (compareResult.overlapStatus) {
    case OverlapStatus_Correct:
        if (compareResult.needCheckDirection && !compareResult.directionValid) {
            // 非法,当前参与对比的图片方位不正确,无法拼接
        } else {
            // 合法
        }
        break;
    case OverlapStatus_TooFar:
        // 非法,两张图重叠度过低
        break;
    case OverlapStatus_TooClose:
        // 非法,两张图重叠度过高
        break;
}
实时拼接
  • 建议调用拼接前参考【对比结果的合法性判断】,用不合法的对比结果进行实时拼接将无法获得正确输出
  • 将要参与拼接的图片必须命名为“now.jpg”(也可使用EasyDLMBStitchApiService.FILENAME_IMAGE_NOW),并保存在[EasyDLMBStitchApiService sharedService].currentTask.workDir指向的目录下,否则实时拼接无法正常工作。成功拼接后"now.jpg"会被SDK重新命名为{index}.jpg,其中{index}代表图片序号。
  • 为获得更快的拼接效率,建议减小参与拼接的图片尺寸;为了保证拼接效果,缩放后的图片尺寸应不小于宽648和高864
- (void)stitchImageWithCompareResult:(CompareResult *)compareResult completionHandler:(CompletionHandler)completionHandler;

// 调用示例
[[EasyDLMBStitchApiService sharedService] stitchImageWithCompareResult:_latestCompareResult completionHandler:^(id responseObject, NSError *error) {
    if (error) {
        NSLog(@"%@", error.localizedDescription);
    } else {
      	// 回调结果
        StitchResult *stitchResult = responseObject;
      	// do something
    }
}];

// 保存now.jpg示例
NSURL *workDirUrl = [EasyDLMBStitchApiService sharedService].currentTask.workDir;
/* 小图为拼接,大图为获得更好的商品检测效果 */
[EasyDLFileManager saveImage:image toUrl:[workDirUrl URLByAppendingPathComponent:FILENAME_IMAGE_NOW] andResizeTo:CGSizeMake(648, 864)];
// SDK默认使用保存的一系列`{index}.jpg`调用商品检测API并取得结果。
// 由于建议减小该系列图片尺寸以获得更优的拼接效率,但同时更小尺寸的图片对商品检测精度有一定影响,因此为提高精度,建议同时保存最佳尺寸的图片用于上传云端。
[EasyDLFileManager saveImageForBestInfer:image toUrl:[workDirUrl URLByAppendingPathComponent:[NSString stringWithFormat:@"%@/%@", DIR_NAME_FULL_IMAGE, FILENAME_IMAGE_NOW]]];

参数说明:

  • compareResult:对比图片回调返回的结果
  • completionHandler:异步回调,在主线程。该回调在拼接任务全部完成后到达,如需更快获取缩略图和完整拼接图,可配置EasyDLMBAPIStitchDelegate协议
StitchResult
// montage_algo/EasyDLStitchAlgo.h

// 拼接错误码,0表示成功,其他为错误
@property(nonatomic) int errCode;
// 最近一张参与拼接的图片的序号
@property(nonatomic) int latestImgIndex;
// 缩略拼接图路径
@property(nonatomic, retain) NSURL *thumbnailUrl;
// 完整拼接图路径
@property(nonatomic, retain) NSURL *fullImageUrl;
EasyDLMBAPIStitchDelegate
// easydl-montage-ios/EasyDLStitch/EasyDLMBStitchApiService.h

@protocol EasyDLMBAPIStitchDelegate <NSObject>
- (void)onStitchThumbnailGenerated:(NSURL *)thumbnailURL;
- (void)onStitchFullImageGenerated:(NSURL *)fullImageURL;
@end
  
// 配置示例
[EasyDLMBStitchApiService sharedService].stitchDelegate = self;
上传云端,得到结果
- (void)mergeDetectedResultsWithCompletionHandler:(CompletionHandler)completionHandler;

// 调用示例
[[EasyDLMBStitchApiService sharedService] mergeDetectedResultsWithCompletionHandler:^(id responseObject, NSError *error) {
    if (error) {
        NSLog(@"%@", error.localizedDescription);
    } else {
      	// 回调结果
        MergeResult *mergeResult = responseObject;
      	// do something
    }
}];

参数说明:

  • completionHandler:异步回调,在主线程。该回调在检测任务全部完成后到达,如需感知检测任务的开始和进度更新,可配置EasyDLMBAPIMergeDelegate协议
MergeResult
// montage_algo/EasyDLStitchAlgo.h

// 错误码,0表示成功,其他为错误
@property(nonatomic) int errCode;
// 商品检测并去重合并后的结果
@property(nonatomic, retain) NSDictionary *correctSKUDict;
EasyDLMBAPIMergeDelegate
// easydl-montage-ios/EasyDLStitch/EasyDLMBStitchApiService.h

@protocol EasyDLMBAPIMergeDelegate <NSObject>
- (void)onMergeResultsStarted:(int)totalImageCount;
- (void)onMergeProgressUpdated:(int)totalImageCount completedCount:(int)completedCount;
@end
  
// 配置示例
[EasyDLMBStitchApiService sharedService].mergeDelegate = self;
撤销拼接

SDK支持撤销最后一次拼接结果,如需撤销多张,请多次操作

- (void)undoLastTakenImageWithCompletionHandler:(CompletionHandler)completionHandler;

// 调用示例
[[EasyDLMBStitchApiService sharedService] undoLastTakenImageWithCompletionHandler:^(id responseObject, NSError *error) {
    if (error) {
        NSLog(@"%@", error.localizedDescription);
    } else {
      	// 回调结果,包含撤销后,当前最后一次参与拼接的图片信息
        ImageInfo *lastImageInfo = responseObject;
      	// do something
    }
}];

参数说明:

  • completionHandler:异步回调,在主线程
ImageInfo
// easydl-montage-ios/EasyDLStitch/EasyDLMBStitchApiService.h

// 图片序号
@property(nonatomic) int index;
// 图片列坐标
@property(nonatomic) int x;
// 图片行坐标
@property(nonatomic) int y;

模糊图像检测

手机端实时拼接已接入AI模型以支持模糊图像检测,除参考库依赖正确引入依赖库,需保证 RES/fuzzy_model 目录下的模型文件存在。调用示例如下,也可参考 EasyDL-Stitch/easydl-stitch-ios/ViewController/MBStitchCameraViewController.m 文件中对 FuzzyModelProxy 的使用:

// 模型初始化
- (NSError *)modelInit;
// 推理图像判断是否模糊
- (void)inferImage:(UIImage *)image completionHandler:(void (^)(BOOL fuzzy, NSError *error))completionHandler;

// 调用示例
FuzzyModelProxy *fuzzyModelProxy = [[FuzzyModelProxy alloc] init];
[fuzzyModelProxy modelInit];
if (fuzzyModelProxy && fuzzyModelProxy.engineActive) {
    [fuzzyModelProxy inferImage:image completionHandler:^(BOOL fuzzy, NSError *error) {
        if (!error && !fuzzy) {
            // 图像非模糊
        } else {
            // 图像模糊或推理失败
        }
    }];
}

阈值设置

手机端实时拼接支持设置:

  • 最小IOU置信度
  • 最大IOU置信度
  • NMS置信度
  • 商品检测API最大重试次数
// easydl-montage-ios/EasyDLStitch/EasyDLMBStitchApiService.h

/**
 * 最小拼接引导置信度
 */
@property(nonatomic) CGFloat minIOUThreshold;
/**
 * 最大拼接引导置信度
 */
@property(nonatomic) CGFloat maxIOUThreshold;
/**
 * 去重置信度
 */
@property(nonatomic) CGFloat nmsIOUThreshold;
/**
 * 商品检测API重试次数
 */
@property(nonatomic) int detectRetryTimes;
/**
 * 商品检测API最大并发数
 */
@property(nonatomic) int maxQPS;

错误码

以下为SDK使用的错误码,API接口错误码参见货架拼接API错误码

错误码 说明
200002 模型配置错误,请检查传入的配置文件是否有效
100006 API,AK/SK 换取token失败
100007 API,请求 API 失败
100008 API,请求商品检测API失败
200001 手机端实时拼接 - 前端引导对比图像出错
200003 手机端实时拼接 - 撤销上一次拼接结果出错
200004 手机端实时拼接 - 商品检测+去重过程中出错
200005 手机端实时拼接 - 拼接出错
300001 手机端实时拼接 - 模糊图像检测出错
上一篇
SDK介绍
下一篇
Android_SDK