Inleiding tot OpenCV met Java

1. Inleiding

In deze tutorial zullen we leer hoe u de OpenCV computer vision-bibliotheek installeert en gebruikt en pas deze toe op realtime gezichtsherkenning.

2. Installatie

Om de OpenCV-bibliotheek in ons project te gebruiken, moeten we de opencv Maven afhankelijkheid van onze pom.xml:

 org.openpnp opencv 3.4.2-0 

Voor Gradle-gebruikers moeten we de afhankelijkheid toevoegen aan onze build.gradle het dossier:

compileer groep: 'org.openpnp', naam: 'opencv', versie: '3.4.2-0'

Nadat we de bibliotheek aan onze afhankelijkheden hebben toegevoegd, kunnen we de functies van OpenCV gebruiken.

3. De bibliotheek gebruiken

Om OpenCV te gaan gebruiken, we moeten de bibliotheek initialiseren, wat we kunnen doen in onze hoofd methode:

OpenCV.loadShared ();

OpenCV is een klasse die methoden bevat die betrekking hebben op het laden van native pakketten vereist door de OpenCV-bibliotheek voor verschillende platforms en architecturen.

Het is vermeldenswaard dat de documentatie de dingen iets anders doet:

System.loadLibrary (Core.NATIVE_LIBRARY_NAME)

Beide methodeaanroepen zullen de vereiste native bibliotheken daadwerkelijk laden.

Het verschil hier is dat de laatste vereist dat de native bibliotheken zijn geïnstalleerd. De eerste kan de bibliotheken echter in een tijdelijke map installeren als ze niet beschikbaar zijn op een bepaalde computer. Door dit verschil de loadShared methode is meestal de beste manier om te gaan.

Nu we de bibliotheek hebben geïnitialiseerd, gaan we kijken wat we ermee kunnen doen.

4. Afbeeldingen laden

Beginnen, laten we de voorbeeldafbeelding van de schijf laden met OpenCV:

openbare statische Mat loadImage (String imagePath) {Imgcodecs imageCodecs = nieuwe Imgcodecs (); retourneer imageCodecs.imread (imagePath); }

Deze methode zal laad de gegeven afbeelding als een Mat object, dat een matrixweergave is.

Om de eerder geladen afbeelding op te slaan, kunnen we de imwrite () methode van de Imgcodecs klasse:

openbare statische leegte saveImage (Mat imageMatrix, String targetPath) {Imgcodecs imgcodecs = nieuwe Imgcodecs (); imgcodecs.imwrite (targetPath, imageMatrix); }

5. Haar Cascade Classifier

Laten we, voordat we in gezichtsherkenning duiken, eerst de kernconcepten begrijpen die dit mogelijk maken.

Simpel gezegd, een classifier is een programma dat probeert een nieuwe waarneming te plaatsen in een groep die afhankelijk is van ervaringen uit het verleden. Trapsgewijze classificaties proberen dit te doen met behulp van een aaneenschakeling van verschillende classificaties. Elke volgende classificator gebruikt de uitvoer van de vorige als aanvullende informatie, waardoor de classificatie aanzienlijk wordt verbeterd.

5.1. Haar-functies

Gezichtsdetectie in OpenCV wordt gedaan door haar-feature-based cascade classifiers.

Haarfuncties zijn filters die worden gebruikt om randen en lijnen op de afbeelding te detecteren. De filters worden gezien als vierkanten met zwarte en witte kleuren:

Deze filters worden meerdere keren per pixel op een afbeelding toegepast en het resultaat wordt als één waarde verzameld. Deze waarde is het verschil tussen de som van pixels onder het zwarte vierkant en de som van pixels onder het witte vierkant.

6. Gezichtsdetectie

Over het algemeen, de cascade classifier moet vooraf worden getraind om überhaupt iets te kunnen detecteren.

Omdat het trainingsproces lang kan zijn en een grote dataset zou vereisen, gaan we een van de vooraf getrainde modellen gebruiken die worden aangeboden door OpenCV. We plaatsen dit XML-bestand in ons middelen map voor gemakkelijke toegang.

Laten we het proces van het detecteren van een gezicht doorlopen:

We zullen proberen het gezicht te detecteren door het te omlijnen met een rode rechthoek.

Om te beginnen, moeten we de afbeelding in Mat formaat van ons bronpad:

Mat loadedImage = loadImage (sourceImagePath);

Vervolgens verklaren we een MatOfRect object om de gezichten op te slaan die we vinden:

MatOfRect facesDetected = nieuwe MatOfRect ();

Vervolgens moeten we het CascadeClassifier om de herkenning te doen:

CascadeClassifier cascadeClassifier = nieuwe 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, nieuwe grootte (minFaceSize, minFaceSize), nieuwe grootte ());

Hierboven geeft de parameter 1.1 de schaalfactor aan die we willen gebruiken, waarbij wordt aangegeven hoeveel de afbeeldingsgrootte wordt verkleind bij elke afbeeldingsschaal. De volgende parameter, 3, is minBuren. Dit is het aantal buren dat een kandidaat-rechthoek moet hebben om deze te behouden.

Ten slotte zullen we de gezichten doorlopen en het resultaat opslaan:

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

Wanneer we onze bronafbeelding invoeren, zouden we nu de uitvoerafbeelding moeten ontvangen met alle gezichten gemarkeerd met een rode rechthoek:

7. Toegang tot de camera met OpenCV

Tot nu toe hebben we gezien hoe gezichtsdetectie op geladen afbeeldingen kan worden uitgevoerd. Maar meestal willen we het in realtime doen. Om dat te kunnen doen, hebben we toegang tot de camera nodig.

Om echter een afbeelding van een camera te kunnen laten zien, hebben we een paar extra dingen nodig, afgezien van het voor de hand liggende: een camera. Om de afbeeldingen te laten zien, gebruiken we JavaFX.

Omdat we een ImageView om de foto's die onze camera heeft gemaakt weer te geven, hebben we een manier nodig om vertaal een OpenCV Mat naar een JavaFX Beeld:

openbare afbeelding mat2Img (Mat mat) {MatOfByte bytes = nieuwe MatOfByte (); Imgcodecs.imencode ("img", mat, bytes); InputStream inputStream = nieuwe ByteArrayInputStream (bytes.toArray ()); retourneer nieuwe afbeelding (inputStream); }

Hier zijn we onze Mat in bytes, en vervolgens de bytes omzetten in een Beeld voorwerp.

We beginnen met het streamen van de cameraweergave naar een JavaFX Stadium.

Laten we nu de bibliotheek initialiseren met de loadShared methode:

OpenCV.loadShared ();

Vervolgens zullen we creëer het podium met een Video opname en een ImageView om het Beeld:

VideoCapture capture = nieuwe VideoCapture (0); ImageView imageView = nieuwe ImageView (); HBox hbox = nieuwe HBox (imageView); Scene scene = nieuwe scene (hbox); stage.setScene (scène); toneelstuk();

Hier, 0 is de ID van de camera die we willen gebruiken. We moeten ook Creëer een Animatietimerom het instellen van de afbeelding af te handelen:

nieuwe AnimationTimer () {@Override public void handle (long l) {imageView.setImage (getCapture ()); }} .start ();

Eindelijk, onze getCapture methode handvatten het omzetten van de Mat aan een Beeld:

openbare afbeelding getCapture () {Mat mat = nieuwe Mat (); capture.read (mat); retour mat2Img (mat); }

De toepassing moet nu een venster maken en vervolgens de weergave van de camera livestreamen naar het imageView venster.

8. Real-time gezichtsherkenning

Ten slotte kunnen we alle punten met elkaar verbinden om een ‚Äč‚Äčapplicatie te maken die een gezicht in realtime detecteert.

De code uit het vorige gedeelte is verantwoordelijk voor het pakken van de afbeelding van de camera en het tonen aan de gebruiker. Nu hoeven we alleen nog maar de opgenomen afbeeldingen te verwerken voordat ze op het scherm worden weergegeven met behulp van onze CascadeClassifier klasse.

Laten we gewoon onze getCapture methode om ook gezichtsdetectie uit te voeren:

openbare afbeelding getCaptureWithFaceDetection () {Mat mat = nieuwe Mat (); capture.read (mat); Mat haarClassifiedImg = detectFace (mat); retourneer mat2Img (haarClassifiedImg); }

Als we nu onze applicatie uitvoeren, moet het gezicht worden gemarkeerd met de rode rechthoek.

We kunnen ook een nadeel zien van de cascade-classificatoren. Als we ons gezicht te veel in een richting draaien, verdwijnt de rode rechthoek. Dit is zo omdat we hebben een specifieke classificatie gebruikt die alleen is getraind om de voorkant van het gezicht te detecteren.

9. Samenvatting

In deze tutorial hebben we geleerd hoe we OpenCV in Java kunnen gebruiken.

We hebben een vooraf getrainde cascadeclassificatie gebruikt om gezichten op de afbeeldingen te detecteren. Met behulp van JavaFX zijn we erin geslaagd om de classificaties de gezichten in realtime te laten detecteren met afbeeldingen van een camera.

Zoals altijd zijn alle codevoorbeelden te vinden op GitHub.