基本思想:使用Android ndk交叉编译一下mnn,然后移植一下Swin_Transformer识别代码到Android 手机上

一、首先搭建交叉编译环境 1、Android 移植C++ 开发的第三方.so包和.a包_sxj731533730-CSDN博客_android c++,然后使用Android ndk交叉编译mnn.主要参考手册推理框架Android编译 · 语雀

我先配置一下openGL

sudo apt-get install build-essential libgl1-mesa-dev
sudo apt-get install freeglut3-dev
sudo apt-get install libglew-dev libsdl2-dev libsdl2-image-dev libglm-dev libfreetype6-dev

cmakelist.txt

cmake_minimum_required(VERSION 3.16)
project(untitled)set(CMAKE_CXX_STANDARD 11)
set(TARGET_LIB"/usr/lib/x86_64-linux-gnu/libGL.so""/usr/lib/x86_64-linux-gnu/libGLU.so""/usr/lib/x86_64-linux-gnu/libglut.so")add_executable(untitled main.cpp)
target_link_libraries(untitled ${TARGET_LIB} )

clion测试一下

#include <GL/glut.h>void init(void)
{glClearColor(0.0, 0.0, 0.0, 0.0);glMatrixMode(GL_PROJECTION);glOrtho(-5, 5, -5, 5, 5, 15);glMatrixMode(GL_MODELVIEW);gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);return;
}void display(void)
{glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 0, 0);glutWireTeapot(3);glFlush();return;
}int main(int argc, char *argv[])
{glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);glutInitWindowPosition(0, 0);glutInitWindowSize(300, 300);glutCreateWindow("OpenGL 3D View");init();glutDisplayFunc(display);glutMainLoop();return 0;
}
//网上的测试代码

测试结果

二、MNN交叉编译Android的静态库

#!/bin/bash
./schema/generate.sh
export ANDROID_NDK=/usr/local/android-ndk-r21e/
rm -rf sx731533730
mkdir sx731533730
cd sx731533730function build_android
{mkdir $PREFIX
cd $PREFIX
cmake ../../../ -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DCMAKE_BUILD_TYPE=Release \
-DANDROID_ABI=$ABI -DANDROID_STL=c++_static -DCMAKE_BUILD_TYPE=Release -DANDROID_NATIVE_API_LEVEL=android-21 \
-DANDROID_TOOLCHAIN=clang -DMNN_USE_LOGCAT=ON -DMNN_SEP_BUILD=OFF -DMNN_BUILD_FOR_ANDROID_COMMAND=ON -DNATIVE_LIBRARY_OUTPUT=. \
-DNATIVE_INCLUDE_OUTPUT=. -DMNN_VULKAN=ON -DMNN_OPENCL=ON -DMNN_USE_THREAD_POOL=ON -DMNN_BUILD_SHARED_LIBS=OFF \
-DMNN_BUILD_CONVERTER=OFF $EXTRCMAKEFLAG ../../
make -j4
cd ..
}#armeabi-v7a
PREFIX=armeabi-v7a
ABI="armeabi-v7a"
EXTRCMAKEFLAG=-DMNN_ARM82=ON
build_android#arm64-v8a
PREFIX=arm64-v8a
ABI="arm64-v8a"
EXTRCMAKEFLAG=-DMNN_ARM82=ON
build_android#x86
PREFIX=x86
ABI="x86"
EXTRCMAKEFLAG=-DMNN_USE_SSE=OFF
build_android#x86_64
PREFIX=x86_64
ABI="x86_64"
EXTRCMAKEFLAG=-DMNN_USE_SSE=OFF
build_android

(1)然后先用简单的 Android Studio工程测试一下,贴一下核心代码结构,因为模型太大了388MB我使用转换工具做了f16预处理

MainActivity.java内容

