9

Bài viết này mô tả cách tạo ứng dụng phát hiện các tính năng khuôn mặt bằng API nhận diện khuôn mặt (Firebase ML Kit) và Android Things. Ý tưởng của bài viết này đến từ dự án của Google có tên “Hoa biểu hiện Android Things”. Ý tưởng dự án này là phát hiện đặc điểm khuôn mặt (hoặc phân loại khuôn mặt) bằng cách sử dụng thị giác máy dựa trên Firebase ML Kit. Hơn nữa, dự án này hiển thị các đặc điểm khuôn mặt bằng màn hình LCD hiển thị và một số biểu tượng cảm xúc.

Để xây dựng dự án này, bạn sẽ cần:

  • Raspberry Pi
  • Máy ảnh Raspberry
  • Màn hình LCD (SSD1306)

Kết quả cuối cùng được hiển thị ở đây:

Firebase ML Kit: Xây dựng ứng dụng phát hiện đặc điểm khuôn mặt với tính năng nhận diện khuôn mặt ...
Firebase ML Kit: Xây dựng ứng dụng phát hiện đặc điểm khuôn mặt với tính năng nhận diện khuôn mặt ...

Tải xuống mã nguồn Android Things

Giới thiệu về Firebase ML Kit

Firebase ML Kit là SDK di động giúp chúng tôi thử nghiệm với các công nghệ máy học. Tensorflow  và CloudVision giúp phát triển các ứng dụng di động sử dụng máy học dễ dàng hơn. Dù sao, các mô hình học máy đứng đằng sau đòi hỏi thời gian và công sức. Firebase ML Kit là nỗ lực của Google để làm cho máy học dễ sử dụng hơn và dễ tiếp cận hơn với những người không biết nhiều về công nghệ máy học, cung cấp các mô hình được đào tạo trước có thể được sử dụng để phát triển ứng dụng Android và Android Things.

Bài viết này mô tả cách triển khai ứng dụng Android Things bằng thị giác máy nhận dạng các đặc điểm khuôn mặt.

Nó sẽ cho thấy việc thêm khả năng học máy vào ứng dụng Android Things dễ dàng như thế nào mà không cần biết nhiều về Học máy cũng như không cần xây dựng và tối ưu hóa mô hình Học máy.

API nhận diện khuôn mặt trong Firebase ML Kit là gì

Sử dụng Firebase ML Kit API phát hiện khuôn mặt có thể phát hiện khuôn mặt trong ảnh hoặc sử dụng máy ảnh. Trong dự án Android Things này, chúng tôi sẽ sử dụng một máy ảnh được kết nối với Raspberry Pi. Hơn nữa, khi khuôn mặt được nhận diện, chúng ta có thể phát hiện các đặc điểm của khuôn mặt như xoay khuôn mặt, kích thước, v.v. Hơn nữa, bằng cách sử dụng API nhận diện khuôn mặt, chúng ta có thể đi sâu hơn trong việc truy xuất phân tích khuôn mặt này:

  • Mốc : điểm quan tâm của khuôn mặt như mắt trái, mắt phải, gốc mũi, v.v.
  • Đường viền : chúng là các điểm theo hình dạng khuôn mặt
  • Phân loại : là khả năng phát hiện đặc điểm khuôn mặt cụ thể. Ví dụ, có thể phát hiện xem một mắt đang nhắm hay mở hoặc khuôn mặt đang cười

Hơn nữa, sử dụng API nhận diện khuôn mặt, có thể theo dõi khuôn mặt trong một chuỗi video. Như bạn có thể thấy, chúng là những tính năng rất thú vị mở ra kịch bản mới trong việc phát triển ứng dụng.

Trong dự án này, như đã nêu trước đây, chúng tôi sẽ sử dụng phân loại khuôn mặt để thể hiện đặc điểm khuôn mặt trong màn hình LCD. Để làm điều đó, ứng dụng sẽ sử dụng những hình ảnh này để đại diện cho các đặc điểm khuôn mặt:

Firebase ML Kit: Xây dựng ứng dụng phát hiện đặc điểm khuôn mặt với tính năng nhận diện khuôn mặt ...
Mặt trung tính
Firebase ML Kit: Xây dựng ứng dụng phát hiện đặc điểm khuôn mặt với tính năng nhận diện khuôn mặt ...
Nhắm mắt phải
Firebase ML Kit: Xây dựng ứng dụng phát hiện đặc điểm khuôn mặt với tính năng nhận diện khuôn mặt ...
Khuôn mặt tươi cười
Firebase ML Kit: Xây dựng ứng dụng phát hiện đặc điểm khuôn mặt với tính năng nhận diện khuôn mặt ...
Nhắm mắt trái


Cách sử dụng API nhận diện khuôn mặt

Bây giờ chúng ta đã biết API nhận diện khuôn mặt là gì, đã đến lúc bắt đầu sử dụng nó để xây dựng ứng dụng Android Things.

Trước khi triển khai ứng dụng của chúng tôi, cần phải định cấu hình một dự án mới bằng Bảng điều khiển Firebase. Đây là một bước rất đơn giản. Cuối cùng, bạn sẽ nhận được tệp JSON để tải xuống, tệp này phải được thêm vào dự án Android Things của bạn.

Thiết lập Bộ ML Firebase

Sau khi dự án được định cấu hình, cần phải định cấu hình API nhận diện khuôn mặt và thêm các phần phụ thuộc phù hợp vào dự án của chúng tôi:

dependencies {
    implementation 'com.google.firebase:firebase-ml-vision:18.0.2'
    implementation 'com.google.firebase:firebase-ml-vision-face-model:17.0.2'
}


Tiếp theo, chúng ta hãy thêm những dòng này vào Manifest.xml:

<uses-permission 
     android:name="android.permission.CAMERA"/>
<uses-permission 
     android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<meta-data
     android:name="com.google.firebase.ml.vision.DEPENDENCIES"
     android:value="face" />


Cách sử dụng phân loại khuôn mặt để phát hiện đặc điểm khuôn mặt

Đã đến lúc bắt đầu sử dụng bộ Firebase ML và chi tiết hơn là API nhận diện khuôn mặt trong ứng dụng Android Things này. Có hai bước cần làm để phát hiện các đặc điểm khuôn mặt như nụ cười, nhắm mắt trái hoặc mắt phải, v.v. Các bước này được hiển thị bên dưới:

  • Sử dụng máy ảnh để chụp ảnh
  • Chuyển ảnh chụp sang Firebase MK Kit để phát hiện khuôn mặt

Bây giờ, chúng ta có thể giả sử rằng hình ảnh được chụp bằng cách nào đó và chúng ta có thể tập trung sự chú ý vào cách sử dụng Firebase ML Kit (API nhận diện khuôn mặt) để phát hiện các đặc điểm khuôn mặt.

Định cấu hình API nhận diện khuôn mặt

Trước khi áp dụng quy trình nhận diện khuôn mặt cho hình ảnh, cần phải khởi chạy Bộ ML Firebase và định cấu hình API nhận diện khuôn mặt. Trong MainActivityvà để biết thêm chi tiết trong onCreatephương pháp, hãy thêm dòng này:

FirebaseApp.initializeApp(this);


Để định cấu hình Bộ dò tìm khuôn mặt, cần sử dụng FirebaseVisionFaceDetectorOptions(thông tin thêm tại đây ) theo cách sau:

 FirebaseVisionFaceDetectorOptions options =
                new FirebaseVisionFaceDetectorOptions.Builder();


Tiếp theo, cần thêm các tùy chọn cấu hình:

FirebaseVisionFaceDetectorOptions options =
         new FirebaseVisionFaceDetectorOptions.Builder()                      
.setClassificationMode(FirebaseVisionFaceDetectorOptions.ALL_CLASSIFICATIONS)
.enableTracking()
.build();


Ứng dụng Android Things quan tâm đến phân loại khuôn mặt, như đã nêu trước đây, vì vậy chúng tôi bật cấu hình này. Hơn nữa, theo mặc định, tính năng nhận diện khuôn mặt sẽ sử dụng FAST_MODE (được bật theo mặc định).

Cuối cùng:

FirebaseVisionFaceDetector detector = FirebaseVision.getInstance().getVisionFaceDetector(options);


