[Android] Add android aar package (#416)

* [Android] Add Android build docs and demo (#26)

* [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

* [Android] init fastdeploy android jar package

* [Backend] support int8 option for lite backend

* [Model] add Backend::Lite to paddle model

* [Backend] use CopyFromCpu for lite backend.

* [Android] package jni srcs and java api into aar

* Update infer.cc

* Update infer.cc

* [Android] Update package build.gradle

* [Android] Update android app examples

* [Android] update android detection app
This commit is contained in:
DefTruth
2022-10-26 17:01:14 +08:00
committed by GitHub
parent b064ddf7ed
commit a51e5a6e55
137 changed files with 4664 additions and 37 deletions

1
java/android/fastdeploy/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,84 @@
import java.security.MessageDigest
apply plugin: 'com.android.library'
android {
compileSdk 28
defaultConfig {
minSdk 15
targetSdk 28
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
externalNativeBuild {
cmake {
arguments '-DANDROID_PLATFORM=android-21', '-DANDROID_STL=c++_shared', "-DANDROID_TOOLCHAIN=clang"
abiFilters 'armeabi-v7a', 'arm64-v8a'
cppFlags "-std=c++11"
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
ndkVersion '20.1.5948944'
}
dependencies {
implementation 'com.android.support:appcompat-v7:28.0.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
def archives = [
[
'src' : 'https://bj.bcebos.com/fastdeploy/test/fastdeploy-android-0.5.0-shared-dev.tgz',
'dest': 'libs'
]
]
task downloadAndExtractLibs(type: DefaultTask) {
doFirst {
println "Downloading and extracting archives including libs ..."
}
doLast {
// Prepare cache folder for archives
String cachePath = "cache"
if (!file("${cachePath}").exists()) {
mkdir "${cachePath}"
}
archives.eachWithIndex { archive, index ->
MessageDigest messageDigest = MessageDigest.getInstance('MD5')
messageDigest.update(archive.src.bytes)
String cacheName = new BigInteger(1, messageDigest.digest()).toString(32)
// Download the target archive if not exists
boolean copyFiles = !file("${archive.dest}").exists()
if (!file("${cachePath}/${cacheName}.tgz").exists()) {
ant.get(src: archive.src, dest: file("${cachePath}/${cacheName}.tgz"))
copyFiles = true // force to copy files from the latest archive files
}
// Extract the target archive if its dest path does not exists
if (copyFiles) {
copy {
from tarTree("${cachePath}/${cacheName}.tgz")
into "${archive.dest}"
}
}
}
}
}
preBuild.dependsOn downloadAndExtractLibs

View File

@@ -0,0 +1 @@
fastdeploy-*

View File

@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@@ -0,0 +1,25 @@
package com.baidu.paddle.fastdeploy;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.baidu.paddle.fastdeploy.test", appContext.getPackageName());
}
}

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.baidu.paddle.fastdeploy">
</manifest>

View File

@@ -0,0 +1,60 @@
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.10.2)
# Declares and names the project.
project("fastdeploy_jni")
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
set(FastDeploy_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/fastdeploy-android-0.5.0-shared-dev")
find_package(FastDeploy REQUIRED)
include_directories(.)
include_directories(${FastDeploy_INCLUDE_DIRS})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math -Ofast -Os -DNDEBUG -fomit-frame-pointer -fno-asynchronous-unwind-tables -fno-unwind-tables")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -fvisibility-inlines-hidden -fdata-sections -ffunction-sections")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections -Wl,-z,nocopyreloc")
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)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log)
# Specifies libraries CMake should link to your target library. You can link
# multiple libraries, such as libraries you define in this build script,
# prebuilt third-party libraries, or system libraries.
target_link_libraries(
# Specifies the target library.
fastdeploy_jni
jnigraphics
${FASTDEPLOY_LIBS}
GLESv2
EGL
${log-lib}
)

View File

@@ -0,0 +1,100 @@
// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "bitmap_jni.h" // NOLINT
#include <android/bitmap.h> // NOLINT
#include "utils_jni.h" // NOLINT
namespace fastdeploy {
namespace jni {
jboolean ARGB888Bitmap2RGBA(JNIEnv *env, jobject j_argb8888_bitmap,
cv::Mat *c_rgba) {
// Convert the android bitmap(ARGB8888) to the OpenCV RGBA image. Actually,
// the data layout of ARGB8888 is R, G, B, A, it's the same as CV RGBA image,
// so it is unnecessary to do the conversion of color format, check
// https://developer.android.com/reference/android/graphics/Bitmap.Config#ARGB_8888
// to get the more details about Bitmap.Config.ARGB8888
AndroidBitmapInfo j_bitmap_info;
if (AndroidBitmap_getInfo(env, j_argb8888_bitmap, &j_bitmap_info) < 0) {
LOGE("Invoke AndroidBitmap_getInfo() failed!");
return JNI_FALSE;
}
if (j_bitmap_info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
LOGE("Only Bitmap.Config.ARGB8888 color format is supported!");
return JNI_FALSE;
}
void *j_bitmap_pixels;
if (AndroidBitmap_lockPixels(env, j_argb8888_bitmap, &j_bitmap_pixels) < 0) {
LOGE("Invoke AndroidBitmap_lockPixels() failed!");
return JNI_FALSE;
}
cv::Mat j_bitmap_im(static_cast<int>(j_bitmap_info.height),
static_cast<int>(j_bitmap_info.width), CV_8UC4,
j_bitmap_pixels);
j_bitmap_im.copyTo(*(c_rgba));
if (AndroidBitmap_unlockPixels(env, j_argb8888_bitmap) < 0) {
LOGE("Invoke AndroidBitmap_unlockPixels() failed!");
return JNI_FALSE;
}
return JNI_TRUE;
}
jboolean ARGB888Bitmap2BGR(JNIEnv *env, jobject j_argb8888_bitmap,
cv::Mat *c_bgr) {
cv::Mat c_rgba;
if (!ARGB888Bitmap2RGBA(env, j_argb8888_bitmap, &c_rgba)) {
return JNI_FALSE;
}
cv::cvtColor(c_rgba, *(c_bgr), cv::COLOR_RGBA2BGR);
return JNI_TRUE;
}
jboolean RGBA2ARGB888Bitmap(JNIEnv *env, jobject j_argb8888_bitmap,
const cv::Mat &c_rgba) {
AndroidBitmapInfo j_bitmap_info;
if (AndroidBitmap_getInfo(env, j_argb8888_bitmap, &j_bitmap_info) < 0) {
LOGE("Invoke AndroidBitmap_getInfo() failed!");
return JNI_FALSE;
}
void *j_bitmap_pixels;
if (AndroidBitmap_lockPixels(env, j_argb8888_bitmap, &j_bitmap_pixels) < 0) {
LOGE("Invoke AndroidBitmap_lockPixels() failed!");
return JNI_FALSE;
}
cv::Mat j_bitmap_im(static_cast<int>(j_bitmap_info.height),
static_cast<int>(j_bitmap_info.width), CV_8UC4,
j_bitmap_pixels);
c_rgba.copyTo(j_bitmap_im);
if (AndroidBitmap_unlockPixels(env, j_argb8888_bitmap) < 0) {
LOGE("Invoke AndroidBitmap_unlockPixels() failed!");
return JNI_FALSE;
}
return JNI_TRUE;
}
jboolean BGR2ARGB888Bitmap(JNIEnv *env, jobject j_argb8888_bitmap,
const cv::Mat &c_bgr) {
if (c_bgr.empty()) {
return JNI_FALSE;
}
cv::Mat c_rgba;
cv::cvtColor(c_bgr, c_rgba, cv::COLOR_BGR2RGBA);
return RGBA2ARGB888Bitmap(env, j_argb8888_bitmap, c_rgba);
}
} // namespace jni
} // namespace fastdeploy

View File

@@ -0,0 +1,39 @@
// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <jni.h> // NOLINT
#include "fastdeploy/vision.h" // NOLINT
namespace fastdeploy {
namespace jni {
// Convert the android bitmap(ARGB8888) to the OpenCV RGBA image. Actually,
// the data layout of ARGB8888 is R, G, B, A, it's the same as CV RGBA image,
// so it is unnecessary to do the conversion of color format, check
// https://developer.android.com/reference/android/graphics/Bitmap.Config#ARGB_8888
// to get the more details about Bitmap.Config.ARGB8888
jboolean ARGB888Bitmap2RGBA(JNIEnv *env, jobject j_argb8888_bitmap,
cv::Mat *c_rgba);
jboolean RGBA2ARGB888Bitmap(JNIEnv *env, jobject j_argb8888_bitmap,
const cv::Mat &c_rgba);
jboolean ARGB888Bitmap2BGR(JNIEnv *env, jobject j_argb8888_bitmap,
cv::Mat *c_bgr);
jboolean BGR2ARGB888Bitmap(JNIEnv *env, jobject j_argb8888_bitmap,
const cv::Mat &c_bgr);
} // namespace jni
} // namespace fastdeploy

View File

@@ -0,0 +1,140 @@
// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <jni.h> // NOLINT
#include <string> // NOLINT
#include <vector> // NOLINT
namespace fastdeploy {
namespace jni {
template <typename OutputType, typename InputType>
OutputType ConvertTo(JNIEnv *env, InputType input);
template <typename OutputType, typename InputType>
OutputType ConvertTo(JNIEnv *env, const InputType *input, int64_t len);
/// jstring -> std::string
template <>
inline std::string ConvertTo(JNIEnv *env, jstring jstr) {
// In java, a unicode char will be encoded using 2 bytes (utf16).
// so jstring will contain characters utf16. std::string in c++ is
// essentially a string of bytes, not characters, so if we want to
// pass jstring from JNI to c++, we have convert utf16 to bytes.
if (!jstr) {
return "";
}
const jclass jstring_clazz = env->GetObjectClass(jstr);
const jmethodID getBytesID =
env->GetMethodID(jstring_clazz, "getBytes", "(Ljava/lang/String;)[B");
const jbyteArray jstring_bytes = (jbyteArray)env->CallObjectMethod(
jstr, getBytesID, env->NewStringUTF("UTF-8"));
size_t length = static_cast<size_t>(env->GetArrayLength(jstring_bytes));
jbyte *jstring_bytes_ptr = env->GetByteArrayElements(jstring_bytes, NULL);
std::string res =
std::string(reinterpret_cast<char *>(jstring_bytes_ptr), length);
env->ReleaseByteArrayElements(jstring_bytes, jstring_bytes_ptr, JNI_ABORT);
env->DeleteLocalRef(jstring_bytes);
env->DeleteLocalRef(jstring_clazz);
return res;
}
/// std::string -> jstring
template <>
inline jstring ConvertTo(JNIEnv *env, std::string str) {
auto *cstr_data_ptr = str.c_str();
jclass jstring_clazz = env->FindClass("java/lang/String");
jmethodID initID =
env->GetMethodID(jstring_clazz, "<init>", "([BLjava/lang/String;)V");
jbyteArray jstring_bytes = env->NewByteArray(strlen(cstr_data_ptr));
env->SetByteArrayRegion(jstring_bytes, 0, strlen(cstr_data_ptr),
reinterpret_cast<const jbyte *>(cstr_data_ptr));
jstring jstring_encoding = env->NewStringUTF("UTF-8");
jstring res = (jstring)(env->NewObject(jstring_clazz, initID, jstring_bytes,
jstring_encoding));
env->DeleteLocalRef(jstring_clazz);
env->DeleteLocalRef(jstring_bytes);
env->DeleteLocalRef(jstring_encoding);
return res;
}
/// jlongArray -> std::vector<int64_t>
template <>
inline std::vector<int64_t> ConvertTo(JNIEnv *env, jlongArray jdata) {
int jdata_size = env->GetArrayLength(jdata);
jlong *jdata_ptr = env->GetLongArrayElements(jdata, nullptr);
std::vector<int64_t> res(jdata_ptr, jdata_ptr + jdata_size);
env->ReleaseLongArrayElements(jdata, jdata_ptr, 0);
return res;
}
/// jfloatArray -> std::vector<float>
template <>
inline std::vector<float> ConvertTo(JNIEnv *env, jfloatArray jdata) {
int jdata_size = env->GetArrayLength(jdata);
jfloat *jdata_ptr = env->GetFloatArrayElements(jdata, nullptr);
std::vector<float> res(jdata_ptr, jdata_ptr + jdata_size);
env->ReleaseFloatArrayElements(jdata, jdata_ptr, 0);
return res;
}
/// std::vector<int64_t> -> jlongArray
template <>
inline jlongArray ConvertTo(JNIEnv *env, const std::vector<int64_t> &cvec) {
jlongArray res = env->NewLongArray(cvec.size());
jlong *jbuf = new jlong[cvec.size()];
for (size_t i = 0; i < cvec.size(); ++i) {
jbuf[i] = (jlong)cvec[i];
}
env->SetLongArrayRegion(res, 0, cvec.size(), jbuf);
delete[] jbuf;
return res;
}
/// cxx float buffer -> jfloatArray
template <>
inline jfloatArray ConvertTo(JNIEnv *env, const float *cbuf, int64_t len) {
jfloatArray res = env->NewFloatArray(len);
env->SetFloatArrayRegion(res, 0, len, cbuf);
return res;
}
/// cxx int buffer -> jintArray
template <>
inline jintArray ConvertTo(JNIEnv *env, const int *cbuf, int64_t len) {
jintArray res = env->NewIntArray(len);
env->SetIntArrayRegion(res, 0, len, cbuf);
return res;
}
/// cxx int8_t buffer -> jbyteArray
template <>
inline jbyteArray ConvertTo(JNIEnv *env, const int8_t *cbuf, int64_t len) {
jbyteArray res = env->NewByteArray(len);
env->SetByteArrayRegion(res, 0, len, cbuf);
return res;
}
} // namespace jni
} // namespace fastdeploy

View File

@@ -0,0 +1,18 @@
// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "bitmap_jni.h" // NOLINT
#include "convert_jni.h" // NOLINT
#include "utils_jni.h" // NOLINT

View File

@@ -0,0 +1,82 @@
//
// Created by qiuyanjun on 2022/10/19.
//
// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "utils_jni.h"
namespace fastdeploy {
namespace jni {
// Assets Loader Utils.
bool AssetsLoaderUtils::detection_labels_loaded_ = false;
bool AssetsLoaderUtils::classification_labels_loaded_ = false;
std::vector<std::string> AssetsLoaderUtils::detection_labels_ = {};
std::vector<std::string> AssetsLoaderUtils::classification_labels_ = {};
bool AssetsLoaderUtils::IsDetectionLabelsLoaded() {
return detection_labels_loaded_;
}
bool AssetsLoaderUtils::IsClassificationLabelsLoaded() {
return classification_labels_loaded_;
}
const std::vector<std::string>& AssetsLoaderUtils::GetDetectionLabels() {
return detection_labels_;
}
const std::vector<std::string>& AssetsLoaderUtils::GetClassificationLabels() {
return classification_labels_;
}
void AssetsLoaderUtils::LoadClassificationLabels(const std::string& path,
bool force_reload) {
if (force_reload || (!classification_labels_loaded_)) {
classification_labels_loaded_ =
LoadLabelsFromTxt(path, &classification_labels_);
}
}
void AssetsLoaderUtils::LoadDetectionLabels(const std::string& path,
bool force_reload) {
if (force_reload || (!detection_labels_loaded_)) {
detection_labels_loaded_ = LoadLabelsFromTxt(path, &detection_labels_);
}
}
bool AssetsLoaderUtils::LoadLabelsFromTxt(const std::string& txt_path,
std::vector<std::string>* labels) {
labels->clear();
std::ifstream file;
file.open(txt_path);
if (!file.is_open()) {
return false;
}
while (file) {
std::string line;
std::getline(file, line);
if (!line.empty() && line != "\n") {
labels->push_back(line);
}
}
file.clear();
file.close();
return labels->size() > 0;
}
} // namespace jni
} // namespace fastdeploy

View File

@@ -0,0 +1,80 @@
// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __ANDROID__
#include <android/log.h> // NOLINT
#endif
#include <fstream> // NOLINT
#include <string> // NOLINT
#include <vector> // NOLINT
#define TAG "[FastDeploy][JNI]"
#ifdef __ANDROID__
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, TAG, __VA_ARGS__)
#else
#define LOGD(...) \
{}
#define LOGI(...) \
{}
#define LOGW(...) \
{}
#define LOGE(...) \
{}
#define LOGF(...) \
{}
#endif
namespace fastdeploy {
namespace jni {
inline int64_t GetCurrentTime() {
struct timeval time;
gettimeofday(&time, NULL);
return 1000000LL * (int64_t)time.tv_sec + (int64_t)time.tv_usec;
}
inline double GetElapsedTime(int64_t time) {
return (GetCurrentTime() - time) / 1000.0f;
}
class AssetsLoaderUtils {
public:
static bool detection_labels_loaded_;
static bool classification_labels_loaded_;
static std::vector<std::string> detection_labels_;
static std::vector<std::string> classification_labels_;
public:
static bool IsDetectionLabelsLoaded();
static bool IsClassificationLabelsLoaded();
static const std::vector<std::string>& GetDetectionLabels();
static const std::vector<std::string>& GetClassificationLabels();
static void LoadClassificationLabels(const std::string& path,
bool force_reload = false);
static void LoadDetectionLabels(const std::string& path,
bool force_reload = false);
private:
static bool LoadLabelsFromTxt(const std::string& txt_path,
std::vector<std::string>* labels);
};
} // namespace jni
} // namespace fastdeploy

View File

@@ -0,0 +1,148 @@
// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <jni.h> // NOLINT
#include "fastdeploy_jni.h" // NOLINT
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jlong JNICALL
Java_com_baidu_paddle_fastdeploy_vision_classification_PaddleClasModel_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 =
fastdeploy::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();
}
auto c_model_ptr = new fastdeploy::vision::classification::PaddleClasModel(
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 classification labels if label path is not empty.
if ((!fastdeploy::jni::AssetsLoaderUtils::IsClassificationLabelsLoaded()) &&
(!c_label_file.empty())) {
fastdeploy::jni::AssetsLoaderUtils::LoadClassificationLabels(c_label_file);
}
// WARN: need to release manually in Java !
return reinterpret_cast<jlong>(c_model_ptr); // native model context
}
JNIEXPORT jlong JNICALL
Java_com_baidu_paddle_fastdeploy_vision_classification_PaddleClasModel_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;
auto t = fastdeploy::jni::GetCurrentTime();
if (!fastdeploy::jni::ARGB888Bitmap2BGR(env, argb8888_bitmap, &c_bgr)) {
return 0;
}
LOGD("Read from bitmap costs %f ms", fastdeploy::jni::GetElapsedTime(t));
auto c_model_ptr =
reinterpret_cast<fastdeploy::vision::classification::PaddleClasModel *>(
native_model_context);
auto c_result_ptr = new fastdeploy::vision::ClassifyResult();
t = fastdeploy::jni::GetCurrentTime();
if (!c_model_ptr->Predict(&c_bgr, c_result_ptr, 100)) {
delete c_result_ptr;
return 0;
}
LOGD("Predict from native costs %f ms", fastdeploy::jni::GetElapsedTime(t));
if (c_model_ptr->EnabledRecordTimeOfRuntime()) {
auto info_of_runtime = c_model_ptr->PrintStatisInfoOfRuntime();
LOGD("Avg runtime costs %f ms", info_of_runtime["avg_time"] * 1000.0f);
}
if (!c_result_ptr->scores.empty() && rendering) {
t = fastdeploy::jni::GetCurrentTime();
cv::Mat c_vis_im;
if (fastdeploy::jni::AssetsLoaderUtils::IsClassificationLabelsLoaded()) {
c_vis_im = fastdeploy::vision::VisClassification(
c_bgr, *(c_result_ptr),
fastdeploy::jni::AssetsLoaderUtils::GetClassificationLabels(), 5,
score_threshold, 1.0f);
} else {
c_vis_im = fastdeploy::vision::VisClassification(
c_bgr, *(c_result_ptr), 5, score_threshold, 1.0f);
}
LOGD("Visualize from native costs %f ms",
fastdeploy::jni::GetElapsedTime(t));
// Rendering to bitmap
t = fastdeploy::jni::GetCurrentTime();
if (!fastdeploy::jni::BGR2ARGB888Bitmap(env, argb8888_bitmap, c_vis_im)) {
delete c_result_ptr;
return 0;
}
LOGD("Write to bitmap from native costs %f ms",
fastdeploy::jni::GetElapsedTime(t));
std::string c_saved_image_path =
fastdeploy::jni::ConvertTo<std::string>(env, saved_image_path);
if (!c_saved_image_path.empty() && saved) {
t = fastdeploy::jni::GetCurrentTime();
cv::imwrite(c_saved_image_path, c_bgr);
LOGD("Save image from native costs %f ms, path: %s",
fastdeploy::jni::GetElapsedTime(t), c_saved_image_path.c_str());
}
}
// WARN: need to release it manually in Java !
return reinterpret_cast<jlong>(c_result_ptr); // native result context
}
JNIEXPORT jboolean JNICALL
Java_com_baidu_paddle_fastdeploy_vision_classification_PaddleClasModel_releaseNative(
JNIEnv *env, jclass clazz, jlong native_model_context) {
auto c_model_ptr =
reinterpret_cast<fastdeploy::vision::classification::PaddleClasModel *>(
native_model_context);
if (c_model_ptr->EnabledRecordTimeOfRuntime()) {
auto info_of_runtime = c_model_ptr->PrintStatisInfoOfRuntime();
LOGD("[End] Avg runtime costs %f ms",
info_of_runtime["avg_time"] * 1000.0f);
}
delete c_model_ptr;
LOGD("[End] Release PaddleClasModel in native !");
return JNI_TRUE;
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,149 @@
// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <jni.h> // NOLINT
#include "fastdeploy_jni.h" // NOLINT
#ifdef __cplusplus
extern "C" {
#endif
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 =
fastdeploy::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();
}
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
}
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;
auto t = fastdeploy::jni::GetCurrentTime();
if (!fastdeploy::jni::ARGB888Bitmap2BGR(env, argb8888_bitmap, &c_bgr)) {
return 0;
}
LOGD("Read from bitmap costs %f ms", fastdeploy::jni::GetElapsedTime(t));
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;
}
LOGD("Predict from native costs %f ms", fastdeploy::jni::GetElapsedTime(t));
if (c_model_ptr->EnabledRecordTimeOfRuntime()) {
auto info_of_runtime = c_model_ptr->PrintStatisInfoOfRuntime();
LOGD("Avg runtime costs %f ms", info_of_runtime["avg_time"] * 1000.0f);
}
if (!c_result_ptr->boxes.empty() && rendering) {
t = fastdeploy::jni::GetCurrentTime();
cv::Mat c_vis_im;
if (fastdeploy::jni::AssetsLoaderUtils::IsDetectionLabelsLoaded()) {
c_vis_im = fastdeploy::vision::VisDetection(
c_bgr, *(c_result_ptr),
fastdeploy::jni::AssetsLoaderUtils::GetDetectionLabels(),
score_threshold, 2, 1.0f);
} else {
c_vis_im = fastdeploy::vision::VisDetection(c_bgr, *(c_result_ptr),
score_threshold, 2, 1.0f);
}
LOGD("Visualize from native costs %f ms",
fastdeploy::jni::GetElapsedTime(t));
// Rendering to bitmap
t = fastdeploy::jni::GetCurrentTime();
if (!fastdeploy::jni::BGR2ARGB888Bitmap(env, argb8888_bitmap, c_vis_im)) {
delete c_result_ptr;
return 0;
}
LOGD("Write to bitmap from native costs %f ms",
fastdeploy::jni::GetElapsedTime(t));
std::string c_saved_image_path =
fastdeploy::jni::ConvertTo<std::string>(env, saved_image_path);
if (!c_saved_image_path.empty() && saved) {
t = fastdeploy::jni::GetCurrentTime();
cv::imwrite(c_saved_image_path, c_vis_im);
LOGD("Save image from native costs %f ms, path: %s",
fastdeploy::jni::GetElapsedTime(t), c_saved_image_path.c_str());
}
}
// WARN: need to release it manually in Java !
return reinterpret_cast<jlong>(c_result_ptr); // native result context
}
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);
if (c_model_ptr->EnabledRecordTimeOfRuntime()) {
auto info_of_runtime = c_model_ptr->PrintStatisInfoOfRuntime();
LOGD("[End] Avg runtime costs %f ms",
info_of_runtime["avg_time"] * 1000.0f);
}
delete c_model_ptr;
LOGD("[End] Release PicoDet in native !");
return JNI_TRUE;
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,132 @@
// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <android/bitmap.h> // NOLINT
#include <jni.h> // NOLINT
#include "fastdeploy/vision.h" // NOLINT
#include "fastdeploy_jni.h" // NOLINT
#ifdef __cplusplus
extern "C" {
#endif
/// Native DetectionResult for vision::DetectionResult.
JNIEXPORT jint JNICALL
Java_com_baidu_paddle_fastdeploy_vision_DetectionResult_copyBoxesNumFromNative(
JNIEnv *env, jclass clazz, jlong native_result_context) {
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::DetectionResult *>(
native_result_context);
return static_cast<jint>(c_result_ptr->boxes.size());
}
JNIEXPORT jfloatArray JNICALL
Java_com_baidu_paddle_fastdeploy_vision_DetectionResult_copyBoxesFromNative(
JNIEnv *env, jclass clazz, jlong native_result_context) {
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::DetectionResult *>(
native_result_context);
if (c_result_ptr->boxes.empty()) {
return {};
}
const auto len = static_cast<int64_t>(c_result_ptr->boxes.size());
float buffer[len * 4];
const auto &boxes = c_result_ptr->boxes;
for (int64_t i = 0; i < len; ++i) {
std::memcpy((buffer + i * 4), (boxes.at(i).data()), 4 * sizeof(float));
}
return fastdeploy::jni::ConvertTo<jfloatArray>(env, buffer, len * 4);
}
JNIEXPORT jfloatArray JNICALL
Java_com_baidu_paddle_fastdeploy_vision_DetectionResult_copyScoresFromNative(
JNIEnv *env, jclass clazz, jlong native_result_context) {
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::DetectionResult *>(
native_result_context);
if (c_result_ptr->scores.empty()) {
return {};
}
const auto len = static_cast<int64_t>(c_result_ptr->scores.size());
const float *buffer = static_cast<float *>(c_result_ptr->scores.data());
return fastdeploy::jni::ConvertTo<jfloatArray>(env, buffer, len);
}
JNIEXPORT jintArray JNICALL
Java_com_baidu_paddle_fastdeploy_vision_DetectionResult_copyLabelIdsFromNative(
JNIEnv *env, jclass clazz, jlong native_result_context) {
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::DetectionResult *>(
native_result_context);
if (c_result_ptr->label_ids.empty()) {
return {};
}
const auto len = static_cast<int64_t>(c_result_ptr->label_ids.size());
const int *buffer = static_cast<int *>(c_result_ptr->label_ids.data());
return fastdeploy::jni::ConvertTo<jintArray>(env, buffer, len);
}
JNIEXPORT jboolean JNICALL
Java_com_baidu_paddle_fastdeploy_vision_DetectionResult_releaseNative(
JNIEnv *env, jclass clazz, jlong native_result_context) {
if (native_result_context == 0) {
return JNI_FALSE;
}
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::DetectionResult *>(
native_result_context);
delete c_result_ptr;
LOGD("Release DetectionResult in native !");
return JNI_TRUE;
}
/// Native ClassifyResult for vision::ClassifyResult.
JNIEXPORT jfloatArray JNICALL
Java_com_baidu_paddle_fastdeploy_vision_ClassifyResult_copyScoresFromNative(
JNIEnv *env, jclass clazz, jlong native_result_context) {
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::ClassifyResult *>(
native_result_context);
if (c_result_ptr->scores.empty()) {
return {};
}
const auto len = static_cast<int64_t>(c_result_ptr->scores.size());
const float *buffer = static_cast<float *>(c_result_ptr->scores.data());
return fastdeploy::jni::ConvertTo<jfloatArray>(env, buffer, len);
}
JNIEXPORT jintArray JNICALL
Java_com_baidu_paddle_fastdeploy_vision_ClassifyResult_copyLabelIdsFromNative(
JNIEnv *env, jclass clazz, jlong native_result_context) {
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::ClassifyResult *>(
native_result_context);
if (c_result_ptr->label_ids.empty()) {
return {};
}
const auto len = static_cast<int64_t>(c_result_ptr->label_ids.size());
const int *buffer = static_cast<int *>(c_result_ptr->label_ids.data());
return fastdeploy::jni::ConvertTo<jintArray>(env, buffer, len);
}
JNIEXPORT jboolean JNICALL
Java_com_baidu_paddle_fastdeploy_vision_ClassifyResult_releaseNative(
JNIEnv *env, jclass clazz, jlong native_result_context) {
if (native_result_context == 0) {
return JNI_FALSE;
}
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::ClassifyResult *>(
native_result_context);
delete c_result_ptr;
LOGD("Release ClassifyResult in native !");
return JNI_TRUE;
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,92 @@
// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <jni.h>
#include "fastdeploy_jni.h"
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jboolean JNICALL
Java_com_baidu_paddle_fastdeploy_vision_Visualize_visDetectionNative(
JNIEnv *env, jclass clazz, jobject argb8888_bitmap, jobjectArray boxes,
jfloatArray scores, jintArray label_ids, jfloat score_threshold,
jint line_size, jfloat font_size, jobjectArray labels) {
// Draw DetectionResult to ARGB8888 Bitmap
int len = env->GetArrayLength(boxes);
if ((len == 0) || (len != env->GetArrayLength(scores)) ||
(len != env->GetArrayLength(label_ids))) {
return JNI_FALSE;
}
fastdeploy::vision::DetectionResult c_result;
c_result.Resize(len);
bool check_validation = true;
for (int i = 0; i < len; ++i) {
auto j_box =
reinterpret_cast<jfloatArray>(env->GetObjectArrayElement(boxes, i));
if (env->GetArrayLength(j_box) == 4) {
jfloat *j_box_ptr = env->GetFloatArrayElements(j_box, nullptr);
std::memcpy(c_result.boxes[i].data(), j_box_ptr, 4 * sizeof(float));
env->ReleaseFloatArrayElements(j_box, j_box_ptr, 0);
} else {
check_validation = false;
break;
}
}
if (!check_validation) {
return JNI_FALSE;
}
jfloat *j_scores_ptr = env->GetFloatArrayElements(scores, nullptr);
std::memcpy(c_result.scores.data(), j_scores_ptr, len * sizeof(float));
env->ReleaseFloatArrayElements(scores, j_scores_ptr, 0);
jint *j_label_ids_ptr = env->GetIntArrayElements(label_ids, nullptr);
std::memcpy(c_result.label_ids.data(), j_label_ids_ptr, len * sizeof(int));
env->ReleaseIntArrayElements(label_ids, j_label_ids_ptr, 0);
// Get labels from Java
std::vector<std::string> c_labels;
int label_len = env->GetArrayLength(labels);
if (label_len > 0) {
c_labels.reserve(label_len);
for (int i = 0; i < label_len; ++i) {
auto j_str =
reinterpret_cast<jstring>(env->GetObjectArrayElement(labels, i));
c_labels.push_back(fastdeploy::jni::ConvertTo<std::string>(env, j_str));
}
}
cv::Mat c_bgr;
// From ARGB Bitmap to BGR
if (!fastdeploy::jni::ARGB888Bitmap2BGR(env, argb8888_bitmap, &c_bgr)) {
return JNI_FALSE;
}
cv::Mat c_vis_im;
if (!c_labels.empty()) {
c_vis_im = fastdeploy::vision::VisDetection(
c_bgr, c_result, c_labels, score_threshold, line_size, font_size);
} else {
c_vis_im = fastdeploy::vision::VisDetection(
c_bgr, c_result, score_threshold, line_size, font_size);
}
// Rendering to bitmap
if (!fastdeploy::jni::BGR2ARGB888Bitmap(env, argb8888_bitmap, c_vis_im)) {
return JNI_FALSE;
}
return JNI_TRUE;
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,8 @@
package com.baidu.paddle.fastdeploy;
public enum FDModelTag {
UNKNOWN,
VISION_DETECTION_PICODET,
VISION_DETECTION_PPYOLOE,
VISION_CLASSIFICATION_PPCLS
}

View File

@@ -0,0 +1,22 @@
package com.baidu.paddle.fastdeploy;
/**
* Initializer for FastDeploy. The initialization methods are called by package
* classes only. Public users don't have to call them. Public users can get
* FastDeploy information constants such as JNI lib name in this class.
*/
public class FastDeployInitializer {
/** name of C++ JNI lib */
public final static String JNI_LIB_NAME = "fastdeploy_jni";
/**
* loads the C++ JNI lib. We only call it in our package, so it shouldn't be
* visible to public users.
*
* @return true if initialize successfully.
*/
public static boolean init() {
System.loadLibrary(JNI_LIB_NAME);
return true;
}
}

View File

@@ -0,0 +1,10 @@
package com.baidu.paddle.fastdeploy;
public enum LitePowerMode {
LITE_POWER_HIGH,
LITE_POWER_LOW,
LITE_POWER_FULL,
LITE_POWER_NO_BIND,
LITE_POWER_RAND_HIGH,
LITE_POWER_RAND_LOW
}

View File

@@ -0,0 +1,64 @@
package com.baidu.paddle.fastdeploy;
public class RuntimeOption {
public int mCpuThreadNum = 1;
public boolean mEnableLiteFp16 = false;
public boolean mEnableRecordTimeOfRuntime = false;
public LitePowerMode mLitePowerMode = LitePowerMode.LITE_POWER_NO_BIND;
public String mLiteOptimizedModelDir = "";
public RuntimeOption() {
mCpuThreadNum = 1;
mEnableLiteFp16 = false;
mEnableRecordTimeOfRuntime = false;
mLitePowerMode = LitePowerMode.LITE_POWER_NO_BIND;
mLiteOptimizedModelDir = "";
}
public void enableLiteFp16() {
mEnableLiteFp16 = true;
}
public void disableLiteFP16() {
mEnableLiteFp16 = false;
}
public void setCpuThreadNum(int threadNum) {
mCpuThreadNum = threadNum;
}
public void setLitePowerMode(LitePowerMode mode) {
mLitePowerMode = mode;
}
public void setLitePowerMode(String modeStr) {
mLitePowerMode = parseLitePowerModeFromString(modeStr);
}
public void setLiteOptimizedModelDir(String modelDir) {
mLiteOptimizedModelDir = modelDir;
}
public void enableRecordTimeOfRuntime() {
mEnableRecordTimeOfRuntime = true;
}
// Helpers: parse lite power mode from string
public static LitePowerMode parseLitePowerModeFromString(String modeStr) {
if (modeStr.equalsIgnoreCase("LITE_POWER_HIGH")) {
return LitePowerMode.LITE_POWER_HIGH;
} else if (modeStr.equalsIgnoreCase("LITE_POWER_LOW")) {
return LitePowerMode.LITE_POWER_LOW;
} else if (modeStr.equalsIgnoreCase("LITE_POWER_FULL")) {
return LitePowerMode.LITE_POWER_FULL;
} else if (modeStr.equalsIgnoreCase("LITE_POWER_NO_BIND")) {
return LitePowerMode.LITE_POWER_NO_BIND;
} else if (modeStr.equalsIgnoreCase("LITE_POWER_RAND_HIGH")) {
return LitePowerMode.LITE_POWER_RAND_HIGH;
} else if (modeStr.equalsIgnoreCase("LITE_POWER_RAND_LOW")) {
return LitePowerMode.LITE_POWER_RAND_LOW;
} else {
return LitePowerMode.LITE_POWER_NO_BIND;
}
}
}

View File

@@ -0,0 +1,51 @@
package com.baidu.paddle.fastdeploy.vision;
import android.support.annotation.NonNull;
public class ClassifyResult {
public float[] mScores; // [n]
public int[] mLabelIds; // [n]
public boolean mInitialized = false;
public ClassifyResult() {
mInitialized = false;
}
public ClassifyResult(long nativeResultContext) {
mInitialized = copyAllFromNativeContext(nativeResultContext);
}
public boolean initialized() {
return mInitialized;
}
private void setScores(@NonNull float[] scoresBuffer) {
if (scoresBuffer.length > 0) {
mScores = scoresBuffer.clone();
}
}
private void setLabelIds(@NonNull int[] labelIdsBuffer) {
if (labelIdsBuffer.length > 0) {
mLabelIds = labelIdsBuffer.clone();
}
}
private boolean copyAllFromNativeContext(long nativeResultContext) {
if (nativeResultContext == 0) {
return false;
}
setScores(copyScoresFromNative(nativeResultContext));
setLabelIds(copyLabelIdsFromNative(nativeResultContext));
// WARN: must release ctx.
return releaseNative(nativeResultContext);
}
// Fetch native buffers from native context.
private static native float[] copyScoresFromNative(long nativeResultContext);
private static native int[] copyLabelIdsFromNative(long nativeResultContext);
private static native boolean releaseNative(long nativeResultContext);
}

View File

@@ -0,0 +1,80 @@
package com.baidu.paddle.fastdeploy.vision;
import android.support.annotation.NonNull;
import com.baidu.paddle.fastdeploy.FastDeployInitializer;
import java.util.Arrays;
public class DetectionResult {
// Not support MaskRCNN now.
public float[][] mBoxes; // [n,4]
public float[] mScores; // [n]
public int[] mLabelIds; // [n]
public boolean mInitialized = false;
public DetectionResult() {
mInitialized = false;
}
public DetectionResult(long nativeResultContext) {
mInitialized = copyAllFromNativeContext(nativeResultContext);
}
public boolean initialized() {
return mInitialized;
}
// Setup results from native buffers.
private boolean copyAllFromNativeContext(long nativeResultContext) {
if (nativeResultContext == 0) {
return false;
}
if (copyBoxesNumFromNative(nativeResultContext) > 0) {
setBoxes(copyBoxesFromNative(nativeResultContext));
setScores(copyScoresFromNative(nativeResultContext));
setLabelIds(copyLabelIdsFromNative(nativeResultContext));
}
// WARN: must release ctx.
return releaseNative(nativeResultContext);
}
private void setBoxes(@NonNull float[] boxesBuffer) {
int boxesNum = boxesBuffer.length / 4;
if (boxesNum > 0) {
mBoxes = new float[boxesNum][4];
for (int i = 0; i < boxesNum; ++i) {
mBoxes[i] = Arrays.copyOfRange(
boxesBuffer, i * 4, (i + 1) * 4);
}
}
}
private void setScores(@NonNull float[] scoresBuffer) {
if (scoresBuffer.length > 0) {
mScores = scoresBuffer.clone();
}
}
private void setLabelIds(@NonNull int[] labelIdsBuffer) {
if (labelIdsBuffer.length > 0) {
mLabelIds = labelIdsBuffer.clone();
}
}
// Fetch native buffers from native context.
private static native int copyBoxesNumFromNative(long nativeResultContext);
private static native float[] copyBoxesFromNative(long nativeResultContext);
private static native float[] copyScoresFromNative(long nativeResultContext);
private static native int[] copyLabelIdsFromNative(long nativeResultContext);
private static native boolean releaseNative(long nativeResultContext);
// Initializes at the beginning.
static {
FastDeployInitializer.init();
}
}

View File

@@ -0,0 +1,85 @@
package com.baidu.paddle.fastdeploy.vision;
import android.graphics.Bitmap;
import com.baidu.paddle.fastdeploy.FastDeployInitializer;
public class Visualize {
// TODO(qiuyanjun):
// VisClassification, VisSegmentation, VisMatting, VisOcr, ...
// Visualize DetectionResult without labels
public static boolean visDetection(Bitmap ARGB8888Bitmap,
DetectionResult result) {
return visDetectionNative(
ARGB8888Bitmap,
result.mBoxes,
result.mScores,
result.mLabelIds,
0.f, 1, 0.5f,
new String[]{});
}
public static boolean visDetection(Bitmap ARGB8888Bitmap,
DetectionResult result,
float score_threshold,
int line_size,
float font_size) {
return visDetectionNative(
ARGB8888Bitmap,
result.mBoxes,
result.mScores,
result.mLabelIds,
score_threshold,
line_size,
font_size,
new String[]{});
}
// Visualize DetectionResult with labels
public static boolean visDetection(Bitmap ARGB8888Bitmap,
DetectionResult result,
String[] labels) {
return visDetectionNative(
ARGB8888Bitmap,
result.mBoxes,
result.mScores,
result.mLabelIds,
0.f, 1, 0.5f,
labels);
}
public static boolean visDetection(Bitmap ARGB8888Bitmap,
DetectionResult result,
float score_threshold,
int line_size,
float font_size,
String[] labels) {
return visDetectionNative(
ARGB8888Bitmap,
result.mBoxes,
result.mScores,
result.mLabelIds,
score_threshold,
line_size,
font_size,
labels);
}
// VisDetection in native
public static native boolean visDetectionNative(Bitmap ARGB8888Bitmap,
float[][] boxes,
float[] scores,
int[] labelIds,
float score_threshold,
int line_size,
float font_size,
String[] labels);
/* Initializes at the beginning */
static {
FastDeployInitializer.init();
}
}

View File

@@ -0,0 +1,172 @@
package com.baidu.paddle.fastdeploy.vision.classification;
import android.graphics.Bitmap;
import com.baidu.paddle.fastdeploy.FastDeployInitializer;
import com.baidu.paddle.fastdeploy.RuntimeOption;
import com.baidu.paddle.fastdeploy.vision.ClassifyResult;
public class PaddleClasModel {
protected long mNativeModelContext = 0; // Context from native.
protected boolean mInitialized = false;
public 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,
String configFile,
RuntimeOption option) {
init_(modelFile, paramsFile, configFile, "", option);
}
// Constructor with label file
public PaddleClasModel(String modelFile,
String paramsFile,
String configFile,
String labelFile,
RuntimeOption option) {
init_(modelFile, paramsFile, configFile, labelFile, option);
}
// Call init manually without label file
public boolean init(String modelFile,
String paramsFile,
String configFile,
RuntimeOption option) {
return init_(modelFile, paramsFile, configFile, "", option);
}
// Call init manually with label file
public boolean init(String modelFile,
String paramsFile,
String configFile,
String labelFile,
RuntimeOption option) {
return init_(modelFile, paramsFile, configFile, labelFile, option);
}
public boolean release() {
mInitialized = false;
if (mNativeModelContext == 0) {
return false;
}
return releaseNative(mNativeModelContext);
}
public boolean initialized() {
return mInitialized;
}
// Predict without image saving and bitmap rendering.
public ClassifyResult predict(Bitmap ARGB8888Bitmap) {
if (mNativeModelContext == 0) {
return new ClassifyResult();
}
// Only support ARGB8888 bitmap in native now.
return new ClassifyResult(predictNative(
mNativeModelContext, ARGB8888Bitmap, false,
"", 0.f, false));
}
// Predict with image saving and bitmap rendering (will cost more times)
public ClassifyResult predict(Bitmap ARGB8888Bitmap,
String savedImagePath,
float scoreThreshold) {
// scoreThreshold is for visualizing only.
if (mNativeModelContext == 0) {
return new ClassifyResult();
}
// Only support ARGB8888 bitmap in native now.
return new ClassifyResult(predictNative(
mNativeModelContext, ARGB8888Bitmap, true,
savedImagePath, scoreThreshold, true));
}
// Internal init_ method
private boolean init_(String modelFile,
String paramsFile,
String configFile,
String labelFile,
RuntimeOption option) {
if (!mInitialized) {
mNativeModelContext = bindNative(
modelFile,
paramsFile,
configFile,
option.mCpuThreadNum,
option.mEnableLiteFp16,
option.mLitePowerMode.ordinal(),
option.mLiteOptimizedModelDir,
option.mEnableRecordTimeOfRuntime, labelFile);
if (mNativeModelContext != 0) {
mInitialized = true;
}
return mInitialized;
} else {
// release current native context and bind a new one.
if (release()) {
mNativeModelContext = bindNative(
modelFile,
paramsFile,
configFile,
option.mCpuThreadNum,
option.mEnableLiteFp16,
option.mLitePowerMode.ordinal(),
option.mLiteOptimizedModelDir,
option.mEnableRecordTimeOfRuntime, labelFile);
if (mNativeModelContext != 0) {
mInitialized = true;
}
return mInitialized;
}
return 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();
}
}

View File

@@ -0,0 +1,170 @@
package com.baidu.paddle.fastdeploy.vision.detection;
import android.graphics.Bitmap;
import com.baidu.paddle.fastdeploy.FastDeployInitializer;
import com.baidu.paddle.fastdeploy.RuntimeOption;
import com.baidu.paddle.fastdeploy.vision.DetectionResult;
public class PicoDet {
protected long mNativeModelContext = 0; // Context from native.
protected boolean mInitialized = false;
public 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,
String configFile,
RuntimeOption option) {
init_(modelFile, paramsFile, configFile, "", option);
}
// Constructor with label file
public PicoDet(String modelFile,
String paramsFile,
String configFile,
String labelFile,
RuntimeOption option) {
init_(modelFile, paramsFile, configFile, labelFile, option);
}
// Call init manually without label file
public boolean init(String modelFile,
String paramsFile,
String configFile,
RuntimeOption option) {
return init_(modelFile, paramsFile, configFile, "", option);
}
// Call init manually with label file
public boolean init(String modelFile,
String paramsFile,
String configFile,
String labelFile,
RuntimeOption option) {
return init_(modelFile, paramsFile, configFile, labelFile, option);
}
public boolean release() {
mInitialized = false;
if (mNativeModelContext == 0) {
return false;
}
return releaseNative(mNativeModelContext);
}
public boolean initialized() {
return mInitialized;
}
// Predict without image saving and bitmap rendering.
public DetectionResult predict(Bitmap ARGB8888Bitmap) {
if (mNativeModelContext == 0) {
return new DetectionResult();
}
// Only support ARGB8888 bitmap in native now.
return new DetectionResult(predictNative(
mNativeModelContext, ARGB8888Bitmap, false,
"", 0.f, false));
}
// Predict with image saving and bitmap rendering (will cost more times)
public DetectionResult predict(Bitmap ARGB8888Bitmap,
String savedImagePath,
float scoreThreshold) {
// scoreThreshold is for visualizing only.
if (mNativeModelContext == 0) {
return new DetectionResult();
}
// Only support ARGB8888 bitmap in native now.
return new DetectionResult(predictNative(
mNativeModelContext, ARGB8888Bitmap, true,
savedImagePath, scoreThreshold, true));
}
private boolean init_(String modelFile,
String paramsFile,
String configFile,
String labelFile,
RuntimeOption option) {
if (!mInitialized) {
mNativeModelContext = bindNative(
modelFile,
paramsFile,
configFile,
option.mCpuThreadNum,
option.mEnableLiteFp16,
option.mLitePowerMode.ordinal(),
option.mLiteOptimizedModelDir,
option.mEnableRecordTimeOfRuntime, labelFile);
if (mNativeModelContext != 0) {
mInitialized = true;
}
return mInitialized;
} else {
// release current native context and bind a new one.
if (release()) {
mNativeModelContext = bindNative(
modelFile,
paramsFile,
configFile,
option.mCpuThreadNum,
option.mEnableLiteFp16,
option.mLitePowerMode.ordinal(),
option.mLiteOptimizedModelDir,
option.mEnableRecordTimeOfRuntime, labelFile);
if (mNativeModelContext != 0) {
mInitialized = true;
}
return mInitialized;
}
return 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();
}
}

View File

@@ -0,0 +1,17 @@
package com.baidu.paddle.fastdeploy;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}