Introduksjon til OpenCV med Java

1. Introduksjon

I denne opplæringen vil vi lære å installere og bruke OpenCV-datasynbiblioteket og bruke det på sanntids ansiktsgjenkjenning.

2. Installasjon

For å bruke OpenCV-biblioteket i prosjektet vårt, må vi legge til opencv Maven avhengighet til vår pom.xml:

 org.openpnp opencv 3.4.2-0 

For Gradle-brukere må vi legge til avhengigheten til vår build.gradle fil:

kompilere gruppe: 'org.openpnp', navn: 'opencv', versjon: '3.4.2-0'

Etter å ha lagt biblioteket til våre avhengigheter, kan vi bruke funksjonene som tilbys av OpenCV.

3. Bruke biblioteket

For å begynne å bruke OpenCV, vi må initialisere biblioteket, som vi kan gjøre i vår hoved- metode:

OpenCV.loadShared ();

OpenCV er en klasse som inneholder metoder relatert til lasting av innfødte pakker kreves av OpenCV-biblioteket for forskjellige plattformer og arkitekturer.

Det er verdt å merke seg at dokumentasjonen gjør ting litt annerledes:

System.loadLibrary (Core.NATIVE_LIBRARY_NAME)

Begge disse metodeanropene vil faktisk laste de nødvendige innfødte bibliotekene.

Forskjellen her er at sistnevnte krever at de innfødte bibliotekene installeres. Førstnevnte kan imidlertid installere bibliotekene i en midlertidig mappe hvis de ikke er tilgjengelige på en gitt maskin. På grunn av denne forskjellen, de loadShared metoden er vanligvis den beste veien å gå.

Nå som vi har initialisert biblioteket, la oss se hva vi kan gjøre med det.

4. Laster inn bilder

Å starte, la oss laste eksempelbildet fra disken ved hjelp av OpenCV:

offentlig statisk matte loadImage (String imagePath) {Imgcodecs imageCodecs = nye Imgcodecs (); returner imageCodecs.imread (imagePath); }

Denne metoden vil last det gitte bildet som en Matte objekt, som er en matrise representasjon.

For å lagre det tidligere lastede bildet kan vi bruke imwrite () metoden for Imgcodecs klasse:

offentlig statisk tomrom saveImage (Mat imageMatrix, String targetPath) {Imgcodecs imgcodecs = new Imgcodecs (); imgcodecs.imwrite (targetPath, imageMatrix); }

5. Haar Cascade Classifier

Før vi dykker ned i ansiktsgjenkjenning, la oss forstå kjernekonseptene som gjør dette mulig.

For å si det enkelt, en klassifikator er et program som søker å plassere en ny observasjon inn i en gruppe avhengig av tidligere erfaringer. Cascading classifiers søker å gjøre dette ved hjelp av en sammenkobling av flere classifiers. Hver påfølgende klassifikator bruker utdataene fra forrige som tilleggsinformasjon, og forbedrer klassifiseringen sterkt.

5.1. Haar Funksjoner

Ansiktsgjenkjenning i OpenCV gjøres av Haar-funksjonsbaserte kaskadeklassifiserere.

Haar-funksjoner er filtre som brukes til å oppdage kanter og linjer på bildet. Filtrene blir sett på som firkanter med svarte og hvite farger:

Disse filtrene blir brukt flere ganger på et bilde, piksel for piksel, og resultatet blir samlet som en enkelt verdi. Denne verdien er forskjellen mellom summen av piksler under den svarte firkanten og summen av piksler under den hvite firkanten.

6. Ansiktsgjenkjenning

Som regel, kaskadeklassifisereren må være trent for å kunne oppdage noe i det hele tatt.

Siden opplæringsprosessen kan være lang og vil kreve et stort datasett, skal vi bruke en av de pre-trente modellene som tilbys av OpenCV. Vi plasserer denne XML-filen i vår ressurser mappe for enkel tilgang.

La oss gå gjennom prosessen med å oppdage et ansikt:

Vi prøver å oppdage ansiktet ved å skissere det med et rødt rektangel.

For å komme i gang, må vi laste inn bildet Matte format fra kildestien vår:

Mat loadingImage = loadImage (sourceImagePath);

Så erklærer vi a MatOfRect motstander for å lagre ansiktene vi finner:

MatOfRect facesDetected = ny MatOfRect ();

Deretter må vi initialisere CascadeClassifier å gjøre anerkjennelsen:

