如何使用 AssetManager 和 Play Asset Delivery 在 Java 中加载 tflite 模型?
how to load a tflite model in Java using AssetManager and Play Asset Delivery?
我有一个 .tflite
大小超过 200MB 的模型文件。由于它增加了 apk 的 150MB 最大大小,我不得不使用 Play Asset Delivery (PAD) 将其捆绑在应用程序包中。
我遵循了 here 中提到的指南:并且能够构建我的 .aab
文件。我已将我的助手添加为 install-time
,因此我不必检查其可用性,它应该与应用程序一起安装。
但似乎无法访问我的 tflite
文件。
我可以使用以下方法完美地从资产文件夹加载模型:
private MappedByteBuffer loadModelFile() throws Exception {
AssetFileDescriptor fileDescriptor = this.getAssets().openFd("model.tflite");
FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
FileChannel fileChannel = inputStream.getChannel();
long startOffset = fileDescriptor.getStartOffset();
long declaredLength = fileDescriptor.getDeclaredLength();
return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
}
但这不适用于 PAD,因为我们需要使用 AssetManager
,如 here 所述。
所以我重写了上面的函数来使用AssetManager
:
Context context = createPackageContext("com.companyname.packagename", 0);
AssetManager assetManager = context.getAssets();
private MappedByteBuffer loadModelFile(AssetManager assetManager, String modelPath) throws IOException {
AssetFileDescriptor fileDescriptor = assetManager.openFd("model.tflite");
FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
FileChannel fileChannel = inputStream.getChannel();
long startOffset = fileDescriptor.getStartOffset();
long declaredLength = fileDescriptor.getDeclaredLength();
return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
}
但是好像没有加载模型。与 interpreter.run()
方法一样,我得到错误:
java.lang.NullPointerException: Attempt to invoke virtual method 'void
org.tensorflow.lite.Interpreter.run(java.lang.Object,
java.lang.Object)' on a null object reference
这表明模型未加载。
这种情况下模型的路径是否不同?我将如何加载 tflite 模型?
事实证明,我上面的函数是使用 AssetManager
.
加载 tflite 模型的正确方法
Context context = createPackageContext("com.companyname.packagename", 0);
AssetManager assetManager = context.getAssets();
private MappedByteBuffer loadModelFile(AssetManager assetManager, String modelPath) throws IOException {
AssetFileDescriptor fileDescriptor = assetManager.openFd("model.tflite");
FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
FileChannel fileChannel = inputStream.getChannel();
long startOffset = fileDescriptor.getStartOffset();
long declaredLength = fileDescriptor.getDeclaredLength();
return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
}
它没有加载模型的原因是因为在使用 Play Asset Delivery 时,install-time
资产只有在 从 下载的游戏安装后才可用来自 Play 商店的捆绑包。
由于 install-time
资产就像普通资产一样,资产的位置保持不变。
我有一个 .tflite
大小超过 200MB 的模型文件。由于它增加了 apk 的 150MB 最大大小,我不得不使用 Play Asset Delivery (PAD) 将其捆绑在应用程序包中。
我遵循了 here 中提到的指南:并且能够构建我的 .aab
文件。我已将我的助手添加为 install-time
,因此我不必检查其可用性,它应该与应用程序一起安装。
但似乎无法访问我的 tflite
文件。
我可以使用以下方法完美地从资产文件夹加载模型:
private MappedByteBuffer loadModelFile() throws Exception {
AssetFileDescriptor fileDescriptor = this.getAssets().openFd("model.tflite");
FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
FileChannel fileChannel = inputStream.getChannel();
long startOffset = fileDescriptor.getStartOffset();
long declaredLength = fileDescriptor.getDeclaredLength();
return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
}
但这不适用于 PAD,因为我们需要使用 AssetManager
,如 here 所述。
所以我重写了上面的函数来使用AssetManager
:
Context context = createPackageContext("com.companyname.packagename", 0);
AssetManager assetManager = context.getAssets();
private MappedByteBuffer loadModelFile(AssetManager assetManager, String modelPath) throws IOException {
AssetFileDescriptor fileDescriptor = assetManager.openFd("model.tflite");
FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
FileChannel fileChannel = inputStream.getChannel();
long startOffset = fileDescriptor.getStartOffset();
long declaredLength = fileDescriptor.getDeclaredLength();
return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
}
但是好像没有加载模型。与 interpreter.run()
方法一样,我得到错误:
java.lang.NullPointerException: Attempt to invoke virtual method 'void org.tensorflow.lite.Interpreter.run(java.lang.Object, java.lang.Object)' on a null object reference
这表明模型未加载。
这种情况下模型的路径是否不同?我将如何加载 tflite 模型?
事实证明,我上面的函数是使用 AssetManager
.
Context context = createPackageContext("com.companyname.packagename", 0);
AssetManager assetManager = context.getAssets();
private MappedByteBuffer loadModelFile(AssetManager assetManager, String modelPath) throws IOException {
AssetFileDescriptor fileDescriptor = assetManager.openFd("model.tflite");
FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
FileChannel fileChannel = inputStream.getChannel();
long startOffset = fileDescriptor.getStartOffset();
long declaredLength = fileDescriptor.getDeclaredLength();
return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
}
它没有加载模型的原因是因为在使用 Play Asset Delivery 时,install-time
资产只有在 从 下载的游戏安装后才可用来自 Play 商店的捆绑包。
由于 install-time
资产就像普通资产一样,资产的位置保持不变。