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

iOS-SDK

简介

本文档介绍iOS飞桨开源模型SDK版本如何进行开发集成

系统支持

系统:

  • 通用ARM: iOS 9.0及以上

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

SDK大小说明

  • 模型资源文件大小影响 SDK 大小
  • SDK 包及 IPA 安装包虽然比较大,但最终安装到设备后所占大小会缩小很多。这与 multi architechtures、bitcode 和 AppStore 的优化有关。

快速开始

文件结构说明

.EasyEdge-iOS-SDK
├── EasyDLDemo	# Demo工程文件
├── LIB			# 依赖库
├── RES
│   ├── easyedge	# 模型资源文件夹
│   │   ├── model
│   │   ├── params
│   │   ├── label_list.txt
│   │   ├── infer_cfg.json
│   │   ├── conf.json
└── DOC			# 文档

测试Demo

按如下步骤可直接运行 SDK 体验 Demo:
步骤一:用 Xcode 打开 EasyDLDemo/EasyDLDemo.xcodeproj
步骤二:配置开发者自己的签名
步骤三:连接手机运行,不支持模拟器

检测模型运行示例:

image.png

SDK使用说明

本节介绍如何将 SDK 接入开发者的项目中使用。

集成指南

步骤一:依赖库集成 步骤二:import <EasyDL/EasyDL.h>

依赖库集成

  1. 复制 LIB 目录至项目合适的位置
  2. 配置 Build Settings 中 Search paths: 以 SDK 中 LIB 目录路径为例
  • Framework Search Paths:${PROJECT_DIR}/../LIB/lib
  • Header Search Paths:${PROJECT_DIR}/../LIB/include
  • Library Search Paths:${PROJECT_DIR}/../LIB/lib

集成过程如出现错误,请参考 Demo 工程对依赖库的引用

调用流程示例

以通用ARM的图像分类预测流程为例,详细说明请参考后续章节:

NSError *err;

// step 1: 初始化模型
EasyDLModel *model = [[EasyDLModel alloc] initModelFromResourceDirectory:@"easyedge" withError:&err];

// step 2: 准备待预测的图像
UIImage *image = ...;

// step 3: 预测图像
NSArray *results = [model detectUIImage:image withFilterScore:0 andError:&err];

// step 4: 解析结果
for (id res in results) {
	EasyDLClassfiData *clsData = (EasyDLClassfiData *) res;
	NSLog(@"labelIndex=%d, labelName=%@, confidence=%f", clsData.category, clsData.label, clsData.accuracy);
}

初始化

// 示例
// 参数一为模型资源文件夹名称
EasyDLModel *model = [[EasyDLModel alloc] initModelFromResourceDirectory:@"easyedge" withError:&err];

模型资源文件夹需以 folder reference 方式加入 Xcode 工程,如 RES/easyedge 文件夹在 Demo 工程中表现为蓝色

预测图像

所有模型类型通过以下接口获取预测结果:

// 返回的数组类型不定
NSArray *results = [model detectUIImage:image withFilterScore:0 andError:&err];

返回的数组类型如下,具体可参考 EasyDLResultData.h 中的定义: | 模型类型 | 类型 | | --- | ---- | | 图像分类 | EasyDLClassfiData | | 物体检测/人脸检测 | EasyDLObjectDetectionData | | 实例分割 | EasyDLObjSegmentationData | | 姿态估计 | EasyDLPoseData | | 文字识别 | EasyDLOcrData |

模型替换说明

模型资源文件位于 RES/easyedge 目录下,开发者可替换运行其他模型:

  • model:模型网络结构文件,对应Paddle1.x的__model__,Paddle2.x的model.pdmodel
  • params:模型网络参数文件,对应Paddle1.x的__params__,Paddle2.x的model.pdiparams
  • label_list.txt:label文件
  • infer_cfg.json:模型推理的预处理、后处理配置文件,具体见下
  • conf.json:【非必需】Demo App 配置文件,建议配置 modelName,缺少不影响运行

infer_cfg.json说明

其中,非标记【必须】的可不填

