Aan de slag met beeldherkenning in Core ML

Met technologische vooruitgang zijn we op het punt gekomen dat onze apparaten hun ingebouwde camera's kunnen gebruiken om afbeeldingen nauwkeurig te identificeren en labelen met behulp van een vooraf ingestelde gegevensset. Je kunt ook je eigen modellen trainen, maar in deze zelfstudie gebruiken we een opensource-model om een ​​app voor beeldclassificatie te maken.

Ik zal je laten zien hoe je een app kunt maken die afbeeldingen kan identificeren. We zullen beginnen met een leeg Xcode-project en stap voor stap beeldherkenning op basis van machine learning implementeren.

Ermee beginnen

Xcode versie

Controleer voordat je begint of je de nieuwste versie van Xcode op je Mac hebt geïnstalleerd. Dit is erg belangrijk omdat Core ML alleen beschikbaar zal zijn op Xcode 9 of nieuwer. U kunt uw versie controleren door Xcode te openen en naar toe te gaan Xcode > Over Xcode in de bovenste werkbalk. 

Als je versie van Xcode ouder is dan Xcode 9, kun je naar de Mac App Store gaan en deze bijwerken, of als je hem niet hebt, download hem dan gratis.

Voorbeeldproject

Nieuw project

Nadat je hebt gecontroleerd of je de juiste versie van Xcode hebt, moet je een nieuw Xcode-project maken. 

Ga je gang en open Xcode en klik Maak een nieuw Xcode-project.

Vervolgens moet je een sjabloon kiezen voor je nieuwe Xcode-project. Het is vrij gebruikelijk om een Single View-app, dus ga je gang en selecteer dat en klik volgende.

Je kunt je project een naam geven die je wilt, maar ik zal de mijne noemen CoreML-beeldclassificatie. Voor dit project gebruiken we Swift, dus zorg ervoor dat het is geselecteerd in de Taal laten vallen.


Voorbereiding op foutopsporing

Een iPhone aansluiten

Omdat de Xcode Simulator geen camera heeft, moet je je iPhone aansluiten. Helaas, als je geen iPhone hebt, moet je er een lenen om deze tutorial (en voor alle andere camera-gerelateerde apps) te kunnen volgen. Als je al een iPhone hebt aangesloten op Xcode, kun je doorgaan naar de volgende stap.

Een handige nieuwe functie in Xcode 9 is dat je je app draadloos kunt debuggen op een apparaat, dus laten we de tijd nemen om dat nu in te stellen:

Kies in de bovenste menubalk Venster > Apparaten en simulatoren.Zorg ervoor dat dit in het venster verschijnt apparaten is bovenaan geselecteerd.

Sluit nu uw apparaat aan met een bliksemsnoer. Hierdoor zou uw apparaat moeten verschijnen in het linkerdeel van de Apparaten en simulatoren venster. Klik eenvoudig op uw apparaat en controleer de Verbind via netwerk doos.

U kunt nu draadloos debuggen op deze iPhone voor alle toekomstige apps. Als u andere apparaten wilt toevoegen, kunt u een vergelijkbaar proces volgen.

Simulator selectie

Als je eindelijk je iPhone wilt gebruiken om fouten op te sporen, selecteer je deze eenvoudig in de vervolgkeuzelijst naast de Rennen knop. U zou een netwerkpictogram ernaast moeten zien dat aantoont dat het verbonden is voor draadloos debuggen. Ik heb geselecteerd Vardhan's iPhone, maar je moet je specifieke apparaat selecteren.

Duiken dieper

Nu je je project hebt gemaakt en je iPhone hebt ingesteld als een simulator, duiken we een beetje dieper en beginnen we met het programmeren van de real-time app voor beeldclassificatie.

Uw project voorbereiden

Een model krijgen

Om te kunnen beginnen met het maken van je Core ML-beeldclassificatie-app, moet je eerst het Core ML-model van Apple's website downloaden. Zoals ik al eerder zei, kun je ook je eigen modellen trainen, maar dat vereist een apart proces. Als je naar de Apple-website voor het leren van computers bladert, kun je een model kiezen en downloaden.

