У меня есть собственный код Android (общий объект C++
), который хочет, чтобы файл read
модели сохранялся в папке assets
при создании APK.
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
?
Я не думаю, что вы можете использовать BuildFromFile
без копирования файла ресурса в локальный файл (что эквивалентно тому, что вы сделали выше, и тогда BuildFromBuffer
более удобен в этом случае).
Если вы хотите избежать копирования памяти, вот что вы можете сделать:
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);
private static native void initJniWithByteBuffer(ByteBuffer modelBuffer)
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));\
}
У меня сработало, с одной оговоркой: если вы храните указатель сопоставления на стороне C++ и повторно используете его позже, не забудьте сохранить объект
MappedByteBuffer
Java до тех пор, пока вам нужен указатель.