Med teknologiske fremskritt er vi på det punktet der våre enheter kan bruke sine innebygde kameraer til å nøyaktig identifisere og merke bilder ved hjelp av et forhåndsutdannet datasett. Du kan også trene dine egne modeller, men i denne opplæringen bruker vi en åpen kildekode modell for å opprette en bildeklassifiseringsapp.
Jeg skal vise deg hvordan du lager en app som kan identifisere bilder. Vi starter med et tomt Xcode-prosjekt, og implementerer maskinlæringsdrevet bildegjenkjenning ett trinn av gangen.
Før du begynner, sørg for at du har den nyeste versjonen av Xcode installert på Mac-en din. Dette er veldig viktig fordi Core ML kun vil være tilgjengelig på Xcode 9 eller nyere. Du kan sjekke din versjon ved å åpne Xcode og gå til Xcode > Om Xcode i den øverste verktøylinjen.
Hvis din versjon av Xcode er eldre enn Xcode 9, kan du gå til Mac App Store og oppdatere den, eller hvis du ikke har den, last den ned gratis.
Når du har sørget for at du har riktig versjon av Xcode, må du lage et nytt Xcode-prosjekt.
Gå videre og åpne Xcode og klikk Opprett et nytt Xcode-prosjekt.
Deretter må du velge en mal for det nye Xcode-prosjektet. Det er ganske vanlig å bruke a Single View App, så gå videre og velg det og klikk neste.
Du kan navngi prosjektet ditt noe du vil, men jeg vil navngi min CoreML Image Classification. For dette prosjektet bruker vi Swift, så sørg for at den er valgt i Språk fall ned.
Siden Xcode Simulator ikke har et kamera, må du plugge inn iPhone. Dessverre, hvis du ikke har en iPhone, må du låne en for å kunne følge med denne opplæringen (og for andre kamerarelaterte apps). Hvis du allerede har en iPhone koblet til Xcode, kan du hoppe videre til neste trinn.
En nydelig ny funksjon i Xcode 9 er at du kan feilsøke appen din på en enhet på en trådløs måte, så la oss ta deg tid til å sette opp det nå:
Velg øverst på menylinjen Vindu > Enheter og simulatorer.Kontroller at i vinduet som vises enheter er valgt øverst.
Nå, koble til enheten din med en lynledning. Dette bør gjøre at enheten din vises i venstre rute i Enheter og simulatorer vindu. Bare klikk på enheten, og merk av Koble via nettverk eske.
Du vil nå kunne feilsøke på denne iPhone på alle fremtidige apps. Hvis du vil legge til andre enheter, kan du følge en lignende prosess.
Når du endelig vil bruke iPhone til å feilsøke, velg du det fra rullegardinmenyen ved siden av Løpe knapp. Du bør se et nettverksikon ved siden av det, og viser at det er koblet til trådløs feilsøking. Jeg har valgt Vardhans iPhone, men du må velge din spesifikke enhet.
Nå som du har opprettet prosjektet ditt og satt opp din iPhone som en simulator, dykker vi litt dypere og begynner å programmere sanntidsbildeklassifiseringsappen.
For å kunne begynne å lage din Core ML image klassifisering app, må du først få Core ML modellen fra Apples nettside. Som nevnt før, kan du også trene dine egne modeller, men det krever en egen prosess. Hvis du ruller ned til bunnen av Apples maskininnlæringsnettsted, kan du velge og laste ned en modell.
I denne opplæringen vil jeg bruke MobileNet.mlmodel modell, men du kan bruke hvilken som helst modell så lenge du kjenner navnet sitt og kan sikre at den slutter .mlmodel.
Det er et par rammer du må importere sammen med det vanlige UIKit
. På toppen av filen, sørg for at følgende importopplysninger er til stede:
importere UIKit import AVKit import Vision
Vi trenger AVKit
fordi vi skal skape en AVCaptureSession
å vise en live feed mens du klassifiserer bilder i sanntid. Også, siden dette bruker datasyn, må vi importere Syn
rammeverk.
En viktig del av denne appen er å vise bildeklassifiseringsdatamerkene, så vel som livevideoen fra enhetens kamera. For å begynne å designe ditt brukergrensesnitt, gå til din Main.storyboard fil.
Hodet til Objektbibliotek og søk etter en Bildevisning. Bare dra dette på View Controller for å legge til det. Hvis du vil, kan du også legge til et plassholderbilde slik at du kan få en generell ide om hvordan appen vil se ut når den brukes.
Hvis du velger å ha et plassholderbilde, må du sørge for at Innholdsmodus er satt til Aspect Fit, og at du merker av boksen som sier Klipp til bånd. På denne måten vil bildet ikke vises strukket, og det vises ikke utenfor UIImageView
eske.
Her ser du hvordan storyboardet ditt skal se ut:
Tilbake i Objektbibliotek, søk etter en Utsikt og dra den på View Controller. Dette vil fungere som en fin bakgrunn for våre etiketter, slik at de ikke blir skjulte i bildet som vises. Vi gjør denne visningen gjennomsiktig slik at noen av forhåndsvisningslaget fortsatt er synlig (dette er bare en fin touch for brukergrensesnittet til appen).
Dra dette til bunnen av skjermen slik at det berører beholderen på tre sider. Det spiller ingen rolle hvilken høyde du velger fordi vi vil sette inn begrensninger for dette i et øyeblikk her.
Dette er kanskje den viktigste delen av brukergrensesnittet. Vi må vise hva vår app mener objektet er, og hvor sikkert det er (konfidensnivå). Som du sikkert har gjettet, må du dra to Merkelapp(S)fra Objektbibliotek til utsikten vi nettopp har opprettet. Dra disse etikettene et sted nær sentrum, stablet ovenpå hverandre.
For topp etiketten, hodet til Attributtsinspektør og klikk på T knappen ved siden av skrifttypestilen og -størrelsen, og velg i popup-vinduet System som font. For å skille dette fra konfidensmerket, velger du Svart som stil. Endelig, endre størrelse til 24.
For den nederste etiketten, følg de samme trinnene, men i stedet for å velge Svart som stil, å velge Regelmessig, og for størrelse, å velge 17.
Bildet nedenfor viser hvordan din Storyboard bør se når du har lagt til alle disse visningene og etikettene. Ikke bekymre deg hvis de ikke er akkurat det samme som din; Vi legger til begrensninger for dem i neste trinn.
For at denne appen skal fungere på forskjellige skjermstørrelser, er det viktig å legge til begrensninger. Dette trinnet er ikke avgjørende for resten av appen, men det anbefales sterkt at du gjør dette i alle iOS-appene dine.
Den første tingen å begrense er vår UIImageView
. For å gjøre dette, velg bildevisningen, og åpne Pin-menyen i nederste verktøylinjen (dette ser ut som et firkant med begrensningene, og det er det andre fra høyre). Deretter må du legge til følgende verdier:
Før du fortsetter, må du kontrollere at Begrens til marginer boksen er ikke merket da dette vil skape et mellomrom mellom skjermen og den faktiske bildevisningen. Deretter treffer du Tast inn.Nå din UIImageView
er sentrert på skjermen, og det bør sees på alle enhetsstørrelser.
Nå er neste trinn å begrense visningen som etikettene vises. Velg visningen, og gå til Pin-menyen en gang til. Legg til følgende verdier:
Nå, bare klikk Tast inn for å lagre verdiene. Visningen din er nå begrenset til bunnen av skjermen.
Siden visningen nå er begrenset, kan du legge til begrensninger på etikettene i forhold til visningen i stedet for skjermen. Dette er nyttig hvis du senere bestemmer deg for å endre plasseringen av etikettene eller visningen.
Velg begge etikettene, og sett dem i en stabelvisning. Hvis du ikke vet hvordan du gjør dette, må du bare trykke på knappen (den andre fra venstre) som ser ut som en bunke med bøker med en nedover pil. Du vil da se at knappene blir et valgbart objekt.
Klikk på stakkvisningen, og klikk deretter på Juster menyen (tredje fra venstre) og kontroller at følgende bokser er merket:
Nå, hit Tast inn. Merkene dine bør være sentrert i visningen fra forrige trinn, og de vil nå vises det samme på alle skjermstørrelser.
Det siste trinnet i brukergrensesnittet er å koble elementene til din ViewController ()
klasse. Bare åpne Assistent Editor og så Kontroll-klikk og Dra hvert element til toppen av klassen din inni ViewController.swift. Her er hva jeg skal navngi dem i denne opplæringen:
UILabel
: objectLabel
UILabel
: confidenceLabel
UIImageView
: bildeVis
Selvfølgelig kan du navngi dem hva du vil, men disse er navnene du finner i koden min.
Den levende videofôten vil kreve en AVCaptureSession
, så la oss lage en nå. Vi vil også vise vår kamerainngang til brukeren i sanntid. Å lage en opptakssesjon er en ganske lang prosess, og det er viktig at du forstår hvordan du gjør det fordi det vil være nyttig i enhver annen utvikling du bruker med kameraet på noen av Apples enheter.
For å begynne, kan vi opprette en klasseutvidelse og deretter gjøre det i samsvar med AVCaptureVideoDataOutputSampleBufferDelegate
protokoll. Du kan enkelt gjøre dette innen selve ViewController
klassen, men vi bruker beste praksis her, slik at koden er pent og organisert (dette er måten du ville gjøre det for produksjonsprogrammer).
Slik at vi kan ringe dette inne i viewDidLoad ()
, vi må opprette en funksjon som heter setupSession ()
som ikke tar noen parametere inn. Du kan nevne dette alt du vil, men vær oppmerksom på navngivelsen når vi kaller denne metoden senere.
Når du er ferdig, bør koden din se slik ut:
// MARK: - AVCaptureSession forlengelse ViewController: AVCaptureVideoDataOutputSampleBufferDelegate func setupSession () // Din kode går her
Det første trinnet i å lage opptakssesjonen er å kontrollere om enheten har et kamera eller ikke. Forsøk å ikke bruke kameraet hvis det ikke er kamera. Vi må da lage den faktiske opptakssesjonen.
Legg til følgende kode i din setupSession ()
metode:
vakt la enheten = AVCaptureDevice.default (for: .video) ellers return vakt la input = prøv? AVCaptureDeviceInput (enhet: enhet) ellers return la session = AVCaptureSession () session.sessionPreset = .hd4K3840x2160
Her bruker vi en vakt la
uttalelse for å kontrollere om enheten (AVCaptureDevice
) har et kamera. Når du prøver å få kameraet på enheten, må du også spesifisere Media type
, som i dette tilfellet er .video
.
Deretter oppretter vi en AVCaptureDeviceInput
, som er en inngang som bringer media fra enheten til opptakssesjonen.
Endelig oppretter vi bare en forekomst av AVCaptureSession
klassen, og tilordne den til en variabel som heter økt
. Vi har tilpasset øktbithastigheten og kvaliteten til Ultra High Definition (UHD) som er 3840 ved 2160 piksler. Du kan eksperimentere med denne innstillingen for å se hva som fungerer for deg.
Det neste trinnet i å gjøre vårt AVCaptureSession
Oppsettet er å lage et forhåndsvisningslag, der brukeren kan se inngangen fra kameraet. Vi legger til dette på UIImageView
Vi opprettet tidligere i Storyboard. Den viktigste delen er imidlertid faktisk å skape vår produksjon for Core ML-modellen til å behandle senere i denne opplæringen, som vi også vil gjøre i dette trinnet.
Legg til følgende kode direkte under koden fra forrige trinn:
et previewLayer = AVCaptureVideoPreviewLayer (sessions: session) previewLayer.frame = view.frame imageView.layer.addSublayer (previewLayer) la output = AVCaptureVideoDataOutput () output.setSampleBufferDelegate (selv, kø: DispatchQueue (label: "videoQueue")) session.addOutput (produksjon)
Vi lager først en forekomst av AVCaptureVideoPreviewLayer
klasse, og deretter initialisere den med økten vi opprettet i forrige trinn. Etter at det er gjort, tilordner vi det til en variabel som heter previewLayer
. Dette laget brukes til å faktisk vise inngangen fra kameraet.
Deretter lagrer vi forhåndsvisningslaget hele skjermbildet ved å sette rammemåttene til visningene. På denne måten vil ønsket utseende fortsette for alle skjermstørrelser. For å vise forhåndsvisningslaget, legger vi det inn som et underlag av UIImageView
som vi opprettet da vi lagde brukergrensesnittet.
Nå, for den viktige delen: Vi lager en forekomst av AVCaptureDataOutput
klasse og tilordne den til en variabel som heter produksjon
.
Endelig er vi ferdige med vår opptakssesjon. Alt som er igjen å gjøre før den faktiske Core ML-koden, er å legge til inngangen og starte opptakssesjonen.
Legg til følgende to kodelinjer direkte under forrige trinn:
// Setter inngangen til AVCaptureSession til enhetens kamerainngangssession.addInput (input) // Starter opptakssesjonen session.startRunning ()
Dette legger til inngangen som vi opprettet tidligere til AVCaptureSession
, fordi før dette hadde vi bare opprettet innspillet og ikke lagt til det. Til slutt starter denne koden med økten som vi har brukt så lenge på å lage.
Vi har allerede lastet ned modellen, så det neste trinnet er å faktisk bruke det i appen vår. Så la oss komme i gang med å bruke den til å klassifisere bilder.
For å begynne, må du legge til følgende delegatemetode i appen din:
func captureOutput (_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, fra tilkobling: AVCaptureConnection) // Din kode går her
Denne delegatemetoden utløses når en ny videoramme er skrevet. I vår app skjer dette hver gang en ramme blir tatt opp via vår live video feed (hastigheten på dette er utelukkende avhengig av maskinvaren som appen kjører på).
Nå skal vi snu bildet (en ramme fra levende feed) til en pikselbuffer, som er gjenkjennelig av modellen. Med dette kan vi senere opprette en VNCoreMLRequest
.
Legg til følgende to kodelinjer inne i delegatemetoden du opprettet tidligere:
vakt la pixelBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer (sampleBuffer) ellers return guard let model = try? VNCoreMLModel (for: MobileNet () .modell) ellers return
Først oppretter vi en pikselbuffer (et format som Core ML aksepterer) fra argumentet som sendes inn gjennom delegatemetoden, og tilordner den deretter til en variabel som kalles pixelBuffer
. Så tildeler vi vår MobileNet modell til en konstant kalt modell
.
Legg merke til at begge disse er opprettet ved hjelp av vakt la
uttalelser, og at funksjonen kommer tilbake hvis en av disse er nil
verdier.
Etter at de to foregående kodelinjene er utført, vet vi at vi har en pikselbuffer og en modell. Det neste skrittet ville være å lage en VNCoreMLRequest
bruker begge to.
Rett under det forrige trinnet, lim inn følgende kodelinjer inne i delegatemetoden:
la request = VNCoreMLRequest (modell: modell) (data, feil) i // Din kode går her
Her skaper vi en konstant kalt be om
og tilordne den verdien av metoden VNCoreMLRequest
når modellen er passert inn i den.
Vi er nesten ferdige! Alt vi trenger å gjøre nå, er å få våre resultater (hva modellen mener bildet er) og så vise dem til brukeren.
Legg til de to neste kodelinjene i fullføringshåndteringen av forespørselen din:
// Kontroller om dataene er i riktig format og tilordner det til resultater, vær så snill å la resultater = data.results som? [VNClassificationObservation] else return // Tilordner det første resultatet (hvis det eksisterer) til firstObject guard la firstObject = results.first else return
Hvis resultatene fra dataene (fra ferdigstillingsbehandleren av forespørselen) er tilgjengelige som en rekke av VNClassificationObservations
, denne linjen med kode får det første objektet fra gruppen vi opprettet tidligere. Det vil da bli tilordnet en konstant kalt firstObject
. Det første objektet i denne gruppen er den som bildekjenningsmotoren har mest tillit til.
Husk da vi opprettet de to etikettene (selvtillit og objekt)? Vi skal nå bruke dem til å vise hva modellen mener bildet er.
Legg til følgende kodelinjer etter forrige trinn:
hvis firstObject.confidence * 100> = 50 self.objectLabel.text = firstObject.identifier.capitalized self.confidenceLabel.text = String (firstObject.confidence * 100) + "%"
De hvis
setningen sørger for at algoritmen er minst 50% sikker på dens identifikasjon av objektet. Da satte vi nettopp firstObject
som teksten til objectLabel
fordi vi vet at konfidensnivået er høyt nok. Vi viser bare sikkerhetsprosenten ved hjelp av tekstegenskapen til confidenceLabel
. Siden firstObject.confidence
er representert som et desimal, må vi multiplisere med 100 for å få prosentandelen.
Den siste tingen å gjøre er å behandle bildet gjennom algoritmen vi nettopp har laget. For å gjøre dette må du skrive følgende linje av kode direkte før du avslutter captureOutput (_: didOutput: fra :)
delegere metode:
prøve? VNImageRequestHandler (cvPixelBuffer: pixelBuffer, alternativer: [:]). Utføre ([request])
Begrepene du har lært i denne opplæringen kan brukes til mange typer apper. Jeg håper du har likt å lære å klassifisere bilder ved hjelp av telefonen din. Selv om det kanskje ikke er perfekt, kan du trene dine egne modeller i fremtiden for å være mer nøyaktig.
Slik ser appen ut når den er ferdig:
Mens du er her, sjekk ut noen av våre andre innlegg på maskinlæring og iOS apputvikling!