Khi máy dò đã sẵn sàng và được định cấu hình chính xác, chúng tôi có thể bắt đầu phát hiện các đặc điểm khuôn mặt (hoặc phân loại khuôn mặt) bằng cách sử dụng hình ảnh đã chụp:

 firebaseImage = FirebaseVisionImage.fromBitmap(displayBitmap);
 result = detector
    .detectInImage(firebaseImage)
    .addOnSuccessListener(new 
      OnSuccessListener<List<FirebaseVisionFace>>() {
       @Override
       public void onSuccess(List<FirebaseVisionFace> faces) {
         for (FirebaseVisionFace face : faces) {
           Log.d(TAG, "****************************");
           Log.d(TAG, "face ["+face+"]");
           Log.d(TAG, "Smiling Prob ["+face.getSmilingProbability()+"]");
           Log.d(TAG, "Left eye open ["+face.getLeftEyeOpenProbability()+"]");
           Log.d(TAG, "Right eye open ["+face.getRightEyeOpenProbability()+"]");
                    checkFaceExpression(face);
         }
      }
});


Có một số khía cạnh cần lưu ý:

  1. Sử dụng displayBitmap, chúng tôi nhận được  firebaseImage đó là hình ảnh mà chúng tôi muốn phát hiện các đặc điểm khuôn mặt.
  2. Ứng dụng gọi phương pháp detectInImageđể bắt đầu phát hiện khuôn mặt (ứng dụng sử dụng phân loại khuôn mặt)
  3. Ứng dụng thêm người nghe để nhận thông báo khi có các đặc điểm trên khuôn mặt
  4. Đối với mỗi khuôn mặt được phát hiện, ứng dụng sẽ có xác suất
  5. Cuối cùng, sử dụng xác suất được truy xuất trước khi ứng dụng Android Things điều khiển màn hình LCD hiển thị biểu tượng cảm xúc

Phương pháp checkFaceExpressionphân loại khuôn mặt xác định các đặc điểm trên khuôn mặt. Cuối cùng, nó thông báo kết quả cho người gọi (như chúng ta sẽ thấy ở phần sau):

private void checkFaceExpression(FirebaseVisionFace face) {
  if (face.getSmilingProbability() > 0.5) {
    Log.d(TAG, "**** Smiling ***");
    listener.onSuccess(FACE_STATUS.SMILING);
   }
   if (face.getLeftEyeOpenProbability() < 0.2 &amp;&amp;
      face.getLeftEyeOpenProbability() != -1 &amp;&amp;
      face.getRightEyeOpenProbability() > 0.5) {
    Log.d(TAG, "Right Open..");
    listener.onSuccess(FACE_STATUS.RIGHT_EYE_OPEN_LEFT_CLOSE)
   }
   if (face.getRightEyeOpenProbability() < 0.2 &amp;&amp;
     face.getRightEyeOpenProbability() != -1 &amp;&amp;
     face.getLeftEyeOpenProbability() > 0.5) {
    Log.d(TAG, "Left Open..");        
    listener.onSuccess(FACE_STATUS.LEFT_EYE_OPEN_RIGHT_CLOSE);
   }
   listener.onSuccess(FACE_STATUS.LEFT_OPEN_RIGHT_OPEN);
}


Cách chụp ảnh bằng máy ảnh trong Android Things

Bây giờ, chúng tôi đã chụp được hình ảnh. Đoạn này hướng dẫn cách thực hiện bằng cách sử dụng máy ảnh được kết nối với Raspberry Pi. Quá trình này khá đơn giản và nó giống như cách chúng ta sử dụng khi triển khai ứng dụng Android. Có thể phá vỡ quá trình này theo các bước sau:

  • Mở máy ảnh
  • Tạo một phiên chụp
  • Xử lý hình ảnh

Mở máy ảnh

Trong bước này, ứng dụng Android Things khởi chạy máy ảnh. Trước khi sử dụng máy ảnh, cần phải thêm quyền phù hợp vào Manifest.xml:

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


Hơn nữa, chúng ta hãy tạo một lớp mới sẽ xử lý tất cả các chi tiết liên quan đến nhận diện khuôn mặt và gọi nó FaceDetector.javavà hàm tạo của nó là:

 public FaceDetector(Context ctx, ImageView img, Looper looper) {
   this.ctx = ctx;
   this.img = img;
   this.looper = looper;
 }