In deze tutorial gebruik ik de MobileNet.mlmodel model, maar u kunt elk model gebruiken zolang u de naam kent en ervoor kunt zorgen dat het eindigt .mlmodel.

Bibliotheken importeren

Er zijn een aantal frameworks die je moet importeren, samen met de gebruikelijke UIKit. Zorg ervoor dat de volgende importinstructies aan de bovenkant van het bestand aanwezig zijn:

importeer UIKit import AVKit import Vision

We zullen nodig hebben AVKit omdat we een maken AVCaptureSession om een ​​live feed weer te geven tijdens het classificeren van afbeeldingen in realtime. Omdat we computervisie gebruiken, moeten we het importeren Visie kader.

Ontwerp van uw gebruikersinterface

Een belangrijk onderdeel van deze app is het weergeven van de gegevenslabels van de beeldclassificatie en de live videofeed van de camera van het apparaat. Om te beginnen met het ontwerpen van uw gebruikersinterface, ga naar uw Main.storyboard het dossier.

Een beeldweergave toevoegen

Ga naar de Objectbibliotheek en zoek naar een Beeldweergave. Sleep dit eenvoudigweg naar uw View Controller om het toe te voegen. Als u wilt, kunt u ook een placeholder-afbeelding toevoegen, zodat u een algemeen idee krijgt van hoe de app eruit zal zien wanneer deze wordt gebruikt.

Als u ervoor kiest om een ​​afbeelding voor placeholder te gebruiken, moet u ervoor zorgen dat de Inhoudsmodus ingesteld op Aspect Fit, en dat je het vakje aanvinkt dat zegt Clip naar grenzen. Op deze manier lijkt de afbeelding niet uitgerekt en verschijnt deze niet buiten de afbeelding UIImageView doos.

Dit is wat je storyboard er nu zou moeten uitzien:

Een weergave toevoegen

Terug in de Objectbibliotheek, zoeken naar een Uitzicht en sleep het naar je View Controller. Dit zal dienen als een mooie achtergrond voor onze labels, zodat ze niet verborgen raken in de afbeelding die wordt weergegeven. We maken deze weergave transparant, zodat een deel van de voorbeeldlaag nog steeds zichtbaar is (dit is gewoon een leuke bijkomstigheid voor de gebruikersinterface van de app).

Sleep dit naar de onderkant van het scherm zodat het de container aan drie zijden raakt. Het maakt niet uit welke hoogte je kiest, omdat we hier in een moment hier beperkingen opleggen.

Labels toevoegen

Dit is misschien het belangrijkste onderdeel van onze gebruikersinterface. We moeten laten zien wat onze app denkt dat het object is en hoe zeker het is (betrouwbaarheidsniveau). Zoals je waarschijnlijk al geraden hebt, moet je er twee slepen Label(S)van de Objectbibliotheek naar de mening die we zojuist hebben gemaakt. Sleep deze labels ergens in de buurt van het midden, op elkaar gestapeld.

Ga voor het bovenste label naar de Kenmerken Inspector en klik op de knop naast de stijl en grootte van het lettertype en selecteer in de pop-up Systeem als de doopvont. Selecteer om dit te onderscheiden van het vertrouwenslabel Zwart als de stijl. Wijzig ten slotte de grootte naar 24.

Volg voor het onderste label dezelfde stappen, maar in plaats van te selecteren Zwart als de stijl, kiezen regelmatig, en voor de grootte, kiezen 17.

De afbeelding hieronder laat zien hoe jouw Storyboard zou eruit moeten zien als je al deze views en labels hebt toegevoegd. Maak je geen zorgen als ze niet precies hetzelfde zijn als de jouwe; we zullen in de volgende stap beperkingen aan hen toevoegen.

Beperkingen toevoegen

Om deze app op verschillende schermformaten te laten werken, is het belangrijk om beperkingen toe te voegen. Deze stap is niet cruciaal voor de rest van de app, maar het wordt ten zeerste aanbevolen dat u dit in al uw iOS-apps doet.

Beperkingen beeldweergave

Het eerste dat je moet beperken, is ons UIImageView. Hiertoe selecteert u uw afbeeldingsweergave en opent u de Pin-menu in de onderste werkbalk (deze ziet eruit als een vierkant met de beperkingen en het is de tweede van rechts). Vervolgens moet u de volgende waarden toevoegen:

Voordat u doorgaat, moet u ervoor zorgen dat de Beperken tot Marges vak is niet aangevinkt, omdat dit een opening zal creëren tussen het scherm en de werkelijke beeldweergave. Sla dan invoeren.Nu jij UIImageView is gecentreerd op het scherm en het zou recht op alle apparaatgroottes moeten lijken.

Beperkingen bekijken

Nu is de volgende stap het beperken van de weergave waarop de labels verschijnen. Selecteer de weergave en ga vervolgens naar Pin-menu nog een keer. Voeg de volgende waarden toe:

Nu, gewoon raken invoeren om de waarden op te slaan. Uw weergave is nu beperkt tot de onderkant van het scherm.

Labelbeperkingen

Omdat de weergave nu is beperkt, kunt u beperkingen toevoegen aan de labels ten opzichte van de weergave in plaats van het scherm. Dit is handig als u later besluit om de positie van de labels of de weergave te wijzigen.

Selecteer beide labels en plaats ze in een stapelweergave. Als u niet weet hoe u dit moet doen, hoeft u alleen maar op de knop te drukken (de tweede van links) die eruitziet als een stapel boeken met een neerwaartse pijl. U ziet dan dat de knoppen een selecteerbaar object worden.

Klik op uw stapelweergave en klik vervolgens op de Menu uitlijnen (derde van links) en zorg ervoor dat de volgende vakjes zijn aangevinkt:

Nu, druk op invoeren. Uw labels moeten in het midden van de vorige stap gecentreerd zijn en ze zullen nu op alle schermformaten hetzelfde zijn.

Uitbreidingspunten voor interfacebouwer

De laatste stap in de gebruikersinterface zou zijn om de elementen met uw te verbinden ViewController () klasse. Open gewoon de Assistent redacteur en dan Controle-Click en Slepen elk element naar de top van je klas binnen ViewController.swift. Dit is wat ik ze in deze tutorial zal noemen:

  • UILabel: objectLabel
  • UILabel: confidenceLabel
  • UIImageView: imageView

Natuurlijk kunt u ze een naam geven die u maar wilt, maar dit zijn de namen die u in mijn code vindt.

Een opnamesessie voorbereiden

De live videofeed vereist een AVCaptureSession, dus laten we er nu een maken. We zullen onze camera-invoer ook in realtime aan de gebruiker tonen. Een opnamesessie maken is een vrij lang proces en het is belangrijk dat je begrijpt hoe je het moet doen, omdat het nuttig zal zijn bij elke andere ontwikkeling die je doet met behulp van de ingebouwde camera op een van de apparaten van Apple.

Klasse-uitbreiding en functie

Om te beginnen kunnen we een klassenextensie maken en deze vervolgens aanpassen aan de AVCaptureVideoDataOutputSampleBufferDelegate protocol. Je kunt dit eenvoudig doen binnen het eigenlijke ViewController klasse, maar we gebruiken hier praktische tips zodat de code netjes en georganiseerd is (dit is de manier waarop je het zou doen voor productie-apps).

Zodat we dit binnenin kunnen noemen viewDidLoad (), we moeten een functie aanmaken met de naam setupSession () die geen parameters opneemt. Je kunt dit alles noemen wat je wilt, maar houd rekening met de naamgeving wanneer we deze methode later noemen.

Als u klaar bent, ziet uw code er als volgt uit:

// MARK: - AVCaptureSession-extensie ViewController: AVCaptureVideoDataOutputSampleBufferDelegate func setupSession () // Uw code komt hier

Device Input en Capture Session

De eerste stap bij het maken van de opnamesessie is controleren of het apparaat een camera heeft. Met andere woorden: probeer de camera niet te gebruiken als er geen camera is. We zullen dan de daadwerkelijke opnamesessie moeten maken.

Voeg de volgende code toe aan uw setupSession () methode:

bewaker laat apparaat = AVCaptureDevice.default (voor: .video) else retour bewaker laten invoeren = proberen? AVCaptureDeviceInput (device: device) else return let session = AVCaptureSession () session.sessionPreset = .hd4K3840x2160

