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
更方便这种情况)。
如果你想避免内存复制,你可以这样做:
- (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);
- (Java) 把映射文件通过jni传递给C++,比如定义如下方法:
private static native void initJniWithByteBuffer(ByteBuffer modelBuffer)
- (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));\
}
我有 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
更方便这种情况)。
如果你想避免内存复制,你可以这样做:
- (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);
- (Java) 把映射文件通过jni传递给C++,比如定义如下方法:
private static native void initJniWithByteBuffer(ByteBuffer modelBuffer)
- (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));\
}