Compila tu primera app de visión artificial en Android o iOS

1. Antes de comenzar

En este codelab, explorarás la forma de compilar una app que maneje el caso de uso principal de Computer Vision y detecta el contenido principal de una imagen. Por lo general, esto se denomina Clasificación de imágenes o Etiquetado de imágenes.

Requisitos previos

Este codelab es parte de la ruta Cómo comenzar con la clasificación de imágenes. Está escrito para desarrolladores experimentados que no tienen experiencia en el aprendizaje automático.

Qué crearás

  • Una app para Android capaz de clasificar la imagen de una flor
  • (Opcional) Una app para iOS capaz de clasificar una imagen de una flor

Requisitos

2. Cómo comenzar

Visión artificial es un campo en la disciplina más amplia del aprendizaje automático, que busca nuevas formas para que las máquinas procesen y extraigan información del contenido de una imagen. Antes, la computadora solo almacena los datos reales de las imágenes, como los valores de los píxeles que la componen, y permite que una computadora analice el contenido de la imagen y obtenga información sobre ella.

Por ejemplo, en el campo de visión artificial, una imagen de un gato podría etiquetarse como que contiene un gato, además de los píxeles que conforman esa imagen. Hay otros campos de la visión artificial que proporcionan más detalles que esto, como la Detección de objetos, en la que la computadora puede ubicar varios elementos en una imagen y derivar los cuadros de límite para ellos.

En este codelab, explorarás cómo compilar una app que maneje el caso de uso principal y detecte el contenido principal de la imagen. Por lo general, esto se denomina Clasificación de imágenes o Etiquetado de imágenes.

Para que la app sea lo más simple posible, usará imágenes que se incluyen con ella como recursos y te mostrará una clasificación a partir de ellas. Las extensiones futuras podrían utilizar un selector de imágenes o extraer imágenes directamente de la cámara.

Para comenzar, deberás completar el proceso de compilación de la app en Android con Android Studio. (Salta al paso 7 para hacer el equivalente en iOS).

  1. Abre Android Studio, ve al menú File y selecciona Create a New Project.
  2. Se te pedirá elegir una plantilla de proyecto. Selecciona Actividad vacía.

859b1875e37c321a.png

  1. Haga clic en Next. Se te pedirá que configures tu proyecto. Ponle el nombre que desees, pero el código de muestra de este codelab usa el nombre de proyecto ImageClassifierStep1 y el nombre de paquete com.google.imageclassifierstep1.

ee3b6a81bad87b3.png

  1. Elige el que prefieras: Kotlin o Java. En este lab, se usa Kotlin, por lo que, si desea continuar exactamente, probablemente deba elegir Kotlin.
  2. Cuando esté listo, haga clic en Finalizar. Android Studio creará la app automáticamente. La configuración puede tardar unos minutos.

3. Importa la biblioteca de etiquetado de imágenes del Kit de AA

