Commencer à reconnaître les images dans Core ML

Grâce aux avancées technologiques, nos appareils peuvent utiliser leurs appareils photo intégrés pour identifier et étiqueter avec précision les images à l'aide d'un ensemble de données pré-formé. Vous pouvez également former vos propres modèles, mais dans ce tutoriel, nous utiliserons un modèle open-source pour créer une application de classification d'images..

Je vais vous montrer comment créer une application capable d'identifier les images. Nous allons commencer avec un projet Xcode vide et mettre en œuvre étape par étape la reconnaissance d'images basée sur l'apprentissage automatique.

Commencer

Version Xcode

Avant de commencer, assurez-vous que la dernière version de Xcode est installée sur votre Mac. Ceci est très important car Core ML ne sera disponible que sur Xcode 9 ou plus récent. Vous pouvez vérifier votre version en ouvrant Xcode et en allant à Xcode > À propos de Xcode dans la barre d'outils supérieure. 

Si votre version de Xcode est antérieure à Xcode 9, vous pouvez aller sur le Mac App Store et la mettre à jour, ou si vous ne l'avez pas, téléchargez-le gratuitement..

Exemple de projet

Nouveau projet

Après vous être assuré d'avoir la bonne version de Xcode, vous devez créer un nouveau projet Xcode.. 

Allez-y et ouvrez Xcode et cliquez sur Créer un nouveau projet Xcode.

Ensuite, vous devrez choisir un modèle pour votre nouveau projet Xcode. C'est assez commun d'utiliser un Single View App, alors allez-y et sélectionnez cela et cliquez sur Suivant.

Vous pouvez nommer votre projet comme bon vous semble, mais je nommerai le mien Classification des images CoreML. Pour ce projet, nous utiliserons Swift, alors assurez-vous qu’il est sélectionné dans le La langue menu déroulant.


Préparation au débogage

Connecter un iPhone

