Cómo crear una aplicación Android de detección de rostros usando el KIT de aprendizaje automático en Firebase

Requisitos previos:

Firebase ML KIT tiene como objetivo hacer que el aprendizaje automático sea más accesible al proporcionar una gama de modelos previamente entrenados que se pueden usar en las aplicaciones de iOS y Android. Usemos la API de detección de rostros de ML Kit, que identificará los rostros en las fotos. Al final de este artículo, tendremos una aplicación que puede identificar caras en una imagen y luego mostrar información sobre estas caras, como si la persona está sonriendo o tiene los ojos cerrados con una GUI maravillosa.

face detection

Acercarse

Paso 1: Crear un nuevo proyecto

  1. Abra un nuevo proyecto en Android Studio con el nombre que desee.
  2. Vamos a trabajar con actividad vacía para el proyecto en particular.
  3. El SDK mínimo requerido para este proyecto en particular es 23 , así que elija cualquier API de 23 o superior.
  4. El lenguaje utilizado para este proyecto sería JAVA .
  5. Deje todas las opciones que no sean las mencionadas anteriormente, intactas.
  6. Haga clic en FINALIZAR .

Paso 2: conéctese con ML KIT en Firebase.

  1. Inicie sesión o regístrese en Firebase .
  2. En la consola Firebase, cree un nuevo proyecto o, si desea trabajar con un proyecto existente, ábralo.
  3. Nombra el proyecto según tu elección.
  4. Ve a Documentos .
  5. Haga clic en Firebase ML y, en el espacio de la izquierda, elija » reconocer texto » en Visión.
  6. Siga los pasos mencionados para una mejor comprensión.
  7. Vuelve a Android Studio.
  8. Vaya a Herramientas -> Firebase -> Analytics -> Conectar con Firebase -> Elija su proyecto en el cuadro de diálogo que aparece -> Haga clic en Conectar. (Este paso conecta su aplicación de Android a Firebase )

Paso 3: Activos personalizados y Gradle

  • Para mejorar la GUI, elija una imagen en formato .png y agréguela a la carpeta res y configúrela como fondo del archivo .xml principal, o configure un color de fondo yendo a la vista de diseño del diseño y personalizando el fondo en Declarado Atributos como se muestra a continuación:

  • Para incluir las dependencias de ML KIT, en la aplicación, vaya a Gradle Script -> build.gradle(Module:app) y agregue una implementación que se menciona a continuación:

implementación ‘com.google.firebase:firebase-ml-vision:17.0.0’

  • Ahora copie el texto mencionado a continuación y péguelo al final del nivel de la aplicación Gradle, fuera de todos los corchetes como se muestra en la imagen a continuación.

aplicar complemento: ‘com.google.gms.google-services’
 

  • A continuación, vaya a build.gradle (proyecto) y copie el texto mencionado a continuación, y péguelo en el classpath de ‘dependencias’ como se muestra en la imagen a continuación.

classpath ‘com.google.gms:google-services:4.2.0’
 

  • Haga clic en sincronizar ahora .

Paso 4: Diseño de la interfaz de usuario

  • A continuación se muestra el código para el archivo XML básico. Agregue un botón para abrir la opción de cámara.

XML

<?xml version="1.0" encoding="UTF-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    tools:context=".MainActivity"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">
 
    <Button
        android:background="#000000"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:text=CAMERA
        android:layout_marginBottom="100dp"
        android:padding="16dp"
        android:id="@+id/camera_button"/>
</androidx.constraintlayout.widget.ConstraintLayout>
  • Ahora la interfaz de usuario se verá así.

  • Ahora vaya a diseño -> nuevo -> archivo de recursos de diseño -> Nombre: fragment_resultdialog.xml. Este archivo se ha creado para personalizar la pantalla de salida, que mostrará un cuadro de diálogo denominado Cuadro de diálogo de resultados con una vista de texto denominada Texto de resultado con todos los atributos de la imagen detectada. A continuación se muestra el archivo XML para el archivo XML creado.

XML

<?xml version="1.0" encoding="UTF-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">
 
    <ScrollView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">
 
 
        <RelativeLayout
            android:id="@+id/relativeLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="20dp"
            android:layout_marginEnd="20dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">
           
            <!--text view to display the result text
                          after reading an image-->
            <TextView
                android:id="@+id/result_text_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="LCOFaceDetection"
                android:textColor="#000000"
                android:textSize="18sp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"/>
           
            <!--a button with text 'ok' written on it-->
            <Button
                android:id="@+id/result_ok_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/result_text_view"
                android:layout_centerInParent="true"
                android:layout_marginTop="20dp"
                android:layout_marginBottom="5dp"
                android:background="#75DA8B"
                android:padding="16dp"
                android:text="ok"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/result_text_view"/>
 
        </RelativeLayout>
 
    </ScrollView>
 
</androidx.constraintlayout.widget.ConstraintLayout>

Paso 5: Inicializador de la aplicación Firebase

  • Cree una nueva clase java con java -> nueva -> clase -> Nombre: LCOFaceDetection.java -> superclase: Aplicación (android.app.Application). A continuación se muestra el código fuente de ejemplo para la clase Java.

Java

import android.app.Application;
import com.google.firebase.FirebaseApp;
 
public class LCOFaceDetection extends Application {
    public final static String RESULT_TEXT = "RESULT_TEXT";
    public final static String RESULT_DIALOG = "RESULT_DIALOG";
 
    // initializing our firebase
    @Override
    public void onCreate()
    {
        super.onCreate();
        FirebaseApp.initializeApp(this);
    }
}

Paso 6: inflar el cuadro de diálogo de resultados

  • Cree una nueva clase java, a saber, ResultDialog.java y una superclase, DialogFragment , que es el archivo java para fragment_resultdialog.xml . A continuación se muestra el código de ejemplo para el archivo java.

Java

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
 
public class ResultDialog extends DialogFragment {
    Button okBtn;
    TextView resultTextView;
 
    @Nullable
    @Override
    public View
    onCreateView(@NonNull LayoutInflater inflater,
                 @Nullable ViewGroup container,
                 @Nullable Bundle savedInstanceState)
    {
 
        // importing View so as to inflate
        // the layout of our result dialog
        // using layout inflater.
        View view = inflater.inflate(
            R.layout.fragment_resultdialog, container,
            false);
        String resultText = "";
 
        // finding the elements by their id's.
        okBtn = view.findViewById(R.id.result_ok_button);
        resultTextView
            = view.findViewById(R.id.result_text_view);
 
        // To get the result text
        // after final face detection
        // and append it to the text view.
        Bundle bundle = getArguments();
        resultText = bundle.getString(
            LCOFaceDetection.RESULT_TEXT);
        resultTextView.setText(resultText);
 
        // Onclick listener so as
        // to make a dismissable button
        okBtn.setOnClickListener(
            new View.OnClickListener() {
                @Override
                public void onClick(View v)
                {
                    dismiss();
                }
            });
        return view;
    }
}

Paso 7: Abra la cámara en un dispositivo real y habilite la detección de rostros

  • A continuación se muestra el código de ejemplo para el archivo java principal .
  • Se necesitan las clases FirebaseVision y FirebaseVisionFaceDetector para esto.
  • Aquí hay una lista de todas las configuraciones que puede configurar en su modelo de detección de rostros.
Ajuste Descripción
Modo de desempeño

RÁPIDO (predeterminado) | PRECISO

Favorece la velocidad o la precisión al detectar rostros.

Detectar puntos de referencia

NO_LANDMARKS (predeterminado) | ALL_LANDMARKS

Ya sea para intentar identificar «puntos de referencia» faciales: 

ojos, oídos, nariz, mejillas, boca, etc.

Detectar contornos

SIN_CONTORNOS (predeterminado) | TODOS_CONTORNOS

Ya sea para detectar los contornos de los rasgos faciales. 

Los contornos se detectan solo para la cara más prominente de una imagen.

Clasificar caras

NO_CLASIFICACIONES (predeterminado) | TODAS LAS CLASIFICACIONES

Clasificar o no las caras en categorías

como «sonriendo» y «ojos abiertos».

Tamaño mínimo de la cara

flotante (predeterminado: 0.1f )

El tamaño mínimo, relativo a la imagen, de las caras a detectar.

Habilitar seguimiento facial

falso (predeterminado) | verdadero

Asignar o no una identificación a las caras, que

se puede utilizar para rastrear caras a través de imágenes.

Tenga en cuenta que cuando la detección de contorno está habilitada,  

solo se detecta un rostro, por lo que el seguimiento de rostros no 

producir resultados útiles. Por ello, y para mejorar

velocidad de detección, no habilite la detección de contornos ni el seguimiento de rostros.

  • Se sugiere leer un análisis detallado de estas clases y trabajar en el código en los documentos de Firebase ML para el reconocimiento de texto.

Java

/*package whatever do not write package name here*/
 
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.DialogFragment;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.FirebaseApp;
import com.google.firebase.ml.vision.FirebaseVision;
import com.google.firebase.ml.vision.common.FirebaseVisionImage;
import com.google.firebase.ml.vision.common.FirebaseVisionPoint;
import com.google.firebase.ml.vision.face.FirebaseVisionFace;
import com.google.firebase.ml.vision.face.FirebaseVisionFaceDetector;
import com.google.firebase.ml.vision.face.FirebaseVisionFaceDetectorOptions;
import com.google.firebase.ml.vision.face.FirebaseVisionFaceLandmark;
import java.util.List;
 
public class MainActivity extends AppCompatActivity {
    Button cameraButton;
 