package com.example.myapplication;import androidx.appcompat.app.AppCompatActivity;import android.content.Context;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;import com.example.myapplication.databinding.ActivityMainBinding;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;public class MainActivity extends AppCompatActivity {// Used to load the 'myapplication' library on application startup.static {System.loadLibrary("myapplication");}private ActivityMainBinding binding;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);binding = ActivityMainBinding.inflate(getLayoutInflater());setContentView(binding.getRoot());// Example of a call to a native methodTextView tv = binding.sampleText;String modelName="model-87_384_sim_fp16.mnn";copyModelFromAssetsToData(modelName);String path = this.getFilesDir() + File.separator;tv.setText(stringFromJNI(modelName, path));}protected void copyModelFromAssetsToData(String modelName) {Toast.makeText(this, "Copy model to data...", Toast.LENGTH_SHORT).show();try {copyAssetFileToFiles(this, modelName);Toast.makeText(this, "Copy model Success", Toast.LENGTH_SHORT).show();} catch (Exception e) {e.printStackTrace();Toast.makeText(this, "Copy model Error", Toast.LENGTH_SHORT).show();}}public void copyAssetFileToFiles(Context context, String filename) throws IOException {InputStream is = context.getAssets().open(filename);byte[] buffer = new byte[is.available()];is.read(buffer);is.close();File of = new File(context.getFilesDir() + File.separator + filename);of.createNewFile();FileOutputStream os = new FileOutputStream(of);os.write(buffer);os.close();}/*** A native method that is implemented by the 'myapplication' native library,* which is packaged with this application.*/public native String stringFromJNI(String name, String path);
}

cmakelists.txt内容 其中MNN的动态库配置方式参考https://github.com/alibaba/MNN/issues/698

