Samouczek: Tworzenie aplikacji dla systemu Android wykrywającej i oznaczającej ramką twarze na obrazieTutorial: Create an Android app to detect and frame faces in an image

W tym samouczku utworzysz prostą aplikację dla systemu Android, która używa interfejsu API rozpoznawania twarzy platformy Azure, za pośrednictwem zestawu SDK Java, do wykrywania twarzy na obrazie.In this tutorial, you will create a simple Android application that uses the Azure Face API, through the Java SDK, to detect human faces in an image. Aplikacja wyświetla wybrany obraz i rysuje ramkę wokół każdej wykrytej twarzy.The application displays a selected image and draws a frame around each detected face.

Ten samouczek przedstawia sposób wykonania następujących czynności:This tutorial shows you how to:

  • Tworzenie aplikacji systemu AndroidCreate an Android application
  • Instalowanie biblioteki klienta interfejsu API rozpoznawania twarzyInstall the Face API client library
  • Korzystanie z biblioteki klienta do wykrywania twarzy na obrazieUse the client library to detect faces in an image
  • Rysowanie ramki wokół każdej wykrytej twarzyDraw a frame around each detected face

Zrzut ekranu z systemu Android ze zdjęciem, na którym widać twarze otoczone czerwoną ramką

Kompletny przykładowy kod jest dostępny w repozytorium Cognitive Services Face Android w witrynie GitHub.The complete sample code is available in the Cognitive Services Face Android repository on GitHub.

Jeśli nie masz subskrypcji platformy Azure, przed rozpoczęciem utwórz bezpłatne konto.If you don't have an Azure subscription, create a free account before you begin.

Wymagania wstępnePrerequisites

  • Klucz subskrypcji interfejsu API rozpoznawania twarzy.A Face API subscription key. Klucz subskrypcji bezpłatnej wersji próbnej możesz uzyskać na stronie Wypróbuj usługi Cognitive Services.You can get a free trial subscription key from Try Cognitive Services. Możesz też wykonać instrukcje z tematu Create a Cognitive Services account (Tworzenie konta usług Cognitive Services), aby subskrybować usługę interfejsu API rozpoznawania twarzy i uzyskać klucz.Or, follow the instructions in Create a Cognitive Services account to subscribe to the Face API service and get your key.
  • Program Android Studio z poziomem interfejsu API 22 lub nowszym (wymagane przez bibliotekę klienta rozpoznawania twarzy).Android Studio with API level 22 or later (required by the Face client library).

Tworzenie projektu programu Android StudioCreate the Android Studio project

Wykonaj następujące kroki, aby utworzyć nowy projekt aplikacji dla systemu Android.Follow these steps to create a new Android application project.

  1. W programie Android Studio wybierz pozycję Start a new Android Studio project (Utwórz nowy projekt programu Android Studio).In Android Studio, select Start a new Android Studio project.
  2. Na ekranie Create Android Project (Tworzenie projektu systemu Android) zmodyfikuj domyślną zawartość pól, jeśli to konieczne, a następnie kliknij przycisk Next (Dalej).On the Create Android Project screen, modify the default fields, if necessary, then click Next.
  3. Na ekranie Target Android Devices (Docelowe urządzenia z systemem Android) użyj rozwijanego selektora, aby wybrać interfejs API 22 lub nowszy, a następnie kliknij przycisk Next (Dalej).On the Target Android Devices screen, use the dropdown selector to choose API 22 or later, then click Next.
  4. Wybierz pozycję Empty Activity (Puste działanie), a następnie kliknij przycisk Next (Dalej).Select Empty Activity, then click Next.
  5. Usuń zaznaczenie pola wyboru Backwards Compatibility (Zgodność z wcześniejszymi wersjami), a następnie kliknij przycisk Finish (Zakończ).Uncheck Backwards Compatibility, then click Finish.

Dodawanie początkowego koduAdd the initial code

Tworzenie interfejsu użytkownikaCreate the UI