    // whenever we request for our customized permission, we
    // need to declare an integer and initialize it to some
    // value .
    private final static int REQUEST_IMAGE_CAPTURE = 124;
    FirebaseVisionImage image;
    FirebaseVisionFaceDetector detector;
 
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        // initializing our firebase in main activity
        FirebaseApp.initializeApp(this);
 
        // finding the elements by their id's alloted.
        cameraButton = findViewById(R.id.camera_button);
 
        // setting an onclick listener to the button so as
        // to request image capture using camera
        cameraButton.setOnClickListener(
            new View.OnClickListener() {
                @Override
                public void onClick(View v)
                {
 
                    // makin a new intent for opening camera
                    Intent intent = new Intent(
                        MediaStore.ACTION_IMAGE_CAPTURE);
                    if (intent.resolveActivity(
                            getPackageManager())
                        != null) {
                        startActivityForResult(
                            intent, REQUEST_IMAGE_CAPTURE);
                    }
                    else {
                        // if the image is not captured, set
                        // a toast to display an error image.
                        Toast
                            .makeText(
                                MainActivity.this,
                                "Something went wrong",
                                Toast.LENGTH_SHORT)
                            .show();
                    }
                }
            });
    }
 
    @Override
    protected void onActivityResult(int requestCode,
                                    int resultCode,
                                    @Nullable Intent data)
    {
        // after the image is captured, ML Kit provides an
        // easy way to detect faces from variety of image
        // types like Bitmap
 
        super.onActivityResult(requestCode, resultCode,
                               data);
        if (requestCode == REQUEST_IMAGE_CAPTURE
            && resultCode == RESULT_OK) {
            Bundle extra = data.getExtras();
            Bitmap bitmap = (Bitmap)extra.get("data");
            detectFace(bitmap);
        }
    }
 
    // If you want to configure your face detection model
    // according to your needs, you can do that with a
    // FirebaseVisionFaceDetectorOptions object.
    private void detectFace(Bitmap bitmap)
    {
        FirebaseVisionFaceDetectorOptions options
            = new FirebaseVisionFaceDetectorOptions
                  .Builder()
                  .setModeType(
                      FirebaseVisionFaceDetectorOptions
                          .ACCURATE_MODE)
                  .setLandmarkType(
                      FirebaseVisionFaceDetectorOptions
                          .ALL_LANDMARKS)
                  .setClassificationType(
                      FirebaseVisionFaceDetectorOptions
                          .ALL_CLASSIFICATIONS)
                  .build();
 
        // we need to create a FirebaseVisionImage object
        // from the above mentioned image types(bitmap in
        // this case) and pass it to the model.
        try {
            image = FirebaseVisionImage.fromBitmap(bitmap);
            detector = FirebaseVision.getInstance()
                           .getVisionFaceDetector(options);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
 
        // It’s time to prepare our Face Detection model.
        detector.detectInImage(image)
            .addOnSuccessListener(new OnSuccessListener<List<FirebaseVisionFace> >() {
                @Override
                // adding an onSuccess Listener, i.e, in case
                // our image is successfully detected, it will
                // append it's attribute to the result
                // textview in result dialog box.
                public void onSuccess(
                    List<FirebaseVisionFace>
                        firebaseVisionFaces)
                {
                    String resultText = "";
                    int i = 1;
                    for (FirebaseVisionFace face :
                         firebaseVisionFaces) {
                        resultText
                            = resultText
                                  .concat("\nFACE NUMBER. "
                                          + i + ": ")
                                  .concat(
                                      "\nSmile: "
                                      + face.getSmilingProbability()
                                            * 100
                                      + "%")
                                  .concat(
                                      "\nleft eye open: "
                                      + face.getLeftEyeOpenProbability()
                                            * 100
                                      + "%")
                                  .concat(
                                      "\nright eye open "
                                      + face.getRightEyeOpenProbability()
                                            * 100
                                      + "%");
                        i++;
                    }
 
                    // if no face is detected, give a toast
                    // message.
                    if (firebaseVisionFaces.size() == 0) {
                        Toast
                            .makeText(MainActivity.this,
                                      "NO FACE DETECT",
                                      Toast.LENGTH_SHORT)
                            .show();
                    }
                    else {
                        Bundle bundle = new Bundle();
                        bundle.putString(
                            LCOFaceDetection.RESULT_TEXT,
                            resultText);
                        DialogFragment resultDialog
                            = new ResultDialog();
                        resultDialog.setArguments(bundle);
                        resultDialog.setCancelable(true);
                        resultDialog.show(
                            getSupportFragmentManager(),
                            LCOFaceDetection.RESULT_DIALOG);
                    }
                }
            }) // adding an onfailure listener as well if
            // something goes wrong.
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e)
                {
                    Toast
                        .makeText(
                            MainActivity.this,
                            "Oops, Something went wrong",
                            Toast.LENGTH_SHORT)
                        .show();
                }
            });
    }
}

Producción

Publicación traducida automáticamente

Artículo escrito por anushree_mishra y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *