- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
好的,所以在我的应用程序中,我正在尝试使用人脸网络模型来实现人脸识别,该模型转换为 tflite,平均约为 93 MB,
但是这个模型最终会增加我的 apk 的大小。
所以我正在尝试寻找替代方法来解决这个问题
首先我能想到的是以某种方式压缩它,然后在安装应用程序时解压缩
另一种方法是我应该将该模型上传到服务器,并在下载后将其加载到我的应用程序中。
但是我似乎不知道如何实现这一点:
默认情况下,face net 允许从 assets 文件夹中实现
var facenet = FaceNet(getAssets());
public FaceNet(AssetManager assetManager) throws IOException {
tfliteModel = loadModelFile(assetManager);
tflite = new Interpreter(tfliteModel, tfliteOptions);
imgData = ByteBuffer.allocateDirect(
BATCH_SIZE
* IMAGE_HEIGHT
* IMAGE_WIDTH
* NUM_CHANNELS
* NUM_BYTES_PER_CHANNEL);
imgData.order(ByteOrder.nativeOrder());
}
private MappedByteBuffer loadModelFile(AssetManager assetManager) throws IOException {
AssetFileDescriptor fileDescriptor = assetManager.openFd(MODEL_PATH);
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);
}
public class FaceNet {
private static final String MODEL_PATH = "facenet.tflite";
private static final float IMAGE_MEAN = 127.5f;
private static final float IMAGE_STD = 127.5f;
private static final int BATCH_SIZE = 1;
private static final int IMAGE_HEIGHT = 160;
private static final int IMAGE_WIDTH = 160;
private static final int NUM_CHANNELS = 3;
private static final int NUM_BYTES_PER_CHANNEL = 4;
private static final int EMBEDDING_SIZE = 512;
private final int[] intValues = new int[IMAGE_HEIGHT * IMAGE_WIDTH];
private ByteBuffer imgData;
private MappedByteBuffer tfliteModel;
private Interpreter tflite;
private final Interpreter.Options tfliteOptions = new Interpreter.Options();
public FaceNet(AssetManager assetManager) throws IOException {
tfliteModel = loadModelFile(assetManager);
tflite = new Interpreter(tfliteModel, tfliteOptions);
imgData = ByteBuffer.allocateDirect(
BATCH_SIZE
* IMAGE_HEIGHT
* IMAGE_WIDTH
* NUM_CHANNELS
* NUM_BYTES_PER_CHANNEL);
imgData.order(ByteOrder.nativeOrder());
}
private MappedByteBuffer loadModelFile(AssetManager assetManager) throws IOException {
AssetFileDescriptor fileDescriptor = assetManager.openFd(MODEL_PATH);
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);
}
private void convertBitmapToByteBuffer(Bitmap bitmap) {
if (imgData == null) {
return;
}
imgData.rewind();
bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
// Convert the image to floating point.
int pixel = 0;
for (int i = 0; i < IMAGE_HEIGHT; ++i) {
for (int j = 0; j < IMAGE_WIDTH; ++j) {
final int val = intValues[pixel++];
addPixelValue(val);
}
}
}
private void addPixelValue(int pixelValue){
//imgData.putFloat((((pixelValue >> 16) & 0xFF) - IMAGE_MEAN) / IMAGE_STD);
//imgData.putFloat((((pixelValue >> 8) & 0xFF) - IMAGE_MEAN) / IMAGE_STD);
//imgData.putFloat(((pixelValue & 0xFF) - IMAGE_MEAN) / IMAGE_STD);
imgData.putFloat(((pixelValue >> 16) & 0xFF) / 255.0f);
imgData.putFloat(((pixelValue >> 8) & 0xFF) / 255.0f);
imgData.putFloat((pixelValue & 0xFF) / 255.0f);
}
public void inspectModel(){
String tag = "Model Inspection";
Log.i(tag, "Number of input tensors: " + String.valueOf(tflite.getInputTensorCount()));
Log.i(tag, "Number of output tensors: " + String.valueOf(tflite.getOutputTensorCount()));
Log.i(tag, tflite.getInputTensor(0).toString());
Log.i(tag, "Input tensor data type: " + tflite.getInputTensor(0).dataType());
Log.i(tag, "Input tensor shape: " + Arrays.toString(tflite.getInputTensor(0).shape()));
Log.i(tag, "Output tensor 0 shape: " + Arrays.toString(tflite.getOutputTensor(0).shape()));
}
private Bitmap resizedBitmap(Bitmap bitmap, int height, int width){
return Bitmap.createScaledBitmap(bitmap, width, height, true);
}
private Bitmap croppedBitmap(Bitmap bitmap, int upperCornerX, int upperCornerY, int height, int width){
return Bitmap.createBitmap(bitmap, upperCornerX, upperCornerY, width, height);
}
private float[][] run(Bitmap bitmap){
bitmap = resizedBitmap(bitmap, IMAGE_HEIGHT, IMAGE_WIDTH);
convertBitmapToByteBuffer(bitmap);
float[][] embeddings = new float[1][512];
tflite.run(imgData, embeddings);
return embeddings;
}
public double getSimilarityScore(Bitmap face1, Bitmap face2){
float[][] face1_embedding = run(face1);
float[][] face2_embedding = run(face2);
double distance = 0.0;
for (int i = 0; i < EMBEDDING_SIZE; i++){
distance += (face1_embedding[0][i] - face2_embedding[0][i]) * (face1_embedding[0][i] - face2_embedding[0][i]);
}
distance = Math.sqrt(distance);
return distance;
}
public void close(){
if (tflite != null) {
tflite.close();
tflite = null;
}
tfliteModel = null;
}
}
最佳答案
好吧,我想不出任何减小模型文件大小的解决方案,但是通过观察您的类,我可以说毕竟它从文件输入流中返回映射的字节缓冲区,因此要从存储中获取文件只需将文件放入外部存储中的 facenet 文件夹,然后在文件输入流上获取映射的字节缓冲区,这是 kotlin 中的解决方案。
class FaceNetStorage @Throws(IOException::class)
constructor() {
private val intValues = IntArray(IMAGE_HEIGHT * IMAGE_WIDTH)
private var imgData: ByteBuffer? = null
private var tfliteModel: MappedByteBuffer? = null
private var tflite: Interpreter? = null
private val tfliteOptions = Interpreter.Options()
init {
val str = Environment.getExternalStorageDirectory().toString()+"/Facenet"
val sd_main = File(str)
var success = true
if (!sd_main.exists()) {
success = sd_main.mkdir()
}
if (success) {
val sd = File(str+"/"+MODEL_PATH)
tfliteModel = loadModelFile(sd)
tflite = Interpreter(tfliteModel!!, tfliteOptions)
imgData = ByteBuffer.allocateDirect(
BATCH_SIZE
* IMAGE_HEIGHT
* IMAGE_WIDTH
* NUM_CHANNELS
* NUM_BYTES_PER_CHANNEL)
imgData!!.order(ByteOrder.nativeOrder())
}
}
@Throws(IOException::class)
private fun loadModelFile(file: File): MappedByteBuffer {
val inputStream = FileInputStream(file)
val fileChannel = inputStream.channel
return fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size())
}
private fun convertBitmapToByteBuffer(bitmap: Bitmap) {
if (imgData == null) {
return
}
imgData!!.rewind()
bitmap.getPixels(intValues, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)
// Convert the image to floating point.
var pixel = 0
for (i in 0 until IMAGE_HEIGHT) {
for (j in 0 until IMAGE_WIDTH) {
val `val` = intValues[pixel++]
addPixelValue(`val`)
}
}
}
private fun addPixelValue(pixelValue: Int) {
imgData!!.putFloat((pixelValue shr 16 and 0xFF) / 255.0f)
imgData!!.putFloat((pixelValue shr 8 and 0xFF) / 255.0f)
imgData!!.putFloat((pixelValue and 0xFF) / 255.0f)
}
fun inspectModel() {
val tag = "Model Inspection"
Log.i(tag, "Number of input tensors: " + tflite!!.inputTensorCount.toString())
Log.i(tag, "Number of output tensors: " + tflite!!.outputTensorCount.toString())
Log.i(tag, tflite!!.getInputTensor(0).toString())
Log.i(tag, "Input tensor data type: " + tflite!!.getInputTensor(0).dataType())
Log.i(tag, "Input tensor shape: " + Arrays.toString(tflite!!.getInputTensor(0).shape()))
Log.i(tag, "Output tensor 0 shape: " + Arrays.toString(tflite!!.getOutputTensor(0).shape()))
}
private fun resizedBitmap(bitmap: Bitmap, height: Int, width: Int): Bitmap {
return Bitmap.createScaledBitmap(bitmap, width, height, true)
}
private fun croppedBitmap(bitmap: Bitmap, upperCornerX: Int, upperCornerY: Int, height: Int, width: Int): Bitmap {
return Bitmap.createBitmap(bitmap, upperCornerX, upperCornerY, width, height)
}
private fun run(bitmap: Bitmap): Array<FloatArray> {
var bitmap = bitmap
bitmap = resizedBitmap(bitmap, IMAGE_HEIGHT, IMAGE_WIDTH)
convertBitmapToByteBuffer(bitmap)
val embeddings = Array(1) { FloatArray(512) }
tflite!!.run(imgData, embeddings)
return embeddings
}
fun getSimilarityScore(face1: Bitmap, face2: Bitmap): Double {
val face1_embedding = run(face1)
val face2_embedding = run(face2)
var distance = 0.0
for (i in 0 until EMBEDDING_SIZE) {
distance += ((face1_embedding[0][i] - face2_embedding[0][i]) * (face1_embedding[0][i] - face2_embedding[0][i])).toDouble()
}
distance = Math.sqrt(distance)
return distance
}
fun close() {
if (tflite != null) {
tflite!!.close()
tflite = null
}
tfliteModel = null
}
companion object {
private val MODEL_PATH = "facenet.tflite"
private val IMAGE_MEAN = 127.5f
private val IMAGE_STD = 127.5f
private val BATCH_SIZE = 1
private val IMAGE_HEIGHT = 160
private val IMAGE_WIDTH = 160
private val NUM_CHANNELS = 3
private val NUM_BYTES_PER_CHANNEL = 4
private val EMBEDDING_SIZE = 512
}
}
关于java - 如何减小 Tflite 模型的大小或下载并以编程方式设置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59048118/
我正在编写一个具有以下签名的 Java 方法。 void Logger(Method method, Object[] args); 如果一个方法(例如 ABC() )调用此方法 Logger,它应该
我是 Java 新手。 我的问题是我的 Java 程序找不到我试图用作的图像文件一个 JButton。 (目前这段代码什么也没做,因为我只是得到了想要的外观第一的)。这是我的主课 代码: packag
好的,今天我在接受采访,我已经编写 Java 代码多年了。采访中说“Java 垃圾收集是一个棘手的问题,我有几个 friend 一直在努力弄清楚。你在这方面做得怎么样?”。她是想骗我吗?还是我的一生都
我的 friend 给了我一个谜语让我解开。它是这样的: There are 100 people. Each one of them, in his turn, does the following
如果我将使用 Java 5 代码的应用程序编译成字节码,生成的 .class 文件是否能够在 Java 1.4 下运行? 如果后者可以工作并且我正在尝试在我的 Java 1.4 应用程序中使用 Jav
有关于why Java doesn't support unsigned types的问题以及一些关于处理无符号类型的问题。我做了一些搜索,似乎 Scala 也不支持无符号数据类型。限制是Java和S
我只是想知道在一个 java 版本中生成的字节码是否可以在其他 java 版本上运行 最佳答案 通常,字节码无需修改即可在 较新 版本的 Java 上运行。它不会在旧版本上运行,除非您使用特殊参数 (
我有一个关于在命令提示符下执行 java 程序的基本问题。 在某些机器上我们需要指定 -cp 。 (类路径)同时执行java程序 (test为java文件名与.class文件存在于同一目录下) jav
我已经阅读 StackOverflow 有一段时间了,现在我才鼓起勇气提出问题。我今年 20 岁,目前在我的家乡(罗马尼亚克卢日-纳波卡)就读 IT 大学。足以介绍:D。 基本上,我有一家提供簿记应用
我有 public JSONObject parseXML(String xml) { JSONObject jsonObject = XML.toJSONObject(xml); r
我已经在 Java 中实现了带有动态类型的简单解释语言。不幸的是我遇到了以下问题。测试时如下代码: def main() { def ks = Map[[1, 2]].keySet()
一直提示输入 1 到 10 的数字 - 结果应将 st、rd、th 和 nd 添加到数字中。编写一个程序,提示用户输入 1 到 10 之间的任意整数,然后以序数形式显示该整数并附加后缀。 public
我有这个 DownloadFile.java 并按预期下载该文件: import java.io.*; import java.net.URL; public class DownloadFile {
我想在 GUI 上添加延迟。我放置了 2 个 for 循环,然后重新绘制了一个标签,但这 2 个 for 循环一个接一个地执行,并且标签被重新绘制到最后一个。 我能做什么? for(int i=0;
我正在对对象 Student 的列表项进行一些测试,但是我更喜欢在 java 类对象中创建硬编码列表,然后从那里提取数据,而不是连接到数据库并在结果集中选择记录。然而,自从我这样做以来已经很长时间了,
我知道对象创建分为三个部分: 声明 实例化 初始化 classA{} classB extends classA{} classA obj = new classB(1,1); 实例化 它必须使用
我有兴趣使用 GPRS 构建车辆跟踪系统。但是,我有一些问题要问以前做过此操作的人: GPRS 是最好的技术吗?人们意识到任何问题吗? 我计划使用 Java/Java EE - 有更好的技术吗? 如果
我可以通过递归方法反转数组,例如:数组={1,2,3,4,5} 数组结果={5,4,3,2,1}但我的结果是相同的数组,我不知道为什么,请帮助我。 public class Recursion { p
有这样的标准方式吗? 包括 Java源代码-测试代码- Ant 或 Maven联合单元持续集成(可能是巡航控制)ClearCase 版本控制工具部署到应用服务器 最后我希望有一个自动构建和集成环境。
我什至不知道这是否可能,我非常怀疑它是否可能,但如果可以,您能告诉我怎么做吗?我只是想知道如何从打印机打印一些文本。 有什么想法吗? 最佳答案 这里有更简单的事情。 import javax.swin
我是一名优秀的程序员,十分优秀!