Criar seu primeiro app Computer Vision no Android ou iOS

1. Antes de começar

Neste codelab, você aprenderá a criar um app que processa o principal caso de uso da visão computacional e detecta o conteúdo principal de uma imagem. Geralmente, isso é chamado de classificação de imagens ou rotulação de imagens.

Prerequisites

Este codelab faz parte do programa de primeiros passos da classificação de imagens. Ele foi criado para desenvolvedores experientes que ainda não conhecem o machine learning.

O que você criará

  • Um app Android capaz de classificar uma imagem de uma flor
  • (Opcional) Um app iOS capaz de classificar uma imagem de uma flor

Pré-requisitos

2. Começar

A visão computacional é um campo na maior disciplina de machine learning que trabalha para encontrar novas maneiras de processar e extrair informações do conteúdo de uma imagem. Antes, um computador só armazenava dados reais de imagens, como os valores dos pixels que a compõem. A visão computacional permite que o computador analise o conteúdo da imagem e colete informações sobre ela.

Por exemplo, no campo de visão computacional, uma imagem de um gato pode ser marcada como contendo um gato, além dos pixels que a compõem. Existem outros campos de visão computacional que entram em mais detalhes do que isso, como a detecção de objetos, em que o computador pode localizar vários itens em uma imagem e derivar caixas delimitadoras para eles.

Neste codelab, você aprenderá a criar um app que processa o principal caso de uso e detecta o conteúdo principal da imagem. Geralmente, isso é chamado de classificação de imagens ou rotulagem de imagens.

Para manter o app o mais simples possível, ele usará imagens que estejam agrupadas como recursos e mostrará uma classificação delas. As próximas extensões podem ser usar um seletor de imagem ou extrair imagens diretamente da câmera.

Você começará passando pelo processo de criação do app no Android usando o Android Studio. Vá para a etapa 7 para fazer o equivalente no iOS.

  1. Abra o Android Studio, acesse o menu File e selecione Create a New Project.
  2. Você precisará escolher um modelo de projeto. Selecione "Atividade vazia".

859b1875e37c321a.png

  1. Clique em Next. Você precisará configurar seu projeto. Dê a ele o nome e o nome do pacote que quiser, mas o exemplo de código neste codelab usa o nome do projeto ImageClassifierStep1 e o nome do pacote com.google.imageclassifierstep1.

ee3b6a81bad87b3.png

  1. Escolha a linguagem que preferir, Kotlin ou Java. Este laboratório usa Kotlin. Portanto, se você quiser continuar acompanhando, escolha o Kotlin.
  2. Quando estiver tudo pronto, clique em "Finish". O Android Studio criará o app para você. A configuração pode levar alguns instantes.

3. Importar a biblioteca de rotulagem de imagens do kit de ML

