简体   繁体   English

Android 本机文件通过 tflite BuildFromFile() 从 assets 文件夹中读取

[英]Android native file read from assets folder by tflite BuildFromFile()

I have Android native code ( C++ shared object), that want to read model file kept in the assets folder while creating APK.我有 Android 本机代码( C++共享对象),想在创建 APK 时read保存在assets文件夹中的 model 文件。

Tensorflow Lite has two APIs: FromFile and FromBuffer Tensorflow Lite 有两个 API:FromFile 和 FromBuffer

static std::unique_ptr<FlatBufferModel> BuildFromFile(const char* filename, ErrorReporter* error_reporter);

static std::unique_ptr<FlatBufferModel> BuildFromBuffer(const char* buffer, size_t buffer_size, ErrorReporter* error_reporter);

with following code i can access FromBuffer:使用以下代码,我可以访问 FromBuffer:

Java code: Java代码:

private AssetManager mgr;

// Get mgr 
mgr = getResources().getAssets();

C++ code: C++代码:

AAssetDir* assetDir = AAssetManager_openDir(mgr, "");
const char* filename = (const char*)NULL;
while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL) {
    AAsset* asset = AAssetManager_open(mgr, filename, AASSET_MODE_STREAMING);
    char buf[BUFSIZ];
    int nb_read = 0;
    FILE* out = fopen(filename, "w");
    while ((nb_read = AAsset_read(asset, buf, BUFSIZ)) > 0)
        fwrite(buf, nb_read, 1, out);
    fclose(out);
    AAsset_close(asset);
}
AAssetDir_close(assetDir);

Any ideas, how can access assets folder to use BuildFromFile ?任何想法,如何访问assets文件夹以使用BuildFromFile

I don't think you can use BuildFromFile without copying the asset file to a local file (which is equivalent to what you've done above, and then BuildFromBuffer is more convenient in this case).我不认为你可以使用BuildFromFile而不将资产文件复制到本地文件(这相当于你上面所做的,然后BuildFromBuffer在这种情况下更方便)。

If you want to avoid memory copy, here is what you can do:如果您想避免 memory 复制,您可以执行以下操作:

  1. (Java) Load the model through memory mapping. (Java) 通过 memory 映射加载 model。
    AssetFileDescriptor fileDescriptor = getResources().getAssets().openFd(filePath);\
    FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());\
    FileChannel fileChannel = inputStream.getChannel();\
    long startOffset = fileDescriptor.getStartOffset();\
    long declaredLength = fileDescriptor.getDeclaredLength();\
    MappedByteBuffer modelBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
  1. (Java) Pass the mapped file to C++ through jni, such as defining the following method: (Java)通过jni将映射文件传递给C++,比如定义如下方法:
    private static native void initJniWithByteBuffer(ByteBuffer modelBuffer)
  1. (C++) Use the buffer file to initialize you model: (C++) 使用缓冲文件初始化 model:
    Java_xxxxxx_initJniWithByteBuffer(JNIEnv* env, jclass thiz, jobject model_buffer) {\
      char* buffer = static_cast<char*>(env->GetDirectBufferAddress(model_buffer));\
      size_t buffer_size = static_cast<size_t>(env->GetDirectBufferCapacity(model_buffer));\
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM