[JAVA] Gesichtserkennungs-App mit OpenCV + Android Studio

Was du machen willst

Erstellen einer Gesichtserkennungs-App mit OpenCV ·Ziel ・ Erfahren Sie vorerst, wie Sie Android Studio (Anfänger) installieren und verwenden. ・ Führen Sie OpenCV unter Android aus ・ Es können sowohl mit der Kamera aufgenommene Bilder als auch in der Galerie gespeicherte Bilder verwendet werden.

Referenz

Ich habe versucht, eine einfache Gesichtserkennungs-Android-Anwendung mit OpenCV zu erstellen https://qiita.com/Kuroakira/items/094ecb236da89949d702 Ergänzung zum absichtlichen Aufrufen der Kamera (hauptsächlich für das Xperia 2.1-Problem) https://gabu.hatenablog.com/entry/20101125/1290681748

Was ich benutzt habe

Android Studio 3.5.3 OpenCV 4.2.0

Rauer Fluss

Die Implementierung werde ich kurz schreiben, da ich mich auf die obigen Vorgänger beziehe.

Drücken Sie die Kamera- und Galerie-Taste ↓ Holen Sie sich Bilder von Kamera, Galerie ↓ Konvertieren Sie das erfasste Bild von der Bitmap in das Mat-Format ↓ Übergeben Sie das Bild im Mat-Format an OpenCV ↓ Erfasst Gesichtserkennungsinformationen und zeigt sie auf dem Bildschirm an

Ergebnis

Solche Koordinateninformationen kamen heraus.

result1.png

Dinge, die in Zukunft verwendet werden können

·Kamera Wenn Sie das von der Kamera aufgenommene Bild in hoher Auflösung erfassen möchten, schreiben Sie es einmal in die URL und erfassen Sie das Bild von der URL. getImg = (Bitmap) data.getExtras (). get ("data"); kann nur Bilder mit niedriger Auflösung für Miniaturansichten abrufen. (Das Bild für die Bilderkennung wird von getImg = (Bitmap) data.getExtras () erhalten. Get ("data"); es scheint jedoch unpraktisch zu sein, wenn die Anzahl der Personen zunimmt oder wenn es sich um ein Zeichenbild handelt.)

MainActivity.java


   getImg = (Bitmap) data.getExtras().get("data");

MainActivity.java


    /**Abkürzung**/
    imageView.setImageURI(mImageUri);
    /**Abkürzung**/

    /**
     *Für die Fotografie
     *Exportieren Sie das aufgenommene Foto einmal in die URL und speichern Sie die Ziel-URL in mImageUri
     */
    protected void takePhoto(){
        String filename = System.currentTimeMillis() + ".jpg ";

        ContentValues values = new ContentValues();
        values.put(MediaStore.Images.Media.TITLE,filename);
        values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
        mImageUri = getContentResolver().insert(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values
        );

        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
        startActivityForResult(intent, RESULT_CAMERA);
    }

Was ich in Zukunft erreichen möchte

・ Klassenteilung nur zur Gesichtserkennung Anfangs habe ich versucht, es durch Klassifizierung zu implementieren, aber ich habe aufgegeben, weil ich nicht wusste, wie ich die folgenden Teile klassifizieren soll. (Sie können nicht mit derselben Beschreibung wie MainActivity.java von einer anderen Klasse auf res / raw zugreifen?)

MainActivity.java


        File cascadeDir = getDir("cscade", Context.MODE_PRIVATE);
        File cascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml");

・ Bildaufnahme von ImageView Durch das Erfassen von Bildern von ImageVIew wird bei Kameras und Galerien die Implementierung jeweils unnötig, sodass möglicherweise der Code reduziert werden kann.

・ Implementierung in Kotlin Ich habe es in einem gut geschriebenen Java implementiert, weil es sich vorerst daran gewöhnen sollte, aber ich würde Kotlin gerne bei der zukünftigen Entwicklung für Android verwenden

Quellcode

MainActivity.java


package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import  java.io.InputStream;

import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Paint;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import org.opencv.android.Utils;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Rect;
import org.opencv.objdetect.CascadeClassifier;

public class MainActivity extends AppCompatActivity {
    private final static int RESULT_CAMERA = 1001; //Für Kameras
    private final static int REQUEST_GALLERY = 1000; //Für die Galerie
    private Uri mImageUri; //Instanzvariable zum Speichern der URL des Bildes
    private Bitmap getImg = null; //Bilder von der Kamera oder Galerie aufgenommen
    private ImageView imageView;//Deklaration der Bildansicht

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageView = findViewById(R.id.image_view);//Verknüpfen Sie zuerst ImageView mit der Layoutansicht-ID

        Button cameraButton = findViewById(R.id.camera_button);
        cameraButton.setOnClickListener(new View.OnClickListener() {//Implementierung mit einer normalen inneren Klasse
            @Override
            public void onClick(View v) {
                takePhoto();
            }
        });

        Button galleyButton = findViewById(R.id.gallery_button);
        galleyButton.setOnClickListener(new View.OnClickListener() {//Implementierung mit einer normalen inneren Klasse
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setType("image/*");
                intent.setAction(Intent.ACTION_GET_CONTENT);
                startActivityForResult(intent, REQUEST_GALLERY);
            }
        });
    }

    //Ich werde das in der Bildansicht aufgenommene Foto von nun an einfügen.
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode == RESULT_CAMERA || requestCode == REQUEST_GALLERY) {
            TextView textView = findViewById(R.id.text1); //Textvorschau(Anzeigen, um den anzuzeigenden Text zu speichern)
            String outputText = ""; //Anzuzeigender Text
            MatOfRect faceRects; //Speichern Sie Gesichtserkennungsdaten

            //Bei der Auswahl eines Bildes von der Kamera
            if (requestCode == RESULT_CAMERA) {
                //Einschließlich stornierter Fälle
                if (data.getExtras() == null) {
                    Log.d("debug", "cancel ?");
                    return;
                } else {
                    imageView.setImageURI(mImageUri);
                    getImg = (Bitmap) data.getExtras().get("data");
                }
            }
            //Bei der Auswahl eines Bildes aus der Galerie
            if (requestCode == REQUEST_GALLERY && resultCode == RESULT_OK) {
                try {
                    InputStream in = getContentResolver().openInputStream(data.getData());
                    getImg = BitmapFactory.decodeStream(in);
                    in.close();
                    //Zeigen Sie das ausgewählte Bild an
                    imageView.setImageBitmap(getImg);
                } catch (Exception e) {
                    //Wenn keine Datei vorhanden ist
                    textView.setText("Datei nicht gefunden");
                }
            }
            //Bild in imageView eingefügt(Erhalten von Kamera, Galerie)Gesichtserkennung von
            try {
                faceRects = checkFaceExistence(getImg);
                outputText = makeOutputText(faceRects);\
                //Zeigen Sie das ausgewählte Bild an
                imageView.setImageBitmap(getImg);
            } catch (IOException e) {
                outputText = "Gesichtserkennungsfehler";
                e.printStackTrace();
            }

            Toast.makeText(this,outputText,Toast.LENGTH_LONG).show();
            textView.setText(outputText);
        }
    }

    /**
     *Für die Fotografie
     *Exportieren Sie das aufgenommene Foto einmal in die URL und speichern Sie die Ziel-URL in mImageUri
     */
    protected void takePhoto(){
        String filename = System.currentTimeMillis() + ".jpg ";

        ContentValues values = new ContentValues();
        values.put(MediaStore.Images.Media.TITLE,filename);
        values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
        mImageUri = getContentResolver().insert(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values
        );

        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
        startActivityForResult(intent, RESULT_CAMERA);
    }

    /**
     *Führen Sie eine Gesichtserkennung basierend auf dem übergebenen Bild durch
     * @param Bitmap Bild zur Gesichtserkennung
     * @Rückgabetext Gesichtserkennungsinformationen
     * @throws IOException
     */
    protected MatOfRect checkFaceExistence(Bitmap bitmap) throws IOException{
        System.loadLibrary("opencv_java4");

        //Bilddaten gesendet(bitmap)Zum Mattenformat
        Mat matImg = new Mat();
        Utils.bitmapToMat(bitmap, matImg);
        String text =  "";   //Text zum Speichern von Gesichtserkennungsinformationen

        //Generieren einer Kaskadenklassifikatorinstanz zur Gesichtserkennung(Exportieren Sie die Datei einmal und erhalten Sie den Dateipfad)
        //Holen Sie sich die XML-Datei, sobald sie unter raw gespeichert ist
        InputStream inStream = getResources().openRawResource(R.raw.haarcascade_frontalface_alt);
        MatOfRect faceRects = new MatOfRect(); //Speichern Sie Gesichtserkennungsdaten

        try {
            //Legen Sie den Pfad der XML-Ausgabedatei auf das Argument von Cascade Classfle fest
            CascadeClassifier faceDetetcor = outputCascadeFile(inStream);
            //Gesichtserkennung durch Übergabe von Bilddaten an den Kaskadenklassifizierer
            faceDetetcor.detectMultiScale(matImg, faceRects);
        }
        catch (IOException e){
            Toast.makeText(this,"Fehler beim Öffnen der Analyseinformationsdatei.",Toast.LENGTH_SHORT).show();
        }

        return faceRects;
    }

    /**
     *Importieren Sie den vorbereiteten openCV-Klassifikator einmal und stellen Sie ihn für den Export zur Verfügung.
     * @param inStream Originaldaten des Klassifikators
     * @Rückgabe der FaceDetector-Klassifikatordaten
     * @throws IOException
     */
    protected CascadeClassifier outputCascadeFile(InputStream inStream) throws IOException {
        File cascadeDir = getDir("cscade", Context.MODE_PRIVATE);
        File cascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml");

        //Geben Sie die erfasste XML-Datei in ein bestimmtes Verzeichnis aus
        FileOutputStream outputStream = new FileOutputStream(cascadeFile);

        byte[] buf = new byte[2048];
        int rdBytes;

        while ((rdBytes = inStream.read(buf)) != -1) {
            try {
                outputStream.write(buf, 0, rdBytes);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        //Legen Sie den Pfad der XML-Ausgabedatei auf das Argument von Cascade Classfle fest
        CascadeClassifier faceDetetcor = new CascadeClassifier((cascadeFile.getAbsolutePath()));

        outputStream.close();

        return faceDetetcor;
    }

    /**
     *Texterstellung für die Ausgabe
     *Stellen Sie die Koordinateninformationen basierend auf den Gesichtserkennungsinformationen auf Text ein
     * @param faceRects
     * @return
     */
    protected String makeOutputText(MatOfRect faceRects){
        String text = "";

        //Geben Sie das Ergebnis der Gesichtserkennung als Zeichenfolge zurück
        if(faceRects.toArray().length > 0){
            for(Rect face: faceRects.toArray()) {
                text = "Vertikale Breite des Gesichts:" + face.height + "\n" +
                        "Gesichtsbreite" + face.width + "\n" +
                        "Gesichtsposition(Y-Koordinate)" + face.y + "\n" +
                        "Gesichtsposition(X-Koordinate)" + face.x;
            }
        }
        else{
            text = "Es wurde kein Gesicht erkannt.";
        }

        return text;
    }

Recommended Posts

Gesichtserkennungs-App mit OpenCV + Android Studio
Gesichtserkennungs-App mit Amazon Rekognition und Java
So erstellen Sie eine App mit Tensorflow mit Android Studio
Importieren Sie Gerätebilder mit der Android App
Eine Reihe von Problemen in der Android Studio-Entwicklung
Ich habe eine Janken App mit Android gemacht
Riot (Chat App) Entwicklung (Einstellungen) in Android Studio
Android Wetter App
[Android] Verzweifelte Geschichte mit UserId und SharedUserId der App
Lassen Sie das Armbandgerät mit Bluetooth über die Android-App vibrieren
Kompatibel mit Android 10 (API 29)
Android App Spectrum Analyzer
Hinweise zu Android Studio
Android Studio Teil 3-6 besiegen
Android Studio Teil 1 und Teil 2 besiegen
Informationen zu Android-App-Komponenten
So machen Sie einen Screenshot mit dem Android Studio-Emulator
Verwenden Sie Java, das in Android Studio enthalten ist, um React Native zu erstellen