Android tflite BuildFromFile() 从资产文件夹读取本机文件

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

我有 Android 本机代码(C++ 共享对象),希望在创建 APK 时将 read 模型文件保存在 assets 文件夹中。

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);

使用以下代码我可以访问 FromBuffer:

Java代码:

private AssetManager mgr;

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

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);

任何想法,如何访问 assets 文件夹以使用 BuildFromFile

我觉得不把asset文件复制到本地文件就不能用BuildFromFile(相当于你上面做的,然后BuildFromBuffer更方便这种情况)。

如果你想避免内存复制,你可以这样做:

  1. (Java) 通过内存映射加载模型。
    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) 把映射文件通过jni传递给C++,比如定义如下方法:
    private static native void initJniWithByteBuffer(ByteBuffer modelBuffer)
  1. (C++) 使用缓冲文件初始化模型:
    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));\
    }