所有文档

          EasyDL定制AI训练平台

          经典版图像分类AndroidSDK集成文档

          简介

          1.1 Android SDK 硬件要求

          通常您下载的SDK只支持固定的某一类芯片。

          • 通用ARM: 支持大部分ARM 架构的手机、平板及开发板。通常选择这个引擎进行推理
          • 高端芯片AI加速模块:

            • 高通骁龙引擎SNPE: 高通骁龙高端SOC,利用自带的DSP加速。其中 660 之后的型号可能含有 Hexagon DSP模块,具体列表见snpe 高通骁龙引擎官网。
            • 华为NPU引擎DDK:华为麒麟970、980的arm-v8a的soc。 具体手机机型为mate10,mate10pro,P20,mate20,荣耀v20等。
            • 华为达芬奇NPU引擎DAVINCI: 华为NPU的后续版本,华为麒麟810,820,990的arm-v8a的soc。具体手机机型为华为mate30,p40,nova6,荣耀v30等。

          通用ARM有额外的加速版,但是有一定的进度损失。 高端芯片AI加速模块, 一般情况下推理速度较快。 运行内存不能过小,一般大于demo的assets目录大小的3倍。

          1.2 功能支持

          引擎 图像分类classify 物体检测detect 图像分割Segmentation 文字识别OCR
          只支持easyedge
          通用ARM
          高通骁龙引擎SNPE
          华为NPU引擎DDK
          华为达芬奇NPU引擎DAVINCI

          1.3 Release Notes

          时间 版本 说明
          2020.10.29 0.9.10 迭代优化
          2020.9.01 0.9.9 迭代优化
          2020.8.11 0.9.8 更新ddk 达芬奇引擎
          2020.7.14 0.9.7 支持arm版ocr模型,模型加载优化
          2020.6.23 0.9.6 支持arm版fasterrcnn模型
          2020.5.14 0.9.5 新增华为新的达芬奇架构npu的部分图像分类模型
          2020.4.17 0.9.4 新增arm通用引擎量化模型支持
          2020.1.17 0.9.3 新增arm通用引擎图像分割模型支持
          2019.12.26 0.9.2 新增华为kirin麒麟芯片的物体检测支持
          2019.12.04 0.9.1 使用paddleLite作为arm预测引擎
          2019.08.30 0.9.0 支持EasyDL专业版
          2019.08.30 0.8.2 支持华为麒麟980的物体检测模型
          2019.08.29 0.8.1 修复相机在开发版调用奔溃的问题
          2019.06.20 0.8.0 高通手机引擎优化
          2019.05.24 0.7.0 升级引擎
          2019.05.14 0.6.0 优化demo程序
          2019.04.12 0.5.0 新增华为麒麟980支持
          2019.03.29 0.4.0 引擎优化,支持sd卡模型读取
          2019.02.28 0.3.0 引擎优化,性能与效果提升;
          2018.11.30 0.2.0 第一版!

          快速开始

          2.1 安装软件及硬件准备

          扫描模型下载SDK处的网页上的二维码,无需任何依赖,直接体验

          如果需要源码方式测试:

          打开AndroidStudio, 点击 "Import Project..."。在一台较新的手机上测试。

          详细步骤如下:

          1. 准备一台较新的手机,如果不是通用arm版本,请参见本文的“硬件要求”,确认是否符合SDK的要求
          2. 安装较新版本的AndroidStudio ,下载地址
          3. 新建一个HelloWorld项目, Android Studio会自动下载依赖, 在这台较新的手机上测试通过这个helloworld项目。注意不支持模拟器。
          4. 解压下载的SDK。
          5. 打开AndroidStudio, 点击 "Import Project..."。 即:File->New-> "Import Project...", 选择解压后的目录。
          6. 此时点击运行按钮(同第3步),手机上会有新app安装完毕,运行效果和二维码扫描的一样。
          7. 手机上UI界面显示后,如果点击UI界面上的“开始使用”按钮,可能会报序列号错误。请参见下文修改

          2.2 使用序列号激活

          如果使用的是easyedge的开源模型,无需序列号,可以跳过本段直接测试。

          建议申请包名为"com.baidu.ai.easyaimobile.demo"的序列号用于测试。

          本文假设已经获取到序列号,并且这个序列号已经绑定包名。

          2.2.1 填写序列号

          打开Android Studio的项目,修改MainActivity类的开头SERIAL_NUM字段。 MainActivity 位于app\src\main\java\com\baidu\ai\edge\demo\MainActivity.java文件内。

           // 请替换为您的序列号
              private static final String SERIAL_NUM = "XXXX-XXXX-XXXX-XXXX"; //这里填您的序列号

          2.2.2 修改包名

          如果申请的包名为"com.baidu.ai.easyaimobile.demo",这个是demo的包名,可以不用修改

          打开app/build.gradle文件,修改"com.baidu.ai.easyaimobile.demo"为申请的包名

              defaultConfig {
                  applicationId "com.baidu.ai.easyaimobile.demo" //  修改为比如“com.xxx.xxx"

          修改序列号和包名后,可以运行测试,效果同扫描二维码的一致

          2.2.3 测试精简版

          对于通用ARM的常见功能,项目内自带精简版,可以忽略开发板不兼容的摄像头。 此外,由于实时摄像开启,会导致接口的耗时变大,此时也可以使用精简版测试。

          目前ARM的图像分类Classify,物体检测Detection,文字识别(OCR)有精简版测试。 具体代码在infertest目录下。 修改方法为:更改app/main/AndroidManifest.xml中的启动Activity。

           <activity android:name=".infertest.MainActivity">  <!--原始的是".MainActivity" -->
                      <intent-filter>
                          <action android:name="android.intent.action.MAIN" />
          
                          <category android:name="android.intent.category.LAUNCHER" />
                      </intent-filter>
                  </activity>

          开启后会自动选择图像分类Classify,物体检测Detection,文字识别(OCR)测试。

          使用说明

          3.1 代码目录结构

          集成时需要“复制到自己的项目里”的目录或者文件:

          1. app/libs
          2. app/src/main/assets/xxxx-xxxxx 如app/src/main/assets/infer-detect
          +app  简单的设置,模拟用户的项目
          |---+libs 实际使用时需要复制到自己的项目里
              |----arm64-v8a v8a的so
              |----armeabi-v7a v7a的so
              |----easyedge-sdk.jar jar库文件
          |---+src/main
              |---+assets 
              	|----demo demo项目的配置,实际集成不需要
              	|----infer-detect 也可能是其它命名, infer表示通用arm, detect表示物体						  检测。 实际使用时可以复制到自己的项目里
          	|---+java/com.baidu.ai.edge/demo
                  |---+infertest 通用Arm精简版测试,里面有SDK的集成逻辑
                      |--- MainActivity  通用Arm精简版启动Activity,会根据assets目录判				                  断当前的模型类型,并运行同目录的一个Task
                      |--- TestInferClassifyTask 通用Arm精简版分类,使用时需要修改里面的                                         序列号
                      |--- TestInferDetectionTask 通用Arm精简版分类,使用时需要修改里面                                         的序列号
                      |--- TestInferClassifyTask 通用Arm精简版OCR
                  |----snpetest SNPE精简版测试
                  |----CameraActivity 摄像头扫描示例,里面有SDK的集成逻辑
                  |----MainActivity 启动Activity , 使用时需要修改里面的序列号
          |---- build.gradle 这里修改包名
          +camera_ui  UI模块,集成时可以忽略 

          3.2 调用流程

          以通用ARM的检测模型功能为例, 代码可以参考TestInferDetectionTask

          1. 准备配置类,如InferConfig, 输入:通常为一个assets目录下的json文件。
          2. 初始化Manager,比如InferManager。输入:第1步的配置类和序列号
          3. 推理图片,可以多次调用 3.1 准备图片, 作为Bitmap输入, 3.2 调用对应的推理方法,比如detect 3.3 解析结果,结果通常是一个List,调用结果类的Get方法,通常能获取想要的结果
          4. 直到长时间不再使用我们的SDK,调用Manger的release方法释放资源。

          3.3 具体接口说明

          下文的示例部分以通用ARM的检测模型功能为例 即接口为InferConfig, InferManager,InferConfig.detect。 其它引擎和模型调用方法类似。

          下文假设已有序列号及对应的包名

          3.3.1 . 准备配置类

          • INFER:通用ARM,InferConfig
          • SNPE:高通骁龙高端SOC,SnpeConfig
          • DDK:华为NPU,DDKConfig
          • DDKDAVINCI:华为达芬奇NPU,DDKConfig
          InferConfig mInferConfig = new InferConfig(getAssets(),
                                          "infer-detect/config.json");
          //assets 目录下的infer-detect , infer表示通用arm, detect表示物体检测
          // 您也可以自己读取config.json,使用InputStream作为参数初始化InferConfig
          输入: assets下的配置
          输出:具体的配置类

          3.3.2. 初始化Manager类

          • INFER:通用ARM,InferManager
          • SNPE:高通骁龙高端SOC,SnpeManager
          • DDK:华为NPU,DDKManager
          • DDKDAVINCI:华为达芬奇NPU,DDKManager
          String SERIAL_NUM = "XXXX-XXXX-XXXX-XXXX";
          
          //InferManager 为例:
          new InferManager(this, config, SERIAL_NUM)); // config为上一步的InferConfig

          注意要点

          1. 同一个时刻只能有唯一有效的InferManager。旧的InferManager必须调用destory后,才能新建一个new InferManager() 。
          2. InferManager的任何方法,都不能在UI线程中调用。
          3. new InferManager() 及InferManager成员方法由于线程同步数据可见性问题,都必须在一个线程中执行。如使用android自带的ThreadHandler类
          输入: 1.配置类 ; 2.序列号
          输出: Manager类

          3.3.3. 推理图片

          • 接口可以多次调用,但是必须在一个线程里,不能并发
          • confidence, 置信度[0-1],小于confidence的结果不返回。 填confidence=0,返回所有结果
          • confidence可以不填,默认用模型推荐的。
          准备图片, 作为Bitmap输入,
          • 输入为Bitmap,其中Bitmap的options为默认。如果强制指定的话,必须使用Bitmap.Config.ARGB_8888
          调用对应的推理方法及结果解析

          见下文的各个模型方法

          3.3.4 分类Classify

          public interface ClassifyInterface {
              List<ClassificationResultModel> classify(Bitmap bitmap, float confidence) throws BaseException;
              
              // 如InferManger 继承 ClassifyInterface
          输入 Bitmap 默认格式或者指定Bitmap.Config.ARGB_8888
          输出 ClassificationResultModel
          异常: 一般首次出现。可以打印出异常错误码。
          
          ClassificationResultModel
          - label: 分类标签, 定义在config.json中
          - confidence :置信度,0-1
          - lableIndex:标签对应的序号

          3.3.5检测Detect

          对于EasyDL口罩检测模型请注意输入图片中人脸大小建议保持在88到9696像素,可根据场景远近程度缩放图片后传入

          public interface DetectInterface {
               List<DetectionResultModel> detect(Bitmap bitmap, float confidence) throws BaseException;
          
              // 如InferManger 继承 DetectInterface
          输入 Bitmap 默认格式或者指定Bitmap.Config.ARGB_8888
          输出 DetectionResultModel List
          异常: 一般首次出现。可以打印出异常错误码。
          
          DetectionResultModel
          - label: 标签, 定义在config.json中
          - confidence :置信度
          - bounds:Rect, 左上角和右下角坐标

          3.3.6 图像分割Segment

          暂时只支持通用ARM引擎,不支持其它引擎

          public interface SegmentInterface {
              List<SegmentationResultModel> segment(Bitmap bitmap, float confidence) throws BaseException;
                // 如InferManger 继承 SegmentInterface
          输入 Bitmap 默认格式或者指定Bitmap.Config.ARGB_8888
          输出 SegmentationResultModel
          异常: 一般首次出现。可以打印出异常错误码。
          
          SegmentationResultModel
          
          - label: 标签, 定义在config.json中
          - confidence :置信度
          - lableIndex:标签对应的序号
          - box: Rect对象表示的对象框
          - mask:byte[]表示的原图大小的0,1掩码,绘制1的像素即可得到当前对象区域
          
          mask 字段说明, 如何绘制掩码也可参考demo工程
          	    1 0 1
          image	1 1 0      =>   mask(byte[])  101 110 011
          	    0 1 1

          3.3.7 文字识别OCR

          暂时只支持通用ARM引擎,不支持其它引擎,暂时只支持EasyEdge的开源OCR模型。

          public interface OcrInterface {
              List<OcrResultModel> ocr(Bitmap bitmap, float confidence) throws BaseException;
              // 如InferManger 继承 OcrInterface
          输入 Bitmap 默认格式或者指定Bitmap.Config.ARGB_8888
          输出 OcrResultModel List, 每个OcrResultModel对应结果里的一个四边形。
          异常: 一般首次出现。可以打印出异常错误码。
          
          OcrResultModel
          
          - label: 识别出的文字
          - confidence :置信度
          - List<Point>:4个点构成四边形

          3.3.8 释放

          释放后这个对象不能再使用,如果需要使用可以重新new一个出来。

           public  void destory() throws BaseException

          3.3.9 整体示例

          以下以SnpeManager为例子, 分类 assets目录下一张图片的整体流程

           // 在新线程且同一线程中运行以下代码
          
              private void testImageFile() throws IOException, BaseException {
          
                 try {
                      // 1. 准备配置类
                      InferConfig config = new InferConfig(context.getAssets(), "infer-detect/config.json");
          
                      // 2. 初始化Manager类
                      InferManager manager = new InferManager(context, config, SERIAL_NUM);
          
                      // 3.1 准备图片, 作为Bitmap输入,
                      InputStream is2 = context.getAssets().open("test.jpg");
                      Bitmap image = BitmapFactory.decodeStream(is2);
                      is2.close();
                      // 在模型销毁前可以不断调用。但是不支持多线程。
                      // 3.2   调用对应的推理方法
                      List<DetectionResultModel> results = manager.detect(image, 0.3f);
                      // 3.3 解析结果
                      for (DetectionResultModel result : results) {
                          Log.i("TestInferDectionTask", result.getLabelIndex() + ":" + result.getConfidence() + ":" + result.getBounds());
                      }
                      //  4. 释放
                      manager.destroy();
                    
                  } catch (Exception e) {
                      Log.e("TestInferDetectionTask", "error", e);
                  }
          
              }

          3.3.3.10 高通骁龙引擎的额外配置

              "autocheck_qcom": true, // 如果改成false, sdk跳过检查手机是否是高通的Soc,非高通的Soc会奔溃直接导致app闪退
          
              "snpe_runtimes_order": [],
          // 不填写为自动,按照 {DSP, GPU, GPU_FLOAT16, CPU}次序尝试初始化,也可以手动指定如[2,1,3,0], 具体数字的定义见下段
          public interface SnpeRuntimeInterface {
              int CPU = 0;
              int GPU = 1;
              int DSP = 2;
              int GPU_FLOAT16 = 3;
          }
          
          // SnpeManager 中,使用public static ArrayList<Integer> getAvailableRuntimes(Context context) 方法可以获取高通SOC支持的运行方式

          集成指南

          1. 复制库文件libs
          2. 添加Manifest权限
          3. 复制模型文件
          4. 添加调用代码(见上一步具体接口说明)

          4.1 复制库文件libs

          A. 如果项目里没有自己的jar文件和so文件:

          复制app/libs 至自己项目的app/libs目录。
          参照demo的app/build.gradle 中添加
          
          android {
             ....
              defaultConfig {
                  ndk {
                      abiFilters  'armeabi-v7a', 'arm64-v8a'
                  }
              }
             sourceSets {
                  main {
                      jniLibs.srcDirs = ['libs']
                  }
              }
          }

          B. 如果项目里有自己的jar文件,但没有so文件

          easyedge.jar文件同自己的jar文件放一起
          arm64-v8a和armeabi-v7a放到app/src/main/jniLibs目录下
          
          参照demo的app/build.gradle 中添加
          
          android {
             ....
              defaultConfig {
                  ndk {
                      abiFilters  'armeabi-v7a', 'arm64-v8a'
                  }
              }

          C. 如果项目里有自己的jar文件和so文件

          easyedge.jar文件同自己的jar文件放一起
          arm64-v8a和armeabi-v7a取交集和自己的so放一起,交集的意思是比如自己的项目里有x86目录,必须删除x86。
          
          参照demo的app/build.gradle 中添加
          
          android {
             ....
              defaultConfig {
                  ndk {
                      abiFilters  'armeabi-v7a', 'arm64-v8a' // abiFilter取交集,即只能少不能多
                  }
              }

          jar文件库如果没有设置成功的,编译的时候可以发现报错。

          so库如果没有编译进去的话,也可以通过解压apk文件确认。运行的时候会有类似jni方法找不到的报错。

          4.2 添加Manifest权限

          参考app/src/main/AndroidManifest.xml文件,添加:

          <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
          -permission android:name="android.permission.INTERNET" />
          -permission android:name="android.permission.ACCESS_NETWORK_STATE" />

          混淆规则(可选)

          请不要混淆SDK里的jar文件。

          -keep class com.baidu.ai.edge.core.*.*{ *; }

          错误码

          报错信息收集

          正常情况下logcat下可以看见日志及崩溃信息。如果遇见某些开发版无法获取,可以使用demo中的xcrash,日志保存在如下位置

          String basePath = Environment.getExternalStorageDirectory().toString() + "/" + context.getPackageName();
          params.setLogDir(basePath + "/xCrash");
          // sd卡下 /sdcard/com.baidu.ai.edge.demo/xCrash
          错误码 错误描述 详细描述及解决方法
          1001 assets 目录下用户指定的配置文件不存在 SDK可以使用assets目录下config.json作为配置文件。如果传入的config.json不在assets目录下,则有此报错
          1002 用户传入的配置文件作为json解析格式不准确,如缺少某些字段 正常情况下,demo中的config.json不要修改
          19xx Sdk内部错误 请与百度人员联系
          2001 XxxxMANAGER 只允许一个实例 如已有XxxxMANAGER对象,请调用destory方法
          2002 XxxxMANAGER 已经调用过destory方法 在一个已经调用destory方法的DETECT_MANAGER对象上,不允许再调用任何方法
          2003 传入的assets下模型文件路径为null XxxxConfig.getModelFileAssetPath() 返回为null。由setModelFileAssetPath(null)导致
          2011 libedge-xxxx.so 加载失败 System.loadLibrary("edge-xxxx"); libedge-xxxx.so 没有在apk中。CPU架构仅支持armeabi-v7a arm-v8a
          2012 JNI内存错误 heap的内存不够
          2103 license过期 license失效或者系统时间有异常
          2601 assets 目录下模型文件打开失败 请根据报错信息检查模型文件是否存在
          2611 检测图片时,传递至引擎的图片二进制与长宽不符合 具体见报错信息
          27xx Sdk内部错误 请与百度人员联系
          28xx 引擎内部错误 请与百度人员联系
          29xx Sdk内部错误 请与百度人员联系
          3000 so加载错误 请确认所有so文件存在于apk中
          3001 模型加载错误 请确认模型放置于能被加载到的合法路径中,并确保config.json配置正确
          3002 模型卸载错误 请与百度人员联系
          3003 调用模型错误 在模型未加载正确或者so库未加载正确的情况下调用了分类接口
          50xx 在线模式调用异常 请与百度人员联系
          上一篇
          设备端SDK简介
          下一篇
          WindowsSDK集成文档