‏إظهار الرسائل ذات التسميات Face Detection. إظهار كافة الرسائل
‏إظهار الرسائل ذات التسميات Face Detection. إظهار كافة الرسائل

الخميس، 20 أغسطس 2015

Introducing Face Detection in the Google Vision APIs

The Google Vision APIs provide two main areas of functionality.

First is Face Tracking -- not to be confused with Facial Recognition -- which gives your apps the ability to detect faces, and landmarks on faces. This is useful for, for example -- writing a camera app that only takes a picture when everyone is smiling, and nobody is blinking, or for fun apps where you can superimpose hats or moustaches on people in the camera preview window. 

Second is recognizing visual codes such as bar codes or QR codes, and making it easy for developers to build apps with them.




~ My step-by-step posts of Face Detection with Google Play services, Mobile Vision API

الثلاثاء، 18 أغسطس 2015

Google Play services Face Detection, detect Smiling

With Face Detection of Google Play services, Mobile Vision API, you can detect various facial states; such as Smiling, Left Eye Open or Right Eye Open.


This example show how to detect Smiling face with getIsSmilingProbability() method of com.google.android.gms.vision.face.Face. You can also use getIsLeftEyeOpenProbability() and getIsRightEyeOpenProbability() methods to test if the face's left or right eye is open.


Modify from last post of "Google Play services Face Detection, get Landmarks (eyes, nose, etc.)". Call setClassificationType(FaceDetector.ALL_CLASSIFICATIONS) method when build FaceDetector with FaceDetector.Builder. Then call getIsSmilingProbability() method of the detected faces to check if it is similing.

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.PointF;
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 com.google.android.gms.vision.face.Landmark;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

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();

}
}
});
}

@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.GREEN);
myRectPaint.setStyle(Paint.Style.STROKE);

Paint landmarksPaint = new Paint();
landmarksPaint.setStrokeWidth(10);
landmarksPaint.setColor(Color.RED);
landmarksPaint.setStyle(Paint.Style.STROKE);

Paint smilingPaint = new Paint();
smilingPaint.setStrokeWidth(4);
smilingPaint.setColor(Color.YELLOW);
smilingPaint.setStyle(Paint.Style.STROKE);

boolean somebodySmiling = false;

//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

//!!!
//Cannot resolve method setTrackingEnabled(boolean)
//FaceDetector faceDetector = new FaceDetector.Builder(getApplicationContext()).build();
//faceDetector.setTrackingEnabled(false);

FaceDetector faceDetector =
new FaceDetector.Builder(getApplicationContext())
.setTrackingEnabled(false)
.setLandmarkType(FaceDetector.ALL_LANDMARKS)
.setClassificationType(FaceDetector.ALL_CLASSIFICATIONS)
.build();

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);

//get Landmarks for the first face
List<Landmark> landmarks = thisFace.getLandmarks();
for(int l=0; l<landmarks.size(); l++){
PointF pos = landmarks.get(l).getPosition();
tempCanvas.drawPoint(pos.x, pos.y, landmarksPaint);
}

//check if this face is Smiling
final float smilingAcceptProbability = 0.5f;
float smilingProbability = thisFace.getIsSmilingProbability();
if(smilingProbability > smilingAcceptProbability){
tempCanvas.drawOval(new RectF(x1, y1, x2, y2), smilingPaint);
somebodySmiling = true;
}
}

imgView.setImageDrawable(new BitmapDrawable(getResources(), tempBitmap));

if(somebodySmiling){
Toast.makeText(MainActivity.this,
"Done - somebody is Smiling",
Toast.LENGTH_LONG).show();
}else{
Toast.makeText(MainActivity.this,
"Done - nobody is Smiling",
Toast.LENGTH_LONG).show();
}

}
}


Other files, AndroidManifest.xml and layout/activity_main.xml, refer to the post "Face Detection with Google Play services, Mobile Vision API".

الأحد، 16 أغسطس 2015

Google Play services Face Detection, get Landmarks (eyes, nose, etc.)

getLandmarks() method of com.google.android.gms.vision.face.Face return a list of Landmarks (eyes, nose, etc.) found on the face. A landmark detector must be specified via setLandmarkType(int) to detect landmarks. The landmark detector may not find all possible landmarks on any given face.


This example modify from the post "Face Detection with Google Play services, Mobile Vision API", with fix of "FaceDetector error: Cannot resolve method setTrackingEnabled(boolean)", add the feature to detect landmarks on detected faces.


Sets detect all landmarks, by calling setLandmarkType(FaceDetector.ALL_LANDMARKS) when build FaceDetector with FaceDetector.Builder.

Then call getLandmarks() for each detected faces.

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.PointF;
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 com.google.android.gms.vision.face.Landmark;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

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.GREEN);
myRectPaint.setStyle(Paint.Style.STROKE);

Paint landmarksPaint = new Paint();
landmarksPaint.setStrokeWidth(10);
landmarksPaint.setColor(Color.RED);
landmarksPaint.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


//!!!
//Cannot resolve method setTrackingEnabled(boolean)
//FaceDetector faceDetector = new FaceDetector.Builder(getApplicationContext()).build();
//faceDetector.setTrackingEnabled(false);

FaceDetector faceDetector =
new FaceDetector.Builder(getApplicationContext())
.setTrackingEnabled(false)
.setLandmarkType(FaceDetector.ALL_LANDMARKS)
.build();

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);

//get Landmarks for the first face
List<Landmark> landmarks = thisFace.getLandmarks();
for(int l=0; l<landmarks.size(); l++){
PointF pos = landmarks.get(l).getPosition();
tempCanvas.drawPoint(pos.x, pos.y, landmarksPaint);
}
}

imgView.setImageDrawable(new BitmapDrawable(getResources(),tempBitmap));

}
}


Other files, AndroidManifest.xml and layout/activity_main.xml, refer to the post "Face Detection with Google Play services, Mobile Vision API".

Next:
- Google Play services Face Detection, detect Smiling

الجمعة، 14 أغسطس 2015

FaceDetector error: Cannot resolve method setTrackingEnabled(boolean)

As mentioned in last post "Face Detection with Google Play services, Mobile Vision API (with demo APK)", calling setTrackingEnabled(false) method of FaceDetector object return error of "Cannot resolve method setTrackingEnabled(boolean)".

After checking reference of com.google.android.gms.vision.face.FaceDetector, setTrackingEnabled(boolean) is not a method of FaceDetector class. It's a method of com.google.android.gms.vision.face.FaceDetector.Builder class.


public FaceDetector.Builder setTrackingEnabled (boolean trackingEnabled)
Enables or disables face tracking, which will maintain a consistent ID for each face when processing consecutive frames. Default: true


If your code uses a MultiProcessor or FocusingProcessor instance, tracking must be enabled. Having tracking enabled is also recommended for handling live video.

Tracking should be disabled for handling a series of non-consecutive still images.


To fix the error, modify the code
        FaceDetector faceDetector = new FaceDetector.Builder(getApplicationContext()).build();
faceDetector.setTrackingEnabled(false);

to:
        FaceDetector faceDetector =
new FaceDetector.Builder(getApplicationContext())
.setTrackingEnabled(false)
.build();


Face Detection with Google Play services, Mobile Vision API (with demo APK)

With the release of Google Play services 7.8, new Mobile Vision APIs was added, to include a new Face API that finds human faces in images and video. ~ source: Android Developers Blog - Face Detection in Google Play services.

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 filesDownload the files (Android Studio Format).

download filesYou 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