El Kit de AA (https://developers.google.com/ml-kit) ofrece una serie de soluciones para desarrolladores que abordan situaciones comunes del aprendizaje automático y les permiten implementar y trabajar en varias plataformas con facilidad. El Kit de AA proporciona una biblioteca lista para usar que se puede usar en esta aplicación, llamada Etiquetado de imágenes. Esta biblioteca incluye un modelo previamente entrenado para reconocer más de 600 clases de imágenes. Por eso, es perfecto para comenzar.

Ten en cuenta que el Kit de AA también te permite usar modelos personalizados con la misma API, de modo que, cuando estés listo, puedas ir más allá de "comenzar" a crear tu app personalizada de etiquetado de imágenes que use un modelo entrenado según tu situación.

En este caso, compilarás un reconocedor de flores. Cuando creas tu primera app y le muestras la imagen de una flor, se reconocerá como una flor. (Más adelante, cuando compiles tu propio modelo de detector de flores, podrás colocarlo en tu app con cambios mínimos gracias al Kit de AA y hacer que el nuevo modelo te indique qué tipo de flor es, como el tulipán o un rosa)

  1. En Android Studio, asegúrate de que la opción Android esté seleccionada en la parte superior.
  2. Abre la carpeta Gradle Scripts y selecciona el archivo build.gradle de la app. Puede haber 2 o más, por lo que debes asegurarte de usar el de la app, como se muestra a continuación:

93c2e157136671aa.png

  1. En la parte inferior del archivo, verás una sección llamada dependencias, donde se almacena una lista de parámetros de configuración de implementation, testImplementation y androidImplementation. Agrega uno nuevo al archivo con este código:
implementation 'com.google.mlkit:image-labeling:17.0.3'

(Asegúrate de que se encuentre dentro de las dependencias { })

  1. Verás que aparece una barra en la parte superior de la ventana que indica que cambió el build.gradle y debes volver a sincronizar. Adelante, hazlo. Si no lo ves, busca el ícono de elefante pequeño en la barra de herramientas en la esquina superior derecha y haz clic en él.

5ef40c7a719077a0.png

Ya importaste el Kit de AA y estás listo para comenzar a etiquetar las imágenes.

A continuación, crearás una interfaz de usuario simple para procesar una imagen y te brindará un botón que, cuando tu usuario la presione, el Kit de AA invoca el modelo de etiquetador de imágenes para analizar el contenido de la imagen.

4. Cómo crear la interfaz de usuario

En Android Studio, puedes editar la interfaz de usuario de cada pantalla (o actividad) mediante un archivo de diseño basado en XML. La app básica que creaste tiene una sola actividad (cuyo código se encuentra en MainActivity, y lo verás en breve), y la declaración de la interfaz de usuario está en activity_main.xml.

Puedes encontrarlo en la carpeta res > layout del explorador de proyectos de Android, de la siguiente manera:

3ed772e9563061e9.png

Se abrirá un editor completo que te permitirá diseñar la interfaz de usuario de tu actividad. Hay mucho ahí, y no es la intención de este lab enseñarle a usarlo. Para obtener más información sobre el editor de diseño, consulta https://developer.android.com/studio/write/layout-editor.

Para los fines de este lab, seleccione la herramienta Código que está en la esquina superior derecha del editor.

1f7dbdef48d9ade6.png

Ahora, solo verás código XML en la parte principal de la ventana. Cambie el código a este:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/imageToLabel"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
        <Button
            android:id="@+id/btnTest"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Label Image"
            android:layout_gravity="center"/>
        <TextView
            android:id="@+id/txtOutput"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:gravity="start|top" />
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

De esta manera, obtendrás un diseño muy simple que contiene un ImageView (para renderizar la imagen), un Button (para que el usuario lo presione) y un TextView donde se mostrarán las etiquetas.

Ahora tiene una interfaz de usuario definida. Antes de comenzar a programar, agrega algunas imágenes como elementos, y la app realizará inferencias en estas imágenes.

5. Empaqueta imágenes con la app

Una forma de agrupar los archivos adicionales con una app para Android es agregarlos como elementos que se compilen en la app. A fin de mantener la simplicidad de la app, lo haremos para agregar una imagen de algunas flores. Más tarde, podrías extender esta app para usar CameraX o cualquier otra biblioteca para tomar una foto y usarla. Por cuestiones de simplicidad, por ahora solo empaquetaremos la imagen.

  1. En el explorador del proyecto, en la app de la parte superior, haga clic con el botón derecho y seleccione New Directory.
  2. En el diálogo que aparece con una lista de directorios diferentes, seleccione src/main/assets.

c93650ea68bb60e9.png

Cuando lo haga, verá una nueva carpeta assets en el explorador del proyecto:

444b4afab73433b8.png

  1. Haga clic con el botón derecho en esta carpeta y verá una ventana emergente con una lista de opciones. Una de ellas será abrir la carpeta en tu sistema de archivos. Encuentra el más adecuado para tu sistema operativo y selecciónalo. En Mac, será Discover in Finder. En Windows, será Open in Explorer. En Ubuntu, será Show in Files. ).

95e0eca881d35f6b.png

  1. Copia un archivo. Puedes descargar imágenes de sitios como Pixabay. Se recomienda cambiar el nombre de la imagen por algo simple. En este caso, se cambió el nombre de la imagen a flower1.jpg.