O Kit de ML (https://developers.google.com/ml-kit) oferece várias soluções para desenvolvedores que atendem a cenários comuns de machine learning e facilitam a implementação e o trabalho em várias plataformas. O Kit de ML fornece uma biblioteca pronta para uso neste app chamada de rotulagem de imagens. Essa biblioteca inclui um modelo pré-treinado para reconhecer mais de 600 classes de imagens. Sendo assim, é perfeito para começar.

O ML Kit também permite usar modelos personalizados com a mesma API. Assim, quando você estiver pronto, vá além dos "Primeiros passos" e comece a criar seu app personalizado de rotulagem de imagens que usa um modelo treinado para seu cenário.

Neste cenário, você criará um reconhecedor de flores. Quando você criar e exibir a primeira imagem de uma flor, ele o reconhecerá como uma flor. Mais tarde, ao criar um modelo de detector de flores próprio, você poderá soltá-lo no app com mudanças mínimas graças ao Kit de ML e fazer com que o novo modelo informe o tipo de flor, como tulipa ou rosa.

  1. No Android Studio, usando o explorador de projetos, verifique se a opção Android está selecionada na parte superior.
  2. Abra a pasta Gradle Scripts e selecione o arquivo build.gradle do app. Pode haver duas ou mais versões. Portanto, use o nível app conforme mostrado abaixo:

93c2e157136671aa.png

  1. Na parte inferior do arquivo, você verá uma seção chamada dependencies, em que uma lista de configurações de implementation, testImplementation e androidImplementation é armazenada. Adicione uma nova ao arquivo com este código:
implementation 'com.google.mlkit:image-labeling:17.0.3'

Confira se ele está dentro das dependências { }

  1. Uma barra será exibida na parte superior da janela, sinalizando que o build.gradle foi alterado, e você precisará sincronizar novamente. Faça isso. Caso não o veja, procure o pequeno ícone de elefante na barra de ferramentas no canto superior direito e clique nele.

5ef40c7a719077a0.png

Você importou o kit de ML e está pronto para iniciar a rotulagem de imagens.

Em seguida, você criará uma interface do usuário simples para renderizar uma imagem e fornecerá um botão que, quando seu usuário pressiona, o Kit de ML invoca o modelo de rotulador de imagens para analisar o conteúdo da imagem.

4. Criar a interface do usuário

No Android Studio, você pode editar a interface do usuário de cada tela (ou atividade) usando um arquivo de layout baseado em XML. O app básico que você criou tem uma única atividade (com código em MainActivity, e você verá isso em breve) e a declaração da interface do usuário está em activity_main.xml.

Isso pode ser encontrado na pasta res > layout do explorador de projetos do Android. Você pode fazer o seguinte:

3ed772e9563061e9.png

Isso abrirá um editor completo que permite que você projete sua interface do usuário da Activity. Há muitas opções, e esse laboratório não é a intenção de ensinar como usá-lo. Para saber mais sobre o editor de layout, acesse: https://developer.android.com/studio/write/layout-editor

Para este laboratório, selecione a ferramenta Code no canto superior direito do editor.

1f7dbdef48d9ade6.png.

Agora você verá apenas o código XML na parte principal da janela. Mude o código para:

<?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>

Isso fornecerá um layout muito simples contendo um ImageView (para renderizar a imagem), um Button (para o usuário pressionar) e um TextView em que os rótulos serão exibidos.

A interface do usuário já está definida. Antes de começar a programar, adicione algumas imagens como recursos para que o app faça inferências sobre elas.

5. Agrupar imagens com o app

Uma forma de agrupar arquivos extras com um app Android é adicioná-los como recursos compilados no app. Para simplificar, adicionaremos uma imagem de algumas flores. Mais tarde, você poderá estender esse app para usar o CameraX ou outras bibliotecas para tirar uma foto e usá-lo. Para simplificar, vamos agrupar a imagem por enquanto.

  1. No explorador de projetos, no canto superior direito do app, clique com o botão direito do mouse e selecione "Novo diretório".
  2. Na caixa de diálogo exibida com uma lista de diretórios diferentes, selecione src/main/assets.

c93650ea68bb60e9.png

Depois de fazer isso, você verá uma nova pasta assets aparecer no explorador de projetos:

444b4afab73433b8.png

  1. Clique com o botão direito do mouse nessa pasta para ver um pop-up com a lista de opções. Uma delas será abrir a pasta no seu sistema de arquivos. Encontre e selecione o sistema adequado para seu sistema operacional. No Mac, ela será Reveal in Finder (link em inglês), no Windows (Open in Explorer) e no Ubuntu (Show in Files). .

95e0eca881d35f6b.png

  1. Copie um arquivo nele. Você pode fazer o download de imagens de sites como o Pixabay. É recomendável renomear a imagem para algo simples. Neste caso, a imagem foi renomeada como flower1.jpg.

Depois de fazer isso, volte ao Android Studio, e você verá seu arquivo na pasta de recursos.

cfa53c9c75a033d8.png

Agora você já pode rotular esta imagem.

6. Escrever o código de classificação para rotular a imagem

(E agora a parte que todos nós estávamos esperando, fazendo a Computer Vision no Android!)

  1. Você escreverá o código no arquivo MainActivity. Portanto, encontre-o na pasta do projeto em com.google.devrel.imageclassifierstep1 (ou qualquer outro namespace equivalente, se tiver escolhido um diferente). Observe que geralmente há três pastas de namespace configuradas em um projeto do Android Studio, uma para o app, uma para o Android Test e outra para o teste. Você verá o MainActivity sem uma descrição depois entre colchetes.

b5aef8dd5e26b6c2.png

Se você optou por usar o Kotlin, talvez esteja se perguntando por que a pasta mãe é chamada de Java. Ele é um artefato histórico de quando o Android Studio era somente Java. As próximas versões podem resolver isso, mas não se preocupe se quiser usar o Kotlin. Tudo bem. É apenas o nome da pasta do código-fonte.

  1. Abra o arquivo MainActivity para ver um arquivo de classe chamado MainActivity no editor de código. Você verá o seguinte:
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

Abaixo da chave de fechamento, adicione o código de extensão que não faça parte da classe, mas que possa ser usado pela classe. Você precisará de uma extensão para ler um arquivo dos recursos como um bitmap. Ela será usada para carregar a imagem que você copiou para a pasta de recursos anteriormente.

  1. Adicione 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 }
}

É provável que o Android Studio reclame agora e destaque parte do código em vermelho, como Context, Bitmap e IOException:

d2bde17e3c04aeed.png

Não se preocupe! Isso ocorre porque você ainda não importou as bibliotecas que as contêm. O Android Studio oferece um atalho útil.

  1. Arraste o cursor sobre a palavra e pressione ALT + Enter (Option + Enter em um Mac) e a importação será gerada para você.
  2. Em seguida, você pode carregar o bitmap dos recursos e colocá-lo na ImageView. De volta ao onCreateFunction da MainActivity, adicione este código logo abaixo da linha 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. Assim como antes, alguns códigos serão destacados em vermelho. Coloque o cursor nessa linha e use Alt + Enter / Option + Enter para adicionar as importações automaticamente.
  2. No arquivo layout.xml criado anteriormente, você deu a ImageView o nome imageToLabel. Portanto, a primeira linha criará uma instância de um objeto ImageView, chamado img, usando essas informações de layout. Ela encontra os detalhes usando findViewById, uma função Android integrada. Em seguida, ele usa o nome de arquivo flower1.jpg para carregar uma imagem da pasta de recursos com a função assetsToBitmap criada na etapa anterior. Por fim, ele usa a classe abstrata para carregar o bitmap em "img".
  3. O arquivo de layout tinha uma TextView que será usada para renderizar os rótulos inferidos para a imagem. Consiga um objeto de código para isso a seguir. Imediatamente abaixo do código anterior, adicione este código:
val txtOutput : TextView = findViewById(R.id.txtOutput)

Como antes, ele encontra as informações do arquivo de layout para a visualização de texto usando o nome (verifique o XML, onde se chama txtOutput) e usa-a para instanciar um objeto TextView chamado txtOutput.

Da mesma forma, você criará um objeto de botão para representar o botão e instanciá-lo com o conteúdo do arquivo de layout.

No arquivo de layout, chamamos o botão de btnTest para poder instanciá-lo assim:

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

Agora que todo o código e os controles foram inicializados, a próxima e última etapa será usá-los para fazer uma inferência na imagem.

Antes de continuar, verifique se o código onCreate tem esta aparência:

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)
}

Nenhuma das palavras-chave deve estar em vermelho, indicando que elas ainda não foram importadas. Se estiverem, volte e faça o truque ALT + Enter para gerar as importações.

Ao usar o rotulador de imagens do Kit de ML, a primeira etapa geralmente é criar um objeto Options para personalizar o comportamento. Você converterá sua imagem para um formato de InputImage que o Kit de ML possa reconhecer. Depois, crie um objeto Labeler para realizar a inferência. Ele retornará uma chamada assíncrona com os resultados, que você poderá analisar.

