Как создать приложение для Android с функцией распознавания лиц с помощью Machine Learning KIT на Firebase

Опубликовано: 4 Января, 2022

Предварительные условия:

  • Комплект машинного обучения Firebase
  • Добавление Firebase в приложение для Android

Firebase ML KIT стремится сделать машинное обучение более доступным, предоставляя ряд предварительно обученных моделей, которые можно использовать в приложениях для iOS и Android. Давайте воспользуемся API распознавания лиц ML Kit, который будет определять лица на фотографиях. К концу этой статьи у нас будет приложение, которое может идентифицировать лица на изображении, а затем отображать информацию об этих лицах, например, улыбается ли человек или закрывает глаза с прекрасным графическим интерфейсом.

Подход

Шаг 1. Создайте новый проект

  1. Откройте новый проект в студии Android с любым именем.
  2. Мы будем работать с пустой активностью для конкретного проекта.
  3. Минимальный SDK, необходимый для этого конкретного проекта, - 23 , поэтому выберите любой API от 23 или выше.
  4. В этом проекте будет использоваться язык JAVA .
  5. Оставьте все варианты, кроме упомянутых выше, нетронутыми.
  6. Щелкните ФИНИШ .

Шаг 2. Подключитесь к ML KIT на Firebase.

  1. Войдите или зарегистрируйтесь на Firebase.
  2. В консоли Firebase создайте новый проект или, если вы хотите работать с существующим проектом, откройте его.
  3. Назовите проект по вашему выбору.
  4. Перейти в Документы .
  5. Нажмите Firebase ML и в левом пространстве выберите « Распознать текст » в разделе Vision.
  6. Выполните указанные шаги для лучшего понимания.
  7. Вернитесь в Android Studio.
  8. Перейдите в Инструменты -> Firebase -> Аналитика -> Подключиться к Firebase -> Выберите свой проект в появившемся диалоговом окне -> Нажмите Подключиться. (Этот шаг подключает ваше приложение для Android к Firebase)

Шаг 3. Пользовательские активы и Gradle

  • Для улучшения графического интерфейса либо выберите изображение в формате .png, добавьте его в папку res и установите в качестве фона основного XML-файла, либо установите цвет фона, перейдя в представление дизайна макета и настроив фон в разделе « Объявлено». Атрибуты как показано ниже:

  • Чтобы включить зависимости ML KIT в приложение, перейдите в Gradle Script -> build.gradle (Module: app) и добавьте реализацию, указанную ниже:

implementation ‘com.google.firebase:firebase-ml-vision:17.0.0’

  • Теперь скопируйте указанный ниже текст и вставьте его в самый конец Gradle уровня приложения, за пределами всех скобок, как показано на изображении ниже.

apply plugin: ‘com.google.gms.google-services’

  • Затем перейдите в bulid.gradle (проект), скопируйте указанный ниже текст и вставьте его в путь к классам «зависимости», как показано на изображении ниже.

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

  • Нажмите на синхронизацию сейчас .

Шаг 4: Разработка пользовательского интерфейса

  • Ниже приведен код базового XML-файла. Добавьте кнопку, чтобы открыть опцию камеры.

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"
  
    <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>
  • Теперь пользовательский интерфейс будет выглядеть так.

  • Теперь перейдите в layout -> new -> файл ресурсов макета -> Name: fragment_resultdialog.xml. Этот файл был создан для настройки экрана вывода, который будет отображать диалоговое окно под названием Диалоговое окно результатов с текстовым представлением под названием Текст результата со всеми атрибутами обнаруженного изображения. Ниже представлен XML-файл для созданного XML-файла.

XML

<? xml version = "1.0" encoding = "UTF-8" ?>
< androidx.constraintlayout.widget.ConstraintLayout
android:layout_height = "match_parent"
android:layout_width = "match_parent"
< 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 diplay 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 >

Шаг 5. Инициализатор приложения Firebase

  • Создайте новый класс java с помощью java -> new -> class -> Name: LCOFaceDetection.java -> superclass: Application (android.app.Application). Ниже приведен пример исходного кода для класса 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 );
}
}

Шаг 6. Расширение диалогового окна результатов

  • Создайте новый класс Java, а именно ResultDialog.java и суперкласс DialogFragment , который является файлом Java для fragment_resultdialog.xml . Ниже приведен пример кода для файла 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;
}
}

Шаг 7. Откройте камеру на реальном устройстве и включите функцию распознавания лиц.

  • Ниже приведен пример кода для основного файла java .
  • Для этого нужны классы FirebaseVision и FirebaseVisionFaceDetector.
  • Вот список всех параметров, которые вы можете настроить в своей модели распознавания лиц.
Параметр Описание
Режим производительности

БЫСТРО (по умолчанию) | ТОЧНЫЙ

Отдайте предпочтение скорости или точности при обнаружении лиц.

Обнаруживать ориентиры

NO_LANDMARKS (по умолчанию) | ALL_LANDMARKS

Следует ли пытаться идентифицировать «ориентиры» на лице:

глаза, уши, нос, щеки, рот и так далее.

Обнаружить контуры

NO_CONTOURS (по умолчанию) | ALL_CONTOURS

Следует ли определять контуры черт лица.

Контуры обнаруживаются только для наиболее заметного лица на изображении.

Классифицируйте лица

NO_CLASSIFICATIONS (по умолчанию) | ВСЕ_КЛАССИФИКАЦИИ

Следует ли классифицировать лица по категориям

такие как «улыбается» и «глаза открываются».

Минимальный размер лица

float (по умолчанию: 0.1f)

Минимальный размер обнаруживаемых лиц относительно изображения.

Включить отслеживание лица

false (по умолчанию) | правда

Следует ли назначать лицам идентификатор, который

можно использовать для отслеживания лиц на изображениях.

Обратите внимание, что когда включено определение контура,

распознается только одно лицо, поэтому отслеживание лиц не выполняется.

дают полезные результаты. По этой причине и для улучшения

скорость обнаружения, не включайте одновременно обнаружение контура и отслеживание лица.

  • Предлагается прочитать подробный анализ этих классов и поработать над кодом в документации Firebase ML для распознавания текста.

Джава

/*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, ie, 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( " FACE NUMBER. "
+ i + ": " )
.concat(
" Smile: "
+ face.getSmilingProbability()
* 100
+ "%" )
.concat(
" left eye open: "
+ face.getLeftEyeOpenProbability()
* 100
+ "%" )
.concat(
" right eye open "
+ face.getRightEyeOpenProbability()
* 100
+ "%" );
i++;
}