Una vez que lo hayas hecho, regresa a Android Studio y verás tu archivo en la carpeta de elementos.

cfa53c9c75a033d8.png

Ya estás listo para etiquetar esta imagen.

6. Escribe el código de clasificación para etiquetar la imagen

(Y ahora la parte que todos estábamos esperando, haciendo Computer Vision en Android).

  1. Escribirás tu código en el archivo MainActivity, por lo que debes buscarlo en la carpeta del proyecto en com.google.devrel.imageclassifierstep1 (o cualquier espacio de nombres equivalente si eliges uno diferente). Ten en cuenta que, por lo general, se configuran 3 carpetas de espacio de nombres en un proyecto de Android Studio: una para la app, otra para Android Test y otra para pruebas. Encontrarás tu MainActivity en el que no tiene una descripción entre corchetes.

b5aef8dd5e26b6c2.png

Si elegiste usar Kotlin, es posible que te preguntes por qué la carpeta superior se llama Java. Se trata de un artefacto histórico en el que Android Studio solo era Java. Las versiones futuras pueden solucionar este problema, pero no te preocupes si quieres usar Kotlin. Solo es el nombre de la carpeta del código fuente.

  1. Abre el archivo MainActivity y verás un archivo de clase llamado MainActivity en el editor de código. Debe tener el siguiente aspecto:
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

Debajo de la llave de cierre, puedes agregar el código de extensión que no forma parte de la clase, pero que esta puede usar. Necesitarás una extensión para leer un archivo de los elementos como un mapa de bits. Este se usará para cargar la imagen que copiaste antes en la carpeta de elementos.

  1. Agrega este código:
// extension function to get bitmap from assets
fun Context.assetsToBitmap(fileName: String): Bitmap?{
    return try {
        with(assets.open(fileName)){
            BitmapFactory.decodeStream(this)
        }
    } catch (e: IOException) { null }
}

Es probable que Android Studio se queje en este punto y destaque parte del código en rojo, como Context, Bitmap y IOException:

d2bde17e3c04aeed.png

No te preocupes. Esto se debe a que todavía no importaste las bibliotecas que las contienen. Android Studio ofrece un acceso directo práctico.

  1. Arrastre el cursor sobre la palabra y presione ALT + Intro (Opción + Intro en una Mac) para que se genere la importación.
  2. Luego, puedes cargar el mapa de bits de los elementos y colocarlo en el objeto ImageView. En onCreateFunction, de MainActivity, agrega este código debajo de la línea setContentView:
val img: ImageView = findViewById(R.id.imageToLabel)
// assets folder image file name with extension
val fileName = "flower1.jpg"
// get bitmap from assets folder
val bitmap: Bitmap? = assetsToBitmap(fileName)
bitmap?.apply {
    img.setImageBitmap(this)
}
  1. Al igual que antes, parte del código se destacará en color rojo. Coloque el cursor en esa línea y use Alt + Intro / Opción + Intro para agregar automáticamente las importaciones.
  2. En el archivo layout.xml que creaste antes, le asignaste a ImageView el nombre imageToLabel. Por lo tanto, la primera línea creará una instancia de un objeto ImageView, llamado img, mediante la información de ese diseño. Encuentra los detalles con findViewById, una función integrada de Android. Luego, usa el nombre de archivo flower1.jpg para cargar una imagen de la carpeta de elementos con la función assetsToBitmap que creaste en el paso anterior. Por último, usa la clase abstracta de mapa de bits para cargar el mapa de bits en img.
  3. El archivo de diseño tenía una TextView que se usará para renderizar las etiquetas que se deducen de la imagen. Obtén un objeto de código para ese paso. Inmediatamente debajo del código anterior, agrega lo siguiente:
val txtOutput : TextView = findViewById(R.id.txtOutput)

Como se explicó anteriormente, esto encuentra la información del archivo de diseño para la vista de texto usando su nombre (verifica en qué archivo XML se llama txtOutput) y la usa para crear una instancia de un objeto TextView llamado txtOutput.