Otwórz plik activity_main.xml.Open activity_main.xml. W edytorze układu Layout Editor wybierz kartę Text (Tekst), a następnie zastąp zawartość następującym kodem.In the Layout Editor, select the Text tab, then replace the contents with the following code.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:id="@+id/imageView1"
        android:layout_above="@+id/button1"
        android:contentDescription="Image with faces to analyze"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Browse for a face image"
        android:id="@+id/button1"
        android:layout_alignParentBottom="true"/>
</RelativeLayout>

Tworzenie głównej klasyCreate the main class

Otwórz plik MainActivity.java i zastąp istniejące instrukcje import następującym kodem.Open MainActivity.java and replace the existing import statements with the following code.

import java.io.*;
import android.app.*;
import android.content.*;
import android.net.*;
import android.os.*;
import android.view.*;
import android.graphics.*;
import android.widget.*;
import android.provider.*;

Następnie zastąp zawartość klasy MainActivity następującym kodem.Then, replace the contents of the MainActivity class with the following code. Utworzy on procedurę obsługi zdarzeń dla elementu Button, która uruchamia nowe działanie pozwalające użytkownikowi wybrać obraz.This creates an event handler on the Button that starts a new activity to allow the user to select a picture. Wyświetla obraz w widoku ImageView.It displays the picture in the ImageView.