No botão que você acabou de criar, faça tudo isso no evento onClickListener. Veja o 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
  }
}
  • Quando o usuário clicar no botão pela primeira vez, o código vai instanciar um rotulador usando ImageLabeling.getClient, transmitindo o ImageLabelerOptions. Isso inclui uma propriedade DEFAULT_OPTIONS que nos permite começar a trabalhar rapidamente.
  • Em seguida, uma InputImage será criada a partir do bitmap usando o método fromBitmap. InputImage é o formato desejado do Kit de ML para processamento de imagens.
  • Por fim, o rotulador processará a imagem e enviará um callback assíncrono, em caso de sucesso ou falha. Se a inferência for bem-sucedida, o callback incluirá uma lista de rótulos. Depois, analise essa lista de rótulos para ler o texto do rótulo e o valor de confiança. Em caso de falha, você receberá uma exceção que poderá ser usada para denunciar ao usuário.

Pronto. Agora, você pode executar o app em um dispositivo Android ou no emulador. Saiba como fazer isso aqui: https://developer.android.com/studio/run/emulator.

Aqui está o app em execução no emulador. Primeiro, você verá a imagem e o botão, e o rótulo ficará vazio.

c07f5f307f070dc7.png

Pressione o botão para receber um conjunto de rótulos para a imagem.

550ccaa783363551.png

Aqui você pode ver que o rotulador determinou que havia alta probabilidade da imagem conter uma pétala, uma flor, uma planta e o céu. Elas estão corretas e demonstram que o modelo está trabalhando para analisar a imagem.

No entanto, ainda não é possível determinar que se trata de uma margarida. Para isso, você precisará de um modelo personalizado treinado com flores específicas e verá como fazer isso no próximo laboratório.

Nas etapas a seguir, você verá como criar esse mesmo app no iOS.

7. Criar um classificador de imagem no iOS - Primeiros passos

Você pode criar um app semelhante no iOS usando o Xcode.

  1. Inicie o Xcode e selecione Novo projeto no menu de arquivos. Você verá essa caixa de diálogo:

8fb0e6a9d6ac275e.png

  1. Selecione App conforme mostrado e clique em Next. Você precisará escolher uma opção para seu projeto. Dê a ela um nome e um identificador de organização, conforme mostrado. Verifique se o tipo de interface é Storyboard e se o idioma é Swift, como mostrado.

76c6bdb5aee7659c.png

  1. Se você quiser implantar em um smartphone e tiver um Perfil do desenvolvedor, defina as configurações da equipe. Caso contrário, deixe-a em Nenhum e você poderá usar o simulador iOS para executar o aplicativo.
  2. Clique em Next e selecione uma pasta para armazenar o projeto e os arquivos dele. Lembre-se do local desse projeto, porque você precisará dele na próxima etapa.
  3. Feche o Xcode por enquanto, porque você o reabrirá usando um arquivo de espaço de trabalho diferente após a próxima etapa.

8. Integrar o kit de ML usando o Cocoapods

Como o Kit de ML também funciona no iOS, é possível usá-lo de forma semelhante para criar um classificador de imagens. Para integrá-lo, você usará o CocoaPods. Se você ainda não o instalou, siga as instruções em https://cocoapods.org/

  1. Abra o diretório em que você criou seu projeto. Ele deve conter o arquivo .xcodeproj.

Aqui você pode ver o arquivo .xcodeproj indicando que estou no local correto.

e2966a47e84eb398.png

  1. Nessa pasta, crie um arquivo chamado Podfile. Não há extensão, é apenas o Podfile. Nela, adicione o seguinte:
platform :ios, '10.0'

target 'ImageClassifierStep1' do
        pod 'GoogleMLKit/ImageLabeling'
end
  1. Salve-o e volte ao terminal. No mesmo diretório, digite pod install. O Cocoapods fará o download das bibliotecas e dependências apropriadas e criará um novo espaço de trabalho que combina seu projeto com as dependências externas.

3b4c628b0cbface8.png.

Ao final, você verá que precisa fechar as sessões do Xcode e usar o arquivo do espaço de trabalho de agora em diante. Abra esse arquivo para iniciar o Xcode com o projeto original e as dependências externas.

32090e0024b6b5ef.png.

Agora você pode passar para a próxima etapa e criar a interface do usuário.

9. Criar a IU do iOS usando o Storyboards

  1. Abra o arquivo Main.storyboard para ver um layout de interface do usuário com uma superfície de design para o smartphone.
  2. No canto superior direito da tela, há um botão + que pode ser usado para adicionar controles. Clique nele para ver a paleta de controles.

e63bc3bafa54cc21.png

  1. Em seguida, arraste e solte uma ImageView, um Button e uma Label na superfície de design. Organize-as de cima para baixo, conforme mostrado:

f9dfc55616b25f11.png

  1. Clique duas vezes no botão para editar o texto do Button para Classify.
  2. Arraste as alças de controle ao redor do rótulo para aumentar. Use a mesma largura da UIImageView e duas vezes a altura.
  3. Com o rótulo ainda selecionado, clique no botão selectors no canto superior direito para mostrar a paleta dos inspetores.
  4. Depois de fazer isso, encontre a configuração Linhas e verifique se ela está definida como 0. Isso permite que o rótulo renderize um número dinâmico de linhas.

a39708b320b56b30.png

Agora você já pode dar o próximo passo: conectar a IU ao código usando tomadas e ações.

10. Criar ações e tomadas

Ao fazer o desenvolvimento para iOS usando storyboards, você faz referência às informações de layout dos seus controles usando tomadas e define o código que será executado quando o usuário realizar uma ação usando um controle.

Na próxima etapa, você precisará criar saídas para o ImageView e o rótulo. A ImageView será referenciada no código para carregar a imagem. O rótulo será referenciado no código para definir o texto dele com base na inferência que vem do kit de ML.

  1. Feche a paleta do inspetor clicando no controle no canto superior direito da tela e, em seguida, no botão Add Editor on Right abaixo.

77255f7d6284750.png

  1. Você terá um layout de tela confuso em que o main.storyboard é aberto duas vezes. À esquerda, no navegador de projetos, selecione ViewController.swift para abrir o código do controlador de visualização. Parece que a superfície de design desapareceu do editor de storyboard à esquerda, mas não se preocupe, ela ainda está lá.
  2. Para recuperá-lo, clique em View Controller no cenário "Ver controlador". Tente fazer com que a IU tenha esta aparência: com o storyboard à esquerda mostrando seu design e o código de ViewController.swift à direita.

7eb21c7f9d43c9bc.png

  1. Selecione a UIImageView na superfície de design à esquerda e, ao pressionar a tecla CTRL, arraste-a para o código à direita, soltando-a logo abaixo da palavra-chave class (na linha 11 da captura de tela acima).

Você verá uma seta enquanto arrasta e, quando soltar, verá um pop-up como este:

37477f0611948318.png

  1. Preencha o campo Nome como "imageView" e clique em Conectar.
  2. Repita esse processo com o rótulo e dê a ele o nome "lblOutput".
  3. Importante: para o botão, você fará a mesma coisa, mas defina o tipo de conexão como Ação, e não Saída.

7281b6eea9fb6c23.png

  1. Nomeie o arquivo como "doClassification" e clique em Conectar.

Ao terminar, o código ficará assim: O rótulo e a visualização da imagem são declarados como IBOutlet (Interface Builder Outlet) e o botão como IBAction (Ação Builder da interface).

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 fim, agrupe a imagem e o app para que a classificação seja fácil. Para fazer isso, arraste o arquivo do explorador de arquivos para o explorador à esquerda do Xcode. Ao soltá-lo, você verá um pop-up como este:

889ff33eaec785ec.png

  1. Verifique se a caixa de seleção na seção Add to Targets está marcada, conforme mostrado, e clique em Finish.

O arquivo será empacotado com o app, e agora você pode classificá-lo facilmente. Agora você já pode programar a interface do usuário para fazer a classificação da imagem.

11. Criar o código para classificação de imagens