{
    "version": 1,
    "model_info": { 
        "best_threshold": 0.3,   // 默认0.3
        "model_kind": 1, // 【必须】 1-分类,2-检测,6-实例分割,14-语义分割,401-人脸,402-姿态
    },
    "pre_process": { // 【必须】
        // 归一化, 预处理会把图像 (origin_img - mean) * scale 
        "skip_norm": false, // 默认为false, 如果设置为true,不做mean scale处理
        "mean": [123, 123, 123],  // 【必须】
        "scale": [0.017, 0.017, 0.017],  // 【必须】
        "color_format": "RGB", // BGR 【必须】
        "channel_order": "CHW", // HWC
        // 大小相关
        "resize": [300, 300],  // w, h 【必须】
        "rescale_mode": "keep_size", // 默认keep_size, keep_ratio, keep_ratio2, keep_raw_size, warp_affine
        "max_size": 1366, // keep_ratio 用。如果没有提供,则用 resize[0]
        "target_size": 800,  // keep_ratio 用。如果没有提供,则用 resize[1]
        "raw_size_range": [100, 10000], // keep_raw_size 用
        "warp_affine_keep_res": // warp_affine模式使用,默认为false
        "center_crop_size": [224, 224], // w, h, 如果需要做center_crop,则提供,否则,无需提供该字段
        "padding": false,
        "padding_mode": "padding_align32",  // 【非必须】默认padding_align32, 其他可指定:padding_fill_size
        "padding_fill_size": [416, 416], // 【非必须】仅padding_fill_size模式下需要提供, [fill_size_w, fill_size_h], 这里padding fill对齐paddle detection实现,在bottom和right方向实现补齐
        "padding_fill_value": [114, 114, 114] // 【非必须】仅padding_fill_size模式下需要提供
        // 其他
        "letterbox": true,
        "ocr_rec_resize": [320, 48], // 【非必须】仅ocr需提供
        "ocr_rec_batch_num": 6, // 【非必须】仅ocr需提供,默认为1
     }
}

预处理的顺序如下(没有的流程自动略过):

  1. 灰度图 -> rgb图变换
  2. resize 尺寸变换
  3. center_crop
  4. rgb/bgr变换
  5. padding_fill_size
  6. letterbox(画个厚边框,填上黑色)
  7. chw/hwc变换
  8. 归一化:mean, scale
  9. padding_align32

rescale_mode说明:

  • keep_size: 将图片缩放到resize指定的大小
  • keep_ratio: 将图片按比例缩放,长边不超过max_size,短边不超过target_size
  • keep_raw_size: 保持原图尺寸,但必须在raw_size_range之间
  • warp_affine: 仿射变换,可以设置warp_affine_keep_res指定是否keep_res,在keep_res为false场景下,宽高通过resize字段指定

错误说明

SDK 的方法会返回 NSError,直接返回的 NSError 的错误码定义在 EasyDLDefine.h - EEasyDLErrorCode 中。NSError 附带 message (有时候会附带 NSUnderlyingError),开发者可根据 code 和 message 进行错误判断和处理。

FAQ

1. 如何多线程并发预测?

SDK内部已经能充分利用多核的计算能力。不建议使用并发来预测。

如果开发者想并发使用,请务必注意EasyDLModel所有的方法都不是线程安全的。请初始化多个实例进行并发使用,如

- (void)testMultiThread {
    UIImage *img = [UIImage imageNamed:@"1.jpeg"];
    NSError *err;
    EasyDLModel * model1 = [[EasyDLModel alloc] initModelFromResourceDirectory:@"easyedge" withError:&err];
    EasyDLModel * model2 = [[EasyDLModel alloc] initModelFromResourceDirectory:@"easyedge" withError:&err];

    dispatch_queue_t queue1 = dispatch_queue_create("testQueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_queue_t queue2 = dispatch_queue_create("testQueue2", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(queue1, ^{
        NSError *detectErr;
        for(int i = 0; i < 1000; ++i) {
            NSArray * res = [model1 detectUIImage:img withFilterScore:0 andError:&detectErr];
            NSLog(@"1: %@", res[0]);
        }
    });

    dispatch_async(queue2, ^{
        NSError *detectErr;
        for(int i = 0; i < 1000; ++i) {
            NSArray * res = [model2 detectUIImage:img withFilterScore:0 andError:&detectErr];
            NSLog(@"2: %@", res[0]);
        }
    });
}

2. 编译时出现 Undefined symbols for architecture arm64: ...

  • 出现 cxx11, vtable 字样:请引入 libc++.tbd
  • 出现 cv::Mat 字样:请引入 opencv2.framework
  • 出现 CoreML, VNRequest 字样:请引入CoreML.framework 并务必#import <CoreML/CoreML.h>

3. 运行时报错 Image not found: xxx ...

请Embed具体报错的库。

4.编译时报错:Invalid bitcode version

这个可能是开发者使用的 Xcode 低于12导致,可以升级至12版本。

上一篇
Android-SDK
下一篇
Linux-CPP-SDK