# 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.18.1)# Declares and names the project.project("myapplication")# 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.add_library( # Sets the name of the library.myapplication# Sets the library as a shared library.SHARED# Provides a relative path to your source file(s).native-lib.cpp)# 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.
include_directories(${CMAKE_SOURCE_DIR}/include)
add_library(libMNN STATIC IMPORTED)
set_target_properties(libMNN PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/libs/mnn/${ANDROID_ABI}/libMNN.a)target_link_libraries( # Specifies the target library.myapplication-Wl,--whole-archivelibMNN-Wl,--no-whole-archivez m# Links the target library to the log library# included in the NDK.${log-lib})

文件结构

内容一

sourceSets{main{jniLibs.srcDirs=["src/main/jniLibs/libs"]}
}

内容二

  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.CAMERA" />

(2)、测试代码使用37、记录使用 Swin Transformer主干网络去实现分类,并转化NCNN、TNN、MNN模型以及部署_sxj731533730-CSDN博客

native-lib.cpp内容

#include <jni.h>
#include <string>
#include <iostream>
#include<MNN/Interpreter.hpp>
#include<MNN/ImageProcess.hpp>
using namespace std;
using namespace MNN;
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_stringFromJNI(JNIEnv* env,jobject /* this */,jstring name, jstring path) {const char *pathTemp = env->GetStringUTFChars(path, 0);std::string modelPath = pathTemp;if (modelPath.empty()) {return env->NewStringUTF("modelPath.empty()");}modelPath = modelPath + env->GetStringUTFChars(name, 0);auto net = std::shared_ptr<MNN::Interpreter>(MNN::Interpreter::createFromFile(modelPath.c_str()));//创建解释器if (net==NULL) {return env->NewStringUTF("net=null");}cout << "Interpreter created" << endl;ScheduleConfig config;config.numThread = 8;config.type = MNN_FORWARD_CPU;auto session = net->createSession(config);//创建sessioncout << "session created" << endl;auto inTensor = net->getSessionInput(session, NULL);auto outTensor = net->getSessionInput(session, NULL);auto _Tensor = MNN::Tensor::create<float>(inTensor->shape(), NULL, MNN::Tensor::CAFFE);for (int i = 0; i < _Tensor->elementSize(); i++) {_Tensor->host<float>()[i] = 1.f;}inTensor->copyFromHostTensor(_Tensor);//推理net->runSession(session);auto output= net->getSessionOutput(session, NULL);
//    MNN::Tensor feat_tensor(output, output->getDimensionType());
//    output->copyToHostTensor(&feat_tensor);
//    feat_tensor.print();MNN::Tensor score_host(output, output->getDimensionType());output->copyToHostTensor(&score_host);auto score_ptr = score_host.host<float>();std::vector<std::pair<float, int>> scores;std::string strNum;char strff[20];for (int i = 0; i < score_host.elementSize(); ++i) {float score = score_ptr[i];if(i%5!=0||i==0){sprintf(strff,"%.5f",score);strNum=strNum+strff+",";std::cout<<score<<" ,";}else {sprintf(strff,"%.5f",score);strNum=strNum+strff+'\n';std::cout<<score<<std::endl;}}return env->NewStringUTF(strNum.c_str());
}

上篇博客的测试数据为

/home/ubuntu/CLionProjects/untitled8/cmake-build-debug/untitled8
Interpreter created
session created
1.02862 ,0.0331715 ,1.20148 ,0.465368 ,0.0783655 ,0.325653
0.266529 ,0.626484 ,-1.99896 ,1.51479 ,-1.55074
-1.02167 ,1.86536 ,-0.728646 ,-0.827346 ,2.82286
2.03924 ,-1.62345 ,-0.837316 ,1.10834 ,0.417171
0.095808 ,0.550832 ,-2.34458 ,0.325013 ,1.9003
0.0731261 ,-0.608058 ,-0.915578 ,0.458301 ,-0.446057
-0.618133 ,0.0880814 ,-1.09998 ,-0.081489 ,-1.22944
0.223052 ,-1.53983 ,-2.24254 ,-0.0980031 ,
Process finished with exit code 0

Android Studio的测试数据

三、然后找个Android Studio 的工程套一下分类模型,改了一下nihui大佬的ncnn-android-yolov5的android 代码,简单贴一下目录结构,代码就不详细贴了

同一张图片比对一下之前的c++输出结果

/home/ubuntu/CLionProjects/untitled3/cmake-build-debug/untitled3
input shape: 1 3 384 384
-1.17208 ,2.52835 ,-1.13784 ,-2.74679 ,-2.28598 ,-2.38782
-7.82185 ,-1.41909 ,-0.53293 ,-4.01217 ,-1.37053
-3.64631 ,-3.05637 ,-2.51102 ,-2.03677 ,-3.42727
-5.13564 ,-5.57135 ,4.7276 ,-3.82109 ,8.2626
-1.66725 ,-0.328283 ,-0.436888 ,0.755527 ,-4.28481
-1.9745 ,-1.26475 ,0.0837912 ,4.7725 ,5.81344
6.51513 ,1.04599 ,1.24563 ,-6.4404 ,-2.84359
14.6626 ,-1.82606 ,-5.77536 ,-4.29771 ,
cls id: 36
cls prob: 0.9978Process finished with exit code 0

android的测试代码我就不放了,测试结果是正确的

2022-02-12 18:18:58.134 30830-30830/com.alibaba.swintransformer D/ViewRootImpl[MainActivity]: dispatchPointerEvent handled=true, event=MotionEvent { action=ACTION_UP, actionButton=0, id[0]=0, x[0]=229.0, y[0]=228.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=62003046, downTime=62002928, deviceId=4, source=0x1002, displayId=0 }
2022-02-12 18:18:58.137 30830-30830/com.alibaba.swintransformer W/swintransformer: type=1400 audit(0.0:1245866): avc: denied { read } for scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:r:runas_app:s0:c512,c768 tclass=file permissive=0 app=com.alibaba.swintransformer
2022-02-12 18:18:59.514 30830-31338/com.alibaba.swintransformer I/swintransforme: ProcessProfilingInfo new_methods=15 is saved saved_to_disk=1 resolve_classes_delay=5000
2022-02-12 18:19:03.371 30830-30830/com.alibaba.swintransformer D/mnn:
-1.17328 ,2.53281 ,-1.14063 ,-2.75316 ,-2.28988 ,
-2.37191 ,-7.83151 ,-1.41509 ,-0.53346 ,-4.01221 ,
-1.37433 ,-3.65032 ,-3.05081 ,-2.51321 ,-2.03674 ,
-3.44181 ,-5.14033 ,-5.57892 ,4.72800 ,-3.83233 ,
8.26629 ,-1.67465 ,-0.32949 ,-0.44187 ,0.75479 ,
-4.28030 ,-1.96979 ,-1.26815 ,0.08604 ,4.78337 ,
5.82265 ,6.52026 ,1.05145 ,1.23829 ,-6.44228 ,
-2.84473 ,14.66623 ,-1.83968 ,-5.77831 ,-4.29981 ,

放个swimtransformer_jni.cpp 写的仓促 不优化了

#include <android/asset_manager.h>
#include <android/log.h>
#include <iostream>
#include<opencv2/core.hpp>
#include<opencv2/imgproc.hpp>
#include<opencv2/highgui.hpp>
#include<MNN/Interpreter.hpp>
#include<MNN/ImageProcess.hpp>
#include <jni.h>#include <android/asset_manager_jni.h>
#include <android/bitmap.h>
#include <android/log.h>#include <jni.h>#include <string>
#include <vector>
#include <numeric>
#include<list>
using namespace std;
using namespace cv;
using namespace MNN;#define IMAGE_SIZE 384
#define TOPK 5struct swimStruct {const char *label;double prob;
};std::list<swimStruct> listSwim;std::shared_ptr<Interpreter> net = nullptr;
MNN::Session *session = nullptr;
MNN::Tensor *inTensor = nullptr;
MNN::Tensor *outTensor = nullptr;
MNN::Tensor *_Tensor = nullptr;
template<typename T>
std::vector<unsigned int> argsort(const std::vector<T> &arr)
{if (arr.empty()) return {};const unsigned int _size = arr.size();std::vector<unsigned int> indices;for (unsigned int i = 0; i < _size; ++i) indices.push_back(i);std::sort(indices.begin(), indices.end(),[&arr](const unsigned int a, const unsigned int b){ return arr[a] > arr[b]; });return indices;
}double myfunction(double num) {return exp(num);
}template <typename T>
void softmax(const typename::std::vector<T> &v, typename::std::vector<T> &s){double sum=0.0;transform(v.begin(), v.end(), s.begin(), myfunction);sum=accumulate(s.begin(), s.end(), sum);for(size_t i=0; i<s.size(); ++i)s.at(i)/=sum;
}
extern "C" {
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {__android_log_print(ANDROID_LOG_DEBUG, "mnn", "JNI_OnLoad");return JNI_VERSION_1_4;
}JNIEXPORT void JNI_OnUnload(JavaVM *vm, void *reserved) {__android_log_print(ANDROID_LOG_DEBUG, "mnn", "JNI_OnUnload");}// public native boolean Init(AssetManager mgr);
JNIEXPORT jboolean JNICALL
Java_com_alibaba_swintransformer_SwimTransformer_Init(JNIEnv *env, jobject thiz, jstring name,jstring path,jboolean use_gpu) {const char *pathTemp = env->GetStringUTFChars(path, 0);std::string modelPath = pathTemp;if (modelPath.empty()) {__android_log_print(ANDROID_LOG_ERROR, "mnn", "modelPath.empty()");return JNI_FALSE;}modelPath = modelPath + env->GetStringUTFChars(name, 0);net = std::shared_ptr<MNN::Interpreter>(MNN::Interpreter::createFromFile(modelPath.c_str()));//创建解释器if (net == nullptr) {__android_log_print(ANDROID_LOG_ERROR, "mnn", "net is nullptr");return JNI_FALSE;}ScheduleConfig config;config.numThread = 8;config.type = MNN_FORWARD_CPU;if (use_gpu) {config.type = MNN_FORWARD_OPENCL;}MNN::BackendConfig backendConfig;// 3. 后端配置int precision  = 2;int power      = 0;int memory     = 0;// memory、power、precision分别为内存、功耗和精度偏好backendConfig.precision = (MNN::BackendConfig::PrecisionMode)precision;backendConfig.power = (MNN::BackendConfig::PowerMode) power;backendConfig.memory = (MNN::BackendConfig::MemoryMode) memory;config.backendConfig = &backendConfig;session = net->createSession(config);//创建sessionif (session == nullptr) {__android_log_print(ANDROID_LOG_ERROR, "mnn", "session is nullptr");return JNI_FALSE;}inTensor = net->getSessionInput(session, NULL);outTensor = net->getSessionInput(session, NULL);_Tensor = MNN::Tensor::create<float>({1, 3, IMAGE_SIZE, IMAGE_SIZE}, NULL, MNN::Tensor::CAFFE);if (_Tensor->elementSize() != 3 * IMAGE_SIZE * IMAGE_SIZE) {__android_log_print(ANDROID_LOG_ERROR, "mnn", "input shape not equal image shape");return JNI_FALSE;}__android_log_print(ANDROID_LOG_DEBUG, "mnn", "Interpreter created");return JNI_TRUE;
}// public native Obj[] Detect(Bitmap bitmap, boolean use_gpu);
JNIEXPORT jobject  JNICALL
Java_com_alibaba_swintransformer_SwimTransformer_Detect(JNIEnv *env, jobject thiz, jobject bitmap) {swimStruct swimItem;listSwim.clear(); //进行预处理和释空间std::list<swimStruct>().swap(listSwim);AndroidBitmapInfo inBmpInfo;void *inPixelsAddress;int ret;if ((ret = AndroidBitmap_getInfo(env, bitmap, &inBmpInfo)) < 0) {__android_log_print(ANDROID_LOG_ERROR, "mnn", "%d",ret);return NULL;}if ((ret = AndroidBitmap_lockPixels(env, bitmap, &inPixelsAddress)) < 0) {__android_log_print(ANDROID_LOG_ERROR, "mnn", "%d",ret);return NULL;}Mat rgbaImage;rgbaImage.create(inBmpInfo.height, inBmpInfo.width, CV_8UC4);Mat inMat(inBmpInfo.height, inBmpInfo.width, CV_8UC4, inPixelsAddress);cvtColor(inMat, rgbaImage, COLOR_mRGBA2RGBA);Mat frame;frame.create(inBmpInfo.height, inBmpInfo.width, CV_8UC3);cvtColor(rgbaImage, frame, COLOR_RGBA2BGR);Mat img_src = frame;std::vector<float> meanVals = {(1.0f / 0.229f) * (1.0 / 255.f),(1.0f / 0.224f) * (1.0 / 255.f),(1.0f / 0.225f) * (1.0 / 255.f)};std::vector<float> normVals = {-0.485f * 255.f * (1.0f / 0.229f) * (1.0 / 255.f),-0.456f * 255.f * (1.0f / 0.224f) * (1.0 / 255.f),-0.406f * 255.f * (1.0f / 0.225f) * (1.0 / 255.f)};cv::Mat img_resized;cv::resize(img_src.clone(), img_resized, cv::Size(IMAGE_SIZE, IMAGE_SIZE), cv::INTER_LINEAR);cv::Mat img_color;cv::cvtColor(img_resized, img_color, COLOR_BGR2RGB);std::vector<cv::Mat> rgbChannels(3);cv::split(img_color, rgbChannels);for (auto i = 0; i < rgbChannels.size(); i++) {rgbChannels[i].convertTo(rgbChannels[i], CV_32FC1, meanVals[i], normVals[i]);for (int j = 0; j < rgbChannels[i].rows; j++) {for (int k = 0; k < rgbChannels[i].cols; k++) {_Tensor->host<float>()[i * IMAGE_SIZE * IMAGE_SIZE + j * IMAGE_SIZE +k] = rgbChannels[i].at<float>(j, k);}}}inTensor->copyFromHostTensor(_Tensor);//推理net->runSession(session);auto output = net->getSessionOutput(session, nullptr);if(output== nullptr){__android_log_print(ANDROID_LOG_ERROR, "mnn", "output==nullptr,");return nullptr;}MNN::Tensor score_host(output, output->getDimensionType());output->copyToHostTensor(&score_host);auto score_ptr = score_host.host<float>();std::vector<std::pair<float, int>> scores;std::vector<float> vec_score,vec_softmax;// 等有时间查看一下mnn 如何自定义层for (int i = 0; i < score_host.elementSize(); ++i) {float score = score_ptr[i];vec_score.push_back(score);vec_softmax.push_back(score);// __android_log_print(ANDROID_LOG_DEBUG, "mnn", "%f ",score);}softmax(vec_score,vec_softmax);std::vector<unsigned int> sorted_indices = argsort<float>(vec_softmax);const char *class_names[40]={ "H_Dry cell","H_Expired drugs","H_ointment","K_Big bone","K_Fishbone","K_Fruit peel","K_Fruit pulp","K_Leaves edible orange roots","K_Tea leaves","K_The shell","K_leftovers","O_Broken flowerpots and dishes","O_Cigarette butts","O_Disposable snack box","O_Stained plastic","O_chopstick","O_toothpick","R_Charging treasure","R_Cosmetics bottles","R_Courier bags","R_Edible oil drum","R_Leather shoes","R_Metal food can","R_Old clothes","R_Plastic bowl tub","R_Plastic hangers","R_Plastic toys","R_Plug wire","R_Plush toys","R_Shampoo bottle","R_Spice bottles","R_The bottle","R_The glass","R_cans","R_carton","R_cutting board","R_drink bottle","R_package","R_pan","R_pillow"};for (unsigned int i = 0; i < TOPK; ++i){__android_log_print(ANDROID_LOG_DEBUG, "mnn", " sorted_indices[i]=%d ", sorted_indices[i]);__android_log_print(ANDROID_LOG_DEBUG, "mnn", "scores[sorted_indices[i]]=%f ",vec_softmax[sorted_indices[i]]);__android_log_print(ANDROID_LOG_DEBUG, "mnn", "class_names[sorted_indices[i]]=%s ",class_names[sorted_indices[i]]);swimItem.prob = vec_softmax[sorted_indices[i]];swimItem.label = class_names[sorted_indices[i]];listSwim.push_back(swimItem);}AndroidBitmap_unlockPixels(env, bitmap);rgbaImage.release();frame.release();// 1. 模拟原C++代码中的结构体//获取ArrayList类引用jclass list_jcs = env->FindClass("java/util/ArrayList");if (list_jcs == NULL) {printf("%s\n", "ArrayList no  find!");return NULL;}//获取ArrayList构造函数, 函数名为 <init> 返回类型必须为 void 即 VjmethodID list_init = env->GetMethodID(list_jcs, "<init>", "()V");//创建一个ArrayList对象jobject list_obj = env->NewObject(list_jcs, list_init, "");//获取ArrayList对象的add()的methodIDjmethodID list_add = env->GetMethodID(list_jcs, "add", "(Ljava/lang/Object;)Z");//获取Path类jclass detectClass = env->FindClass("com/alibaba/swintransformer/SwimTransformerItem");if (detectClass == NULL) {printf("%s\n", "detectYoloClass Class not find!");return NULL;}//获取Path的构造函数jmethodID detectYoloConstruct = env->GetMethodID(detectClass, "<init>","(Ljava/lang/String;D)V");  //括号里为签名见下图if (detectYoloConstruct == NULL) {printf("%s\n", "detectYoloConstruct init not find!");return NULL;}for (std::list<swimStruct>::iterator detectObject = listSwim.begin();detectObject != listSwim.end(); detectObject++) {//通过Path的构造函数创建Path对象const char *name = detectObject->label;double confidence = detectObject->prob;jobject path_obj = env->NewObject(detectClass,detectYoloConstruct,env->NewStringUTF(name),confidence);env->CallBooleanMethod(list_obj, list_add, path_obj);}return list_obj;
}}