Le simulateur Xcode n'ayant pas d'appareil photo, vous devez brancher votre iPhone. Malheureusement, si vous n'avez pas d'iPhone, vous devrez en emprunter un pour pouvoir suivre ce didacticiel (et pour toute autre application liée à l'appareil photo). Si vous avez déjà un iPhone connecté à Xcode, vous pouvez passer à l'étape suivante..

Une nouvelle fonctionnalité intéressante de Xcode 9 est que vous pouvez déboguer sans fil votre application sur un appareil. Prenons donc le temps de le configurer maintenant:

Dans la barre de menu supérieure, choisissez La fenêtre > Appareils et simulateurs.Dans la fenêtre qui apparaît, assurez-vous que Dispositifs est sélectionné en haut.

Maintenant, branchez votre appareil avec un câble Lightning. Cela devrait faire apparaître votre appareil dans le volet gauche de la fenêtre. Appareils et simulateurs la fenêtre. Il suffit de cliquer sur votre appareil et de vérifier la Se connecter via le réseau boîte.

Vous pourrez désormais déboguer sans fil sur cet iPhone pour toutes les applications futures. Pour ajouter d'autres appareils, vous pouvez suivre un processus similaire..

Sélection du simulateur

Lorsque vous souhaitez enfin utiliser votre iPhone pour déboguer, sélectionnez-le simplement dans le menu déroulant situé en regard de la fenêtre. Courir bouton. Vous devriez voir une icône de réseau à côté, indiquant qu'il est connecté pour le débogage sans fil. J'ai sélectionné IPhone de Vardhan, mais vous devez sélectionner votre appareil spécifique.

Plonger plus profondément

Maintenant que vous avez créé votre projet et configuré votre iPhone comme simulateur, nous allons plonger un peu plus loin et commencer à programmer l'application de classification des images en temps réel.

Préparer votre projet

Obtenir un modèle

Pour pouvoir créer votre application de classification d’images Core ML, vous devez d’abord obtenir le modèle Core ML sur le site Web d’Apple. Comme je l'ai déjà mentionné, vous pouvez également former vos propres modèles, mais cela nécessite un processus séparé. Si vous faites défiler l'écran vers le bas du site Web d'apprentissage automatique d'Apple, vous pourrez choisir et télécharger un modèle..

Dans ce tutoriel, je vais utiliser le MobileNet.mlmodel modèle, mais vous pouvez utiliser n’importe quel modèle tant que vous connaissez son nom et que vous pouvez vous assurer qu’il se termine par. .mlmodel.

Importer des bibliothèques

Il y a quelques cadres que vous aurez besoin d'importer avec les fonctions habituelles. UIKit. En haut du fichier, assurez-vous que les instructions d'importation suivantes sont présentes:

importer UIKit importer AVKit import Vision

Nous aurons besoin AVKit parce que nous allons créer un AVCaptureSession pour afficher un flux en direct tout en classant les images en temps réel. En outre, puisque cela utilise la vision par ordinateur, nous devrons importer le Vision cadre.

Concevoir votre interface utilisateur

Une partie importante de cette application affiche les étiquettes de données de classification des images, ainsi que le flux vidéo en direct de la caméra de l'appareil. Pour commencer à concevoir votre interface utilisateur, dirigez-vous vers votre Tableau principal fichier.

Ajout d'une vue d'image

Dirigez-vous vers le Bibliothèque d'objets et rechercher un Vue d'image. Faites-le simplement glisser sur votre contrôleur de vue pour l'ajouter. Si vous le souhaitez, vous pouvez également ajouter une image de substitution afin d'avoir une idée générale de ce à quoi ressemblera l'application lorsqu'elle sera utilisée..

Si vous choisissez d’avoir une image de marque de réservation, assurez-vous que le Mode de contenu est réglé sur Aspect Fit, et que vous cochez la case qui dit Clip to Bounds. De cette façon, l'image n'apparaîtra pas étirée et n'apparaîtra pas en dehors du UIImageView boîte.

Voici à quoi devrait ressembler votre story-board:

Ajout d'une vue

Retour dans le Bibliothèque d'objets, rechercher un Vue et faites-le glisser sur votre contrôleur de vue. Cela servira de joli fond pour nos étiquettes afin qu'elles ne soient pas cachées dans l'image affichée. Nous allons rendre cette vue transparente afin qu'une partie de la couche d'aperçu soit toujours visible (il s'agit simplement d'une belle retouche pour l'interface utilisateur de l'application)..

Faites-le glisser vers le bas de l'écran pour qu'il touche le conteneur sur trois côtés. Peu importe la hauteur que vous choisissez car nous établirons des contraintes pour cela dans un instant ici.

Ajout d'étiquettes

C’est peut-être la partie la plus importante de notre interface utilisateur. Nous devons afficher ce que pense notre application de l'objet et son niveau de confiance (niveau de confiance). Comme vous l'avez probablement deviné, vous devrez faire glisser deux Étiquette(s)du Bibliothèque d'objets à la vue que nous venons de créer. Faites glisser ces étiquettes quelque part près du centre, empilées les unes sur les autres.

Pour l’étiquette du haut, dirigez-vous vers le Inspecteur d'attributs et cliquez sur le bouton en regard du style et de la taille de la police et, dans la fenêtre contextuelle, sélectionnez Système comme le Police de caractère. Pour le différencier de l'étiquette de confiance, sélectionnez Noir comme le style. Enfin, changez le Taille à 24.

Pour l’étiquette du bas, suivez les mêmes étapes, mais au lieu de sélectionner Noir comme le style, sélectionner Ordinaire, et pour le Taille, sélectionner 17.

L'image ci-dessous montre comment votre Storyboard devrait regarder lorsque vous avez ajouté toutes ces vues et étiquettes. Ne vous inquiétez pas si elles ne sont pas exactement les mêmes que les vôtres. nous ajouterons des contraintes à la prochaine étape.

Ajout de contraintes

Pour que cette application fonctionne sur différentes tailles d'écran, il est important d'ajouter des contraintes. Cette étape n'est pas cruciale pour le reste de l'application, mais il est vivement recommandé de le faire dans toutes vos applications iOS..

Contraintes de vue d'image

La première chose à contraindre est notre UIImageView. Pour ce faire, sélectionnez votre vue d'image et ouvrez le Menu Pin dans la barre d'outils inférieure (cela ressemble à un carré avec les contraintes et c'est la seconde à partir de la droite). Ensuite, vous devrez ajouter les valeurs suivantes:

Avant de continuer, assurez-vous que le Contraindre aux marges La case n'est pas cochée car cela créera un espace entre l'écran et la vue réelle de l'image. Ensuite, appuyez sur Entrer.Maintenant votre UIImageView est centré sur l'écran, et il devrait ressembler à toutes les tailles de périphériques.

Afficher les contraintes

La prochaine étape consiste à contraindre la vue sur laquelle les étiquettes apparaissent. Sélectionnez la vue, puis allez à la Menu Pin encore. Ajoutez les valeurs suivantes:

Maintenant, appuyez simplement sur Entrer pour sauvegarder les valeurs. Votre vue est maintenant limitée au bas de l'écran..

Contraintes d'étiquette

Étant donné que la vue est maintenant contrainte, vous pouvez ajouter des contraintes aux étiquettes par rapport à la vue plutôt qu'à l'écran. Ceci est utile si vous décidez ultérieurement de modifier la position des étiquettes ou la vue..

Sélectionnez les deux étiquettes et placez-les dans une vue de pile. Si vous ne savez pas comment faire cela, il vous suffit d’appuyer sur le bouton (le deuxième en partant de la gauche) qui ressemble à une pile de livres avec une flèche vers le bas. Vous verrez alors que les boutons deviennent un objet sélectionnable..

Cliquez sur votre vue de pile, puis cliquez sur le bouton Aligner le menu (troisième à gauche) et assurez-vous que les cases suivantes sont cochées:

Maintenant, appuyez sur Entrer. Vos étiquettes doivent être centrées dans la vue de l'étape précédente et elles apparaîtront désormais de la même manière sur toutes les tailles d'écran..

Points de vente d'Interface Builder

La dernière étape de l’interface utilisateur consisterait à connecter les éléments à votre ViewController () classe. Ouvrez simplement le Assistant rédacteur et alors Clic de contrôle et Traîne chaque élément au sommet de votre classe à l'intérieur ViewController.swift. Voici ce que je vais les nommer dans ce tutoriel:

  • UILabel: objectLabel
  • UILabel: confianceLabel
  • UIImageView: imageView

Bien sûr, vous pouvez les nommer comme vous voulez, mais ce sont les noms que vous trouverez dans mon code.

Préparation d'une session de capture

Le flux vidéo en direct nécessitera une AVCaptureSession, alors créons-en un maintenant. Nous allons également afficher notre entrée de caméra à l'utilisateur en temps réel. Faire une session de capture est un processus assez long, et il est important que vous compreniez comment le faire car cela vous sera utile dans tout autre développement que vous réalisez en utilisant l'appareil photo embarqué sur n'importe quel appareil Apple..

Extension de classe et fonction

Pour commencer, nous pouvons créer une extension de classe puis la rendre conforme à la AVCaptureVideoDataOutputSampleBufferDelegate protocole. Vous pouvez facilement le faire dans le réel ViewController classe, mais nous utilisons ici les meilleures pratiques pour que le code soit soigné et organisé (c’est ce que vous feriez pour les applications de production).

Pour que nous puissions appeler cela à l'intérieur de viewDidLoad (), nous devrons créer une fonction appelée setupSession () qui ne prend aucun paramètre. Vous pouvez nommer ce que vous voulez, mais faites attention quand vous appelez cette méthode plus tard..

Une fois que vous avez terminé, votre code devrait ressembler à ceci:

// MARK: - Extension AVCaptureSession ViewController: AVCaptureVideoDataOutputSampleBufferDelegate func setupSession () // Votre code va ici

Session d'entrée et de capture de périphérique

La première étape de la création de la session de capture consiste à vérifier si le périphérique est équipé d'une caméra. En d'autres termes, n'essayez pas d'utiliser l'appareil photo s'il n'y en a pas. Nous aurons ensuite besoin de créer la session de capture réelle.

Ajoutez le code suivant à votre setupSession () méthode:

guard let device = AVCaptureDevice.default (for: .video) else return guard let input = try? AVCaptureDeviceInput (device: device) else return let session = AVCaptureSession () session.sessionPreset = .hd4K3840x2160

Ici, nous utilisons un garde a laissé déclaration pour vérifier si le périphérique (AVCaptureDevice) a une caméra. Lorsque vous essayez d’obtenir la caméra du périphérique, vous devez également spécifier la type de support, qui, dans ce cas, est .vidéo.

Ensuite, nous créons un AVCaptureDeviceInput, qui est une entrée qui porte le média de l'appareil à la session de capture.

Enfin, nous créons simplement une instance du AVCaptureSession classe, puis l'assigner à une variable appelée session. Nous avons personnalisé le débit et la qualité de la session pour Ultra-Haute Définition (UHD), soit 3 840 x 2 160 pixels. Vous pouvez expérimenter avec ce paramètre pour voir ce qui fonctionne pour vous..

Couche d'aperçu et sortie

La prochaine étape pour faire notre AVCaptureSession La configuration consiste à créer un calque de prévisualisation dans lequel l’utilisateur peut voir les données saisies par la caméra. Nous allons ajouter cela sur le UIImageView nous avons créé plus tôt dans notre Storyboard. La partie la plus importante, cependant, consiste à créer notre sortie pour que le modèle Core ML puisse être traitée ultérieurement dans ce didacticiel, ce que nous ferons également à cette étape..

Ajoutez le code suivant directement sous le code de l'étape précédente:

et previewLayer = AVCaptureVideoPreviewLayer (session: session) previewLayer.frame = view.frame imageView.layer.addSublayer (previewLayer) let output = AVCaptureVideoDataOutput () output.setSampleBufferDelegate (auto, file d'attente, DispatchQueue (label: videoQueue)) (sortie)

Nous créons d’abord une instance du AVCaptureVideoPreviewLayer classe, puis initialisez-le avec la session que nous avons créée à l'étape précédente. Après cela, nous l'attribuons à une variable appelée previewLayer. Cette couche est utilisée pour afficher les entrées de la caméra.

Ensuite, nous allons faire en sorte que la couche d'aperçu remplisse tout l'écran en définissant les dimensions du cadre sur celles de la vue. De cette façon, l'apparence souhaitée persistera pour toutes les tailles d'écran. Pour afficher la couche d'aperçu, nous l'ajouterons en tant que sous-couche de la UIImageView que nous avons créé lorsque nous faisions l'interface utilisateur.

Maintenant, pour la partie importante: Nous créons une instance du AVCaptureDataOutput classe et l'affecter à une variable appelée sortie

Session d'entrée et de démarrage

Enfin, nous avons terminé notre session de capture. Tout ce qui reste à faire avant le code Core ML actuel consiste à ajouter l'entrée et à démarrer la session de capture.. 

Ajoutez les deux lignes de code suivantes directement sous l'étape précédente:

// Définit l'entrée de AVCaptureSession sur l'entrée de caméra du périphérique session.addInput (input) // Démarre la session de capture session.startRunning ()

Cela ajoute l'entrée que nous avons créée précédemment à la AVCaptureSession, car avant cela, nous n'avions créé que l'entrée et nous ne l'avions pas ajoutée. Enfin, cette ligne de code démarre la session que nous avons passé si longtemps à créer.

Intégration du modèle de base ML

Nous avons déjà téléchargé le modèle. La prochaine étape consiste à l'utiliser dans notre application. Commençons donc à l'utiliser pour classer les images. 

Méthode déléguée

Pour commencer, vous devez ajouter la méthode de délégation suivante à votre application:

func captureOutput (_ sortie: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, depuis la connexion: AVCaptureConnection) // Votre code va ici

Cette méthode de délégation est déclenchée lors de l'écriture d'une nouvelle image vidéo. Dans notre application, cela se produit chaque fois qu'une image est enregistrée via notre flux vidéo en direct (la vitesse de cette opération dépend uniquement du matériel sur lequel l'application est exécutée)..

Pixel Buffer et Model

Nous allons maintenant transformer l'image (une image du flux en direct) en un tampon de pixels, qui est reconnaissable par le modèle. Avec cela, nous pourrons créer plus tard un VNCoreMLRequest

Ajoutez les deux lignes de code suivantes dans la méthode de délégation créée précédemment:

guard let pixelBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer (sampleBuffer) else return guard let modèle = essayer? VNCoreMLModel (for: MobileNet (). Model) else retour

Tout d'abord, nous créons un tampon de pixels (un format accepté par Core ML) à partir de l'argument transmis via la méthode delegate, puis nous l'affectons à une variable appelée pixelBuffer. Ensuite, nous assignons notre MobileNet modèle à une constante appelée modèle.

Notez que les deux sont créés en utilisant garde a laissé déclarations, et que la fonction retournera si l’un de ces éléments est néant valeurs.

Créer une demande

Après l'exécution des deux lignes de code précédentes, nous savons avec certitude que nous disposons d'un tampon de pixels et d'un modèle. La prochaine étape serait de créer un VNCoreMLRequest en utilisant les deux. 

Juste en dessous de l'étape précédente, collez les lignes de code suivantes à l'intérieur de la méthode delegate:

let request = VNCoreMLRequest (modèle: modèle) (données, erreur) dans // Votre code va ici

Ici, nous créons une constante appelée demande et en lui assignant la valeur de retour de la méthode VNCoreMLRequest quand notre modèle est passé dedans.

Obtention et tri des résultats

Nous avons presque fini! Il ne nous reste plus qu'à obtenir nos résultats (ce que le modèle considère comme notre image) et les afficher ensuite à l'utilisateur.. 

Ajoutez les deux lignes de code suivantes dans le gestionnaire d’achèvement de votre demande:

// Vérifie si le format des données est correct et l’assigne à la protection des résultats. Laisse results = data.results as? [VNClassificationObservation] else return // Assigne le premier résultat (s'il existe) à la protection firstObject, laissant à firstObject = results.first else return

Si les résultats des données (du gestionnaire d’achèvement de la demande) sont disponibles sous la forme d’un tableau de VNClassificationObservations, cette ligne de code obtient le premier objet du tableau que nous avons créé précédemment. Il sera ensuite affecté à une constante appelée firstObject. Le premier objet de ce tableau est celui pour lequel le moteur de reconnaissance d’image a le plus de confiance..

Affichage de données et traitement d'images

Rappelez-vous quand nous avons créé les deux étiquettes (confiance et objet)? Nous allons maintenant les utiliser pour afficher ce que le modèle pense que l'image est.

Ajoutez les lignes de code suivantes après l'étape précédente:

si firstObject.confidence * 100> = 50 self.objectLabel.text = firstObject.identifier.capitalized self.confidenceLabel.text = Chaîne (firstObject.confidence * 100) + "%"

le si Cette instruction garantit que l’algorithme est certain à au moins 50% de son identification de l’objet. Ensuite, nous venons de définir le firstObject comme le texte de la objectLabel parce que nous savons que le niveau de confiance est suffisamment élevé. Nous allons simplement afficher le pourcentage de certitude en utilisant la propriété text de confianceLabel. Puisque firstObject.confidence est représenté sous forme décimale, nous devrons multiplier par 100 pour obtenir le pourcentage.

La dernière chose à faire est de traiter l'image à l'aide de l'algorithme que nous venons de créer. Pour ce faire, vous devez taper la ligne de code suivante directement avant de quitter le captureOutput (_: didOutput: from :) méthode déléguée:

essayer? VNImageRequestHandler (cvPixelBuffer: pixelBuffer, options: [:]). Perform ([demande])

Conclusion

Les concepts que vous avez appris dans ce tutoriel peuvent être appliqués à de nombreux types d'applications. J'espère que vous avez aimé apprendre à classer les images à l'aide de votre téléphone. Bien que cela ne soit pas encore parfait, vous pouvez former vos propres modèles à l'avenir pour être plus précis..

Voici à quoi devrait ressembler l'application lorsqu'elle est terminée:

Pendant que vous êtes ici, consultez certains de nos autres articles sur l'apprentissage automatique et le développement d'applications iOS.!