Del mismo modo, crearás un objeto de botón para representar el botón y creará una instancia de este con el contenido del archivo de diseño.

En el archivo de diseño, llamamos al botón btnTest, para que podamos crear una instancia de la siguiente manera:

val btn: Button = findViewById(R.id.btnTest)

Ahora que ya inicializaste todo el código y los controles, el siguiente paso (el último) será usarlos para obtener una inferencia sobre la imagen.

Antes de continuar, asegúrate de que tu código onCreate se vea de la siguiente manera:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val img: ImageView = findViewById(R.id.imageToLabel)
    // assets folder image file name with extension
    val fileName = "flower1.jpg"
    // get bitmap from assets folder
    val bitmap: Bitmap? = assetsToBitmap(fileName)
    bitmap?.apply {
        img.setImageBitmap(this)
    }
    val txtOutput : TextView = findViewById(R.id.txtOutput)
    val btn: Button = findViewById(R.id.btnTest)
}

Ninguna de las palabras clave debe ser de color rojo, lo cual indica que aún no se importó. Si es así, vuelva y haga el truco ALT + Intro para generar las importaciones.

Cuando se usa el etiquetador de imágenes del Kit de AA, por lo general, el primer paso es crear un objeto Options para personalizar el comportamiento. Convertirá su imagen a un formato InputImage que el Kit de AA pueda reconocer. Luego, debes crear un objeto Labeler para realizar la inferencia. Te mostrará una llamada asíncrona con los resultados, que luego puedes analizar.

En el botón que acabas de crear, haz todo eso dentro de su evento onClickListener. Este es el código completo:

btn.setOnClickListener {
  val labeler = ImageLabeling.getClient(ImageLabelerOptions.DEFAULT_OPTIONS)
  val image = InputImage.fromBitmap(bitmap!!, 0)
  var outputText = ""
  labeler.process(image)
    .addOnSuccessListener { labels ->
      // Task completed successfully
      for (label in labels) {
        val text = label.text
        val confidence = label.confidence
        outputText += "$text : $confidence\n"
      }
      txtOutput.text = outputText
  }
    .addOnFailureListener { e ->
      // Task failed with an exception
  }
}
  • Cuando el usuario hace clic por primera vez en el botón, el código creará una instancia de un etiquetador mediante ImageLabeling.getClient y le pasará ImageLabelerOptions. Esto incluye una propiedad DEFAULT_OPTIONS que nos permite comenzar a trabajar rápidamente.
  • A continuación, se creará una InputImage a partir del mapa de bits con su método fromBitmap. InputImage es el formato deseado del Kit de AA para procesar imágenes.
  • Por último, el etiquetador procesará la imagen y mostrará una devolución de llamada asíncrona, ya sea cuando se realice correctamente o no. Si la inferencia se realiza correctamente, la devolución de llamada incluirá una lista de etiquetas. Luego, puedes analizar esta lista de etiquetas para leer el texto y el valor de confianza. Si falla, te enviará una excepción que puedes utilizar para informar al usuario.

y listo. Ahora podrás ejecutar la app en un dispositivo Android o en el emulador. Si es la primera vez que lo haces, obtén información sobre cómo hacerlo aquí: https://developer.android.com/studio/run/emulator

Esta es la app que se está ejecutando en el emulador. Al principio, verá la imagen y el botón, y la etiqueta estará vacía.

c07f5f307f070dc7.png

Presiona el botón para obtener un conjunto de etiquetas de imagen.

550ccaa783363551.png

Aquí, se puede ver que el etiquetador determinó que había altas probabilidades de que la imagen contuviera un pétalo, una flor, una planta y el cielo. Todas son correctas y demuestran que el modelo está trabajando para analizar la imagen.

Pero aún no puede determinar si se trata de una imagen de una margarita. Para ello, necesitará un modelo personalizado entrenado con flores específicas y verá cómo hacerlo en el próximo lab.

En los siguientes pasos, explorarás cómo compilar esta misma app en iOS.

7. Crea un clasificador de imágenes en iOS: Cómo comenzar

Puedes crear una app similar en iOS con Xcode.

  1. Inicia Xcode y, en el menú de archivos, selecciona New Project. Verás este diálogo:

8fb0e6a9d6ac275e.png

  1. Selecciona App como se muestra y haz clic en Siguiente. Se te pedirá que elijas opciones para tu proyecto. Asígnale un nombre y un identificador de la organización, como se muestra a continuación. Asegúrate de que el tipo de interfaz sea Storyboard y que el lenguaje sea Swift, como se muestra.

76c6bdb5aee7659c.png

  1. Si deseas implementar en un teléfono y tienes configurado un perfil de desarrollador, puedes establecer la configuración del equipo. De lo contrario, déjalo en None y podrás usar el simulador de iOS para ejecutar tu app.
  2. Haz clic en Siguiente y selecciona una carpeta para almacenar tu proyecto y sus archivos. Recuerda la ubicación de este proyecto, ya que la necesitarás en el próximo paso.
  3. Cierra Xcode por ahora, ya que volverás a abrirlo con un archivo de espacio de trabajo diferente después del siguiente paso.

8. Cómo integrar el Kit de AA con CocoaPods

Como el Kit de AA también funciona en iOS, puedes usarlo de una manera muy similar para compilar un clasificador de imágenes. Para integrarlo, usarás CocoaPods. Si aún no la tienes instalada, puedes hacerlo con las instrucciones que se encuentran en https://cocoapods.org/.

  1. Abre el directorio en el que creaste tu proyecto. Debe contener el archivo .xcodeproj.

Aquí puede ver el archivo .xcodeproj que indica que estoy en la ubicación correcta.

e2966a47e84eb398.png

  1. En esta carpeta, crea un archivo nuevo llamado Podfile. No hay una extensión, solo es Podfile. En él, agregue lo siguiente:
platform :ios, '10.0'

target 'ImageClassifierStep1' do
        pod 'GoogleMLKit/ImageLabeling'
end
  1. Guárdalo y regresa a la terminal. En el mismo tipo de directorio pod install. CocoaPods descargará las bibliotecas y dependencias adecuadas y creará un nuevo lugar de trabajo que combine tu proyecto con sus dependencias externas.

3b4c628b0cbface8.png

Ten en cuenta que, al final, te pedirá que cierres tus sesiones de Xcode y uses el archivo de espacio de trabajo de ahora en adelante. Abre este archivo, y Xcode se iniciará con el proyecto original y las dependencias externas.

32090e0024b6b5ef.png

Ya puedes continuar con el siguiente paso y crear la interfaz de usuario.

9. Cómo crear la IU de iOS con storyboards

  1. Abre el archivo Main.storyboard; verás un diseño de la interfaz de usuario con una superficie de diseño para un teléfono.
  2. En la parte superior derecha de la pantalla, hay un botón + que puedes usar para agregar controles. Haz clic en él para obtener la paleta de controles.

e63bc3bafa54cc21.png

  1. Desde allí, arrastra y suelta una ImageView, un Button y una Label en la superficie de diseño. Ordénelas de arriba abajo, como se muestra a continuación:

f9dfc55616b25f11.png

  1. Haz doble clic en el botón para editar su texto de Button a Classify.
  2. Arrastra los controladores de la etiqueta para agrandarla. (Di el mismo ancho que la UIImageView y el doble de la altura).
  3. Con la etiqueta igualmente seleccionada, haz clic en el botón selectores en la parte superior derecha para mostrar la paleta de inspectores.
  4. A continuación, busca la configuración Líneas y asegúrate de que sea 0. Esto permite que la etiqueta renderice una cantidad dinámica de líneas.

a39708b320b56b30.png

Ya estás listo para dar el siguiente paso: conectar la IU al código con tomacorrientes y acciones.

10. Crea acciones y salidas

Cuando desarrolles iOS con storyboards, consulta la información de diseño de tus controles mediante sockets y define el código que se ejecutará cuando el usuario realice una acción en un control mediante acciones.

