Follow the code lab "Face Detection with the Mobile Vision API", you can create an App to process an image that is already present in your app, to detects faces.
In this exercise, I modify the code lab to add the feature to load photos using Intent of ACTION_GET_CONTENT, such that you can test it with your own photos. APK is available on the bottom of this post.
- Make sure you have Google Play Services 7.8 or higher installed on your testing devices (Check your installed Google Play Services version).
- Create your app of "Blank Activity", with Min Sdk Version of API 17 (Android 4.2.2) or higher.
- Add dependency for Google Play services in Android Studio Project, make sure you have Google Play Services version 26 or higher installed.
- Edit your AndroidManifest.xml to add the statement of <meta-data...>:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidfacedetection" >
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.google.android.gms.vision.DEPENDENCIES"
android:value="face" />
</application>
</manifest>
layout/activity_main.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="18dp"
android:text="Face Detection with the Mobile Vision API" />
<Button
android:id="@+id/btnLoad"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Load Photo"/>
<Button
android:id="@+id/btnDetectFace"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Detect Face" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imgview"/>
</LinearLayout>
com.example.androidfacedetection.MainActivity.java
package com.example.androidfacedetection;
import android.content.Intent;
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.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.SparseArray;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import com.google.android.gms.vision.Frame;
import com.google.android.gms.vision.face.Face;
import com.google.android.gms.vision.face.FaceDetector;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class MainActivity extends AppCompatActivity {
private static final int RQS_LOADIMAGE = 1;
private Button btnLoad, btnDetFace;
private ImageView imgView;
private Bitmap myBitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnLoad = (Button)findViewById(R.id.btnLoad);
btnDetFace = (Button)findViewById(R.id.btnDetectFace);
imgView = (ImageView)findViewById(R.id.imgview);
btnLoad.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intent, RQS_LOADIMAGE);
}
});
btnDetFace.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
if(myBitmap == null){
Toast.makeText(MainActivity.this,
"myBitmap == null",
Toast.LENGTH_LONG).show();
}else{
detectFace();
Toast.makeText(MainActivity.this,
"Done",
Toast.LENGTH_LONG).show();
}
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RQS_LOADIMAGE
&& resultCode == RESULT_OK){
if(myBitmap != null){
myBitmap.recycle();
}
try {
InputStream inputStream =
getContentResolver().openInputStream(data.getData());
myBitmap = BitmapFactory.decodeStream(inputStream);
inputStream.close();
imgView.setImageBitmap(myBitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
super.onActivityResult(requestCode, resultCode, data);
}
/*
reference:
https://search-codelabs.appspot.com/codelabs/face-detection
*/
private void detectFace(){
//Create a Paint object for drawing with
Paint myRectPaint = new Paint();
myRectPaint.setStrokeWidth(5);
myRectPaint.setColor(Color.RED);
myRectPaint.setStyle(Paint.Style.STROKE);
//Create a Canvas object for drawing on
Bitmap tempBitmap = Bitmap.createBitmap(myBitmap.getWidth(), myBitmap.getHeight(), Bitmap.Config.RGB_565);
Canvas tempCanvas = new Canvas(tempBitmap);
tempCanvas.drawBitmap(myBitmap, 0, 0, null);
//Detect the Faces
FaceDetector faceDetector = new FaceDetector.Builder(getApplicationContext()).build();
//!!!
//Cannot resolve method setTrackingEnabled(boolean)
//skip for now
//faceDetector.setTrackingEnabled(false);
Frame frame = new Frame.Builder().setBitmap(myBitmap).build();
SparseArray<Face> faces = faceDetector.detect(frame);
//Draw Rectangles on the Faces
for(int i=0; i<faces.size(); i++) {
Face thisFace = faces.valueAt(i);
float x1 = thisFace.getPosition().x;
float y1 = thisFace.getPosition().y;
float x2 = x1 + thisFace.getWidth();
float y2 = y1 + thisFace.getHeight();
tempCanvas.drawRoundRect(new RectF(x1, y1, x2, y2), 2, 2, myRectPaint);
}
imgView.setImageDrawable(new BitmapDrawable(getResources(),tempBitmap));
}
}
In my trial:
- The calling of faceDetector.setTrackingEnabled(false) report error of "Cannot resolve method setTrackingEnabled(boolean)"! So I skip it in this example.
(fixed in next post: "FaceDetector error: Cannot resolve method setTrackingEnabled(boolean)")
- It work on RedMi 2, running Android 4.4.4, with Google Play services version 7.8.99 installed.
- But cannot detect face on Nexus 7 2012 (WITHOUT front camera) running Android 5.1.1, with the same Google Play services version 7.8.99 installed! with warning of "FaceDetectorHandle﹕ Native face detector not yet available. Reverting to no-op detection".
Test on RedMi 2, running Android 4.4.4, with Google Play services version 7.8.99 installed.
Download the files (Android Studio Format).
You can also Download the APK here, for test without coding.
Next:
- FaceDetector error: Cannot resolve method setTrackingEnabled(boolean)
- Google Play services Face Detection, get Landmarks (eyes, nose, etc.)
- Detect Smiling
- Introducing Face Detection in the Google Vision APIs, from 100 Days of Google Dev
I tried this but it is not installing the local libraries on my phone. Even when I run your apk I get W/FaceDetectorHandle﹕ Native face detector not yet available. Reverting to no-op detection. I have Google Play Services 7.8.99 and Android 5.1
ReplyDeletehello Tyler Carberry,
ReplyDeleteSame case with my Nexus 7 2012!
What device you use?
Moto X 2014
ReplyDeleteIt just installed the dependencies without me needed to do anything.
ReplyDeleteIt worked on nexus 7 4.3,
ReplyDeleteBut it doesn't work on any other phone.
What is the problem ?!