CascadeClassifier cascadeClassifier = ny CascadeClassifier (); int minFaceSize = Math.round (loadedImage.rows () * 0.1f); cascadeClassifier.load ("./ src / main / resources / haarcascades / haarcascade_frontalface_alt.xml"); cascadeClassifier.detectMultiScale (loadedImage, facesDetected, 1.1, 3, Objdetect.CASCADE_SCALE_IMAGE, new Size (minFaceSize, minFaceSize), new Size ());

Over angir parameteren 1.1 skaleringsfaktoren vi vil bruke, og angir hvor mye bildestørrelsen blir redusert på hver bildeskala. Den neste parameteren, 3, er minNaboene. Dette er antall naboer et kandidatrektangel skal ha for å beholde det.

Til slutt vil vi løpe gjennom ansiktene og lagre resultatet:

Rect [] facesArray = facesDetected.toArray (); for (Rect face: facesArray) {Imgproc.rectangle (loadedImage, face.tl (), face.br (), new Scalar (0, 0, 255), 3); } saveImage (loadedImage, targetImagePath);

Når vi legger inn kildebildet vårt, skal vi nå motta utgangsbildet med alle ansiktene merket med et rødt rektangel:

7. Få tilgang til kameraet ved hjelp av OpenCV

Så langt har vi sett hvordan vi kan utføre ansiktsgjenkjenning på lastede bilder. Men mesteparten av tiden ønsker vi å gjøre det i sanntid. For å kunne gjøre det, må vi få tilgang til kameraet.

For å kunne vise et bilde fra et kamera trenger vi imidlertid noen ekstra ting, bortsett fra det åpenbare - et kamera. For å vise bildene bruker vi JavaFX.

Siden vi bruker en ImageView for å vise bildene kameraet vårt har tatt, trenger vi en måte å oversette en OpenCV Matte til en JavaFX Bilde:

public Image mat2Img (Mat mat) {MatOfByte bytes = new MatOfByte (); Imgcodecs.imencode ("img", matte, byte); InputStream inputStream = ny ByteArrayInputStream (bytes.toArray ()); returner nytt bilde (inputStream); }

Her konverterer vi vår Matte til byte, og deretter konvertere byte til et Bilde gjenstand.

Vi starter med å streame kameravisningen til en JavaFX Scene.

La oss nå initialisere biblioteket ved hjelp av loadShared metode:

OpenCV.loadShared ();

Neste skal vi skape scenen med en Videoopptak og en ImageView for å vise Bilde:

VideoCapture capture = new VideoCapture (0); ImageView imageView = ny ImageView (); HBox hbox = ny HBox (imageView); Scenescene = ny scene (hbox); scene.setScene (scene); scene.show ();

Her, 0 er ID-en til kameraet vi vil bruke. Vi må også lage en Animasjonstimerfor å håndtere innstillingen av bildet:

nytt AnimationTimer () {@Override offentlig tomhåndtak (langt l) {imageView.setImage (getCapture ()); } }.start();

Til slutt, vår getCapture metodehåndtak konvertere Matte til en Bilde:

public Image getCapture () {Mat mat = new Mat (); capture.read (matte); retur mat2Img (matte); }

Programmet skal nå opprette et vindu og deretter live-streame utsikten fra kameraet til imageView vindu.

8. Sanntids ansiktsgjenkjenning

Til slutt kan vi koble alle punktene for å lage et program som oppdager et ansikt i sanntid.

Koden fra forrige avsnitt er ansvarlig for å ta tak i bildet fra kameraet og vise det til brukeren. Nå er alt vi trenger å gjøre å behandle de hentede bildene før du viser dem på skjermen ved å bruke vår CascadeClassifier klasse.

La oss bare endre vår getCapture metode for også å utføre ansiktsgjenkjenning:

offentlig bilde getCaptureWithFaceDetection () {Mat mat = ny Mat (); capture.read (matte); Mat haarClassifiedImg = detectFace (mat); retur mat2Img (haarClassifiedImg); }

Nå, hvis vi kjører applikasjonen vår, skal ansiktet være merket med det røde rektangelet.

Vi kan også se en ulempe med kaskadeklassifiseringsapparatene. Hvis vi vender ansiktet for mye i noen retning, forsvinner det røde rektangelet. Dette er fordi Vi har brukt en spesifikk klassifikator som bare ble trent for å oppdage forsiden av ansiktet.

9. Oppsummering

I denne opplæringen lærte vi hvordan du bruker OpenCV i Java.

Vi brukte en ferdig trent kaskadeklassifiseringsmiddel for å oppdage ansikter på bildene. Ved hjelp av JavaFX klarte vi å få klassifikatorene til å oppdage ansiktene i sanntid med bilder fra et kamera.

Som alltid kan alle kodeeksemplene finnes på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found