En el siguiente paso, deberás crear salidas para ImageView y la etiqueta. Se hará referencia al objeto ImageView en el código para cargar la imagen a él. La etiqueta se denominará en el código para configurar su texto en función de la inferencia que proviene del Kit de AA.

  1. Para cerrar la paleta de inspectores, haz clic en el control en la parte superior derecha de la pantalla y, luego, en el botón Agregar editor a la derecha que está justo debajo.

77255f7d6284750.png

  1. Tendrás un diseño de pantalla confuso en el que se abre dos veces. A la izquierda, en el navegador del proyecto, seleccione ViewController.swift para que se abra el código del controlador de vista. Parece que la superficie de diseño desapareció del editor de storyboard de la izquierda, pero no te preocupes, sigue allí.
  2. Para recuperarlo, haz clic en Ver controlador en la vista Ver control. Intenta que tu IU se vea de esta manera: el guion gráfico a la izquierda muestra tu diseño y el código a ViewController.swift, a la derecha.

7eb21c7f9d43c9bc.png

  1. Selecciona UIImageView en la superficie de diseño de la izquierda y, mientras presionas la tecla CONTROL, arrástrala al código a la derecha y suéltala debajo de la palabra clave class (en la línea 11 de la captura de pantalla anterior).

Si arrastras una flecha, verás una ventana emergente como la siguiente:

37477f0611948318.png

  1. Complete el campo Nombre como "imageView" y haga clic en Conectar.
  2. Repita este proceso con la etiqueta y asígnele el nombre "lblOutput".
  3. Importante: Para el botón, harás lo mismo, pero asegúrate de establecer el tipo de conexión en Action y no en Outlet.

7281b6eea9fb6c23.png

  1. Asígnele el nombre "doClassification" y haga clic en Connect.

Cuando termines, tu código debería verse de la siguiente manera (ten en cuenta que la etiqueta y la vista de imagen se declaran como IBOutlet (Interfaz Builder Outlet) y el botón como IBAction (Interfaz Builder Action).

import UIKit

class ViewController: UIViewController {

    @IBAction func doClassification(_ sender: Any) {
    }
    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var lblOutput: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

}
  1. Por último, agrupa una imagen con la app para que podamos clasificarla con facilidad. Para ello, arrastra el archivo desde el explorador de archivos hasta el explorador de la izquierda de Xcode. Cuando lo sueltes, verás una ventana emergente como esta:

889ff33eaec785ec.png

  1. Asegúrese de que la casilla de verificación Add to Targets esté marcada como se muestra y, luego, haga clic en Finish.

El archivo se agrupará con tu app, y podrás clasificarlo fácilmente. Ya está listo para codificar la interfaz de usuario a fin de realizar la clasificación de las imágenes.

11. Escribe el código para la clasificación de imágenes

Ahora que todo está configurado, es muy sencillo escribir el código para realizar la clasificación de las imágenes.

  1. Primero, cierra el diseñador de storyboard. Para ello, haz clic en la X ubicada en la esquina superior izquierda, encima de la superficie de diseño. Esto te permitirá enfocarte solo en el código. En el resto de este lab, editará ViewController.swift.
  2. Importa las bibliotecas MLMLVision y MLKit ImageLabeling agregando este código en la parte superior, justo debajo de la importación de UIKit:
import MLKitVision
import MLKitImageLabeling
  1. Luego, en tu función viewDidLoad, inicializa la ImageView con el archivo que agrupamos en la app:
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    imageView.image = UIImage(named:"flower1.jpg")
}
  1. Crea una función auxiliar para obtener las etiquetas de la imagen, justo debajo de viewDidLoad():
