|
- // Tencent is pleased to support the open source community by making ncnn available.
- //
- // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
- //
- // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
- // in compliance with the License. You may obtain a copy of the License at
- //
- // https://opensource.org/licenses/BSD-3-Clause
- //
- // 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>
- #include <android/log.h>
-
- #include <jni.h>
-
- #include <string>
- #include <vector>
-
- // ncnn
- #include "net.h"
-
- #include "squeezenet_v1.1.id.h"
-
- #include <sys/time.h>
- #include <unistd.h>
-
- static struct timeval tv_begin;
- static struct timeval tv_end;
- static double elasped;
-
- static void bench_start()
- {
- gettimeofday(&tv_begin, NULL);
- }
-
- static void bench_end(const char* comment)
- {
- gettimeofday(&tv_end, NULL);
- elasped = ((tv_end.tv_sec - tv_begin.tv_sec) * 1000000.0f + tv_end.tv_usec - tv_begin.tv_usec) / 1000.0f;
- // fprintf(stderr, "%.2fms %s\n", elasped, comment);
- __android_log_print(ANDROID_LOG_DEBUG, "SqueezeNcnn", "%.2fms %s", elasped, comment);
- }
-
- static ncnn::UnlockedPoolAllocator g_blob_pool_allocator;
- static ncnn::PoolAllocator g_workspace_pool_allocator;
-
- static ncnn::Mat squeezenet_param;
- static ncnn::Mat squeezenet_bin;
- static std::vector<std::string> squeezenet_words;
- static ncnn::Net squeezenet;
-
- static std::vector<std::string> split_string(const std::string& str, const std::string& delimiter)
- {
- std::vector<std::string> strings;
-
- std::string::size_type pos = 0;
- std::string::size_type prev = 0;
- while ((pos = str.find(delimiter, prev)) != std::string::npos)
- {
- strings.push_back(str.substr(prev, pos - prev));
- prev = pos + 1;
- }
-
- // To get the last substring (or only, if delimiter is not found)
- strings.push_back(str.substr(prev));
-
- return strings;
- }
-
- extern "C" {
-
- JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
- {
- __android_log_print(ANDROID_LOG_DEBUG, "SqueezeNcnn", "JNI_OnLoad");
-
- ncnn::create_gpu_instance();
-
- return JNI_VERSION_1_4;
- }
-
- JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved)
- {
- __android_log_print(ANDROID_LOG_DEBUG, "SqueezeNcnn", "JNI_OnUnload");
-
- ncnn::destroy_gpu_instance();
- }
-
- // public native boolean Init(byte[] param, byte[] bin, byte[] words);
- JNIEXPORT jboolean JNICALL Java_com_tencent_squeezencnn_SqueezeNcnn_Init(JNIEnv* env, jobject thiz, jbyteArray param, jbyteArray bin, jbyteArray words)
- {
- // use vulkan compute
- if (ncnn::get_gpu_count() != 0)
- squeezenet.use_vulkan_compute = 1;
-
- // init param
- {
- int len = env->GetArrayLength(param);
- squeezenet_param.create(len, (size_t)1u);
- env->GetByteArrayRegion(param, 0, len, (jbyte*)squeezenet_param);
- int ret = squeezenet.load_param((const unsigned char*)squeezenet_param);
- __android_log_print(ANDROID_LOG_DEBUG, "SqueezeNcnn", "load_param %d %d", ret, len);
- }
-
- // init bin
- {
- int len = env->GetArrayLength(bin);
- squeezenet_bin.create(len, (size_t)1u);
- env->GetByteArrayRegion(bin, 0, len, (jbyte*)squeezenet_bin);
- int ret = squeezenet.load_model((const unsigned char*)squeezenet_bin);
- __android_log_print(ANDROID_LOG_DEBUG, "SqueezeNcnn", "load_model %d %d", ret, len);
- }
-
- // init words
- {
- int len = env->GetArrayLength(words);
- std::string words_buffer;
- words_buffer.resize(len);
- env->GetByteArrayRegion(words, 0, len, (jbyte*)words_buffer.data());
- squeezenet_words = split_string(words_buffer, "\n");
- }
-
- ncnn::Option opt;
- opt.lightmode = true;
- opt.num_threads = 4;
- opt.blob_allocator = &g_blob_pool_allocator;
- opt.workspace_allocator = &g_workspace_pool_allocator;
-
- ncnn::set_default_option(opt);
-
- return JNI_TRUE;
- }
-
- // public native String Detect(Bitmap bitmap, boolean use_gpu);
- JNIEXPORT jstring JNICALL Java_com_tencent_squeezencnn_SqueezeNcnn_Detect(JNIEnv* env, jobject thiz, jobject bitmap, jboolean use_gpu)
- {
- if (use_gpu == JNI_TRUE && ncnn::get_gpu_count() == 0)
- {
- return env->NewStringUTF("no vulkan capable gpu");
- }
-
- bench_start();
-
- // ncnn from bitmap
- ncnn::Mat in;
- {
- AndroidBitmapInfo info;
- AndroidBitmap_getInfo(env, bitmap, &info);
- int width = info.width;
- int height = info.height;
- if (width != 227 || height != 227)
- return NULL;
- if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888)
- return NULL;
-
- void* indata;
- AndroidBitmap_lockPixels(env, bitmap, &indata);
-
- in = ncnn::Mat::from_pixels((const unsigned char*)indata, ncnn::Mat::PIXEL_RGBA2BGR, width, height);
-
- AndroidBitmap_unlockPixels(env, bitmap);
- }
-
- // squeezenet
- std::vector<float> cls_scores;
- {
- const float mean_vals[3] = {104.f, 117.f, 123.f};
- in.substract_mean_normalize(mean_vals, 0);
-
- ncnn::Extractor ex = squeezenet.create_extractor();
-
- ex.set_vulkan_compute(use_gpu);
-
- ex.input(squeezenet_v1_1_param_id::BLOB_data, in);
-
- ncnn::Mat out;
- ex.extract(squeezenet_v1_1_param_id::BLOB_prob, out);
-
- cls_scores.resize(out.w);
- for (int j=0; j<out.w; j++)
- {
- cls_scores[j] = out[j];
- }
- }
-
- // return top class
- int top_class = 0;
- float max_score = 0.f;
- for (size_t i=0; i<cls_scores.size(); i++)
- {
- float s = cls_scores[i];
- // __android_log_print(ANDROID_LOG_DEBUG, "SqueezeNcnn", "%d %f", i, s);
- if (s > max_score)
- {
- top_class = i;
- max_score = s;
- }
- }
-
- const std::string& word = squeezenet_words[top_class];
- char tmp[32];
- sprintf(tmp, "%.3f", max_score);
- std::string result_str = std::string(word.c_str() + 10) + " = " + tmp;
-
- // +10 to skip leading n03179701
- jstring result = env->NewStringUTF(result_str.c_str());
-
- bench_end("detect");
-
- return result;
- }
-
- }
|