mirror of
https://github.com/PaddlePaddle/FastDeploy.git
synced 2025-10-11 03:20:20 +08:00
[Doc] Add PicoDet & PaddleClas Android demo docs (#412)
* [Backend] Add override flag to lite backend * [Docs] Add Android C++ SDK build docs * [Doc] fix android_build_docs typos * Update CMakeLists.txt * Update android.md * [Doc] Add PicoDet Android demo docs * [Doc] Update PicoDet Andorid demo docs * [Doc] Update PaddleClasModel Android demo docs * [Doc] Update fastdeploy android jni docs * [Doc] Update fastdeploy android jni usage docs Co-authored-by: Jason <jiangjiajun@baidu.com>
This commit is contained in:
@@ -102,3 +102,4 @@ make install
|
||||
如何使用FastDeploy Android C++ SDK 请参考使用案例文档:
|
||||
- [图像分类Android使用文档](../../../examples/vision/classification/paddleclas/android/README.md)
|
||||
- [目标检测Android使用文档](../../../examples/vision/detection/paddledetection/android/README.md)
|
||||
- [在 Android 通过 JNI 中使用 FastDeploy C++ SDK](../../../../../docs/cn/faq/use_cpp_sdk_on_android.md)
|
||||
|
231
docs/cn/faq/use_cpp_sdk_on_android.md
Normal file
231
docs/cn/faq/use_cpp_sdk_on_android.md
Normal file
@@ -0,0 +1,231 @@
|
||||
# 在 Android 中通过 JNI 使用 FastDeploy C++ SDK
|
||||
本文档将以PicoDet为例,讲解如何通过JNI,将FastDeploy中的模型封装到Android中进行调用。阅读本文档,您至少需要了解C++、Java、JNI以及Android的基础知识。如果您主要关注如何在Java层如何调用FastDeploy的API,则可以不阅读本文档。
|
||||
|
||||
## 目录
|
||||
- [新建Java类并定义native API](#Java)
|
||||
- [Android Studio 生成JNI函数定义](#JNI)
|
||||
- [在C++层实现JNI函数](#CPP)
|
||||
- [编写CMakeLists.txt及配置build.gradle](#CMakeAndGradle)
|
||||
- [更多FastDeploy Android 使用案例](#Examples)
|
||||
|
||||
## 新建Java类并定义native API
|
||||
<div id="Java"></div>
|
||||
|
||||
```java
|
||||
public class PicoDet {
|
||||
protected long mNativeModelContext = 0; // Context from native.
|
||||
protected boolean mInitialized = false;
|
||||
// ...
|
||||
// Bind predictor from native context.
|
||||
private static native long bindNative(String modelFile,
|
||||
String paramsFile,
|
||||
String configFile,
|
||||
int cpuNumThread,
|
||||
boolean enableLiteFp16,
|
||||
int litePowerMode,
|
||||
String liteOptimizedModelDir,
|
||||
boolean enableRecordTimeOfRuntime,
|
||||
String labelFile);
|
||||
|
||||
// Call prediction from native context.
|
||||
private static native long predictNative(long nativeModelContext,
|
||||
Bitmap ARGB8888Bitmap,
|
||||
boolean saved,
|
||||
String savedImagePath,
|
||||
float scoreThreshold,
|
||||
boolean rendering);
|
||||
|
||||
// Release buffers allocated in native context.
|
||||
private static native boolean releaseNative(long nativeModelContext);
|
||||
|
||||
// Initializes at the beginning.
|
||||
static {
|
||||
FastDeployInitializer.init();
|
||||
}
|
||||
}
|
||||
```
|
||||
这些被标记为native的接口是需要通过JNI的方式实现,并在Java层供PicoDet类调用。完整的PicoDet Java代码请参考 [PicoDet.java](../../../examples/vision/detection/paddledetection/android/app/src/main/java/com/baidu/paddle/fastdeploy/vision/detection/PicoDet.java) 。各个函数说明如下:
|
||||
- `bindNative`: C++层初始化模型资源,如果成功初始化,则返回指向该模型的指针(long类型),否则返回0指针
|
||||
- `predictNative`: 通过已经初始化好的模型指针,在C++层执行预测代码,如果预测成功则返回指向预测结果的指针,否则返回0指针。注意,该结果指针在当次预测使用完之后需要释放,具体操作请参考 [PicoDet.java](../../../examples/vision/detection/paddledetection/android/app/src/main/java/com/baidu/paddle/fastdeploy/vision/detection/PicoDet.java) 中的predict函数。
|
||||
- `releaseNative`: 根据传入的模型指针,在C++层释放模型资源。
|
||||
|
||||
## Android Studio 生成JNI函数定义
|
||||
<div id="JNI"></div>
|
||||
|
||||
Android Studio 生成 JNI 函数定义: 鼠标停留在Java中定义的native函数上,Android Studio 便会提示是否要创建JNI函数定义;这里,我们把JNI函数定义创建在一个事先创建好的c++文件`picodet_jni.cc`上;
|
||||
|
||||
- 使用Android Studio创建JNI函数定义:
|
||||

|
||||
|
||||
- 将JNI函数定义创建在picodet_jni.cc上:
|
||||

|
||||
|
||||
- 创建的JNI函数定义如下:
|
||||

|
||||
|
||||
其他native函数对应的JNI函数定义的创建和此流程一样。
|
||||
|
||||
## 在C++层实现JNI函数
|
||||
<div id="CPP"></div>
|
||||
|
||||
以下为PicoDet JNI层实现的示例,相关的辅助函数不在此处赘述,完整的C++代码请参考 [android/app/src/main/cpp](../../../examples/vision/detection/paddledetection/android/app/src/main/cpp/).
|
||||
```C++
|
||||
#include <jni.h> // NOLINT
|
||||
#include "fastdeploy_jni.h" // NOLINT
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// 绑定C++层的模型
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_com_baidu_paddle_fastdeploy_vision_detection_PicoDet_bindNative(
|
||||
JNIEnv *env, jclass clazz, jstring model_file, jstring params_file,
|
||||
jstring config_file, jint cpu_num_thread, jboolean enable_lite_fp16,
|
||||
jint lite_power_mode, jstring lite_optimized_model_dir,
|
||||
jboolean enable_record_time_of_runtime, jstring label_file) {
|
||||
std::string c_model_file = fastdeploy::jni::ConvertTo<std::string>(env, model_file);
|
||||
std::string c_params_file = fastdeploy::jni::ConvertTo<std::string>(env, params_file);
|
||||
std::string c_config_file = astdeploy::jni::ConvertTo<std::string>(env, config_file);
|
||||
std::string c_label_file = fastdeploy::jni::ConvertTo<std::string>(env, label_file);
|
||||
std::string c_lite_optimized_model_dir = fastdeploy::jni::ConvertTo<std::string>(env, lite_optimized_model_dir);
|
||||
auto c_cpu_num_thread = static_cast<int>(cpu_num_thread);
|
||||
auto c_enable_lite_fp16 = static_cast<bool>(enable_lite_fp16);
|
||||
auto c_lite_power_mode = static_cast<fastdeploy::LitePowerMode>(lite_power_mode);
|
||||
fastdeploy::RuntimeOption c_option;
|
||||
c_option.UseCpu();
|
||||
c_option.UseLiteBackend();
|
||||
c_option.SetCpuThreadNum(c_cpu_num_thread);
|
||||
c_option.SetLitePowerMode(c_lite_power_mode);
|
||||
c_option.SetLiteOptimizedModelDir(c_lite_optimized_model_dir);
|
||||
if (c_enable_lite_fp16) {
|
||||
c_option.EnableLiteFP16();
|
||||
}
|
||||
// 如果您实现的是其他模型,比如PPYOLOE,请注意修改此处绑定的C++类型
|
||||
auto c_model_ptr = new fastdeploy::vision::detection::PicoDet(
|
||||
c_model_file, c_params_file, c_config_file, c_option);
|
||||
// Enable record Runtime time costs.
|
||||
if (enable_record_time_of_runtime) {
|
||||
c_model_ptr->EnableRecordTimeOfRuntime();
|
||||
}
|
||||
// Load detection labels if label path is not empty.
|
||||
if ((!fastdeploy::jni::AssetsLoaderUtils::IsDetectionLabelsLoaded()) &&
|
||||
(!c_label_file.empty())) {
|
||||
fastdeploy::jni::AssetsLoaderUtils::LoadDetectionLabels(c_label_file);
|
||||
}
|
||||
// WARN: need to release manually in Java !
|
||||
return reinterpret_cast<jlong>(c_model_ptr); // native model context
|
||||
}
|
||||
|
||||
// 通过传入的模型指针在C++层进行预测
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_com_baidu_paddle_fastdeploy_vision_detection_PicoDet_predictNative(
|
||||
JNIEnv *env, jclass clazz, jlong native_model_context,
|
||||
jobject argb8888_bitmap, jboolean saved, jstring saved_image_path,
|
||||
jfloat score_threshold, jboolean rendering) {
|
||||
if (native_model_context == 0) {
|
||||
return 0;
|
||||
}
|
||||
cv::Mat c_bgr;
|
||||
if (!fastdeploy::jni::ARGB888Bitmap2BGR(env, argb8888_bitmap, &c_bgr)) {
|
||||
return 0;
|
||||
}
|
||||
auto c_model_ptr = reinterpret_cast<fastdeploy::vision::detection::PicoDet *>(
|
||||
native_model_context);
|
||||
auto c_result_ptr = new fastdeploy::vision::DetectionResult();
|
||||
t = fastdeploy::jni::GetCurrentTime();
|
||||
if (!c_model_ptr->Predict(&c_bgr, c_result_ptr)) {
|
||||
delete c_result_ptr;
|
||||
return 0;
|
||||
}
|
||||
// ...
|
||||
return reinterpret_cast<jlong>(c_result_ptr); // native result context
|
||||
}
|
||||
|
||||
// 在C++层释放模型资源
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_baidu_paddle_fastdeploy_vision_detection_PicoDet_releaseNative(
|
||||
JNIEnv *env, jclass clazz, jlong native_model_context) {
|
||||
if (native_model_context == 0) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
auto c_model_ptr = reinterpret_cast<fastdeploy::vision::detection::PicoDet *>(
|
||||
native_model_context);
|
||||
// ...
|
||||
delete c_model_ptr;
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
```
|
||||
## 编写CMakeLists.txt及配置build.gradle
|
||||
<div id="CMakeAndGradle"></div>
|
||||
|
||||
实现好的JNI代码,需要被编译成so库,才能被Java调用,为实现该目的,需要在build.gradle中添加JNI项目支持,并编写对应的CMakeLists.txt。
|
||||
- build.gradle中配置NDK、CMake以及Android ABI
|
||||
```java
|
||||
android {
|
||||
defaultConfig {
|
||||
// 省略其他配置 ...
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments '-DANDROID_PLATFORM=android-21', '-DANDROID_STL=c++_shared', "-DANDROID_TOOLCHAIN=clang"
|
||||
abiFilters 'armeabi-v7a', 'arm64-v8a'
|
||||
cppFlags "-std=c++11"
|
||||
}
|
||||
}
|
||||
}
|
||||
// 省略其他配置 ...
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path file('src/main/cpp/CMakeLists.txt')
|
||||
version '3.10.2'
|
||||
}
|
||||
}
|
||||
ndkVersion '20.1.5948944'
|
||||
}
|
||||
```
|
||||
- 编写CMakeLists.txt示例
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.10.2)
|
||||
project("fastdeploy_jni")
|
||||
|
||||
set(FastDeploy_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/fastdeploy-android-0.4.0-shared")
|
||||
|
||||
find_package(FastDeploy REQUIRED)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${FastDeploy_INCLUDE_DIRS})
|
||||
|
||||
add_library(
|
||||
fastdeploy_jni
|
||||
SHARED
|
||||
utils_jni.cc
|
||||
bitmap_jni.cc
|
||||
vision/results_jni.cc
|
||||
vision/visualize_jni.cc
|
||||
vision/detection/picodet_jni.cc
|
||||
vision/classification/paddleclas_model_jni.cc)
|
||||
|
||||
find_library(log-lib log)
|
||||
|
||||
target_link_libraries(
|
||||
# Specifies the target library.
|
||||
fastdeploy_jni
|
||||
jnigraphics
|
||||
${FASTDEPLOY_LIBS}
|
||||
GLESv2
|
||||
EGL
|
||||
${log-lib}
|
||||
)
|
||||
```
|
||||
完整的工程示例,请参考 [android/app/src/main/cpp/CMakelists.txt](../../../examples/vision/detection/paddledetection/android/app/src/main/cpp/) 以及 [android/app/build.gradle](../../../examples/vision/detection/paddledetection/android/app/build.gradle).
|
||||
|
||||
## 更多FastDeploy Android 使用案例
|
||||
<div id="Examples"></div>
|
||||
|
||||
更多FastDeploy Android 使用案例请参考以下文档:
|
||||
- [图像分类Android使用文档](../../../examples/vision/classification/paddleclas/android/README.md)
|
||||
- [目标检测Android使用文档](../../../examples/vision/detection/paddledetection/android/README.md)
|
2
docs/cn/faq/use_java_sdk_on_android.md
Normal file
2
docs/cn/faq/use_java_sdk_on_android.md
Normal file
@@ -0,0 +1,2 @@
|
||||
## 在 Android 中使用 FastDeploy Java SDK
|
||||
- TODO
|
@@ -1,3 +1,155 @@
|
||||
## 图像分类 Android Demo 使用文档
|
||||
## 图像分类 PaddleClas Android Demo 使用文档
|
||||
|
||||
- TODO
|
||||
在 Android 上实现实时的图像分类功能,此 Demo 有很好的的易用性和开放性,如在 Demo 中跑自己训练好的模型等。
|
||||
|
||||
## 环境准备
|
||||
|
||||
1. 在本地环境安装好 Android Studio 工具,详细安装方法请见[Android Stuido 官网](https://developer.android.com/studio)。
|
||||
2. 准备一部 Android 手机,并开启 USB 调试模式。开启方法: `手机设置 -> 查找开发者选项 -> 打开开发者选项和 USB 调试模式`
|
||||
|
||||
**注意**:如果您的 Android Studio 尚未配置 NDK ,请根据 Android Studio 用户指南中的[安装及配置 NDK 和 CMake ](https://developer.android.com/studio/projects/install-ndk)内容,预先配置好 NDK 。您可以选择最新的 NDK 版本,或者使用 FastDeploy Android 预测库版本一样的 NDK
|
||||
|
||||
## 部署步骤
|
||||
|
||||
1. 目标检测 PaddleClas Demo 位于 `fastdeploy/examples/vision/classification/paddleclas/android` 目录
|
||||
2. 用 Android Studio 打开 paddleclas/android 工程
|
||||
3. 手机连接电脑,打开 USB 调试和文件传输模式,并在 Android Studio 上连接自己的手机设备(手机需要开启允许从 USB 安装软件权限)
|
||||
|
||||
<p align="center">
|
||||
<img width="1280" alt="image" src="https://user-images.githubusercontent.com/31974251/197338597-2c9e1cf0-569b-49b9-a7fb-cdec71921af8.png">
|
||||
</p>
|
||||
|
||||
> **注意:**
|
||||
>> 如果您在导入项目、编译或者运行过程中遇到 NDK 配置错误的提示,请打开 ` File > Project Structure > SDK Location`,修改 `Andriod NDK location` 为您本机配置的 NDK 所在路径。本工程默认使用的NDK版本为20.
|
||||
>> 如果您是通过 Andriod Studio 的 SDK Tools 下载的 NDK (见本章节"环境准备"),可以直接点击下拉框选择默认路径。
|
||||
>> 还有一种 NDK 配置方法,你可以在 `paddleclas/android/local.properties` 文件中手动完成 NDK 路径配置,如下图所示
|
||||
>> 如果以上步骤仍旧无法解决 NDK 配置错误,请尝试根据 Andriod Studio 官方文档中的[更新 Android Gradle 插件](https://developer.android.com/studio/releases/gradle-plugin?hl=zh-cn#updating-plugin)章节,尝试更新Android Gradle plugin版本。
|
||||
|
||||
4. 点击 Run 按钮,自动编译 APP 并安装到手机。(该过程会自动下载预编译的 FastDeploy Android 库,需要联网)
|
||||
成功后效果如下,图一:APP 安装到手机;图二: APP 打开后的效果,会自动识别图片中的物体并标记;图三:APP设置选项,点击右上角的设置图片,可以设置不同选项进行体验。
|
||||
|
||||
| APP 图标 | APP 效果 | APP设置项
|
||||
| --- | --- | --- |
|
||||
|  |  |  |
|
||||
|
||||
## PaddleClasModel Java API 说明
|
||||
- 模型初始化 API: 模型初始化API包含两种方式,方式一是通过构造函数直接初始化;方式二是,通过调用init函数,在合适的程序节点进行初始化。PaddleClasModel初始化参数说明如下:
|
||||
- modelFile: String, paddle格式的模型文件路径,如 model.pdmodel
|
||||
- paramFile: String, paddle格式的参数文件路径,如 model.pdiparams
|
||||
- configFile: String, 模型推理的预处理配置文件,如 infer_cfg.yml
|
||||
- labelFile: String, 可选参数,表示label标签文件所在路径,用于可视化,如 imagenet1k_label_list.txt,每一行包含一个label
|
||||
- option: RuntimeOption,可选参数,模型初始化option。如果不传入该参数则会使用默认的运行时选项。
|
||||
|
||||
```java
|
||||
// 构造函数: constructor w/o label file
|
||||
public PaddleClasModel(); // 空构造函数,之后可以调用init初始化
|
||||
public PaddleClasModel(String modelFile, String paramsFile, String configFile);
|
||||
public PaddleClasModel(String modelFile, String paramsFile, String configFile, String labelFile);
|
||||
public PaddleClasModel(String modelFile, String paramsFile, String configFile, RuntimeOption option);
|
||||
public PaddleClasModel(String modelFile, String paramsFile, String configFile, String labelFile, RuntimeOption option);
|
||||
// 手动调用init初始化: call init manually w/o label file
|
||||
public boolean init(String modelFile, String paramsFile, String configFile, RuntimeOption option);
|
||||
public boolean init(String modelFile, String paramsFile, String configFile, String labelFile, RuntimeOption option);
|
||||
```
|
||||
- 模型预测 API:模型预测API包含直接预测的API以及带可视化功能的API。直接预测是指,不保存图片以及不渲染结果到Bitmap上,仅预测推理结果。预测并且可视化是指,预测结果以及可视化,并将可视化后的图片保存到指定的途径,以及将可视化结果渲染在Bitmap(目前支持ARGB8888格式的Bitmap), 后续可将该Bitmap在camera中进行显示。
|
||||
```java
|
||||
// 直接预测:不保存图片以及不渲染结果到Bitmap上
|
||||
public ClassifyResult predict(Bitmap ARGB8888Bitmap);
|
||||
// 预测并且可视化:预测结果以及可视化,并将可视化后的图片保存到指定的途径,以及将可视化结果渲染在Bitmap上
|
||||
public ClassifyResult predict(Bitmap ARGB8888Bitmap, String savedImagePath, float scoreThreshold)
|
||||
```
|
||||
- 模型资源释放 API:调用 release() API 可以释放模型资源,返回true表示释放成功,false表示失败;调用 initialized() 可以判断模型是否初始化成功,true表示初始化成功,false表示失败。
|
||||
```java
|
||||
public boolean release(); // 释放native资源
|
||||
public boolean initialized(); // 检查是否初始化成功
|
||||
```
|
||||
- RuntimeOption设置说明
|
||||
```java
|
||||
public void enableLiteFp16(); // 开启fp16精度推理
|
||||
public void disableLiteFP16(); // 关闭fp16精度推理
|
||||
public void setCpuThreadNum(int threadNum); // 设置线程数
|
||||
public void setLitePowerMode(LitePowerMode mode); // 设置能耗模式
|
||||
public void setLitePowerMode(String modeStr); // 通过字符串形式设置能耗模式
|
||||
public void enableRecordTimeOfRuntime(); // 是否打印模型运行耗时
|
||||
```
|
||||
|
||||
- 模型结果ClassifyResult说明
|
||||
```java
|
||||
public float[] mScores; // [n] 得分
|
||||
public int[] mLabelIds; // [n] 分类ID
|
||||
public boolean initialized(); // 检测结果是否有效
|
||||
```
|
||||
|
||||
- 模型调用示例1:使用构造函数以及默认的RuntimeOption
|
||||
```java
|
||||
import java.nio.ByteBuffer;
|
||||
import android.graphics.Bitmap;
|
||||
import android.opengl.GLES20;
|
||||
|
||||
import com.baidu.paddle.fastdeploy.vision.ClassifyResult;
|
||||
import com.baidu.paddle.fastdeploy.vision.classification.PaddleClasModel;
|
||||
|
||||
// 初始化模型
|
||||
PaddleClasModel model = new PaddleClasModel("MobileNetV1_x0_25_infer/inference.pdmodel",
|
||||
"MobileNetV1_x0_25_infer/inference.pdiparams",
|
||||
"MobileNetV1_x0_25_infer/inference_cls.yml");
|
||||
|
||||
// 读取图片: 以下仅为读取Bitmap的伪代码
|
||||
ByteBuffer pixelBuffer = ByteBuffer.allocate(width * height * 4);
|
||||
GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pixelBuffer);
|
||||
Bitmap ARGB8888ImageBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
ARGB8888ImageBitmap.copyPixelsFromBuffer(pixelBuffer);
|
||||
|
||||
// 模型推理
|
||||
ClassifyResult result = model.predict(ARGB8888ImageBitmap);
|
||||
|
||||
// 释放模型资源
|
||||
model.release();
|
||||
```
|
||||
|
||||
- 模型调用示例2: 在合适的程序节点,手动调用init,并自定义RuntimeOption
|
||||
```java
|
||||
// import 同上 ...
|
||||
import com.baidu.paddle.fastdeploy.RuntimeOption;
|
||||
import com.baidu.paddle.fastdeploy.LitePowerMode;
|
||||
import com.baidu.paddle.fastdeploy.vision.ClassifyResult;
|
||||
import com.baidu.paddle.fastdeploy.vision.classification.PaddleClasModel;
|
||||
// 新建空模型
|
||||
PaddleClasModel model = new PaddleClasModel();
|
||||
// 模型路径
|
||||
String modelFile = "MobileNetV1_x0_25_infer/inference.pdmodel";
|
||||
String paramFile = "MobileNetV1_x0_25_infer/inference.pdiparams";
|
||||
String configFile = "MobileNetV1_x0_25_infer/inference_cls.yml";
|
||||
// 指定RuntimeOption
|
||||
RuntimeOption option = new RuntimeOption();
|
||||
option.setCpuThreadNum(2);
|
||||
option.setLitePowerMode(LitePowerMode.LITE_POWER_HIGH);
|
||||
option.enableRecordTimeOfRuntime();
|
||||
option.enableLiteFp16();
|
||||
// 使用init函数初始化
|
||||
model.init(modelFile, paramFile, configFile, option);
|
||||
// Bitmap读取、模型预测、资源释放 同上 ...
|
||||
```
|
||||
更详细的用法请参考 [MainActivity](./app/src/main/java/com/baidu/paddle/fastdeploy/examples/MainActivity.java#L207) 中的用法
|
||||
|
||||
## 替换 FastDeploy 预测库和模型
|
||||
替换FastDeploy预测库和模型的步骤非常简单。预测库所在的位置为 `app/libs/fastdeploy-android-xxx-shared`,其中 `xxx` 表示当前您使用的预测库版本号。模型所在的位置为,`app/src/main/assets/models/MobileNetV1_x0_25_infer`。
|
||||
- 替换FastDeploy预测库的步骤:
|
||||
- 下载或编译最新的FastDeploy Android预测库,解压缩后放在 `app/libs` 目录下;
|
||||
- 修改 `app/src/main/cpp/CMakeLists.txt` 中的预测库路径,指向您下载或编译的预测库路径。如:
|
||||
```cmake
|
||||
set(FastDeploy_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/fastdeploy-android-xxx-shared")
|
||||
```
|
||||
- 替换PaddleClas模型的步骤:
|
||||
- 将您的PaddleClas分类模型放在 `app/src/main/assets/models` 目录下;
|
||||
- 修改 `app/src/main/res/values/strings.xml` 中模型路径的默认值,如:
|
||||
```xml
|
||||
<!-- 将这个路径指修改成您的模型,如 models/MobileNetV2_x0_25_infer -->
|
||||
<string name="MODEL_DIR_DEFAULT">models/MobileNetV1_x0_25_infer</string>
|
||||
<string name="LABEL_PATH_DEFAULT">labels/imagenet1k_label_list.txt</string>
|
||||
```
|
||||
|
||||
## 如何通过 JNI 在 Native 层接入 FastDeploy C++ API ?
|
||||
如果您对如何通过JNI来接入FastDeploy C++ API感兴趣,可以参考以下内容:
|
||||
- [app/src/main/cpp 代码实现](./app/src/main/cpp/)
|
||||
- [在 Android 中通过 JNI 使用 FastDeploy C++ SDK](../../../../../docs/cn/faq/use_cpp_sdk_on_android.md)
|
||||
|
@@ -14,6 +14,20 @@ public class PaddleClasModel {
|
||||
mInitialized = false;
|
||||
}
|
||||
|
||||
// Constructor with default runtime option
|
||||
public PaddleClasModel(String modelFile,
|
||||
String paramsFile,
|
||||
String configFile) {
|
||||
init_(modelFile, paramsFile, configFile, "", new RuntimeOption());
|
||||
}
|
||||
|
||||
public PaddleClasModel(String modelFile,
|
||||
String paramsFile,
|
||||
String configFile,
|
||||
String labelFile) {
|
||||
init_(modelFile, paramsFile, configFile, labelFile, new RuntimeOption());
|
||||
}
|
||||
|
||||
// Constructor without label file
|
||||
public PaddleClasModel(String modelFile,
|
||||
String paramsFile,
|
||||
|
@@ -14,6 +14,20 @@ public class PicoDet {
|
||||
mInitialized = false;
|
||||
}
|
||||
|
||||
// Constructor with default runtime option
|
||||
public PicoDet(String modelFile,
|
||||
String paramsFile,
|
||||
String configFile) {
|
||||
init_(modelFile, paramsFile, configFile, "", new RuntimeOption());
|
||||
}
|
||||
|
||||
public PicoDet(String modelFile,
|
||||
String paramsFile,
|
||||
String configFile,
|
||||
String labelFile) {
|
||||
init_(modelFile, paramsFile, configFile, labelFile, new RuntimeOption());
|
||||
}
|
||||
|
||||
// Constructor without label file
|
||||
public PicoDet(String modelFile,
|
||||
String paramsFile,
|
||||
|
@@ -1,3 +1,156 @@
|
||||
## 目标检测 Android Demo 使用文档
|
||||
# 目标检测 PicoDet Android Demo 使用文档
|
||||
|
||||
- TODO
|
||||
在 Android 上实现实时的目标检测功能,此 Demo 有很好的的易用性和开放性,如在 Demo 中跑自己训练好的模型等。
|
||||
|
||||
## 环境准备
|
||||
|
||||
1. 在本地环境安装好 Android Studio 工具,详细安装方法请见[Android Stuido 官网](https://developer.android.com/studio)。
|
||||
2. 准备一部 Android 手机,并开启 USB 调试模式。开启方法: `手机设置 -> 查找开发者选项 -> 打开开发者选项和 USB 调试模式`
|
||||
|
||||
**注意**:如果您的 Android Studio 尚未配置 NDK ,请根据 Android Studio 用户指南中的[安装及配置 NDK 和 CMake ](https://developer.android.com/studio/projects/install-ndk)内容,预先配置好 NDK 。您可以选择最新的 NDK 版本,或者使用 FastDeploy Android 预测库版本一样的 NDK
|
||||
|
||||
## 部署步骤
|
||||
|
||||
1. 目标检测 PicoDet Demo 位于 `fastdeploy/examples/vision/detection/paddledetection/android` 目录
|
||||
2. 用 Android Studio 打开 paddledetection/android 工程
|
||||
3. 手机连接电脑,打开 USB 调试和文件传输模式,并在 Android Studio 上连接自己的手机设备(手机需要开启允许从 USB 安装软件权限)
|
||||
|
||||
<p align="center">
|
||||
<img width="1280" alt="image" src="https://user-images.githubusercontent.com/31974251/197168120-7f77fbb7-3850-44f0-b6fa-865a98951226.png">
|
||||
</p>
|
||||
|
||||
> **注意:**
|
||||
>> 如果您在导入项目、编译或者运行过程中遇到 NDK 配置错误的提示,请打开 ` File > Project Structure > SDK Location`,修改 `Andriod NDK location` 为您本机配置的 NDK 所在路径。本工程默认使用的NDK版本为20.
|
||||
>> 如果您是通过 Andriod Studio 的 SDK Tools 下载的 NDK (见本章节"环境准备"),可以直接点击下拉框选择默认路径。
|
||||
>> 还有一种 NDK 配置方法,你可以在 `paddledetection/android/local.properties` 文件中手动完成 NDK 路径配置,如下图所示
|
||||
>> 如果以上步骤仍旧无法解决 NDK 配置错误,请尝试根据 Andriod Studio 官方文档中的[更新 Android Gradle 插件](https://developer.android.com/studio/releases/gradle-plugin?hl=zh-cn#updating-plugin)章节,尝试更新Android Gradle plugin版本。
|
||||
|
||||
4. 点击 Run 按钮,自动编译 APP 并安装到手机。(该过程会自动下载预编译的 FastDeploy Android 库,需要联网)
|
||||
成功后效果如下,图一:APP 安装到手机;图二: APP 打开后的效果,会自动识别图片中的物体并标记;图三:APP设置选项,点击右上角的设置图片,可以设置不同选项进行体验。
|
||||
|
||||
| APP 图标 | APP 效果 | APP设置项
|
||||
| --- | --- | --- |
|
||||
|  |  |  |
|
||||
|
||||
## PicoDet Java API 说明
|
||||
- 模型初始化 API: 模型初始化API包含两种方式,方式一是通过构造函数直接初始化;方式二是,通过调用init函数,在合适的程序节点进行初始化。PicoDet初始化参数说明如下:
|
||||
- modelFile: String, paddle格式的模型文件路径,如 model.pdmodel
|
||||
- paramFile: String, paddle格式的参数文件路径,如 model.pdiparams
|
||||
- configFile: String, 模型推理的预处理配置文件,如 infer_cfg.yml
|
||||
- labelFile: String, 可选参数,表示label标签文件所在路径,用于可视化,如 coco_label_list.txt,每一行包含一个label
|
||||
- option: RuntimeOption,可选参数,模型初始化option。如果不传入该参数则会使用默认的运行时选项。
|
||||
|
||||
```java
|
||||
// 构造函数: constructor w/o label file
|
||||
public PicoDet(); // 空构造函数,之后可以调用init初始化
|
||||
public PicoDet(String modelFile, String paramsFile, String configFile);
|
||||
public PicoDet(String modelFile, String paramsFile, String configFile, String labelFile);
|
||||
public PicoDet(String modelFile, String paramsFile, String configFile, RuntimeOption option);
|
||||
public PicoDet(String modelFile, String paramsFile, String configFile, String labelFile, RuntimeOption option);
|
||||
// 手动调用init初始化: call init manually w/o label file
|
||||
public boolean init(String modelFile, String paramsFile, String configFile, RuntimeOption option);
|
||||
public boolean init(String modelFile, String paramsFile, String configFile, String labelFile, RuntimeOption option);
|
||||
```
|
||||
- 模型预测 API:模型预测API包含直接预测的API以及带可视化功能的API。直接预测是指,不保存图片以及不渲染结果到Bitmap上,仅预测推理结果。预测并且可视化是指,预测结果以及可视化,并将可视化后的图片保存到指定的途径,以及将可视化结果渲染在Bitmap(目前支持ARGB8888格式的Bitmap), 后续可将该Bitmap在camera中进行显示。
|
||||
```java
|
||||
// 直接预测:不保存图片以及不渲染结果到Bitmap上
|
||||
public DetectionResult predict(Bitmap ARGB8888Bitmap);
|
||||
// 预测并且可视化:预测结果以及可视化,并将可视化后的图片保存到指定的途径,以及将可视化结果渲染在Bitmap上
|
||||
public DetectionResult predict(Bitmap ARGB8888Bitmap, String savedImagePath, float scoreThreshold)
|
||||
```
|
||||
- 模型资源释放 API:调用 release() API 可以释放模型资源,返回true表示释放成功,false表示失败;调用 initialized() 可以判断模型是否初始化成功,true表示初始化成功,false表示失败。
|
||||
```java
|
||||
public boolean release(); // 释放native资源
|
||||
public boolean initialized(); // 检查是否初始化成功
|
||||
```
|
||||
- RuntimeOption设置说明
|
||||
```java
|
||||
public void enableLiteFp16(); // 开启fp16精度推理
|
||||
public void disableLiteFP16(); // 关闭fp16精度推理
|
||||
public void setCpuThreadNum(int threadNum); // 设置线程数
|
||||
public void setLitePowerMode(LitePowerMode mode); // 设置能耗模式
|
||||
public void setLitePowerMode(String modeStr); // 通过字符串形式设置能耗模式
|
||||
public void enableRecordTimeOfRuntime(); // 是否打印模型运行耗时
|
||||
```
|
||||
|
||||
- 模型结果DetectionResult说明
|
||||
```java
|
||||
public float[][] mBoxes; // [n,4] 检测框 (x1,y1,x2,y2)
|
||||
public float[] mScores; // [n] 得分
|
||||
public int[] mLabelIds; // [n] 分类ID
|
||||
public boolean initialized(); // 检测结果是否有效
|
||||
```
|
||||
|
||||
- 模型调用示例1:使用构造函数以及默认的RuntimeOption
|
||||
```java
|
||||
import java.nio.ByteBuffer;
|
||||
import android.graphics.Bitmap;
|
||||
import android.opengl.GLES20;
|
||||
|
||||
import com.baidu.paddle.fastdeploy.vision.DetectionResult;
|
||||
import com.baidu.paddle.fastdeploy.vision.detection.PicoDet;
|
||||
|
||||
// 初始化模型
|
||||
PicoDet model = new PicoDet("picodet_s_320_coco_lcnet/model.pdmodel",
|
||||
"picodet_s_320_coco_lcnet/model.pdiparams",
|
||||
"picodet_s_320_coco_lcnet/infer_cfg.yml");
|
||||
|
||||
// 读取图片: 以下仅为读取Bitmap的伪代码
|
||||
ByteBuffer pixelBuffer = ByteBuffer.allocate(width * height * 4);
|
||||
GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pixelBuffer);
|
||||
Bitmap ARGB8888ImageBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
ARGB8888ImageBitmap.copyPixelsFromBuffer(pixelBuffer);
|
||||
|
||||
// 模型推理
|
||||
DetectionResult result = model.predict(ARGB8888ImageBitmap);
|
||||
|
||||
// 释放模型资源
|
||||
model.release();
|
||||
```
|
||||
|
||||
- 模型调用示例2: 在合适的程序节点,手动调用init,并自定义RuntimeOption
|
||||
```java
|
||||
// import 同上 ...
|
||||
import com.baidu.paddle.fastdeploy.RuntimeOption;
|
||||
import com.baidu.paddle.fastdeploy.LitePowerMode;
|
||||
import com.baidu.paddle.fastdeploy.vision.DetectionResult;
|
||||
import com.baidu.paddle.fastdeploy.vision.detection.PicoDet;
|
||||
// 新建空模型
|
||||
PicoDet model = new PicoDet();
|
||||
// 模型路径
|
||||
String modelFile = "picodet_s_320_coco_lcnet/model.pdmodel";
|
||||
String paramFile = "picodet_s_320_coco_lcnet/model.pdiparams";
|
||||
String configFile = "picodet_s_320_coco_lcnet/infer_cfg.yml";
|
||||
// 指定RuntimeOption
|
||||
RuntimeOption option = new RuntimeOption();
|
||||
option.setCpuThreadNum(2);
|
||||
option.setLitePowerMode(LitePowerMode.LITE_POWER_HIGH);
|
||||
option.enableRecordTimeOfRuntime();
|
||||
option.enableLiteFp16();
|
||||
// 使用init函数初始化
|
||||
model.init(modelFile, paramFile, configFile, option);
|
||||
// Bitmap读取、模型预测、资源释放 同上 ...
|
||||
```
|
||||
更详细的用法请参考 [MainActivity](./app/src/main/java/com/baidu/paddle/fastdeploy/examples/MainActivity.java#L207) 中的用法
|
||||
|
||||
## 替换 FastDeploy 预测库和模型
|
||||
替换FastDeploy预测库和模型的步骤非常简单。预测库所在的位置为 `app/libs/fastdeploy-android-xxx-shared`,其中 `xxx` 表示当前您使用的预测库版本号。模型所在的位置为,`app/src/main/assets/models/picodet_s_320_coco_lcnet`。
|
||||
- 替换FastDeploy预测库的步骤:
|
||||
- 下载或编译最新的FastDeploy Android预测库,解压缩后放在 `app/libs` 目录下;
|
||||
- 修改 `app/src/main/cpp/CMakeLists.txt` 中的预测库路径,指向您下载或编译的预测库路径。如:
|
||||
```cmake
|
||||
set(FastDeploy_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/fastdeploy-android-xxx-shared")
|
||||
```
|
||||
- 替换PicoDet模型的步骤:
|
||||
- 将您的PicoDet模型放在 `app/src/main/assets/models` 目录下;
|
||||
- 修改 `app/src/main/res/values/strings.xml` 中模型路径的默认值,如:
|
||||
```xml
|
||||
<!-- 将这个路径指修改成您的模型,如 models/picodet_l_320_coco_lcnet -->
|
||||
<string name="MODEL_DIR_DEFAULT">models/picodet_s_320_coco_lcnet</string>
|
||||
<string name="LABEL_PATH_DEFAULT">labels/coco_label_list.txt</string>
|
||||
```
|
||||
|
||||
## 如何通过 JNI 在 Native 层接入 FastDeploy C++ API ?
|
||||
如果您对如何通过JNI来接入FastDeploy C++ API感兴趣,可以参考以下内容:
|
||||
- [app/src/main/cpp 代码实现](./app/src/main/cpp/)
|
||||
- [在 Android 中使用 FastDeploy C++ SDK](../../../../../docs/cn/faq/use_cpp_sdk_on_android.md)
|
||||
|
@@ -14,6 +14,20 @@ public class PaddleClasModel {
|
||||
mInitialized = false;
|
||||
}
|
||||
|
||||
// Constructor with default runtime option
|
||||
public PaddleClasModel(String modelFile,
|
||||
String paramsFile,
|
||||
String configFile) {
|
||||
init_(modelFile, paramsFile, configFile, "", new RuntimeOption());
|
||||
}
|
||||
|
||||
public PaddleClasModel(String modelFile,
|
||||
String paramsFile,
|
||||
String configFile,
|
||||
String labelFile) {
|
||||
init_(modelFile, paramsFile, configFile, labelFile, new RuntimeOption());
|
||||
}
|
||||
|
||||
// Constructor without label file
|
||||
public PaddleClasModel(String modelFile,
|
||||
String paramsFile,
|
||||
|
@@ -14,6 +14,20 @@ public class PicoDet {
|
||||
mInitialized = false;
|
||||
}
|
||||
|
||||
// Constructor with default runtime option
|
||||
public PicoDet(String modelFile,
|
||||
String paramsFile,
|
||||
String configFile) {
|
||||
init_(modelFile, paramsFile, configFile, "", new RuntimeOption());
|
||||
}
|
||||
|
||||
public PicoDet(String modelFile,
|
||||
String paramsFile,
|
||||
String configFile,
|
||||
String labelFile) {
|
||||
init_(modelFile, paramsFile, configFile, labelFile, new RuntimeOption());
|
||||
}
|
||||
|
||||
// Constructor without label file
|
||||
public PicoDet(String modelFile,
|
||||
String paramsFile,
|
||||
|
Reference in New Issue
Block a user