Qué compilarás
En este instructivo, descargarás un modelo personalizado de TensorFlow Lite exportado que se creó mediante AutoML Vision Edge. Luego, ejecutarás una app para Android prediseñada que usa el modelo a fin de identificar imágenes de flores.
Objetivos
En esta introducción detallada, usarás el código para lo siguiente:
- Ejecutar un modelo previamente entrenado en una app para Android con el intérprete de TFLite
Antes de comenzar
Entrena un modelo desde AutoML Vision Edge
Antes de implementar un modelo en un dispositivo de Edge, sigue la guía de inicio rápido sobre modelos de dispositivos de Edge para entrenar y exportar un modelo de TF Lite desde AutoML Vision Edge.
Después de completar la guía de inicio rápido, debes tener exportados los siguientes archivos de modelos entrenados: un archivo de TF Lite, un archivo de etiquetas y un archivo de metadatos, como se muestra a continuación.
Instala TensorFlow
Antes de comenzar el instructivo, debes instalar varios tipos de software:
- instala tensorflow versión 1.7
- instala PILLOW
Si tienes una instalación de Python que funcione, ejecuta los siguientes comandos para descargar este software:
pip install --upgrade "tensorflow==1.7.*" pip install PILLOW
Consulta la documentación de TensorFlow oficial si tienes problemas con este proceso.
Clona el repositorio de Git
Con la línea de comandos, clona el repositorio de Git mediante el siguiente comando:
git clone https://github.com/googlecodelabs/tensorflow-for-poets-2
Navega al directorio del clon local del repositorio (directorio tensorflow-for-poets-2
). Ejecutarás todas las siguientes muestras de códigos de este directorio.
cd tensorflow-for-poets-2
Configura la app para Android
Instala Android Studio
Si es necesario, instala Android Studio 3.0+ de forma local.
Abre el proyecto con Android Studio
Para abrir un proyecto con Android Studio, sigue estos pasos:
Abre Android Studio . Después de que se cargue, selecciona “Abrir un proyecto existente de Android Studio” (Open an existing Android Studio project) en esta ventana emergente:
En el selector de archivos, selecciona
tensorflow-for-poets-2/android/tflite
en el directorio de trabajo.La primera vez que abras el proyecto, aparecerá una ventana emergente de “Gradle Sync” (Sincronización de Gradle) en la que se pregunta si deseas usar el wrapper de Gradle. Selecciona “OK” (Aceptar).
Haz una ejecución de prueba de la app
La app puede ejecutarse en un dispositivo Android real o en Android Studio Emulator.
Configura un dispositivo Android
No puedes cargar la app de Android Studio al teléfono, a menos que actives el “modo de desarrollador” y la “depuración por USB”.
Para completar este proceso de configuración único, sigue estas instrucciones.
Configura el emulador con acceso a la cámara (opcional)
Si eliges usar un emulador en lugar de un dispositivo Android real, Android Studio facilita la configuración del emulador.
Debido a que esta app usa la cámara, configura la del emulador para que puedas usar la cámara de la computadora en lugar del patrón de prueba predeterminado.
Para configurar la cámara del emulador, debes crear un dispositivo nuevo en el “Android Virtual Device Manager” (Administrador de dispositivos virtuales de Android), un servicio al que puedes acceder con este botón . En la página principal de AVDM, selecciona “Create Virtual Device” (Crear un dispositivo virtual):
Luego, en la página “Verify Configuration” (Verificar configuración), la última página de la configuración del dispositivo virtual, selecciona “Show Advanced Settings” (Mostrar configuración avanzada):
Con la configuración avanzada que se muestra, puedes configurar ambas fuentes de cámaras para usar la cámara web de la computadora host:
Ejecuta la app original
Antes de realizar cambios en la app, ejecuta la versión que viene con el repositorio.
Para iniciar el proceso de compilación y de instalación, ejecuta una sincronización de Gradle.
Después de ejecutar una sincronización de Gradle, selecciona reproducir .
Después de seleccionar el botón de reproducción, deberás seleccionar el dispositivo en esta ventana emergente:
Después de seleccionar el dispositivo, debes permitir que la demostración de Tensorflow acceda a tu cámara y a tus archivos:
Ahora que la app está instalada, haz clic en el ícono de la app para iniciarla. Esta versión de la app usa MobileNet estándar, previamente entrenado en las 1,000 categorías de ImageNet.
Debería ser similar a esto:
Ejecuta la app personalizada
La configuración predeterminada de la app clasifica las imágenes en una de las 1,000 clases de ImageNet mediante MobileNet estándar sin necesidad de realizar otro entrenamiento.
Ahora, realiza modificaciones a fin de que la app use un modelo que creó AutoML Vision Edge para las categorías de imágenes personalizadas.
Agrega los archivos del modelo al proyecto
El proyecto de demostración está configurado para buscar un graph.lite
y un archivo labels.txt
en el directorio android/tflite/app/src/main/assets/
.
Reemplaza los dos archivos originales por tus versiones con los siguientes comandos:
cp [Downloads]/model.tflite android/tflite/app/src/main/assets/graph.lite cp [Downloads]/dict.txt android/tflite/app/src/main/assets/labels.txt
Modifica tu app
Esta app usa un modelo de número de punto flotante, mientras que el modelo que creó AutoML Vision Edge es cuantizado. Debes hacer algunos cambios de código para permitir que la app use el modelo.
Cambia el tipo de datos de labelProbArray
y filterLabelProbArray
de número de punto flotante a byte en la definición de miembros de la clase y en el inicializador ImageClassifier
.
private byte[][] labelProbArray = null;
private byte[][] filterLabelProbArray = null;
labelProbArray = new byte[1][labelList.size()];
filterLabelProbArray = new byte[FILTER_STAGES][labelList.size()];
Asigna el imgData
basado en el tipo int8, en el inicializador ImageClassifier
.
imgData =
ByteBuffer.allocateDirect(
DIM_BATCH_SIZE * DIM_IMG_SIZE_X * DIM_IMG_SIZE_Y * DIM_PIXEL_SIZE);
Convierte el tipo de datos de labelProbArray
de int8 a número de punto flotante en printTopKLabels()
:
private String printTopKLabels() {
for (int i = 0; i < labelList.size(); ++i) {
sortedLabels.add(
new AbstractMap.SimpleEntry<>(labelList.get(i), (float)labelProbArray[0][i]));
if (sortedLabels.size() > RESULTS_TO_SHOW) {
sortedLabels.poll();
}
}
String textToShow = "";
final int size = sortedLabels.size();
for (int i = 0; i < size; ++i) {
Map.Entry<String, Float> label = sortedLabels.poll();
textToShow = String.format("\n%s: %4.2f",label.getKey(),label.getValue()) + textToShow;
}
return textToShow;
}
Ejecuta tu app
En Android Studio, ejecuta una sincronización de Gradle para que el sistema de compilación pueda encontrar tus archivos:
Después de ejecutar una sincronización de Gradle, selecciona reproducir para iniciar el proceso de compilación e instalación como antes.
Debería ser similar a esto:
Puedes mantener presionados los botones de encendido y de bajar volumen a la vez para tomar una captura de pantalla.
Si deseas probar la app actualizada, apunta la cámara a diferentes imágenes de flores para ver si se clasifican de forma correcta.
¿Cómo funciona?
Ahora que tienes la app en ejecución, examina el código específico de TensorFlow Lite.
AAR de TensorFlow-Android
Esta app usa un Android ARchive (AAR) de TFLite ya compilado. Este AAR está alojado en jcenter.
En las siguientes líneas del archivo build.gradle
del módulo, se incluye la versión más reciente del AAR del repositorio de TensorFlow de Bintray y Maven del proyecto.
repositories { maven { url 'https://google.bintray.com/tensorflow' } } dependencies { // ... compile 'org.tensorflow:tensorflow-lite:+' }
Usa el siguiente bloque para indicar a Android Asset Packaging Tool que los elementos .lite
o .tflite
no deben comprimirse.
Esto es importante, ya que el archivo .lite
se asignará en memoria y no funcionará cuando el archivo esté comprimido.
android { aaptOptions { noCompress "tflite" noCompress "lite" } }
Usa la API de TFLite para Java
El código que interactúa con TFLite está incluido en ImageClassifier.java
.
Configuración
El primer bloque de interés es el constructor de ImageClassifier
:
ImageClassifier(Activity activity) throws IOException { tflite = new Interpreter(loadModelFile(activity)); labelList = loadLabelList(activity); imgData = ByteBuffer.allocateDirect( 4 * DIM_BATCH_SIZE * DIM_IMG_SIZE_X * DIM_IMG_SIZE_Y * DIM_PIXEL_SIZE); imgData.order(ByteOrder.nativeOrder()); labelProbArray = new float[1][labelList.size()]; Log.d(TAG, "Created a Tensorflow Lite Image Classifier."); }
Hay algunas líneas de interés especial.
Con la siguiente línea, se crea el intérprete de TFLite:
tflite = new Interpreter(loadModelFile(activity));
Con esta línea se crea una instancia del intérprete de TFLite. El intérprete funciona de manera similar a una tf.Session
(para aquellos familiarizados con TensorFlow, fuera de TFLite).
Debes enviarle al intérprete un MappedByteBuffer
que contenga el modelo.
La función local loadModelFile
crea un MappedByteBuffer
que contiene el archivo de elementos graph.lite
de la actividad.
Con las siguientes líneas, se crea el búfer de datos de entrada:
imgData = ByteBuffer.allocateDirect( 4 * DIM_BATCH_SIZE * DIM_IMG_SIZE_X * DIM_IMG_SIZE_Y * DIM_PIXEL_SIZE);
Este búfer de bytes puede contener los datos de imágenes una vez que se convirtieron en float.
El intérprete puede aceptar arreglos de número de punto flotante directamente como entrada, pero el ByteBuffer
es más eficaz, ya que evita copias adicionales en el intérprete.
Con las siguientes líneas, se carga la lista de etiquetas y se crea el búfer de salida:
labelList = loadLabelList(activity); //... labelProbArray = new float[1][labelList.size()];
El búfer de salida es un arreglo de números de punto flotante con un elemento para cada etiqueta en el que el modelo escribirá las probabilidades de salida.
Ejecuta el modelo
El segundo bloque de interés es el método classifyFrame
.
Este método toma un Bitmap
como entrada, ejecuta el modelo y muestra el texto que se imprimirá en la app.
String classifyFrame(Bitmap bitmap) { // ... convertBitmapToByteBuffer(bitmap); // ... tflite.run(imgData, labelProbArray); // ... String textToShow = printTopKLabels(); // ... }
Este método realiza tres acciones. Primero, el método convierte y copia el Bitmap
de entrada en imgData
ByteBuffer
para la entrada del modelo.
Luego, llama al método de ejecución del intérprete y pasa el búfer de entrada y el arreglo de salida como argumentos. El intérprete establece los valores del arreglo de salida según la probabilidad calculada para cada clase.
Los nodos de entrada y de salida se definen mediante los argumentos del paso de conversión toco
que creó el archivo del modelo .lite
antes.
Próximos pasos
Completaste un instructivo de una app de clasificación de flores de Android mediante un modelo de Edge. Probaste una app de clasificación de imágenes antes de hacerle modificaciones y obtener anotaciones de muestra. Luego examinaste el código específico de TensorFlow Lite para comprender la funcionalidad subyacente.
- Obtén más información sobre TFLite en la documentación oficial y el repositorio de códigos.
- Prueba la versión cuantizada de esta app de demostración para obtener un modelo más potente en un paquete más pequeño.
- Prueba otros modelos preparados para TFLite, como un detector de palabras clave por voz y una versión de respuesta inteligente en el dispositivo.
- Obtén más información sobre TensorFlow en general con la documentación de introducción.