private final int PICK_IMAGE = 1;
private ProgressDialog detectionProgressDialog;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button button1 = findViewById(R.id.button1);
    button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.setType("image/*");
            startActivityForResult(Intent.createChooser(
                    intent, "Select Picture"), PICK_IMAGE);
        }
    });

    detectionProgressDialog = new ProgressDialog(this);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == PICK_IMAGE && resultCode == RESULT_OK &&
            data != null && data.getData() != null) {
        Uri uri = data.getData();
        try {
            Bitmap bitmap = MediaStore.Images.Media.getBitmap(
                    getContentResolver(), uri);
            ImageView imageView = findViewById(R.id.imageView1);
            imageView.setImageBitmap(bitmap);

            // Comment out for tutorial
            detectAndFrame(bitmap);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Testowanie aplikacjiTry the app

Oznacz jako komentarz wywołanie funkcji detectAndFrame w metodzie onActivityResult.Comment out the call to detectAndFrame in the onActivityResult method. Następnie naciśnij pozycję Uruchom w menu, aby przetestować aplikację.Then press Run on the menu to test your app. Gdy aplikacja zostanie otwarta, w emulatorze lub na podłączonym urządzeniu, kliknij pozycję Przeglądaj na dole.When the app opens, either in an emulator or a connected device, click the Browse on the bottom. Powinno zostać wyświetlone okno dialogowe wyboru pliku urządzenia.The device's file selection dialog should appear. Wybierz obraz i sprawdź, czy jest on wyświetlany w oknie.Choose an image and verify that it displays in the window. Następnie zamknij aplikację i przejdź do kolejnego kroku.Then, close the app and advance to the next step.

Zrzut ekranu z systemu Android przedstawiający zdjęcie z twarzami

Dodawanie zestawu SDK interfejsu API rozpoznawania twarzyAdd the Face SDK

Dodawanie zależności narzędzia GradleAdd the Gradle dependency

W okienku Project (Projekt) wybierz za pomocą rozwijanego selektora pozycję Android.In the Project pane, use the dropdown selector to select Android. Rozwiń pozycję Gradle Scripts (Skrypty Gradle), a następnie otwórz plik build.gradle (Module: app).Expand Gradle Scripts, then open build.gradle (Module: app). Dodaj zależność dla biblioteki klienta rozpoznawania twarzy, com.microsoft.projectoxford:face:1.4.3, jak pokazano na poniższym zrzucie ekranu, a następnie kliknij pozycję Sync now (Synchronizuj teraz).Add a dependency for the Face client library, com.microsoft.projectoxford:face:1.4.3, as shown in the screenshot below, then click Sync Now.

Zrzut ekranu z programu Android Studio przedstawiający plik build.gradle aplikacji

Wróć do pliku MainActivity.java i dodaj następujące instrukcje import:Go back to MainActivity.java and add the following import statements:

import com.microsoft.projectoxford.face.*;
import com.microsoft.projectoxford.face.contract.*;

Następnie wstaw następujący kod w klasie MainActivity powyżej metody onCreate:Then, insert the following code in the MainActivity class, above the onCreate method:

// Replace `<API endpoint>` with the Azure region associated with
// your subscription key. For example,
// apiEndpoint = "https://westcentralus.api.cognitive.microsoft.com/face/v1.0"
private final String apiEndpoint = "<API endpoint>";

// Replace `<Subscription Key>` with your subscription key.
// For example, subscriptionKey = "0123456789abcdef0123456789ABCDEF"
private final String subscriptionKey = "<Subscription Key>";

private final FaceServiceClient faceServiceClient =
        new FaceServiceRestClient(apiEndpoint, subscriptionKey);

Konieczne będzie zastąpienie elementu <Subscription Key> kluczem subskrypcji.You will need to replace <Subscription Key> with your subscription key. Należy także zastąpić element <API endpoint> punktem końcowym interfejsu API rozpoznawania twarzy, używając odpowiedniego identyfikatora regionu dla swojego klucza (zobacz dokumentację interfejsu API rozpoznawania twarzy, aby zapoznać się z listą wszystkich punktów końcowych regionów).Also, replace <API endpoint> with your Face API endpoint, using the appropriate region identifier for your key (see the Face API docs for a list of all region endpoints). Klucze subskrypcji bezpłatnej wersji próbnej są generowane w regionie westus.Free trial subscription keys are generated in the westus region.

W okienku Project (Projekt) rozwiń pozycje app i manifests, a następnie otwórz plik AndroidManifest.xml.In the Project pane, expand app, then manifests, and open AndroidManifest.xml. Wstaw następujący element jako bezpośredni element podrzędny elementu manifest:Insert the following element as a direct child of the manifest element:

<uses-permission android:name="android.permission.INTERNET" />

Przekazywanie obrazu i wykrywanie twarzyUpload image and detect faces

Aplikacja będzie wykrywała twarze, wywołując metodę FaceServiceClient.detect, która opakowuje interfejs API REST wykrywania i zwraca listę wystąpień obiektu Face.Your app will detect faces by calling the FaceServiceClient.detect method, which wraps the Detect REST API and returns a list of Face instances.

Każdy zwrócony element Face zawiera prostokąt wskazujący lokalizację twarzy wraz z serią opcjonalnych atrybutów twarzy.Each returned Face includes a rectangle to indicate its location, combined with a series of optional face attributes. W tym przykładzie żądane są tylko prostokąty wskazujące lokalizację twarzy.In this example, only the face rectangles are requested.

Wstaw następujące dwie metody do klasy MainActivity.Insert the following two methods into the MainActivity class. Należy pamiętać, że po zakończeniu procesu wykrywania twarzy aplikacja wywołuje metodę drawFaceRectanglesOnBitmap, aby zmodyfikować widok ImageView.Note that when face detection completes, the app calls the drawFaceRectanglesOnBitmap method to modify the ImageView. Zdefiniujesz tę metodę w następnej kolejności.You will define this method next.

// Detect faces by uploading a face image.
// Frame faces after detection.
private void detectAndFrame(final Bitmap imageBitmap) {
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
    ByteArrayInputStream inputStream =
            new ByteArrayInputStream(outputStream.toByteArray());

    AsyncTask<InputStream, String, Face[]> detectTask =
            new AsyncTask<InputStream, String, Face[]>() {
                String exceptionMessage = "";

                @Override
                protected Face[] doInBackground(InputStream... params) {
                    try {
                        publishProgress("Detecting...");
                        Face[] result = faceServiceClient.detect(
                                params[0],
                                true,         // returnFaceId
                                false,        // returnFaceLandmarks
                                null          // returnFaceAttributes:
                                /* new FaceServiceClient.FaceAttributeType[] {
                                    FaceServiceClient.FaceAttributeType.Age,
                                    FaceServiceClient.FaceAttributeType.Gender }
                                */
                        );
                        if (result == null){
                            publishProgress(
                                    "Detection Finished. Nothing detected");
                            return null;
                        }
                        publishProgress(String.format(
                                "Detection Finished. %d face(s) detected",
                                result.length));
                        return result;
                    } catch (Exception e) {
                        exceptionMessage = String.format(
                                "Detection failed: %s", e.getMessage());
                        return null;
                    }
                }

                @Override
                protected void onPreExecute() {
                    //TODO: show progress dialog
                    detectionProgressDialog.show();
                }
                @Override
                protected void onProgressUpdate(String... progress) {
                    //TODO: update progress
                    detectionProgressDialog.setMessage(progress[0]);
                }
                @Override
                protected void onPostExecute(Face[] result) {
                    //TODO: update face frames
                    detectionProgressDialog.dismiss();

                    if(!exceptionMessage.equals("")){
                        showError(exceptionMessage);
                    }
                    if (result == null) return;

                    ImageView imageView = findViewById(R.id.imageView1);
                    imageView.setImageBitmap(
                            drawFaceRectanglesOnBitmap(imageBitmap, result));
                    imageBitmap.recycle();
                }
            };

    detectTask.execute(inputStream);
}

private void showError(String message) {
    new AlertDialog.Builder(this)
            .setTitle("Error")
            .setMessage(message)
            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                }})
            .create().show();
}

Rysowanie prostokątów twarzyDraw face rectangles

Wstaw następującą metodę pomocniczą do klasy MainActivity.Insert the following helper method into the MainActivity class. Ta metoda rysuje prostokąt wokół każdej wykrytej twarzy przy użyciu współrzędnych prostokąta każdego wystąpienia elementu Face.This method draws a rectangle around each detected face, using the rectangle coordinates of each Face instance.

private static Bitmap drawFaceRectanglesOnBitmap(
        Bitmap originalBitmap, Face[] faces) {
    Bitmap bitmap = originalBitmap.copy(Bitmap.Config.ARGB_8888, true);
    Canvas canvas = new Canvas(bitmap);
    Paint paint = new Paint();
    paint.setAntiAlias(true);
    paint.setStyle(Paint.Style.STROKE);
    paint.setColor(Color.RED);
    paint.setStrokeWidth(10);
    if (faces != null) {
        for (Face face : faces) {
            FaceRectangle faceRectangle = face.faceRectangle;
            canvas.drawRect(
                    faceRectangle.left,
                    faceRectangle.top,
                    faceRectangle.left + faceRectangle.width,
                    faceRectangle.top + faceRectangle.height,
                    paint);
        }
    }
    return bitmap;
}

Na koniec usuń znaczniki komentarza z wywołania metody detectAndFrame w metodzie onActivityResult.Finally, uncomment the call to the detectAndFrame method in onActivityResult.

Uruchamianie aplikacjiRun the app

Uruchom aplikację i znajdź obraz z twarzą.Run the application and browse for an image with a face. Zaczekaj kilka sekund, aby umożliwić usłudze rozpoznawania twarzy udzielenie odpowiedzi.Wait a few seconds to allow the Face service to respond. Wokół każdej twarzy na obrazie powinien pojawić się czerwony prostokąt.You should see a red rectangle on each of the faces in the image.

Zrzut ekranu systemu Android przedstawiający twarze z czerwonymi prostokątami narysowanymi wokół nich

Kolejne krokiNext steps

W tym samouczku przedstawiono podstawowy proces korzystania z zestawu SDK języka Java interfejsu API rozpoznawania twarzy dla usługi rozpoznawania twarzy oraz utworzono aplikację do wykrywania i oznaczania ramkami twarzy na obrazie.In this tutorial, you learned the basic process for using the Face API Java SDK and created an application to detect and frame faces in an image. Teraz dowiedz się więcej o szczegółach wykrywania twarzy.Next, learn more about the details of face detection.