2
votes

Tensorflow Lite: impossible de convertir entre un tampon TensorFlowLite et un ByteBuffer

J'ai essayé de migrer un modèle personnalisé vers la plate-forme Android. La version tensorflow est la 1.12. J'ai utilisé la ligne de commande recommandée comme ci-dessous:

2019-03-04 10:31:46.822 17884-17884/android.example.com.tflitecamerademo E/AndroidRuntime: FATAL EXCEPTION: main
    Process: android.example.com.tflitecamerademo, PID: 17884
    java.lang.RuntimeException: Unable to start activity ComponentInfo{android.example.com.tflitecamerademo/com.example.android.tflitecamerademo.CameraActivity}: java.lang.IllegalArgumentException: Cannot convert between a TensorFlowLite buffer with 786432 bytes and a ByteBuffer with 4049856 bytes.

pour convertir le fichier .pb au format tflite.

J'ai vérifié la forme du tenseur d'entrée de mon fichier .pb dans tensorboard :

imgData = ByteBuffer.allocateDirect(
          4 * 1 * 712 * 474 * 3);

Ensuite, je déploie le fichier tflite sur Android, et j'alloue l'entrée ByteBuffer qui prévoyait d'alimenter le modèle comme:

dtype
{"type":"DT_FLOAT"}
shape
{"shape":{"dim":[{"size":474},{"size":712},{"size":3}]}}

Lorsque j'exécute le modèle sur un appareil Android, l'application plante, puis logcat s'imprime comme:

tflite_convert \
  --output_file=test.tflite \
  --graph_def_file=./models/test_model.pb \
  --input_arrays=input_image \
  --output_arrays=generated_image

C'est tellement bizarre puisque ByteBuffer alloué est exactement le produit de 4 * 3 * 474 * 712 alors que le tampon tensorflow lite n'est pas le multiple de 474 ou 712. Je ne comprends pas pourquoi le modèle tflite a une mauvaise forme.

Merci d'avance si quelqu'un peut donner une solution.


0 commentaires

3 Réponses :


3
votes

Vous pouvez visualiser le modèle TFLite pour déboguer les tailles de tampon réellement allouées aux tenseurs d'entrée.

Les modèles TensorFlow Lite peuvent être visualisés à l'aide du visualize.py script.

Si la taille de la mémoire tampon du tenseur d'entrée n'est pas ce que vous attendez, il peut y avoir un bug avec la conversion (ou avec les arguments fournis à tflite_convert )


3 commentaires

J'ai résolu cependant en accordant le tenseur d'entrée et de sortie dans la même forme. Bref, merci!


comment utiliser ce script visualize.py pour la visualisation du modèle tflite


@HarshGupta: tensorflow.org/lite/guide/faq#how_do_i_inspect_a_tflite



0
votes

J'avais changé les dimensions de l'image de la norme 224 plus tôt dans le processus de création du modèle à 299 pour d'autres raisons, alors j'ai juste cherché mon projet Android Studio pour 224 et mis à jour les deux final références dans ImageClassifier.java à 299, et j'étais de retour dans les affaires.


0 commentaires

0
votes

Bonjour les gars , J'ai également eu le même problème hier. Je voudrais mentionner une solution qui fonctionne pour moi.

On dirait que TSLite ne prend en charge que les entrées bitmap carrées exactes Comme Détection de taille 256 * 256 fonctionnant La détection de taille 256 * 255 ne fonctionne pas en jetant une exception

Et la taille maximale prise en charge 257 * 257 doit être la largeur et la hauteur maximales pour toute entrée bitmap

Voici l'exemple de code pour recadrer et redimensionner le bitmap

private fun cropBitmap(bitmap: Bitmap): Bitmap {
val bitmapRatio = bitmap.height.toFloat() / bitmap.width
val modelInputRatio = MODEL_HEIGHT.toFloat() / MODEL_WIDTH
var croppedBitmap = bitmap

// Acceptable difference between the modelInputRatio and bitmapRatio to skip cropping.
val maxDifference = 1e-5

// Checks if the bitmap has similar aspect ratio as the required model input.
when {
  abs(modelInputRatio - bitmapRatio) < maxDifference -> return croppedBitmap
  modelInputRatio < bitmapRatio -> {
    // New image is taller so we are height constrained.
    val cropHeight = bitmap.height - (bitmap.width.toFloat() / modelInputRatio)
    croppedBitmap = Bitmap.createBitmap(
      bitmap,
      0,
      (cropHeight / 2).toInt(),
      bitmap.width,
      (bitmap.height - cropHeight).toInt()
    )
  }
  else -> {
    val cropWidth = bitmap.width - (bitmap.height.toFloat() * modelInputRatio)
    croppedBitmap = Bitmap.createBitmap(
      bitmap,
      (cropWidth / 2).toInt(),
      0,
      (bitmap.width - cropWidth).toInt(),
      bitmap.height
    )
  }
}
return croppedBitmap
}

Recadrer le bitmap

val scaledBitmap = Bitmap.createScaledBitmap(croppedBitmap, MODEL_WIDTH, MODEL_HEIGHT, true)

Création d'une version mise à l'échelle du bitmap pour l'entrée de modèle

val croppedBitmap = cropBitmap(bitmap)

https://github.com/tensorflow/examples/blob/master/lite/examples/posenet/android/app/src/main/java/org/tensorflow/lite/examples/posenet /PosenetActivity.kt#L578

Recadrer le bitmap pour conserver les proportions de l'entrée du modèle.

private var MODEL_HEIGHT = 257
private var MODEL_WIDTH = 257

https://github.com/tensorflow/examples/blob/master/lite/examples/posenet/andr oid / app / src / main / java / org / tensorflow / lite / examples / posenet / PosenetActivity.kt # L451 Merci et salutations Pankaj


0 commentaires