Hier gebruiken we een bewaker laten verklaring om te controleren of het apparaat (AVCaptureDevice) heeft een camera. Wanneer u probeert de camera van het apparaat te krijgen, moet u ook het mediatype, wat in dit geval is .video-.

Vervolgens maken we een AVCaptureDeviceInput, wat een input is die de media van het apparaat naar de opnamesessie brengt.

Ten slotte maken we eenvoudig een instantie van de AVCaptureSession klasse en wijs deze toe aan een variabele met de naam sessie. We hebben de bitrate en kwaliteit van de sessie aangepast aan Ultra-High-Definition (UHD) van 3840 bij 2160 pixels. Je kunt met deze instelling experimenteren om te zien wat voor jou werkt.

Voorvertoning van laag en uitvoer

De volgende stap in het doen van onze AVCaptureSession setup is om een ​​preview-laag te maken, waar de gebruiker de invoer van de camera kan zien. We zullen dit toevoegen aan de UIImageView we hebben eerder in ons storyboard gemaakt. Het belangrijkste onderdeel is echter eigenlijk het creëren van onze uitvoer voor het Core ML-model om later in deze tutorial te verwerken, wat we ook in deze stap zullen doen.

Voeg de volgende code direct toe onder de code uit de vorige stap:

et previewLayer = AVCaptureVideoPreviewLayer (sessie: sessie) previewLayer.frame = view.frame imageView.layer.addSublayer (previewLayer) let output = AVCaptureVideoDataOutput () output.setSampleBufferDelegate (self, wachtrij: DispatchQueue (label: "videoQueue")) session.addOutput (output)

We maken eerst een instantie van de AVCaptureVideoPreviewLayer klasse en initialiseer deze met de sessie die we in de vorige stap hebben gemaakt. Nadat dat is gebeurd, wijzen we het toe aan een variabele genaamd previewLayer. Deze laag wordt gebruikt om de invoer van de camera daadwerkelijk weer te geven.

Vervolgens vullen we de voorbeeldlaag met het volledige scherm door de framedimensies in te stellen op die van de weergave. Op deze manier blijft het gewenste uiterlijk bestaan ​​voor alle schermformaten. Als u de voorbeeldlaag daadwerkelijk wilt weergeven, voegen we deze toe als een sublaag van de UIImageView die we hebben gemaakt toen we de gebruikersinterface aan het maken waren.

Nu, voor het belangrijkste deel: We maken een instantie van de AVCaptureDataOutput klasse en wijs het toe aan een variabele genaamd uitgang

Sessie starten en starten

Eindelijk zijn we klaar met onze opnamesessie. Het enige wat u hoeft te doen voordat de eigenlijke Core ML-code is, is om de invoer toe te voegen en de opnamesessie te starten. 

Voeg de volgende twee regels code direct toe onder de vorige stap:

// Stelt de invoer van de AVCaptureSession in op de camera-ingangssessie van het apparaat.addInput (invoer) // Start de opnamesessie-sessie. StartRunning ()

Hiermee wordt de invoer toegevoegd die we eerder hebben gemaakt voor de AVCaptureSession, omdat we daarvoor eerst de invoer hadden gemaakt en deze niet hadden toegevoegd. Ten slotte start deze coderegel de sessie die we al zo lang hebben gemaakt.

Integratie van het Core ML-model

We hebben het model al gedownload, dus de volgende stap is om het daadwerkelijk te gebruiken in onze app. Dus laten we aan de slag gaan met het gebruik om afbeeldingen te classificeren. 

Gedelegeerde methode

Om te beginnen moet u de volgende deelnemersmethode toevoegen aan uw app:

func captureOutput (_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) // Uw code komt hier

Deze gedelegeerde methode wordt geactiveerd wanneer een nieuw videoframe wordt geschreven. In onze app gebeurt dit elke keer dat een frame wordt opgenomen via onze livevideo-feed (de snelheid hiervan is uitsluitend afhankelijk van de hardware waarop de app wordt uitgevoerd).

Pixelbuffer en model

Nu zullen we de afbeelding (één frame van de live feed) omzetten in een pixelbuffer, die herkenbaar is aan het model. Hiermee kunnen we later een maken VNCoreMLRequest

Voeg de volgende twee regels code toe aan de gedelegeerde methode die u eerder hebt gemaakt:

bewaker laat pixelBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer (sampleBuffer) else retour bewaker laat model = proberen? VNCoreMLModel (voor: MobileNet (). Model) else retour

Eerst maken we een pixelbuffer (een formaat dat door Core ML wordt geaccepteerd) van het argument dat wordt doorgegeven via de gedelegeerde methode en dan toewijzen aan een variabele genaamd pixelBuffer. Vervolgens wijzen we onze toe MobileNet model voor een constante genaamd model-.

Merk op dat beide zijn gemaakt met behulp van bewaker laten en dat de functie zal terugkeren als een van deze beide zijn nul waarden.

Een verzoek creëren

Nadat de vorige twee regels code zijn uitgevoerd, weten we zeker dat we een pixelbuffer en een model hebben. De volgende stap zou zijn om een VNCoreMLRequest beide gebruiken. 

Precies onder de vorige stap, plak de volgende regels code in de gedelegeerde methode:

let request = VNCoreMLRequest (model: model) (data, error) in // Uw code komt hier

Hier creëren we een constante genaamd verzoek en het toewijzen van de geretourneerde waarde van de methode VNCoreMLRequest wanneer ons model erin wordt ingevoerd.

Resultaten ophalen en sorteren

We zijn bijna klaar! Het enige wat we nu hoeven te doen is onze resultaten te krijgen (wat het model denkt dat onze afbeelding is) en deze vervolgens aan de gebruiker te tonen. 

Voeg de volgende twee regels code toe aan de voltooiingshandler van uw aanvraag:

// Controleert of de gegevens de juiste indeling hebben en wijst deze toe aan resultaten guard let results = data.results as? [VNClassificationObservation] else return // Wijst het eerste resultaat toe (als het bestaat) aan firstObject guard laat firstObject = results.first else return

Als de resultaten van de gegevens (van de voltooiingshandler van het verzoek) beschikbaar zijn als een array van VNClassificationObservations, deze regel code krijgt het eerste object uit de array die we eerder hebben gemaakt. Het zal dan worden toegewezen aan een constante genaamd firstObject. Het eerste object in deze array is degene waarvoor de beeldherkenningsengine het meeste vertrouwen heeft.

Gegevens- en beeldverwerking weergeven

Weet je nog toen we de twee labels creëerden (vertrouwen en object)? We zullen ze nu gebruiken om weer te geven wat het model denkt dat de afbeelding is.

Voeg de volgende regels code toe na de vorige stap:

if firstObject.confidence * 100> = 50 self.objectLabel.text = firstObject.identifier.capitalized self.confidenceLabel.text = String (firstObject.confidence * 100) + "%"

De als statement zorgt ervoor dat het algoritme minstens 50% zeker is over de identificatie van het object. Dan hebben we gewoon de firstObject als de tekst van de objectLabel omdat we weten dat het betrouwbaarheidsniveau hoog genoeg is. We geven alleen het zekerheidspercentage weer met de eigenschap text van confidenceLabel. Sinds firstObject.confidence wordt weergegeven als een decimaal, we moeten ons vermenigvuldigen met 100 om het percentage te krijgen.

Het laatste dat u hoeft te doen, is de afbeelding verwerken via het algoritme dat we zojuist hebben gemaakt. Om dit te doen, moet u de volgende regel code direct invoeren voordat u de captureOutput (_: didOutput: van :) gedelegeerde methode:

proberen? VNImageRequestHandler (cvPixelBuffer: pixelBuffer, opties: [:]). Uitvoeren ([verzoek])

Conclusie

De concepten die u in deze zelfstudie hebt geleerd, kunnen op veel soorten apps worden toegepast. Ik hoop dat je het leuk vond om te leren afbeeldingen te classificeren met je telefoon. Hoewel het misschien nog niet perfect is, kunt u uw eigen modellen in de toekomst trainen om nauwkeuriger te zijn.

Dit is hoe de app eruit zou moeten zien als hij klaar is:

Kijk terwijl je hier bent naar enkele van onze andere berichten over machine learning en de ontwikkeling van iOS-apps!