Créer votre première application de vision par ordinateur sur Android ou iOS

1. Avant de commencer

Dans cet atelier de programmation, vous allez apprendre à créer une application qui gère le cas d'utilisation principal de Vision par ordinateur, en détectant le contenu principal d'une image. C'est ce qu'on appelle la classification d'images ou l'étiquetage d'image.

Prérequis

Cet atelier de programmation fait partie du parcours Premiers pas avec la classification d'images. Cette page a été rédigée pour les développeurs expérimentés qui ne connaissent pas le machine learning.

Ce que vous allez faire

  • Application Android capable de classer une image de fleur
  • (Facultatif) Application iOS capable de classer une image de fleur

Prérequis

  • Android Studio, disponible sur https://developer.android.com/studio pour la partie Android de l'atelier de programmation
  • Xcode, disponible sur l'App Store d'Apple pour la partie iOS de l'atelier de programmation

2. Premiers pas

La vision par ordinateur est un champ plus complexe de machine learning qui vise à trouver de nouvelles façons de traiter et d'extraire des informations à partir du contenu d'une image. Avant qu'un ordinateur ne stocke que les données réelles d'images, comme les valeurs des pixels qui composent l'image, la vision par ordinateur permet à un ordinateur d'analyser le contenu de l'image et d'obtenir des informations sur son contenu.

Par exemple, dans le champ d'application de la vision par ordinateur, l'image d'un chat peut être libellée comme contenant un chat, en plus des pixels qui la composent. Il existe d'autres champs de vision plus détaillés, tels que la détection d'objets, qui permettent à l'ordinateur de localiser plusieurs éléments dans une image et d'en retirer des cadres de délimitation.

Dans cet atelier de programmation, vous allez apprendre à créer une application qui gère le cas d'utilisation principal et à détecter le contenu principal de l'image. C'est ce qu'on appelle la classification d'images ou l'étiquetage d'image.

Pour que l'application soit aussi simple que possible, elle utilise les images associées à celle-ci en tant que ressources et vous en indique la classification. À l'avenir, vous pourrez utiliser un sélecteur d'images ou extraire des images directement depuis l'appareil photo.

Vous allez commencer par développer l'application sur Android à l'aide d'Android Studio. (Passez à l'étape 7 pour obtenir l'équivalent sur iOS.)

  1. Ouvrez Android Studio, accédez au menu "File" (Fichier) et sélectionnez "Create a New Project" (Créer un projet).
  2. Vous serez invité à choisir un modèle de projet. Sélectionnez "Activité vide".

859b1875e37c321a.png

  1. Cliquez sur Suivant. Vous serez alors invité à Configurer votre projet. Attribuez-lui le nom et le nom de package de votre choix, mais l'exemple de code de cet atelier de programmation utilise le nom de projet ImageClassifierStep1 et le nom de package com.google.imageclassifierstep1.

EE3b6a81bad87b3.png

  1. Sélectionnez le langage de votre choix, Kotlin ou Java. Cet atelier utilise Kotlin. Par conséquent, si vous souhaitez le suivre exactement, vous devrez probablement l'utiliser.
  2. Lorsque vous avez terminé, cliquez sur "Terminer". Android Studio crée l'application pour vous. La configuration peut prendre quelques instants.

3. Importer la bibliothèque d'étiquetage d'images de ML Kit

ML Kit (https://developers.google.com/ml-kit) propose plusieurs solutions pour les développeurs, répondant aux scénarios de machine learning les plus courants et facilitant leur mise en œuvre et leur utilisation sur plusieurs plates-formes. ML Kit fournit une bibliothèque clé en main que vous pouvez utiliser dans cette application. Cette bibliothèque comprend un modèle pré-entraîné pour reconnaître plus de 600 classes d'images. C'est donc idéal pour vous lancer.

Notez que ML Kit vous permet d'utiliser des modèles personnalisés avec la même API. Ainsi, lorsque vous êtes prêt, vous pouvez aller au-delà de la section "Premiers pas" et commencer à créer votre application d'étiquetage d'images personnalisées qui utilise un modèle entraîné pour votre scénario.

Dans ce scénario, vous allez créer un outil de reconnaissance de fleurs. Lorsque vous créez votre première application et que vous lui montrez une fleur, elle la reconnaît en tant que fleur. Plus tard, lorsque vous créerez votre propre modèle de détecteur de fleurs, vous pourrez l'intégrer à votre application avec un minimum de modifications grâce au ML Kit, et le nouveau modèle vous indiquera le type de fleur tel que la tulipe ou le tulipe. rose)

  1. Dans Android Studio, vérifiez que Android est sélectionné en haut de l'écran de l'explorateur de projets.
  2. Ouvrez leScripts Gradle , puis sélectionnez le dossierbuild.gradle pour l'application. Il peut y en avoir deux ou plus, alors utilisez leapplication niveau 1, comme illustré ici:

93c2e157136671aa.png

  1. En bas du fichier, vous verrez une section intitulée dépendances, dans laquelle une liste de paramètres implementation, testImplementation et androidImplementation est stockée. Ajoutez-en un nouveau avec le code suivant:
implementation 'com.google.mlkit:image-labeling:17.0.3'

(Vérifiez qu'il se trouve bien dans les dépendances { }.)

  1. Une barre apparaîtra en haut de la fenêtre indiquant que la build.gradle a été modifiée et vous devez la resynchroniser. Faites-le. Si vous ne la voyez pas, cliquez sur l'icône en forme de petit éléphant dans la barre d'outils située en haut à droite.

5ef40c7a719077a.png

Vous avez importé le ML Kit et vous êtes prêt à appliquer l'étiquetage d'image.

Vous allez maintenant créer une interface utilisateur simple pour afficher une image et vous donner un bouton lorsque l'utilisateur appuiera dessus : ML Kit appelle le modèle d'étiqueteur d'image pour analyser le contenu de l'image.

4. Créer l'interface utilisateur

Dans Android Studio, vous pouvez modifier l'interface utilisateur de chaque écran (ou activité) à l'aide d'un fichier de mise en page au format XML. L'application de base que vous avez créée comporte une seule activité (dont le code est en MainActivity, et vous allez bientôt le voir), alors que la déclaration de l'interface utilisateur est en activity_main.xml.

Vous le trouverez dans le dossier res > layout (Mise en page) : dans l'explorateur de projets Android, comme suit :

3ed772e9563061e9.png

Un éditeur complet s'ouvre, vous permettant de concevoir l'interface utilisateur de votre activité. Il y a beaucoup de choses à faire, et cet objectif n'est pas de vous apprendre à l'utiliser. Pour en savoir plus sur l'éditeur de mise en page, consultez la page https://developer.android.com/studio/write/layout-editor.

Pour les besoins de cet atelier, sélectionnez l'outil de programmation dans l'angle supérieur droit de l'éditeur.

1f7dbdef48d9ade6.png

Le code XML n'apparaît plus dans la partie principale de la fenêtre. Remplacez ce code par le code suivant:

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

Vous obtenez une mise en page très simple contenant un ImageView (pour afficher l'image), une Button (pour que l'utilisateur appuie dessus) et un TextView où les libellés s'afficheront.

Votre interface utilisateur est désormais définie. Avant de commencer à coder, ajoutez des images en tant qu'éléments. L'application effectuera une inférence sur ces images.

5. Regrouper des images avec l'application

Pour regrouper des fichiers supplémentaires dans une application Android, vous pouvez les ajouter en tant qu'éléments compilés dans cette application. Pour simplifier cette appli, nous allons ajouter une image de fleurs. Par la suite, vous pourrez étendre cette application à l'aide de CameraX ou d'autres bibliothèques pour prendre une photo et l'utiliser. Pour plus de simplicité, nous allons juste regrouper l'image pour le moment.

  1. Dans l'explorateur de projets, application En haut de la page, effectuez un clic droit et sélectionnez "New Directory" (Nouvel annuaire).
  2. Dans la boîte de dialogue qui s'affiche avec un répertoire différent, sélectionnez src/main/assets.

C93650ea68bb60e9.png

Un nouveau dossier assets s'affiche alors dans l'explorateur de projets:

444b4afab73433b8.png

  1. Effectuez un clic droit sur ce dossier. Une fenêtre pop-up s'affiche avec une liste d'options. L'un de ces éléments consiste à ouvrir le dossier dans votre système de fichiers. Trouvez celui qui convient à votre système d'exploitation et sélectionnez-le. (sous Mac, il s'agit de l'option Reveal in Finder [Afficher dans le Finder], sous Open in Explorer (Ouvrir dans l'explorateur) sous Windows, et Show in Files (Afficher dans les fichiers). .)

95e0eca881d35f6b.png

  1. Copiez un fichier dans celui-ci. Vous pouvez télécharger des images à partir de sites tels que Pixabay. Nous vous recommandons de renommer l'image de manière simple. Dans le cas présent, l'image a été renommée flower1.jpg.

Ensuite, revenez dans Android Studio. Le fichier devrait s'afficher dans le dossier des éléments.

cfa53c9c75a033d8.png

Vous êtes maintenant prêt à ajouter un libellé à cette image.

6. Écrire le code de classification pour ajouter un libellé à l'image

Une partie que nous attendions tous depuis longtemps : la vision par ordinateur sur Android !

  1. Vous écrivez votre code dans le fichier MainActivity. Vous le trouverez donc dans le dossier du projet sous com.google.devrel.imageclassifierstep1 (ou tout autre espace de noms équivalent si vous en avez sélectionné un autre). Notez qu'en règle générale, trois dossiers d'espace de noms sont configurés dans un projet Android Studio, un pour l'application et un pour l'application Android Test. Vous trouverez votre MainActivity dans celui dont la description ne figure pas entre crochets.

B5aef8dd5e26b6c2.png

Si vous avez choisi d'utiliser Kotlin, vous vous demandez peut-être pourquoi le dossier parent s'appelle Java. Il s'agit d'un artefact historique, créé à partir de l'époque où Android Studio n'était Java que. Les versions ultérieures peuvent résoudre ce problème, mais ne vous inquiétez pas si vous souhaitez utiliser Kotlin, c'est un problème. Il s'agit simplement du nom de dossier du code source.

  1. Ouvrez le fichier MainActivity. Vous y trouverez un fichier de classe appelé "MainActivity" dans l'éditeur de code. Elle doit se présenter comme ceci :
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

Sous l'accolade fermante, vous pouvez ajouter un code d'extension qui ne fait pas partie de la classe, mais qui peut être utilisé par la classe. Vous aurez besoin d'une extension pour lire un fichier à partir des éléments sous forme de bitmap. Permet de charger l'image précédemment copiée dans le dossier des éléments.

  1. Ajoutez ce code:
// 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 }
}

Android Studio se plaindra probablement à ce stade et mettra en évidence une partie du code en rouge, comme Context, Bitmap et IOException:

D2bde17e3c04aeed.png

Ne vous inquiétez pas, En effet, vous n'avez pas encore importé les bibliothèques qui les contiennent. Android Studio propose un raccourci pratique.

  1. Faites glisser le curseur sur le mot, puis appuyez sur Alt+Entrée (Option+Entrée sur Mac) pour générer l'importation.
  2. Vous pouvez ensuite charger le bitmap à partir des éléments et le placer dans ImageView. Revenez dans la section onCreateFunction de MainActivity, puis ajoutez le code suivant juste en dessous de la ligne 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. Comme précédemment, une partie du code est mise en surbrillance en rouge. Placez le curseur sur cette ligne, puis utilisez les touches Alt+Entrée / Option+Entrée pour ajouter automatiquement les importations.
  2. Dans le fichier layout.xml que vous avez créé précédemment, vous avez attribué le nom ImageToLabel à la vue ImageView. La première ligne crée donc une instance d'un objet ImageView, appelée img, à l'aide des informations de mise en page. Elle trouve les détails à l'aide de findViewById, une fonction Android intégrée. Il utilise ensuite le nom de fichier flower1.jpg pour charger une image à partir du dossier des éléments à l'aide de la fonction assetsToBitmap que vous avez créée à l'étape précédente. Enfin, il utilise la classe abstraite bitmap pour charger le bitmap dans img.
  3. Le fichier de mise en page comporte un élément TextView qui sera utilisé pour afficher les libellés déduits de l'image. Récupérez un objet de code pour cette étape. Immédiatement sous le code précédent, ajoutez le code suivant:
val txtOutput : TextView = findViewById(R.id.txtOutput)

Comme précédemment, cette commande recherche les informations du fichier de mise en page pour l'affichage de texte à l'aide de son nom (vérifiez le XML à l'aide du nom txtOutput) et l'utilise pour instancier un objet TextView appelé txtOutput.

De la même manière, vous allez créer un objet button pour représenter le bouton et l'instancier avec le contenu du fichier de mise en page.

Dans le fichier de mise en page, nous avons appelé le bouton btnTest, et nous pouvons donc l'instancier comme suit:

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

Maintenant que le code et les commandes sont initialisés, l'étape suivante (et finale) consiste à les utiliser pour obtenir une inférence sur l'image.

Avant de poursuivre, assurez-vous que le code onCreate se présente comme suit:

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

Aucun des mots clés ne doit être rouge, ce qui signifie qu'ils n'ont pas encore été importés. Si tel est le cas, revenez en arrière et effectuez les actions ALT+Entrée pour générer les importations.

Lorsque vous utilisez l'étiqueteur d'images de ML Kit, la première étape consiste généralement à créer un objet Options pour personnaliser le comportement. Vous allez convertir votre image dans un format InputImage reconnu par ML Kit. Vous créerez ensuite un objet Labeler pour effectuer l'inférence. Vous recevrez un rappel asynchrone des résultats, que vous pourrez ensuite analyser.

Sur le bouton que vous venez de créer, effectuez toutes ces opérations dans son événement onClickListener. Voici le code complet:

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
  }
}
  • Lorsque l'utilisateur clique pour la première fois sur le bouton, le code instancie un étiqueteur à l'aide de ImageLabeling.getClient, en lui transmettant des ImageLabelerOptions. Il inclut une propriété DEFAULT_OPTIONS, qui nous permet d'être opérationnel rapidement.
  • Vous allez ensuite créer une Image d'entrée à partir du bitmap à l'aide de la méthode fromBitmap. InputImage est le format souhaité par ML Kit pour le traitement des images.
  • Enfin, l'étiqueteur traitera l'image et effectuera un rappel asynchrone en cas de réussite ou d'échec. Si l'inférence réussit, le rappel inclura une liste de libellés. Vous pouvez ensuite analyser cette liste d'étiquettes pour lire le texte et l'indice de confiance. Si elle échoue, elle vous renvoie une exception que vous pouvez utiliser pour signaler à l'utilisateur.

Voilà, c'est terminé ! Vous pouvez désormais exécuter l'application sur un appareil Android ou dans l'émulateur. Pour en savoir plus, consultez la page https://developer.android.com/studio/run/emulator.

Voici l'application exécutée dans l'émulateur. L'image et le bouton s'affichent, et le libellé est vide.

C07f5f307f070dc7.png

Appuyez sur le bouton. Vous obtenez un ensemble de libellés pour l'image.

550ccaa783363551.png

Ici, vous pouvez constater que l'étiqueteur a déterminé que l'image avait de grandes chances de contenir un pétale, une fleur, une plante et le ciel. Tous ces éléments sont corrects, et ils montrent tous que le modèle s'efforce d'analyser l'image.

Mais il ne permet pas encore de déterminer qu'il s'agit d'une marguerite. Pour cela, vous aurez besoin d'un modèle personnalisé entraîné sur des fleurs spécifiques, et vous apprendrez à le faire dans le prochain atelier.

Dans les étapes suivantes, vous allez découvrir comment créer cette application sur iOS.

7. Créer un classificateur d'images sur iOS – Premiers pas

Vous pouvez créer une application similaire sur iOS à l'aide de Xcode.

  1. Lancez Xcode et, dans le menu du fichier, sélectionnez New Project (Nouveau projet). La boîte de dialogue suivante s'affiche:

8fb0e6a9d6ac275e.png

  1. Sélectionnez App (Application) comme indiqué, puis cliquez sur Next (Suivant). Vous serez invité à choisir des options pour votre projet. Donnez-lui un nom et un identifiant d'organisation comme indiqué. Assurez-vous que le type d'interface est Storyboard et que la langue est Swift, comme indiqué.

76c6bdb5aee7659c.png

  1. Si vous souhaitez déployer sur un téléphone et avoir configuré un profil de développeur, vous pouvez définir un paramètre d'équipe. Sinon, laissez-le sur Aucun. Vous pouvez utiliser le simulateur iOS pour exécuter votre application.
  2. Cliquez sur Suivant, puis sélectionnez un dossier dans lequel stocker votre projet et ses fichiers. Notez l'emplacement de ce projet, car vous en aurez besoin à l'étape suivante.
  3. Fermez Xcode pour le moment, car vous le rouvrirez à l'aide d'un autre fichier d'espace de travail à la prochaine étape.

8. Intégrer ML Kit à l'aide de CocoaPods

ML Kit fonctionne également sur iOS, mais vous pouvez l'utiliser de la même façon qu'un classificateur d'images. Pour l'intégrer, vous allez utiliser CocoaPods. Si ce n'est pas déjà fait, suivez les instructions de la page https://cocoapods.org/

  1. Ouvrez le répertoire dans lequel vous avez créé votre projet. Il doit contenir votre fichier .xcodeproj.

Ici, vous pouvez voir le fichier .xcodeproj dans lequel je me trouve au bon endroit.

E2966A47E84eb398.png

  1. Dans ce dossier, créez un fichier nommé Podfile. Il n'y a pas d'extension : il s'agit simplement de Podfile. Dans celui-ci, ajoutez la ligne suivante:
platform :ios, '10.0'

target 'ImageClassifierStep1' do
        pod 'GoogleMLKit/ImageLabeling'
end
  1. Enregistrez-la, puis revenez au terminal. Dans le même annuaire, saisissez pod install. CocoaPods téléchargera les bibliothèques et les dépendances appropriées, puis créera un espace de travail qui combinera votre projet avec ses dépendances externes.

3b4c628b0cbface8.png

Notez qu'à la fin, vous serez invité à fermer vos sessions Xcode et à utiliser le fichier Workspace à partir de maintenant. Ouvrez ce fichier, et Xcode se lancera avec votre projet d'origine et les dépendances externes.

32090e0024b6b5ef.png

Vous pouvez à présent passer à l'étape suivante et créer l'interface utilisateur.

9. Créer l'interface utilisateur iOS à l'aide des storyboards

  1. Ouvrez le fichier Main.storyboard. Vous verrez une mise en page d'interface utilisateur avec une surface de conception pour un téléphone.
  2. En haut à droite de l'écran, un bouton + vous permet d'ajouter des commandes. Cliquez dessus pour obtenir la palette des commandes.

e63bc4bafa54cc21.png

  1. Ensuite, glissez-déposez ImageView sur un élément Button (Bouton) et Label (Libellé) sur la surface de conception. Classez-les de haut en bas comme indiqué:

f9dfc55616b25f11.png

  1. Double-cliquez sur le bouton pour remplacer le texte du bouton par le bouton Button par Classifier.
  2. Faites glisser les poignées de contrôle autour du libellé pour l'agrandir. (Choisissez la même largeur que UIImageView et doublez la hauteur.)
  3. Après avoir sélectionné le libellé, cliquez sur le bouton des sélecteurs en haut à droite pour afficher la palette des inspecteurs.
  4. Ensuite, recherchez le paramètre Lignes et assurez-vous qu'il est défini sur 0. Cela permet au libellé d'afficher un nombre dynamique de lignes.

A39708b320b56b30.png

Vous êtes désormais prêt à passer à l'étape suivante, qui consiste à raccorder l'interface utilisateur au code à l'aide de prises et d'actions.

10. Créer des actions et des sorties

Lorsque vous développez des applications iOS à l'aide de storyboards, vous consultez les informations de mise en page de vos commandes à l'aide de prises et vous définissez le code à exécuter lorsque l'utilisateur effectue une action à l'aide d'actions.

À l'étape suivante, vous devrez créer des prises pour ImageView et le libellé. La classe ImageView sera référencée dans le code pour y charger l'image. L'étiquette sera référencée dans le code pour définir son texte sur la base de l'inférence donnée par ML Kit.

  1. Fermez la palette d'inspection en cliquant sur la commande en haut à droite de l'écran, puis sur le bouton Add Editor on Right (Ajouter un éditeur à droite) situé juste en dessous.

77255f7d6284750.png

  1. L'écran sera flou, là où le fichier main.storyboard est ouvert deux fois. Sur la gauche, dans le navigateur de projets, sélectionnez ViewController.swift afin que le code du contrôleur s'ouvre. Il semble que la surface de votre création ait disparu de l'éditeur de storyboard à gauche, mais ne vous inquiétez pas, elle est toujours présente.
  2. Pour la récupérer, cliquez sur Afficher la manette dans la scène View Controller. Vérifiez que votre UI se présente comme suit (avec le storyboard à gauche et le code pour ViewController.swift à droite).

7eb21c7f9d43c9bc.png

  1. Sélectionnez UIImageView dans la surface de conception à gauche, puis, tout en appuyant sur la touche CONTRÔLE, faites-la glisser vers le code à droite, en le déposant juste sous le mot clé class (à la ligne 11 de la capture d'écran ci-dessus).

Une flèche s'affiche lorsque vous faites glisser la notification. Voici un pop-up qui s'affiche:

37477f0613948318.png

  1. Remplissez le champ Name (Nom) avec "imageView" et cliquez sur Connect (Connecter).
  2. Répétez le processus avec le libellé et nommez-le "lblOutput".
  3. Important: Vous allez effectuer la même opération pour le bouton, mais veillez à définir le type de connexion sur Action et non sur Prise.

7281b6eea9fb6c23.png

  1. Donnez-lui le nom "doClassification", puis cliquez sur Connect (Connecter).

Une fois que vous avez terminé, votre code doit se présenter comme suit: (notez que le libellé et la vue d'image sont déclarés comme étant IBOutlet (Interface Builder Outlet) et que le bouton sous IBAction (Interface 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. Enfin, regroupez une image avec l'application afin de pouvoir classer facilement les images. Pour cela, faites glisser le fichier depuis l'explorateur de fichiers vers l'explorateur à gauche de Xcode. Lorsque vous le supprimez, un pop-up s'affiche comme suit:

889ff33eaec785ec.png

  1. Assurez-vous que la case à cocher de la section Add to Targets (Ajouter aux cibles) est cochée, puis cliquez sur Finish (Terminer).

Le fichier est fourni avec votre application, et vous pouvez désormais le classer facilement. Vous pouvez à présent coder l'interface utilisateur pour classer les images.

11. Rédiger le code de classification des images

Maintenant que tout est configuré, il est très facile d'écrire le code pour effectuer la classification des images.

  1. Pour fermer le graphiste, cliquez sur le X dans l'angle supérieur gauche, au-dessus de la surface de conception. Vous pourrez ainsi vous concentrer uniquement sur votre code. Dans la suite de cet atelier, vous allez modifier ViewController.swift.
  2. Importez les bibliothèques MLKitVision et MLKit ImageLabeling en ajoutant le code suivant en dessous de l'importation d'UIKit:
import MLKitVision
import MLKitImageLabeling
  1. Ensuite, dans votre fonction viewDidLoad, initialisez l'élément ImageView à l'aide du fichier fourni dans l'application:
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    imageView.image = UIImage(named:"flower1.jpg")
}
  1. Créez une fonction d'assistance pour obtenir les étiquettes de l'image, immédiatement en dessous de viewDidLoad():
func getLabels(with image: UIImage){
  1. Créez une image VisionImage. ML Kit utilise ce type lors de la classification d'images. Dans le fond "getLabels", ajoutez le code suivant:
let visionImage = VisionImage(image: image)
visionImage.orientation = image.imageOrientation
  1. Créez ensuite les options pour l'étiqueteur d'images. Il sera initialisé à l'aide de ces options. Dans ce cas, il vous suffit de définir une option de base pour confidenceThreshold. Cela signifie que vous ne devez demander à l'étiqueteur que de renvoyer des étiquettes ayant un niveau de confiance supérieur ou égal à 0,4. Par exemple, pour notre fleur, les classes comme "plante" ou "pétale" auront une confiance élevée, mais celles comme "basket" ou "voiture" en possède une faible.
let options = ImageLabelerOptions()
options.confidenceThreshold = 0.4
  1. Créez ensuite l'étiqueteur à l'aide des options suivantes:
let labeler = ImageLabeler.imageLabeler(options: options)
  1. Une fois l'étiqueteur installé, vous pouvez le traiter. Vous recevrez un rappel asynchrone avec des étiquettes (en cas de réussite) et une erreur (en cas d'échec). Vous pourrez ensuite traiter une autre fonction que nous créerons dans un instant.
labeler.process(visionImage) { labels, error in
    self.processResult(from: labels, error: error)
  }

Si Xcode se plaint qu'il n'y a pas de membre processResult, ne vous inquiétez pas. Vous ne l'avez pas encore implémenté, et vous le ferez par la suite.

Pour vous simplifier la tâche, voici le guide complet sur getLabels:

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

Vous devez donc implémenter la fonction processResult. C'est très simple à présent, puisque nous disposons d'étiquettes et d'un objet d'erreur qui nous sont renvoyés. Les étiquettes doivent être castées dans le type ImageLabel de ML Kit.

Une fois cela fait, vous pouvez itérer l'ensemble d'étiquettes, extraire la description et la valeur de confiance, puis les ajouter à un var appelé labeltexts. Une fois que vous effectuez toutes ces itérations, il vous suffit de définir l'élément lblOutput.text sur cette valeur.

Voici la fonction complète:

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

Il suffit d'appeler getLabels lorsque l'utilisateur appuie sur le bouton.

Lorsque vous avez créé l'action, tout a été programmé pour vous. Il vous suffit donc de mettre à jour le IBAction appelé doClassificaiton que vous avez créé précédemment pour appeler getLabels.

Voici le code pour l'appeler avec le contenu de imageView:

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

Maintenant, exécutez votre application et essayez. comme vous pouvez le voir ici:

eb8e6c1b2e2c65e0.png

Notez que votre mise en page peut varier en fonction de votre appareil.

L'atelier de programmation n'explore pas différents types de mises en page par appareil, ce qui est assez complexe en soi. Si l'interface utilisateur ne s'affiche pas correctement, revenez à l'éditeur de storyboard. En bas de l'écran, vous verrez une section Afficher en tant que qui vous permet de sélectionner un appareil spécifique. Choisissez-en une qui correspond à l'image ou à l'appareil que vous testez, puis modifiez l'interface utilisateur en conséquence.

À mesure que vous vous développez dans le développement iOS, vous apprendrez à utiliser des contraintes pour vous assurer de la cohérence de votre interface utilisateur sur les différents téléphones, mais cela dépasse le cadre de cet atelier.

12. Félicitations !

Vous venez de mettre en œuvre une application sur Android et iOS qui fournit une vision globale de votre ordinateur grâce à un modèle générique. Vous avez déjà effectué la majeure partie du travail.

Dans l'atelier de programmation suivant, vous allez créer un modèle personnalisé qui reconnaît différents types de fleurs. En seulement quelques lignes de code, vous pourrez l'implémenter dans l'application pour le rendre plus utile.