mirror of
https://github.com/PaddlePaddle/FastDeploy.git
synced 2025-10-06 00:57:33 +08:00
[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:
1
java/android/fastdeploy/.gitignore
vendored
Normal file
1
java/android/fastdeploy/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
84
java/android/fastdeploy/build.gradle
Normal file
84
java/android/fastdeploy/build.gradle
Normal 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
|
0
java/android/fastdeploy/consumer-rules.pro
Normal file
0
java/android/fastdeploy/consumer-rules.pro
Normal file
1
java/android/fastdeploy/libs/.gitignore
vendored
Normal file
1
java/android/fastdeploy/libs/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
fastdeploy-*
|
21
java/android/fastdeploy/proguard-rules.pro
vendored
Normal file
21
java/android/fastdeploy/proguard-rules.pro
vendored
Normal 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
|
@@ -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());
|
||||
}
|
||||
}
|
5
java/android/fastdeploy/src/main/AndroidManifest.xml
Normal file
5
java/android/fastdeploy/src/main/AndroidManifest.xml
Normal 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>
|
60
java/android/fastdeploy/src/main/cpp/CMakeLists.txt
Normal file
60
java/android/fastdeploy/src/main/cpp/CMakeLists.txt
Normal 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}
|
||||
)
|
100
java/android/fastdeploy/src/main/cpp/bitmap_jni.cc
Normal file
100
java/android/fastdeploy/src/main/cpp/bitmap_jni.cc
Normal 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
|
39
java/android/fastdeploy/src/main/cpp/bitmap_jni.h
Normal file
39
java/android/fastdeploy/src/main/cpp/bitmap_jni.h
Normal 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
|
140
java/android/fastdeploy/src/main/cpp/convert_jni.h
Normal file
140
java/android/fastdeploy/src/main/cpp/convert_jni.h
Normal 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
|
18
java/android/fastdeploy/src/main/cpp/fastdeploy_jni.h
Normal file
18
java/android/fastdeploy/src/main/cpp/fastdeploy_jni.h
Normal 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
|
82
java/android/fastdeploy/src/main/cpp/utils_jni.cc
Normal file
82
java/android/fastdeploy/src/main/cpp/utils_jni.cc
Normal 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
|
80
java/android/fastdeploy/src/main/cpp/utils_jni.h
Normal file
80
java/android/fastdeploy/src/main/cpp/utils_jni.h
Normal 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
|
@@ -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
|
@@ -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
|
132
java/android/fastdeploy/src/main/cpp/vision/results_jni.cc
Normal file
132
java/android/fastdeploy/src/main/cpp/vision/results_jni.cc
Normal 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
|
92
java/android/fastdeploy/src/main/cpp/vision/visualize_jni.cc
Normal file
92
java/android/fastdeploy/src/main/cpp/vision/visualize_jni.cc
Normal 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
|
@@ -0,0 +1,8 @@
|
||||
package com.baidu.paddle.fastdeploy;
|
||||
|
||||
public enum FDModelTag {
|
||||
UNKNOWN,
|
||||
VISION_DETECTION_PICODET,
|
||||
VISION_DETECTION_PPYOLOE,
|
||||
VISION_CLASSIFICATION_PPCLS
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user