Friday, October 14, 2016

Học máy trong lập trình Android - Face Detection

Có rất nhiều APIs cho Học Máy - Machine Learning trên cloud và mobile
Trong bài này mình sẽ sử dụng Mobile Vision APIs. Mobile Version API hiện tại bao gồm 3 loại: Face Detection API, Barcode Detection API và the Text API

Face Detection API:
API này sử dụng để phát hiện và theo dõi khuôn mặt của người trong ảnh hoặc video nhưng nó chưa cung cấp khả năng nhận dạng khuôn mặt. Nó cho phép phát hiện các điểm trên mặt như mắt, mũi và miệng và phân loại mặt. Phân loại mặt được sử dụng để kiểm tra các đặc điểm như mặt đang cười hoặc nhắm mắt...API này cũng phát hiện được mặt ở các góc độ khác nhau

Hướng dẫn cụ thể
Bước 1:
Dùng Android Studio để tạo Project
Hướng dẫn cài đặt Android Studio
Mình dùng bản 2.2.1
Tạo mới 1 project: AndroidFaceDetection
Import Google Play Services SDK trong file build.gradle

 compile 'com.google.android.gms:play-services-vision:9.6.1'  


Để kích hoạt thư viện có sẵn đại diện cho face dectection, thêm thẻ meta-data sau vào manifest file:

 <meta-data  
   android:name="com.google.android.gms.vision.DEPENDENCIES"  
   android:value="face"/>  

Bước 2: Viết code
File giao diện activity_main.xml:
Tạo một Button và một ImageView


  • Button: khởi tạo xử lý dectetion
  • ImageView: ảnh xử lý, ở đây mình lấy ảnh cố định, bạn có thể xử lý bằng cách chụp ảnh từ camera hoặc xử lý lấy ảnh có sẵn trong điện thoại


 <?xml version="1.0" encoding="utf-8"?>  
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
   xmlns:tools="http://schemas.android.com/tools"  
   android:id="@+id/activity_main"  
   android:layout_width="match_parent"  
   android:layout_height="match_parent"  
   android:paddingBottom="@dimen/activity_vertical_margin"  
   android:paddingLeft="@dimen/activity_horizontal_margin"  
   android:paddingRight="@dimen/activity_horizontal_margin"  
   android:paddingTop="@dimen/activity_vertical_margin"  
   android:orientation="vertical"  
   tools:context="com.hust.tuanbk.facedetection.MainActivity">  
   <Button  
     android:id="@+id/detection"  
     android:layout_width="100dp"  
     android:layout_height="wrap_content"  
     android:text="Detection"  
     />  
   <ImageView  
     android:layout_marginTop="20dp"  
     android:id="@+id/face"  
     android:src="@drawable/face"  
     android:layout_width="wrap_content"  
     android:layout_height="wrap_content" />  
 </LinearLayout>  

MainActivity.java

 package com.hust.tuanbk.facedetection;  
 import android.graphics.Bitmap;  
 import android.graphics.BitmapFactory;  
 import android.graphics.Canvas;  
 import android.graphics.Color;  
 import android.graphics.Paint;  
 import android.graphics.RectF;  
 import android.graphics.drawable.BitmapDrawable;  
 import android.os.Bundle;  
 import android.support.v7.app.AlertDialog;  
 import android.support.v7.app.AppCompatActivity;  
 import android.util.SparseArray;  
 import android.view.View;  
 import android.widget.Button;  
 import android.widget.ImageView;  
 import com.google.android.gms.vision.Frame;  
 import com.google.android.gms.vision.face.Face;  
 import com.google.android.gms.vision.face.FaceDetector;  
 import com.google.android.gms.vision.face.Landmark;  
 public class MainActivity extends AppCompatActivity {  
   Button btDetection;  
   ImageView imageFace;  
   @Override  
   protected void onCreate(Bundle savedInstanceState) {  
     super.onCreate(savedInstanceState);  
     setContentView(R.layout.activity_main);  
     imageFace = (ImageView) findViewById(R.id.face);  
     btDetection = (Button) findViewById(R.id.detection);  
     btDetection.setOnClickListener(new View.OnClickListener() {  
       @Override  
       public void onClick(View v) {  
         // create a new BitmapFactory.Options object and set inmutable to true.  
         // This is to ensure that the bitmap is mutable so that we are able  
         // to programmatically apply effects to it  
         BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();  
         bitmapOptions.inMutable = true;  
         Bitmap defaultBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.face, bitmapOptions);  
         //Create a Paint object and set the style to stroke.  
         // This ensures that the shape is not filled in because we want to see  
         // the parts of the head that make it into the rectangle  
         Paint rectPaint = new Paint();  
         rectPaint.setStrokeWidth(5);  
         rectPaint.setColor(Color.CYAN);  
         rectPaint.setStyle(Paint.Style.STROKE);  
         //canvas to display our bitmap  
         Bitmap temporaryBitmap = Bitmap.createBitmap(defaultBitmap.getWidth(), defaultBitmap  
             .getHeight(), Bitmap.Config.RGB_565);  
         Canvas canvas = new Canvas(temporaryBitmap);  
         canvas.drawBitmap(defaultBitmap, 0, 0, null);  
         // get to point where we use the FaceDectector API  
         FaceDetector faceDetector = new FaceDetector.Builder(MainActivity.this)  
             .setTrackingEnabled(false)  
             .setLandmarkType(FaceDetector.ALL_LANDMARKS)  
             .build();  
         //Check if the face detector is operational already.  
         // There’s a possibility that it won’t work the first time because a library needs to be downloaded  
         // to the device and it might not have been completed in time when you need to use it.  
         if (!faceDetector.isOperational()) {  
           new AlertDialog.Builder(MainActivity.this)  
               .setMessage("Face Detector could not be set up on your device :(")  
               .show();  
           return;  
         }  
         //create a frame using the default bitmap and call on the face detector to get the face objects.  
         Frame frame = new Frame.Builder().setBitmap(defaultBitmap).build();  
         SparseArray<Face> sparseArray = faceDetector.detect(frame);  
         //drawn rectangle over the faces  
         for (int i = 0; i < sparseArray.size(); i++) {  
           Face face = sparseArray.valueAt(i);  
           float left = face.getPosition().x;  
           float top = face.getPosition().y;  
           float right = left + face.getWidth();  
           float bottom = right + face.getHeight();  
           float cornerRadius = 2.0f;  
           RectF rectF = new RectF(left, top, right, bottom);  
           canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, rectPaint);  
           for (Landmark landmark : face.getLandmarks()) {  
             int x = (int) (landmark.getPosition().x);  
             int y = (int) (landmark.getPosition().y);  
             float radius = 10.0f;  
             canvas.drawCircle(x, y, radius, rectPaint);  
           }  
         }  
         // set ImageView from our layout after which we release the face detector.  
         imageFace.setImageDrawable(new BitmapDrawable(getResources(), temporaryBitmap));  
         faceDetector.release();  
       }  
     });  
   }  
 }  

Kết quả ta được như sau:

Lưu ý: Khi chạy trên máy thật, lần đầu chạy sẽ không phát hiện được ngay vì nó còn download thư viện xuống.
Kết luận: Vậy là đã xong cảm ơn các bạn đã quan tâm. Nhớ theo dõi blog của mình thường xuyên nhé :D
Tham khảo: Moyinoluwa Adeyemi

0 comments:

Post a Comment