func getLabels(with image: UIImage){
  1. Crea una VisionImage a partir de la imagen. El Kit de AA usa este tipo cuando realiza la clasificación de imágenes. Por lo tanto, en el func de getLabels, agrega este código:
let visionImage = VisionImage(image: image)
visionImage.orientation = image.imageOrientation
  1. A continuación, crea las opciones para el etiquetador de imágenes. Se inicializarán con estas opciones. En este caso, solo configurarás una opción básica de confidenceThreshold. Esto significa que solo solicitarás al etiquetador que muestre etiquetas con una confianza de 0.4 o superior. Por ejemplo, para nuestra flor, las clases como "planta" o "pétalo" tendrán una confianza alta, pero aquellas como "baloncesto" o "coche" tendrán una baja.
let options = ImageLabelerOptions()
options.confidenceThreshold = 0.4
  1. Ahora, crea el etiquetador con estas opciones:
let labeler = ImageLabeler.imageLabeler(options: options)
  1. Una vez que tengas el etiquetador, podrás procesarlo. Le brindará una devolución de llamada asíncrona con etiquetas (si se completó correctamente) y error (si falló), que luego podrá procesar en otra función que crearemos en un momento.
labeler.process(visionImage) { labels, error in
    self.processResult(from: labels, error: error)
  }

No te preocupes si Xcode se queja de que no hay un miembro processResult. Aún no lo implementó, y lo hará a continuación.

Para mayor comodidad, a continuación, te mostramos la función getLabels completa:

// This is called when the user presses the button
func getLabels(with image: UIImage){
    // Get the image from the UI Image element and set its orientation
    let visionImage = VisionImage(image: image)
    visionImage.orientation = image.imageOrientation

    // Create Image Labeler options, and set the threshold to 0.4
    // so we will ignore all classes with a probability of 0.4 or less
    let options = ImageLabelerOptions()
    options.confidenceThreshold = 0.4

    // Initialize the labeler with these options
    let labeler = ImageLabeler.imageLabeler(options: options)

    // And then process the image, with the callback going to self.processresult
    labeler.process(visionImage) { labels, error in
        self.processResult(from: labels, error: error)
 }
}

Por lo tanto, debes implementar la función processResult. Esto es muy simple, ahora que tenemos etiquetas y un objeto de error que nos han devuelto. Las etiquetas deben convertirse en el tipo ImageLabel del Kit de AA.

Una vez que lo hagas, puedes iterar en el conjunto de etiquetas, extraer la descripción y el valor de confianza, y agregarlos a un var llamado labeltexts. Una vez que se iteren a través de todos, solo debe establecer lblOutput.text en ese valor.

A continuación, le mostramos la función completa:

// This gets called by the labeler's callback
func processResult(from labels: [ImageLabel]?, error: Error?){
    // String to hold the labels
    var labeltexts = ""
    // Check that we have valid labels first
    guard let labels = labels else{
        return
    }
  // ...and if we do we can iterate through the set to get the description and confidence
    for label in labels{
        let labelText = label.text + " : " + label.confidence.description + "\n"
        labeltexts += labelText
    }
    // And when we're done we can update the UI with the list of labels
    lblOutput.text = labeltexts
}

Solo queda llamar a getLabels cuando el usuario presiona el botón.

Cuando creaste la acción, todo se transfirió por ti, por lo que solo necesitas actualizar el IBAction llamado doClassificaiton que creaste antes para llamar a getLabels.

Este es el código para simplemente llamarlo con el contenido de imageView:

@IBAction func doClassification(_ sender: Any) {
    getLabels(with: imageView.image!)
}

Ahora, ejecuta tu app y pruébala. Aquí puede ver cómo funciona:

eb8e6c1b1e2c65e0.png

Ten en cuenta que el diseño puede variar según el dispositivo.

El codelab no explora diferentes tipos de diseño por dispositivo, lo que es un concepto bastante complejo en sí mismo. Si no ves la IU correctamente, regresa al editor de storyboards y, en la parte inferior, verás la sección Ver como:, donde podrás elegir un dispositivo en particular. Elige una que coincida con la imagen o el dispositivo que estás probando y edita la IU para que se adapte a ella.

A medida que avance en el desarrollo de iOS, aprenderá a usar restricciones para asegurarse de que su IU sea coherente en todos los teléfonos, pero eso está fuera del alcance de este lab.

12. ¡Felicitaciones!

Ya implementaste una app en iOS y Android que te ofrece una visión artificial básica con un modelo genérico. Ya hiciste la mayor parte del trabajo pesado.

En el siguiente codelab, compilarás un modelo personalizado que reconozca diferentes tipos de flores y, con solo unas pocas líneas de código, podrás implementar el modelo personalizado en esta app para que sea más útil.