测试结果

D/mnn:  sorted_indices[i]=36
D/mnn: scores[sorted_indices[i]]=0.997798
D/mnn: class_names[sorted_indices[i]]=R_drink bottle
D/mnn:  sorted_indices[i]=20
D/mnn: scores[sorted_indices[i]]=0.001658
D/mnn: class_names[sorted_indices[i]]=R_Edible oil drum
D/mnn:  sorted_indices[i]=31
D/mnn: scores[sorted_indices[i]]=0.000289
D/mnn: class_names[sorted_indices[i]]=R_The bottle
D/mnn:  sorted_indices[i]=30
D/mnn: scores[sorted_indices[i]]=0.000144
D/mnn: class_names[sorted_indices[i]]=R_Spice bottles
D/mnn:  sorted_indices[i]=29
D/mnn: scores[sorted_indices[i]]=0.000051
D/mnn: class_names[sorted_indices[i]]=R_Shampoo bottle 

测试图 有点迷 为啥cl比没有cl耗时长~

更新一版

MNN库自己编译导入吧

github:https://github.com/sxj731533730/swintransformer.git

参考链接

https://www.yuque.com/mnn/cn/tool_test#HwH00

https://github.com/alibaba/MNN/issues/698

https://github.com/nihui/ncnn-android-yolov5

