[Android] Add PicoDet android jni demo (#405)

* [Android] Add picodet android jni demo

* [Android] Add picodet android jni demo

* [CMake] exclude jni files from examples exe srcs
This commit is contained in:
DefTruth
2022-10-21 09:30:04 +08:00
committed by GitHub
parent e51b8fc90e
commit ea1f3e6600
104 changed files with 4385 additions and 2 deletions

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.4.0-shared")
find_package(FastDeploy REQUIRED)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${FastDeploy_INCLUDE_DIRS})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math -Ofast -Os -DNDEBUG -fno-exceptions -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