Agora que tudo está configurado, escrever o código para realizar a classificação da imagem é muito simples.

  1. Para começar, feche o designer de storyboard clicando no X no canto superior esquerdo acima da superfície de design. Assim, você poderá se concentrar apenas no seu código. Você editará ViewController.swift no restante deste laboratório.
  2. Importe as bibliotecas MLKitVision e MLKit ImageLabeling adicionando este código na parte superior, logo abaixo da importação do UIKit:
import MLKitVision
import MLKitImageLabeling
  1. Em seguida, na função viewDidLoad, inicialize a ImageView usando o arquivo que agrupamos no app:
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    imageView.image = UIImage(named:"flower1.jpg")
}
  1. Crie uma função auxiliar para conseguir os rótulos da imagem imediatamente abaixo do viewDidLoad():
func getLabels(with image: UIImage){
  1. Crie uma VisionImage a partir da imagem. O Kit de ML usa esse tipo ao realizar a classificação de imagens. Portanto, na função getLabels, adicione este código:
let visionImage = VisionImage(image: image)
visionImage.orientation = image.imageOrientation
  1. Em seguida, crie as opções do rotulador de imagens. Ele será inicializado com essas opções. Nesse caso, você vai definir apenas uma opção básica do confidenceThreshold. Isso significa que você solicitará que o rotulador retorne apenas rótulos com confiança de 0,4 ou mais. Por exemplo, no caso das nossas flores, classes como "planta" ou " pétala" terão uma alta confiança, mas aquelas como "basquete" ou "carro" terão um nível mais baixo.
let options = ImageLabelerOptions()
options.confidenceThreshold = 0.4
  1. Agora crie o rotulador usando estas opções:
let labeler = ImageLabeler.imageLabeler(options: options)
  1. Depois de encontrar o rotulador, você pode processá-lo. Você receberá um callback assíncrono com rótulos (se tiver êxito) e um erro (se houver falha) que poderão ser processados em outra função que será criada em alguns instantes.
labeler.process(visionImage) { labels, error in
    self.processResult(from: labels, error: error)
  }

Não se preocupe se o Xcode reclamar que não há um membro processResult. Você ainda não implementou esse recurso, e fará isso em seguida.

Por conveniência, aqui está a função 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)
 }
}

Portanto, agora é necessário implementar a função processResult. Isso é muito simples, já que temos rótulos e um objeto de erro retornado para nós. Os rótulos devem ser transmitidos para o tipo ImageLabel do kit de ML.

Depois de fazer isso, é possível iterar o conjunto de rótulos, extrair a descrição e o valor de confiança e adicioná-los a um var com o nome labeltexts. Depois de iterar todos eles, basta definir o lblOutput.text com esse valor.

Veja a função 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
}

Só falta chamar getLabels quando o usuário pressionar o botão.

Quando você criou a ação, tudo estava conectado. Então, basta atualizar a IBAction, chamada doClassificaiton, que você criou anteriormente para chamar getLabels.

Veja o código para chamá-lo com o conteúdo da imageView:

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

Agora, execute o app e teste-o. Veja um exemplo aqui:

eb8e6c1b2e2c65e0.png

O layout pode ser diferente dependendo do dispositivo.

O codelab não aborda diferentes tipos de layout por dispositivo, o que é um conceito muito complexo por si só. Se a IU não for exibida corretamente, volte ao editor do storyboard e, na parte inferior, você verá uma seção Ver como: para escolher um dispositivo específico. Escolha uma imagem que corresponda ao dispositivo ou ao teste e edite a IU de acordo com a necessidade.

Ao se aprofundar no desenvolvimento para iOS, você aprenderá a usar restrições para garantir que a IU seja consistente em todos os smartphones, mas isso está além do escopo deste laboratório.

12. Parabéns!

Agora, você implementou um app no Android e no iOS que oferece visão computacional básica com um modelo genérico. Você já fez a maior parte do trabalho pesado.

No próximo codelab, você criará um modelo personalizado que reconhece diferentes tipos de flores. Com apenas algumas linhas de código, você poderá implementar o modelo personalizado neste app para torná-lo mais útil.