Read part one of this article from the following link.
Introduction
Android is one of the most popular operating systems for mobiles. In this article, I will show you how to detect a face with the help of Microsoft Face API.
Requirements
- Android Studio
- Little knowledge of XML and Java
- Android Emulator (or) Android mobile
- Stable internet connection
Step 1
Go to activity_main.xml file and click the text botton. This XML file contains the designing code for Android app. In activity_main.xml, copy and paste the below code.
Activity_main.xml code
- <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=".ui.MainActivity">
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:orientation="horizontal"
- android:layout_marginBottom="@dimen/view_margin" >
-
- <ScrollView
- android:layout_width="0dp"
- android:layout_weight="1"
- android:layout_height="match_parent" >
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:gravity="center_vertical"
- android:text="@string/detection_description" />
-
- </ScrollView>
-
- <Button
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:text="@string/detection"
- android:layout_weight="1"
- android:layout_marginLeft="@dimen/view_margin"
- android:layout_marginStart="@dimen/view_margin"
- android:onClick="detection"
- style="@style/ButtonStyle" />
-
- </LinearLayout>
-
-
- </LinearLayout>
![Android]()
Step 2
Create a new activity_detection.xml file (File ⇒ New ⇒Activity⇒Empty_activity).
Go to activity_detection.xml, and click the text botton. This XML file contains the designing code for Android app. In activity_detection.xml, copy and paste the below code.
activity_detection.xml code
![Android]()
Step 3
Create new activity_select_image.xml file (File ⇒ New ⇒Activity⇒Empty_activity).
Go to activity_select_image.xml and click the text bottom. In activity_select_image.xml, copy and paste the below code.
activity_select_image.xml code
- <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:baselineAligned="false"
- android:orientation="vertical"
- tools:context="ganeshannt.faceapi.ui.SelectImageActivity">
-
- <RelativeLayout android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="2">
-
- <Button
- android:id="@+id/button_take_a_photo"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/take_photo"
- android:layout_centerHorizontal="true"
- android:layout_alignParentBottom="true"
- android:onClick="takePhoto"
- style="@style/ButtonStyle" />
-
- <TextView
- android:id="@id/info"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:layout_above="@id/button_take_a_photo"
- android:layout_gravity="center" />
-
- </RelativeLayout>
-
- <RelativeLayout android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1">
-
- <Button
- android:id="@+id/button_select_a_photo_in_album"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/select_image_in_album"
- android:layout_centerHorizontal="true"
- android:layout_centerVertical="true"
- android:onClick="selectImageInAlbum"
- style="@style/ButtonStyle" />
- </RelativeLayout>
-
- </LinearLayout>
![Android]()
Step 4
Create new item_face_with_description.xml file (File ⇒ New ⇒Activity⇒Empty_activity).
Go to item_face_with_description.xml, then click the text bottom. In item_face_with_description.xml, copy and paste the below code.
item_face_with_description.xml code
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <ImageView
- android:id="@+id/face_thumbnail"
- android:layout_width="80dp"
- android:layout_height="80dp" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:layout_marginLeft="@dimen/view_margin"
- android:layout_marginStart="@dimen/view_margin"
- android:id="@+id/text_detected_face" />
-
- </LinearLayout>
Step 5
In MainActivity.java file, copy and paste the below code. Do not replace your package name otherwise the app will not run.
MainActivity.java code
- package ganeshannt.faceapi.ui;
-
- import android.app.AlertDialog;
- import android.content.Intent;
- import android.os.Bundle;
- import android.support.v7.app.AppCompatActivity;
- import android.view.View;
-
- import ganeshannt.faceapi.R;
-
- public class MainActivity extends AppCompatActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
-
- if (getString(R.string.subscription_key).startsWith("Please")) {
- new AlertDialog.Builder(this)
- .setTitle(getString(R.string.add_subscription_key_tip_title))
- .setMessage(getString(R.string.add_subscription_key_tip))
- .setCancelable(false)
- .show();
- }
- }
-
- public void detection(View view) {
- Intent intent = new Intent(this, DetectionActivity.class);
- startActivity(intent);
- }
-
- }
Step 6Create three (name : helper , log , ui) Android package folders (java->>new->>folder->>package folder).
Step 7
In helper folder, create file (class name: embeddedgridview,Imagehelper,storagehelper ) (File ⇒ New ⇒Java class).
In EmbeddedGridView.java, copy and paste the below code. Do not replace your package name otherwise app will not run.
EmbeddedGridView.java code
- package ganeshannt.faceapi.helper;
-
- import android.content.Context;
- import android.util.AttributeSet;
- import android.widget.GridView;
-
- public class EmbeddedGridView extends GridView {
- public EmbeddedGridView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int newHeightMeasureSpec =
- MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK, MeasureSpec.AT_MOST);
-
- super.onMeasure(widthMeasureSpec, newHeightMeasureSpec);
- getLayoutParams().height = getMeasuredHeight();
- }
- }
ImageHelper.java code
It is used to pick the image from photos album.
- package ganeshannt.faceapi.helper;
-
- import android.content.ContentResolver;
- import android.database.Cursor;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Matrix;
- import android.graphics.Paint;
- import android.graphics.Rect;
- import android.media.ExifInterface;
- import android.net.Uri;
- import android.provider.MediaStore;
-
- import com.microsoft.projectoxford.face.contract.Face;
-
-
-
- import com.microsoft.projectoxford.face.contract.FaceRectangle;
-
- import java.io.IOException;
- import java.io.InputStream;
-
-
-
-
- public class ImageHelper {
-
-
-
- private static final int IMAGE_MAX_SIDE_LENGTH = 1280;
-
-
- private static final double FACE_RECT_SCALE_RATIO = 1.3;
-
-
-
-
-
-
-
- public static Bitmap loadSizeLimitedBitmapFromUri(
- Uri imageUri,
- ContentResolver contentResolver) {
- try {
-
- InputStream imageInputStream = contentResolver.openInputStream(imageUri);
-
-
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inJustDecodeBounds = true;
- Rect outPadding = new Rect();
- BitmapFactory.decodeStream(imageInputStream, outPadding, options);
-
-
- int maxSideLength =
- options.outWidth > options.outHeight ? options.outWidth: options.outHeight;
- options.inSampleSize = 1;
- options.inSampleSize = calculateSampleSize(maxSideLength, IMAGE_MAX_SIDE_LENGTH);
- options.inJustDecodeBounds = false;
- if (imageInputStream != null) {
- imageInputStream.close();
- }
-
-
- imageInputStream = contentResolver.openInputStream(imageUri);
- Bitmap bitmap = BitmapFactory.decodeStream(imageInputStream, outPadding, options);
- maxSideLength = bitmap.getWidth() > bitmap.getHeight()
- ? bitmap.getWidth(): bitmap.getHeight();
- double ratio = IMAGE_MAX_SIDE_LENGTH / (double) maxSideLength;
- if (ratio < 1) {
- bitmap = Bitmap.createScaledBitmap(
- bitmap,
- (int)(bitmap.getWidth() * ratio),
- (int)(bitmap.getHeight() * ratio),
- false);
- }
-
- return rotateBitmap(bitmap, getImageRotationAngle(imageUri, contentResolver));
- } catch (Exception e) {
- return null;
- }
- }
-
-
-
- public static Bitmap drawFaceRectanglesOnBitmap(
- Bitmap originalBitmap, Face[] faces, boolean drawLandmarks) {
- 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.GREEN);
- int stokeWidth = Math.max(originalBitmap.getWidth(), originalBitmap.getHeight()) / 100;
- if (stokeWidth == 0) {
- stokeWidth = 1;
- }
- paint.setStrokeWidth(stokeWidth);
-
- if (faces != null) {
- for (Face face : faces) {
- FaceRectangle faceRectangle =
- calculateFaceRectangle(bitmap, face.faceRectangle, FACE_RECT_SCALE_RATIO);
-
- canvas.drawRect(
- faceRectangle.left,
- faceRectangle.top,
- faceRectangle.left + faceRectangle.width,
- faceRectangle.top + faceRectangle.height,
- paint);
-
- if (drawLandmarks) {
- int radius = face.faceRectangle.width / 30;
- if (radius == 0) {
- radius = 1;
- }
- paint.setStyle(Paint.Style.FILL);
- paint.setStrokeWidth(radius);
-
- canvas.drawCircle(
- (float) face.faceLandmarks.pupilLeft.x,
- (float) face.faceLandmarks.pupilLeft.y,
- radius,
- paint);
-
- canvas.drawCircle(
- (float) face.faceLandmarks.pupilRight.x,
- (float) face.faceLandmarks.pupilRight.y,
- radius,
- paint);
-
- canvas.drawCircle(
- (float) face.faceLandmarks.noseTip.x,
- (float) face.faceLandmarks.noseTip.y,
- radius,
- paint);
-
- canvas.drawCircle(
- (float) face.faceLandmarks.mouthLeft.x,
- (float) face.faceLandmarks.mouthLeft.y,
- radius,
- paint);
-
- canvas.drawCircle(
- (float) face.faceLandmarks.mouthRight.x,
- (float) face.faceLandmarks.mouthRight.y,
- radius,
- paint);
-
- paint.setStyle(Paint.Style.STROKE);
- paint.setStrokeWidth(stokeWidth);
- }
- }
- }
-
- return bitmap;
- }
-
-
- public static Bitmap highlightSelectedFaceThumbnail(Bitmap originalBitmap) {
- 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.parseColor("#3399FF"));
- int stokeWidth = Math.max(originalBitmap.getWidth(), originalBitmap.getHeight()) / 10;
- if (stokeWidth == 0) {
- stokeWidth = 1;
- }
- bitmap.getWidth();
- paint.setStrokeWidth(stokeWidth);
- canvas.drawRect(
- 0,
- 0,
- bitmap.getWidth(),
- bitmap.getHeight(),
- paint);
-
- return bitmap;
- }
-
-
-
- public static Bitmap generateFaceThumbnail(
- Bitmap originalBitmap,
- FaceRectangle faceRectangle) throws IOException {
- FaceRectangle faceRect =
- calculateFaceRectangle(originalBitmap, faceRectangle, FACE_RECT_SCALE_RATIO);
-
- return Bitmap.createBitmap(
- originalBitmap, faceRect.left, faceRect.top, faceRect.width, faceRect.height);
- }
-
-
-
- private static int calculateSampleSize(int maxSideLength, int expectedMaxImageSideLength) {
- int inSampleSize = 1;
-
- while (maxSideLength > 2 * expectedMaxImageSideLength) {
- maxSideLength /= 2;
- inSampleSize *= 2;
- }
-
- return inSampleSize;
- }
-
-
- private static int getImageRotationAngle(
- Uri imageUri, ContentResolver contentResolver) throws IOException {
- int angle = 0;
- Cursor cursor = contentResolver.query(imageUri,
- new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, null, null, null);
- if (cursor != null) {
- if (cursor.getCount() == 1) {
- cursor.moveToFirst();
- angle = cursor.getInt(0);
- }
- cursor.close();
- } else {
- ExifInterface exif = new ExifInterface(imageUri.getPath());
- int orientation = exif.getAttributeInt(
- ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
-
- switch (orientation) {
- case ExifInterface.ORIENTATION_ROTATE_270:
- angle = 270;
- break;
- case ExifInterface.ORIENTATION_ROTATE_180:
- angle = 180;
- break;
- case ExifInterface.ORIENTATION_ROTATE_90:
- angle = 90;
- break;
- default:
- break;
- }
- }
- return angle;
- }
-
-
- private static Bitmap rotateBitmap(Bitmap bitmap, int angle) {
-
- if (angle != 0) {
- Matrix matrix = new Matrix();
- matrix.postRotate(angle);
- return Bitmap.createBitmap(
- bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
- } else {
- return bitmap;
- }
- }
-
-
-
- private static FaceRectangle calculateFaceRectangle(
- Bitmap bitmap, FaceRectangle faceRectangle, double faceRectEnlargeRatio) {
-
- double sideLength = faceRectangle.width * faceRectEnlargeRatio;
- sideLength = Math.min(sideLength, bitmap.getWidth());
- sideLength = Math.min(sideLength, bitmap.getHeight());
-
-
- double left = faceRectangle.left
- - faceRectangle.width * (faceRectEnlargeRatio - 1.0) * 0.5;
- left = Math.max(left, 0.0);
- left = Math.min(left, bitmap.getWidth() - sideLength);
-
-
- double top = faceRectangle.top
- - faceRectangle.height * (faceRectEnlargeRatio - 1.0) * 0.5;
- top = Math.max(top, 0.0);
- top = Math.min(top, bitmap.getHeight() - sideLength);
-
-
- double shiftTop = faceRectEnlargeRatio - 1.0;
- shiftTop = Math.max(shiftTop, 0.0);
- shiftTop = Math.min(shiftTop, 1.0);
- top -= 0.15 * shiftTop * faceRectangle.height;
- top = Math.max(top, 0.0);
-
-
- FaceRectangle result = new FaceRectangle();
- result.left = (int)left;
- result.top = (int)top;
- result.width = (int)sideLength;
- result.height = (int)sideLength;
- return result;
- }
- }
StorageHelper.java code
It is used to allocate the storage space for face detecting images.
- package ganeshannt.faceapi.helper;
-
- import android.content.Context;
- import android.content.SharedPreferences;
-
- import java.util.HashSet;
- import java.util.List;
- import java.util.Set;
-
-
-
-
- public class StorageHelper {
- public static Set<String> getAllPersonGroupIds(Context context) {
- SharedPreferences personGroupIdSet =
- context.getSharedPreferences("PersonGroupIdSet", Context.MODE_PRIVATE);
- return personGroupIdSet.getStringSet("PersonGroupIdSet", new HashSet<String>());
- }
-
- public static String getPersonGroupName(String personGroupId, Context context) {
- SharedPreferences personGroupIdNameMap =
- context.getSharedPreferences("PersonGroupIdNameMap", Context.MODE_PRIVATE);
- return personGroupIdNameMap.getString(personGroupId, "");
- }
-
- public static void setPersonGroupName(String personGroupIdToAdd, String personGroupName, Context context) {
- SharedPreferences personGroupIdNameMap =
- context.getSharedPreferences("PersonGroupIdNameMap", Context.MODE_PRIVATE);
-
- SharedPreferences.Editor personGroupIdNameMapEditor = personGroupIdNameMap.edit();
- personGroupIdNameMapEditor.putString(personGroupIdToAdd, personGroupName);
- personGroupIdNameMapEditor.commit();
-
- Set<String> personGroupIds = getAllPersonGroupIds(context);
- Set<String> newPersonGroupIds = new HashSet<>();
- for (String personGroupId: personGroupIds) {
- newPersonGroupIds.add(personGroupId);
- }
- newPersonGroupIds.add(personGroupIdToAdd);
- SharedPreferences personGroupIdSet =
- context.getSharedPreferences("PersonGroupIdSet", Context.MODE_PRIVATE);
- SharedPreferences.Editor personGroupIdSetEditor = personGroupIdSet.edit();
- personGroupIdSetEditor.putStringSet("PersonGroupIdSet", newPersonGroupIds);
- personGroupIdSetEditor.commit();
- }
-
- public static void deletePersonGroups(List<String> personGroupIdsToDelete, Context context) {
- SharedPreferences personGroupIdNameMap =
- context.getSharedPreferences("PersonGroupIdNameMap", Context.MODE_PRIVATE);
- SharedPreferences.Editor personGroupIdNameMapEditor = personGroupIdNameMap.edit();
- for (String personGroupId: personGroupIdsToDelete) {
- personGroupIdNameMapEditor.remove(personGroupId);
- }
- personGroupIdNameMapEditor.commit();
-
- Set<String> personGroupIds = getAllPersonGroupIds(context);
- Set<String> newPersonGroupIds = new HashSet<>();
- for (String personGroupId: personGroupIds) {
- if (!personGroupIdsToDelete.contains(personGroupId)) {
- newPersonGroupIds.add(personGroupId);
- }
- }
- SharedPreferences personGroupIdSet =
- context.getSharedPreferences("PersonGroupIdSet", Context.MODE_PRIVATE);
- SharedPreferences.Editor personGroupIdSetEditor = personGroupIdSet.edit();
- personGroupIdSetEditor.putStringSet("PersonGroupIdSet", newPersonGroupIds);
- personGroupIdSetEditor.commit();
- }
-
- public static Set<String> getAllPersonIds(String personGroupId, Context context) {
- SharedPreferences personIdSet =
- context.getSharedPreferences(personGroupId + "PersonIdSet", Context.MODE_PRIVATE);
- return personIdSet.getStringSet("PersonIdSet", new HashSet<String>());
- }
-
- public static String getPersonName(String personId, String personGroupId, Context context) {
- SharedPreferences personIdNameMap =
- context.getSharedPreferences(personGroupId + "PersonIdNameMap", Context.MODE_PRIVATE);
- return personIdNameMap.getString(personId, "");
- }
-
- public static void setPersonName(String personIdToAdd, String personName, String personGroupId, Context context) {
- SharedPreferences personIdNameMap =
- context.getSharedPreferences(personGroupId + "PersonIdNameMap", Context.MODE_PRIVATE);
-
- SharedPreferences.Editor personIdNameMapEditor = personIdNameMap.edit();
- personIdNameMapEditor.putString(personIdToAdd, personName);
- personIdNameMapEditor.commit();
-
- Set<String> personIds = getAllPersonIds(personGroupId, context);
- Set<String> newPersonIds = new HashSet<>();
- for (String personId: personIds) {
- newPersonIds.add(personId);
- }
- newPersonIds.add(personIdToAdd);
- SharedPreferences personIdSet =
- context.getSharedPreferences(personGroupId + "PersonIdSet", Context.MODE_PRIVATE);
- SharedPreferences.Editor personIdSetEditor = personIdSet.edit();
- personIdSetEditor.putStringSet("PersonIdSet", newPersonIds);
- personIdSetEditor.commit();
- }
-
- public static void deletePersons(List<String> personIdsToDelete, String personGroupId, Context context) {
- SharedPreferences personIdNameMap =
- context.getSharedPreferences(personGroupId + "PersonIdNameMap", Context.MODE_PRIVATE);
- SharedPreferences.Editor personIdNameMapEditor = personIdNameMap.edit();
- for (String personId: personIdsToDelete) {
- personIdNameMapEditor.remove(personId);
- }
- personIdNameMapEditor.commit();
-
- Set<String> personIds = getAllPersonIds(personGroupId, context);
- Set<String> newPersonIds = new HashSet<>();
- for (String personId: personIds) {
- if (!personIdsToDelete.contains(personId)) {
- newPersonIds.add(personId);
- }
- }
- SharedPreferences personIdSet =
- context.getSharedPreferences(personGroupId + "PersonIdSet", Context.MODE_PRIVATE);
- SharedPreferences.Editor personIdSetEditor = personIdSet.edit();
- personIdSetEditor.putStringSet("PersonIdSet", newPersonIds);
- personIdSetEditor.commit();
- }
-
- public static Set<String> getAllFaceIds(String personId, Context context) {
- SharedPreferences faceIdSet =
- context.getSharedPreferences(personId + "FaceIdSet", Context.MODE_PRIVATE);
- return faceIdSet.getStringSet("FaceIdSet", new HashSet<String>());
- }
-
- public static String getFaceUri(String faceId, Context context) {
- SharedPreferences faceIdUriMap =
- context.getSharedPreferences("FaceIdUriMap", Context.MODE_PRIVATE);
- return faceIdUriMap.getString(faceId, "");
- }
-
- public static void setFaceUri(String faceIdToAdd, String faceUri, String personId, Context context) {
- SharedPreferences faceIdUriMap =
- context.getSharedPreferences("FaceIdUriMap", Context.MODE_PRIVATE);
-
- SharedPreferences.Editor faceIdUriMapEditor = faceIdUriMap.edit();
- faceIdUriMapEditor.putString(faceIdToAdd, faceUri);
- faceIdUriMapEditor.commit();
-
- Set<String> faceIds = getAllFaceIds(personId, context);
- Set<String> newFaceIds = new HashSet<>();
- for (String faceId: faceIds) {
- newFaceIds.add(faceId);
- }
- newFaceIds.add(faceIdToAdd);
- SharedPreferences faceIdSet =
- context.getSharedPreferences(personId + "FaceIdSet", Context.MODE_PRIVATE);
- SharedPreferences.Editor faceIdSetEditor = faceIdSet.edit();
- faceIdSetEditor.putStringSet("FaceIdSet", newFaceIds);
- faceIdSetEditor.commit();
- }
-
- public static void deleteFaces(List<String> faceIdsToDelete, String personId, Context context) {
- Set<String> faceIds = getAllFaceIds(personId, context);
- Set<String> newFaceIds = new HashSet<>();
- for (String faceId: faceIds) {
- if (!faceIdsToDelete.contains(faceId)) {
- newFaceIds.add(faceId);
- }
- }
- SharedPreferences faceIdSet =
- context.getSharedPreferences(personId + "FaceIdSet", Context.MODE_PRIVATE);
- SharedPreferences.Editor faceIdSetEditor = faceIdSet.edit();
- faceIdSetEditor.putStringSet("FaceIdSet", newFaceIds);
- faceIdSetEditor.commit();
- }
- }
Step 8
In log folder, create file(class name:DetectionLogActivity ) (File ⇒ New ⇒Java class).
In DetectionLogActivity.java, copy and paste the below code. Do not replace your package name otherwise the app will not run.
DetectionLogActivity.java code
- package ganeshannt.faceapi.log;
-
- import android.content.Context;
- import android.os.Bundle;
- import android.support.v7.app.AppCompatActivity;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.BaseAdapter;
- import android.widget.ListView;
- import android.widget.TextView;
-
- import ganeshannt.faceapi.R;
- import ganeshannt.faceapi.helper.LogHelper;
-
- import java.util.List;
-
- public class DetectionLogActivity extends AppCompatActivity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_detection_log);
-
- LogAdapter logAdapter = new LogAdapter();
- ListView listView = (ListView) findViewById(R.id.log);
- listView.setAdapter(logAdapter);
- }
-
-
- private class LogAdapter extends BaseAdapter {
-
- List<String> log;
-
- LogAdapter() {
- log = LogHelper.getDetectionLog();
- }
-
- @Override
- public boolean isEnabled(int position) {
- return false;
- }
-
- @Override
- public int getCount() {
- return log.size();
- }
-
- @Override
- public Object getItem(int position) {
- return log.get(position);
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
-
- @Override
- public View getView(final int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- LayoutInflater layoutInflater =
- (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- convertView = layoutInflater.inflate(R.layout.item_log, parent, false);
- }
- convertView.setId(position);
-
- ((TextView)convertView.findViewById(R.id.log)).setText(log.get(position));
-
- return convertView;
- }
- }
- }
Step 9In ui folder, create file (class name:DetectionActivity,Select-Image_Activity,MainActivity ) (File ⇒ New ⇒Java class).
In DetectionActivity.java, copy and paste the below code. Do not replace your package name otherwise the app will not run.
DetectionActivity.java code
- package ganeshannt.faceapi.ui;
-
- import android.app.ProgressDialog;
- import android.content.Context;
- import android.content.Intent;
- import android.graphics.Bitmap;
- import android.net.Uri;
- import android.os.AsyncTask;
- import android.os.Bundle;
- import android.support.annotation.NonNull;
- import android.support.v7.app.AppCompatActivity;
- import android.text.TextUtils;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.BaseAdapter;
- import android.widget.Button;
- import android.widget.ImageView;
- import android.widget.ListView;
- import android.widget.TextView;
-
- import com.microsoft.projectoxford.face.FaceServiceClient;
- import com.microsoft.projectoxford.face.contract.Accessory;
- import com.microsoft.projectoxford.face.contract.Blur;
- import com.microsoft.projectoxford.face.contract.Emotion;
- import com.microsoft.projectoxford.face.contract.Exposure;
- import com.microsoft.projectoxford.face.contract.Face;
- import com.microsoft.projectoxford.face.contract.FacialHair;
- import com.microsoft.projectoxford.face.contract.Hair;
- import com.microsoft.projectoxford.face.contract.HeadPose;
- import com.microsoft.projectoxford.face.contract.Makeup;
- import com.microsoft.projectoxford.face.contract.Noise;
- import com.microsoft.projectoxford.face.contract.Occlusion;
- import ganeshannt.faceapi.R;
- import ganeshannt.faceapi.helper.ImageHelper;
- import ganeshannt.faceapi.helper.LogHelper;
- import ganeshannt.faceapi.helper.SampleApp;
- import ganeshannt.faceapi.log.DetectionLogActivity;
-
- import java.io.ByteArrayInputStream;
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.text.DecimalFormat;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
-
- public class DetectionActivity extends AppCompatActivity {
-
- private class DetectionTask extends AsyncTask<InputStream, String, Face[]> {
- private boolean mSucceed = true;
-
- @Override
- protected Face[] doInBackground(InputStream... params) {
-
- FaceServiceClient faceServiceClient = SampleApp.getFaceServiceClient();
- try {
- publishProgress("Detecting...");
-
-
- return faceServiceClient.detect(
- params[0],
- true,
- true,
-
-
- new FaceServiceClient.FaceAttributeType[] {
- FaceServiceClient.FaceAttributeType.Age,
- FaceServiceClient.FaceAttributeType.Gender,
- FaceServiceClient.FaceAttributeType.Smile,
- FaceServiceClient.FaceAttributeType.Glasses,
- FaceServiceClient.FaceAttributeType.FacialHair,
- FaceServiceClient.FaceAttributeType.Emotion,
- FaceServiceClient.FaceAttributeType.HeadPose,
- FaceServiceClient.FaceAttributeType.Accessories,
- FaceServiceClient.FaceAttributeType.Blur,
- FaceServiceClient.FaceAttributeType.Exposure,
- FaceServiceClient.FaceAttributeType.Hair,
- FaceServiceClient.FaceAttributeType.Makeup,
- FaceServiceClient.FaceAttributeType.Noise,
- FaceServiceClient.FaceAttributeType.Occlusion
- });
- } catch (Exception e) {
- mSucceed = false;
- publishProgress(e.getMessage());
- addLog(e.getMessage());
- return null;
- }
- }
-
- @Override
- protected void onPreExecute() {
- mProgressDialog.show();
- addLog("Request: Detecting in image " + mImageUri);
- }
-
- @Override
- protected void onProgressUpdate(String... progress) {
- mProgressDialog.setMessage(progress[0]);
- setInfo(progress[0]);
- }
-
- @Override
- protected void onPostExecute(Face[] result) {
- if (mSucceed) {
- addLog("Response: Success. Detected " + (result == null ? 0 : result.length)
- + " face(s) in " + mImageUri);
- }
-
-
- setUiAfterDetection(result, mSucceed);
- }
- }
-
-
- private static final int REQUEST_SELECT_IMAGE = 0;
-
-
- private Uri mImageUri;
-
-
- private Bitmap mBitmap;
-
-
- ProgressDialog mProgressDialog;
-
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_detection);
-
- mProgressDialog = new ProgressDialog(this);
- mProgressDialog.setTitle(getString(R.string.progress_dialog_title));
-
-
- setDetectButtonEnabledStatus(false);
-
- LogHelper.clearDetectionLog();
- }
-
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
-
- outState.putParcelable("ImageUri", mImageUri);
- }
-
-
- @Override
- protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
-
- mImageUri = savedInstanceState.getParcelable("ImageUri");
- if (mImageUri != null) {
- mBitmap = ImageHelper.loadSizeLimitedBitmapFromUri(
- mImageUri, getContentResolver());
- }
- }
-
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- switch (requestCode) {
- case REQUEST_SELECT_IMAGE:
- if (resultCode == RESULT_OK) {
-
- mImageUri = data.getData();
- mBitmap = ImageHelper.loadSizeLimitedBitmapFromUri(
- mImageUri, getContentResolver());
- if (mBitmap != null) {
-
- ImageView imageView = (ImageView) findViewById(R.id.image);
- imageView.setImageBitmap(mBitmap);
-
-
- addLog("Image: " + mImageUri + " resized to " + mBitmap.getWidth()
- + "x" + mBitmap.getHeight());
- }
-
-
- FaceListAdapter faceListAdapter = new FaceListAdapter(null);
- ListView listView = (ListView) findViewById(R.id.list_detected_faces);
- listView.setAdapter(faceListAdapter);
-
-
- setInfo("");
-
-
- setDetectButtonEnabledStatus(true);
- }
- break;
- default:
- break;
- }
- }
-
-
- public void selectImage(View view) {
- Intent intent = new Intent(this, SelectImageActivity.class);
- startActivityForResult(intent, REQUEST_SELECT_IMAGE);
- }
-
-
- public void detect(View view) {
-
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, output);
- ByteArrayInputStream inputStream = new ByteArrayInputStream(output.toByteArray());
-
-
- new DetectionTask().execute(inputStream);
-
-
- setAllButtonsEnabledStatus(false);
- }
-
-
- public void viewLog(View view) {
- Intent intent = new Intent(this, DetectionLogActivity.class);
- startActivity(intent);
- }
-
-
- private void setUiAfterDetection(Face[] result, boolean succeed) {
-
- mProgressDialog.dismiss();
-
-
- setAllButtonsEnabledStatus(true);
-
-
- setDetectButtonEnabledStatus(false);
-
- if (succeed) {
-
- String detectionResult;
- if (result != null) {
- detectionResult = result.length + " face"
- + (result.length != 1 ? "s" : "") + " detected";
-
-
- ImageView imageView = (ImageView) findViewById(R.id.image);
- imageView.setImageBitmap(ImageHelper.drawFaceRectanglesOnBitmap(
- mBitmap, result, true));
-
-
- FaceListAdapter faceListAdapter = new FaceListAdapter(result);
-
-
- ListView listView = (ListView) findViewById(R.id.list_detected_faces);
- listView.setAdapter(faceListAdapter);
- } else {
- detectionResult = "0 face detected";
- }
- setInfo(detectionResult);
- }
-
- mImageUri = null;
- mBitmap = null;
- }
-
-
- private void setDetectButtonEnabledStatus(boolean isEnabled) {
- Button detectButton = (Button) findViewById(R.id.detect);
- detectButton.setEnabled(isEnabled);
- }
-
-
- private void setAllButtonsEnabledStatus(boolean isEnabled) {
- Button selectImageButton = (Button) findViewById(R.id.select_image);
- selectImageButton.setEnabled(isEnabled);
-
- Button detectButton = (Button) findViewById(R.id.detect);
- detectButton.setEnabled(isEnabled);
-
- Button ViewLogButton = (Button) findViewById(R.id.view_log);
- ViewLogButton.setEnabled(isEnabled);
- }
-
-
- private void setInfo(String info) {
- TextView textView = (TextView) findViewById(R.id.info);
- textView.setText(info);
- }
-
-
- private void addLog(String log) {
- LogHelper.addDetectionLog(log);
- }
-
-
- private class FaceListAdapter extends BaseAdapter {
-
- List<Face> faces;
-
-
- List<Bitmap> faceThumbnails;
-
-
- FaceListAdapter(Face[] detectionResult) {
- faces = new ArrayList<>();
- faceThumbnails = new ArrayList<>();
-
- if (detectionResult != null) {
- faces = Arrays.asList(detectionResult);
- for (Face face : faces) {
- try {
-
- faceThumbnails.add(ImageHelper.generateFaceThumbnail(
- mBitmap, face.faceRectangle));
- } catch (IOException e) {
-
- setInfo(e.getMessage());
- }
- }
- }
- }
-
- @Override
- public boolean isEnabled(int position) {
- return false;
- }
-
- @Override
- public int getCount() {
- return faces.size();
- }
-
- @Override
- public Object getItem(int position) {
- return faces.get(position);
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
-
- @Override
- public View getView(final int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- LayoutInflater layoutInflater =
- (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- convertView = layoutInflater.inflate(R.layout.item_face_with_description, parent, false);
- }
- convertView.setId(position);
-
-
- ((ImageView) convertView.findViewById(R.id.face_thumbnail)).setImageBitmap(
- faceThumbnails.get(position));
-
-
- DecimalFormat formatter = new DecimalFormat("#0.0");
- String face_description = String.format("Age: %s Gender: %s\nHair: %s FacialHair: %s\nMakeup: %s %s\nForeheadOccluded: %s Blur: %s\nEyeOccluded: %s %s\n" +
- "MouthOccluded: %s Noise: %s\nGlassesType: %s\nHeadPose: %s\nAccessories: %s",
- faces.get(position).faceAttributes.age,
- faces.get(position).faceAttributes.gender,
- getHair(faces.get(position).faceAttributes.hair),
- getFacialHair(faces.get(position).faceAttributes.facialHair),
- getMakeup((faces.get(position)).faceAttributes.makeup),
- getEmotion(faces.get(position).faceAttributes.emotion),
- faces.get(position).faceAttributes.occlusion.foreheadOccluded,
- faces.get(position).faceAttributes.blur.blurLevel,
- faces.get(position).faceAttributes.occlusion.eyeOccluded,
- faces.get(position).faceAttributes.exposure.exposureLevel,
- faces.get(position).faceAttributes.occlusion.mouthOccluded,
- faces.get(position).faceAttributes.noise.noiseLevel,
- faces.get(position).faceAttributes.glasses,
- getHeadPose(faces.get(position).faceAttributes.headPose),
- getAccessories(faces.get(position).faceAttributes.accessories)
- );
- ((TextView) convertView.findViewById(R.id.text_detected_face)).setText(face_description);
-
- return convertView;
- }
-
- private String getHair(Hair hair) {
- if (hair.hairColor.length == 0)
- {
- if (hair.invisible)
- return "Invisible";
- else
- return "Bald";
- }
- else
- {
- int maxConfidenceIndex = 0;
- double maxConfidence = 0.0;
-
- for (int i = 0; i < hair.hairColor.length; ++i)
- {
- if (hair.hairColor[i].confidence > maxConfidence)
- {
- maxConfidence = hair.hairColor[i].confidence;
- maxConfidenceIndex = i;
- }
- }
-
- return hair.hairColor[maxConfidenceIndex].color.toString();
- }
- }
-
- private String getMakeup(Makeup makeup) {
- return (makeup.eyeMakeup || makeup.lipMakeup) ? "Yes" : "No" ;
- }
-
- private String getAccessories(Accessory[] accessories) {
- if (accessories.length == 0)
- {
- return "NoAccessories";
- }
- else
- {
- String[] accessoriesList = new String[accessories.length];
- for (int i = 0; i < accessories.length; ++i)
- {
- accessoriesList[i] = accessories[i].type.toString();
- }
-
- return TextUtils.join(",", accessoriesList);
- }
- }
-
- private String getFacialHair(FacialHair facialHair) {
- return (facialHair.moustache + facialHair.beard + facialHair.sideburns > 0) ? "Yes" : "No";
- }
-
- private String getEmotion(Emotion emotion)
- {
- String emotionType = "";
- double emotionValue = 0.0;
- if (emotion.anger > emotionValue)
- {
- emotionValue = emotion.anger;
- emotionType = "Anger";
- }
- if (emotion.contempt > emotionValue)
- {
- emotionValue = emotion.contempt;
- emotionType = "Contempt";
- }
- if (emotion.disgust > emotionValue)
- {
- emotionValue = emotion.disgust;
- emotionType = "Disgust";
- }
- if (emotion.fear > emotionValue)
- {
- emotionValue = emotion.fear;
- emotionType = "Fear";
- }
- if (emotion.happiness > emotionValue)
- {
- emotionValue = emotion.happiness;
- emotionType = "Happiness";
- }
- if (emotion.neutral > emotionValue)
- {
- emotionValue = emotion.neutral;
- emotionType = "Neutral";
- }
- if (emotion.sadness > emotionValue)
- {
- emotionValue = emotion.sadness;
- emotionType = "Sadness";
- }
- if (emotion.surprise > emotionValue)
- {
- emotionValue = emotion.surprise;
- emotionType = "Surprise";
- }
- return String.format("%s: %f", emotionType, emotionValue);
- }
-
- private String getHeadPose(HeadPose headPose)
- {
- return String.format("Pitch: %s, Roll: %s, Yaw: %s", headPose.pitch, headPose.roll, headPose.yaw);
- }
- }
- }
Select_image_Activity.java code
MainActivity.java code
- package ganeshannt.faceapi.ui;
-
- import android.app.AlertDialog;
- import android.content.Intent;
- import android.os.Bundle;
- import android.support.v7.app.AppCompatActivity;
- import android.view.View;
-
- import ganeshannt.faceapi.R;
-
- public class MainActivity extends AppCompatActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
-
- if (getString(R.string.subscription_key).startsWith("Please")) {
- new AlertDialog.Builder(this)
- .setTitle(getString(R.string.add_subscription_key_tip_title))
- .setMessage(getString(R.string.add_subscription_key_tip))
- .setCancelable(false)
- .show();
- }
- }
-
- public void detection(View view) {
- Intent intent = new Intent(this, DetectionActivity.class);
- startActivity(intent);
- }
-
- }
Step 10Click the "Make Project" option and run.
Deliverables
Here, we have successfully detected the face using Face API in Android app.
![Android]()
![Android]()
![Android]()
![Android]()
![Android]()
Don’t forgot to like and follow me. If you have any doubts, just comment below.