Chúng ta sẽ xem sau vai trò của  ImageView. Tiếp theo, hãy kiểm tra xem máy ảnh có xuất hiện hay không và mở nó:

private void openCamera(CameraManager camManager) {
  try {
   String[] camIds = camManager.getCameraIdList();
   if (camIds.length < 1) {
     Log.e(TAG, "Camera not available");
     listener.onError();
     return;
   }

  camManager.openCamera(camIds[0],
      new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice camera) {
          Log.i(TAG, "Camera opened");
          startCamera(camera);
        }
        @Override
        public void onDisconnected(@NonNull CameraDevice camera) 
         {}
        @Override
        public void onError(@NonNull CameraDevice camera, int error) {
         Log.e(TAG, "Error ["+error+"]");
         listener.onError();
        }
      },
      backgroundHandler);
  }
  catch(CameraAccessException cae) {
    cae.printStackTrace();
    listener.onError();
  }
}


Ở đâu:

CameraManager cameraManager = (CameraManager) ctx.getSystemService(Context.CAMERA_SERVICE);


Mã này khá đơn giản; nó là cần thiết để thực hiện một người nghe để nhận được thông báo khi máy ảnh được mở hoặc một số lỗi xảy ra. Đó là tất cả.

Tạo một phiên chụp

Bước tiếp theo là tạo phiên chụp để ứng dụng Android Things có thể chụp ảnh. Hãy để chúng tôi thêm một phương pháp mới:

private void startCamera(CameraDevice cameraDevice) {
    try {
     final CaptureRequest.Builder requestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            requestBuilder.addTarget(mImageReader.getSurface());
            cameraDevice.createCaptureSession(Collections.singletonList(mImageReader.getSurface()),
                    new CameraCaptureSession.StateCallback() {
                        @Override
                        public void onConfigured(@NonNull CameraCaptureSession session) {
                            Log.i(TAG, "Camera configured..");
                            CaptureRequest request = requestBuilder.build();
                            try {                               session.setRepeatingRequest(request, null, backgroundHandler);
                            }
                            catch (CameraAccessException cae) {
                                Log.e(TAG, "Camera session error");
                                cae.printStackTrace();
                            }
                        }

                        @Override
                        public void onConfigureFailed(@NonNull CameraCaptureSession session) {

                        }
                    },
            backgroundHandler);
        }
        catch (CameraAccessException cae) {
            Log.e(TAG, "Camera Access Error");
            cae.printStackTrace();
            listener.onError();
        }

    }


Trong phương pháp này, ứng dụng Android Things bắt đầu phiên chụp và ứng dụng này sẽ được thông báo khi hình ảnh được chụp.

Xử lý hình ảnh

Bước cuối cùng là xử lý hình ảnh đã chụp. Hình ảnh này sẽ được gửi đến Firebase ML Kit để lấy các đặc điểm trên khuôn mặt. Với mục đích này, cần phải triển khai một phương thức gọi lại:

 @Override
 public void onImageAvailable(ImageReader reader) {
   //Log.i(TAG, "Image Ready..");
   Image image = reader.acquireLatestImage();
   // We have to convert the image before
   // use it in Firebase ML Kit
   ...
}


Đó là tất cả. Hình ảnh đã sẵn sàng và máy ảnh đã chụp để chúng tôi có thể bắt đầu phát hiện các đặc điểm khuôn mặt.

Dưới đây là một số tài nguyên hữu ích khác:

Hiển thị các đặc điểm nhận diện khuôn mặt bằng Android Things và LCD

Trong bước này, chúng tôi sẽ hướng dẫn cách hiển thị các đặc điểm khuôn mặt được lấy bởi Firebase ML Kit. Trong dự án này, Raspberry Pi được kết nối với màn hình LCD (SSD1306) sẽ hiển thị các đặc điểm trên khuôn mặt. Bằng cách này, ứng dụng Android Things có thể điều khiển các thiết bị bằng cách sử dụng khuôn mặt được phát hiện.