https://github.com/nihui/opencv-mobile

https://github.com/cmdbug/MNN_Demo

8、Android Studio 使用MNN进行Swin_Transformer分类识别相关推荐

  1. android studio 简单二维码扫描识别代码

    使用android studio 生成 扫描二维码app,简单粗暴好用 自己白天找了一上午代码也没找到 ,然后用了个github包 写了个简单的 下面上图 首先使用android studio创建一个 ...

  2. Android Studio编写一个手写字体识别程序

    1.activity_main.xml 的代码 <?xml version="1.0" encoding="utf-8"?> <LinearL ...

  3. 超详细教程:Android Studio搭建一个与百度AI识别接口连接的Activity,用来识别植物

    最近做了一个小项目,想要搭建一个能够进行图像识别的安卓APP,一路上也碰了不少坑,就在这里写一篇博客,希望萌新们也少踩坑里,也值得我以后再回来看看复习一下. 1.声明权限 <uses-permi ...

  4. android studio怎么添加按钮,Android Studio 工具栏添加常用按钮

    本文中 Android Studio 的版本为 android Studio 2.2 ,操作系统为 Windows,如有操作不同,可能是版本差异. 在工具栏中添加一些常用的按钮,如设置.DDMS,有利 ...

  5. Android Studio 无法识别MuMu模拟器、夜神模拟器的解决办法

    Android studio自带的模拟器在很多场景下不是非常好用,而且很多时候需要设置CPU.开启虚拟化等等.很多Android 开发人员喜欢使用.也有不少人使用MuMu模拟器.夜神模拟器等第三方模拟 ...

  6. 入门Mac快捷键详细分类整理,包括Eclipse和Android Studio中一些常用的快捷键

    [通用] control(^) shift(⇧)   ⬆️ option/alt (⌥) command(⌘) fn 副功能键 [效率] 1.编辑 control + space 切换输入法(改键:a ...

  7. 安卓Android Studio布局文件分类存放,java文件分类存放

    备注:此备注将会存在本人的每一条博客,将会定期更改 1.使用的软件是Android studio 版本是3.5 当项目比较大的时候文件很多很复杂,这个时候就可以把一些布局文件进行归类存放 问题是我们自 ...

  8. 《ArcGIS Runtime SDK for Android开发笔记》——(6)、基于Android Studio的ArcGIS Android工程结构解析...

    1.前言 Android Studio 是第一个Google官方的 Android 开发环境.其他工具,例如 Eclipse,在 Android Studio 发布之前已经有了大规模的使用.为了帮助开 ...

  9. 将Eclipse代码导入到Android Studio的两种方式

    转: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0104/2259.html 说到使用Android Studio,除了新建 ...

最新文章

  1. SSH putty Disconnected: Server protocol violation: unexpected SSH2_MSG_UNIMPLEMENTED packet
  2. Cow Line(洛谷-P3014)
  3. Visual Studio 2019 16.2.2 发布
  4. 搜索、推荐、广告中的曝光偏差问题
  5. ubuntu mysql 5.7 出错_ubuntu mysql5.7 启动提示错误:/var/run/mysqld/mysqld.sock
  6. tensorflow2 搭建LeNet5训练MINST手写数字数据集并用c++ opencv4.5.5 DNN加载模型预测结果
  7. c语言电脑写程序的软件,c语言编程软件下载电脑版
  8. 【洞察】152号令,重量级行业信息技术法规
  9. 分布式系统互斥算法---令牌环算法
  10. 03.整体管理+变更管理
  11. 20220606 关于矩阵的Young不等式
  12. 远程控制工具哪个好?向日葵VS ToDesk,安卓移动设备远程操控哪个更好用?
  13. it民工的华丽亦或是失败的转型(一)
  14. Hadoop Java对应版本号
  15. openGL glColor3f函数颜色
  16. Kong Dashboard系列【三】添加插件----rate-limiting
  17. 面试常问问题: 剖析ArrayList源码还不会? 看这篇就够啦 !
  18. Windows 远程桌面复制问题
  19. {转发}尚硅谷资料集锦
  20. 网友评价 iPhone 8:大爱玻璃后壳、True Tone 屏幕

热门文章

  1. MaxEnt分析流程和推荐的分析内容
  2. java计算机毕业设计实验室耗材管理系统源程序+mysql+系统+lw文档+远程调试
  3. 收集了几个有趣的代码注释
  4. autorecover mac的ppt_Office for Mac快捷键之苹果PowerPoint幻灯片PPT篇
  5. Android 源码分享之小米文件管理器
  6. 爬虫之爬取英雄联盟战绩详细数据
  7. 什么是同类群组联合学习 (FLoC)?
  8. PCI GXL学习之再造篇
  9. 未转变者rust服务器推荐,你能在这些最佳生存游戏中活多久?
  10. VMware vSphere 服务器虚拟化部署安装图解