Trước khi bắt đầu, sẽ hữu ích cho bạn cách kết nối Raspberry Pi với SSD1306:

Firebase ML Kit: Xây dựng ứng dụng phát hiện đặc điểm khuôn mặt với tính năng nhận diện khuôn mặt ...

Như bạn có thể nhận thấy, kết nối rất đơn giản. Để xử lý màn hình LCD, cần phải thêm trình điều khiển phù hợp vào dự án Android Things của chúng tôi. Trong dòng build.gradlethêm dòng này:

implementation 'com.google.android.things.contrib:driver-ssd1306:1.1'


Để xử lý tất cả các chi tiết liên quan đến màn hình LCD, chúng ta hãy tạo một lớp mới được gọi là DisplayManager. Mục đích của lớp này là hiển thị hình ảnh phù hợp theo các đặc điểm khuôn mặt được phát hiện. Chúng ta có thể thể hiện những đặc điểm khác nhau này bằng cách sử dụng bốn hình ảnh khác nhau như đã mô tả trước đây. Những hình ảnh này phải ở trong drawable(nút).

Để hiển thị hình ảnh này theo các đặc điểm khuôn mặt được phát hiện, chúng tôi sẽ thêm phương thức này vào lớp này:

public void setImage(Resources res, int resId) {
  display.clearPixels();
  Bitmap bmp = BitmapFactory.decodeResource(res, resId);
  BitmapHelper.setBmpData(display, 0,0, bmp, true);
  try {
    display.show();
  }
  catch (IOException ioe) {
    ioe.printStackTrace();
  }
}


Bước cuối cùng

Trong bước cuối cùng này, chúng tôi sẽ dán mọi thứ để ứng dụng hoạt động chính xác. Để làm điều đó, cần phải thêm một người nghe để người nghe MainActivitysẽ được thông báo khi các đặc điểm trên khuôn mặt được phát hiện. Hãy để chúng tôi xác định trình nghe cho FaceDetector:

 public interface CameraListener {
   public void onError();
   public void onSuccess(FACE_STATUS status);
 }


Ở đâu:

 // Face status
 enum FACE_STATUS {
    SMILING,
    LEFT_EYE_OPEN_RIGHT_CLOSE,
    RIGHT_EYE_OPEN_LEFT_CLOSE,
    LEFT_OPEN_RIGHT_OPEN
 }


Bây giờ, trong MainActivity, chúng tôi sẽ triển khai trình nghe:

 FaceDetector fc = new FaceDetector(this, img, getMainLooper());
 fc.setListener(new FaceDetector.CameraListener() {
    @Override
    public void onError() {
      // Handle error
    }
    @Override
    public void onSuccess(FaceDetector.FACE_STATUS status) {
       Log.d(TAG, "Face ["+status+"]");
       switch (status) {
         case SMILING:
           display.setImage(getResources(), 
 R.drawable.smiling_face);
           break;
         case LEFT_EYE_OPEN_RIGHT_CLOSE:
             display.setImage(getResources(), R.drawable.right_eyes_closed);
            break;
         case RIGHT_EYE_OPEN_LEFT_CLOSE:
             display.setImage(getResources(), R.drawable.left_eyes_closed);
             break;
         default:
            display.setImage(getResources(), R.drawable.neutral_face);
         }
     }
 });


Tạo giao diện người dùng ứng dụng

Nếu bạn muốn tạo giao diện người dùng của ứng dụng Android Things, bạn phải thêm bố cục:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
  <ImageView android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:id="@+id/img" />

</android.support.constraint.ConstraintLayout>


Cân nhắc cuối cùng

Vào cuối bài viết này, hy vọng bạn đã có được kiến ​​thức về cách sử dụng Firebase ML Kit với Android Things. Chúng tôi đã khám phá cách phát hiện đặc điểm khuôn mặt bằng cách sử dụng máy học. Firebase ML Kit cung cấp khả năng kiểm tra và sử dụng học máy mà không cần biết nhiều về nó cũng như không tốn thời gian và công sức trong việc xây dựng các mô hình ML. Sử dụng API Bộ công cụ nhận diện khuôn mặt, bạn có thể dễ dàng tạo ứng dụng Android Things phát hiện các đặc điểm khuôn mặt.

|