Skip to content

Commit 8973ad2

Browse files
committed
created photo-demo app
This is a "hello world" style app for the face API, to be released to third parties via GitHub. It runs face/landmark detection on a photo and displays the photo with graphics indicating the landmark positions. Also updated the face tracker demo to remove the titlebar and change to the new mobile vision icon. Change-Id: I2a3c88a7c83efd1efa6b9b8d17b13e532daa7d70
1 parent 8ac9103 commit 8973ad2

File tree

27 files changed

+621
-1
lines changed

27 files changed

+621
-1
lines changed

face/FaceTracker/app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
android:name="com.google.android.gms.samples.vision.face.facetracker.FaceTrackerActivity"
2828
android:icon="@drawable/icon"
2929
android:label="Face Tracker"
30+
android:theme="@android:style/Theme.Black.NoTitleBar"
3031
android:screenOrientation="fullSensor">
3132
<intent-filter>
3233
<action android:name="android.intent.action.MAIN" />
@@ -36,4 +37,4 @@
3637
</activity>
3738
</application>
3839

39-
</manifest>
40+
</manifest>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading

face/photo-demo/.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.gradle
2+
/local.properties
3+
/.idea/workspace.xml
4+
/.idea/libraries
5+
.DS_Store
6+
/build
7+
/captures

face/photo-demo/app/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

face/photo-demo/app/build.gradle

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
apply plugin: 'com.android.application'
2+
3+
android {
4+
compileSdkVersion 22
5+
buildToolsVersion "22.0.1"
6+
7+
defaultConfig {
8+
applicationId "com.google.android.gms.samples.vision.face.photo"
9+
minSdkVersion 19
10+
targetSdkVersion 22
11+
versionCode 1
12+
versionName "1.0"
13+
}
14+
buildTypes {
15+
release {
16+
minifyEnabled false
17+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18+
}
19+
}
20+
}
21+
22+
dependencies {
23+
compile fileTree(dir: 'libs', include: ['*.jar'])
24+
compile 'com.android.support:appcompat-v7:22.0.0'
25+
compile 'com.google.android.gms:play-services:7.8.+'
26+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Add project specific ProGuard rules here.
2+
# By default, the flags in this file are appended to flags specified
3+
# in /usr/local/google/home/mccartney/android/ub-gcore-master/prebuilts/fullsdk/linux/tools/proguard/proguard-android.txt
4+
# You can edit the include path and order by changing the proguardFiles
5+
# directive in build.gradle.
6+
#
7+
# For more details, see
8+
# http://developer.android.com/guide/developing/tools/proguard.html
9+
10+
# Add any project specific keep options here:
11+
12+
# If your project uses WebView with JS, uncomment the following
13+
# and specify the fully qualified class name to the JavaScript interface
14+
# class:
15+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16+
# public *;
17+
#}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (C) The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.google.android.gms.samples.vision.face.photo;
17+
18+
import android.app.Application;
19+
import android.test.ApplicationTestCase;
20+
21+
/**
22+
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
23+
*/
24+
public class ApplicationTest extends ApplicationTestCase<Application> {
25+
public ApplicationTest() {
26+
super(Application.class);
27+
}
28+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
package="com.google.android.gms.samples.vision.face.photo"
4+
android:installLocation="auto"
5+
android:versionCode="1"
6+
android:versionName="1" >
7+
8+
<uses-sdk
9+
android:minSdkVersion="11"
10+
android:targetSdkVersion="21" />
11+
12+
<application
13+
android:hardwareAccelerated="true"
14+
android:label="FacePhotoDemo"
15+
android:allowBackup="true"
16+
android:icon="@drawable/icon">
17+
18+
<meta-data android:name="com.google.android.gms.vision.DEPENDENCIES" android:value="face"/>
19+
20+
<activity
21+
android:name=".PhotoViewerActivity"
22+
android:icon="@drawable/icon"
23+
android:label="@string/title_activity_photo_viewer"
24+
android:theme="@android:style/Theme.Black.NoTitleBar"
25+
android:screenOrientation="fullSensor">
26+
<intent-filter>
27+
<action android:name="android.intent.action.MAIN" />
28+
<category android:name="android.intent.category.LAUNCHER" />
29+
</intent-filter>
30+
</activity>
31+
</application>
32+
33+
</manifest>
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Copyright (C) The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.google.android.gms.samples.vision.face.photo;
17+
18+
import android.content.Context;
19+
import android.graphics.Bitmap;
20+
import android.graphics.Canvas;
21+
import android.graphics.Color;
22+
import android.graphics.Paint;
23+
import android.graphics.Rect;
24+
import android.util.AttributeSet;
25+
import android.util.SparseArray;
26+
import android.view.View;
27+
28+
import com.google.android.gms.vision.face.Face;
29+
import com.google.android.gms.vision.face.Landmark;
30+
31+
/**
32+
* View which displays a bitmap containing a face along with overlay graphics that identify the
33+
* locations of detected facial landmarks.
34+
*/
35+
public class FaceView extends View {
36+
private Bitmap mBitmap;
37+
private SparseArray<Face> mFaces;
38+
39+
public FaceView(Context context, AttributeSet attrs) {
40+
super(context, attrs);
41+
}
42+
43+
/**
44+
* Sets the bitmap background and the associated face detections.
45+
*/
46+
void setContent(Bitmap bitmap, SparseArray<Face> faces) {
47+
mBitmap = bitmap;
48+
mFaces = faces;
49+
invalidate();
50+
}
51+
52+
/**
53+
* Draws the bitmap background and the associated face landmarks.
54+
*/
55+
@Override
56+
protected void onDraw(Canvas canvas) {
57+
super.onDraw(canvas);
58+
if ((mBitmap != null) && (mFaces != null)) {
59+
double scale = drawBitmap(canvas);
60+
drawFaceAnnotations(canvas, scale);
61+
}
62+
}
63+
64+
/**
65+
* Draws the bitmap background, scaled to the device size. Returns the scale for future use in
66+
* positioning the facial landmark graphics.
67+
*/
68+
private double drawBitmap(Canvas canvas) {
69+
double viewWidth = canvas.getWidth();
70+
double viewHeight = canvas.getHeight();
71+
double imageWidth = mBitmap.getWidth();
72+
double imageHeight = mBitmap.getHeight();
73+
double scale = Math.min(viewWidth / imageWidth, viewHeight / imageHeight);
74+
75+
Rect destBounds = new Rect(0, 0, (int)(imageWidth * scale), (int)(imageHeight * scale));
76+
canvas.drawBitmap(mBitmap, null, destBounds, null);
77+
return scale;
78+
}
79+
80+
/**
81+
* Draws a small circle for each detected landmark, centered at the detected landmark position.
82+
* <p>
83+
*
84+
* Note that eye landmarks are defined to be the midpoint between the detected eye corner
85+
* positions, which tends to place the eye landmarks at the lower eyelid rather than at the
86+
* pupil position.
87+
*/
88+
private void drawFaceAnnotations(Canvas canvas, double scale) {
89+
Paint paint = new Paint();
90+
paint.setColor(Color.GREEN);
91+
paint.setStyle(Paint.Style.STROKE);
92+
paint.setStrokeWidth(5);
93+
94+
for (int i = 0; i < mFaces.size(); ++i) {
95+
Face face = mFaces.valueAt(i);
96+
for (Landmark landmark : face.getLandmarks()) {
97+
int cx = (int) (landmark.getPosition().x * scale);
98+
int cy = (int) (landmark.getPosition().y * scale);
99+
canvas.drawCircle(cx, cy, 10, paint);
100+
}
101+
}
102+
}
103+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright (C) The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.google.android.gms.samples.vision.face.photo;
17+
18+
import android.app.Activity;
19+
import android.graphics.Bitmap;
20+
import android.graphics.BitmapFactory;
21+
import android.os.Bundle;
22+
import android.util.SparseArray;
23+
24+
import com.google.android.gms.vision.Frame;
25+
import com.google.android.gms.vision.face.Face;
26+
import com.google.android.gms.vision.face.FaceDetector;
27+
28+
import java.io.InputStream;
29+
30+
/**
31+
* Demonstrates basic usage of the GMS vision face detector by running face landmark detection on a
32+
* photo and displaying the photo with associated landmarks in the UI.
33+
*/
34+
public class PhotoViewerActivity extends Activity {
35+
@Override
36+
protected void onCreate(Bundle savedInstanceState) {
37+
super.onCreate(savedInstanceState);
38+
setContentView(R.layout.activity_photo_viewer);
39+
40+
InputStream stream = getResources().openRawResource(R.raw.face);
41+
Bitmap bitmap = BitmapFactory.decodeStream(stream);
42+
43+
// A new face detector is created for detecting the face and its landmarks.
44+
//
45+
// Setting "tracking enabled" to false is recommended for detection with unrelated
46+
// individual images (as opposed to video or a series of consecutively captured still
47+
// images). For detection on unrelated individual images, this will give a more accurate
48+
// result.
49+
//
50+
// By default, landmark detection is not enabled since it increases detection time. We
51+
// enable it here in order to visualize detected landmarks.
52+
FaceDetector detector = new FaceDetector.Builder(getApplicationContext())
53+
.setTrackingEnabled(false)
54+
.setLandmarkType(FaceDetector.ALL_LANDMARKS)
55+
.build();
56+
57+
// Run face detection on the bitmap.
58+
Frame frame = new Frame.Builder().setBitmap(bitmap).build();
59+
SparseArray<Face> faces = detector.detect(frame);
60+
61+
// Note: The first time that an app using face API is installed on a device, GMS will
62+
// download a native library to the device in order to do detection. Usually this
63+
// completes before the app is run for the first time. But if that download has not yet
64+
// completed, then the above call will not detect any faces. The detector.isOperational()
65+
// method can be used to check if the required native library is currently available.
66+
67+
FaceView overlay = (FaceView) findViewById(R.id.faceView);
68+
overlay.setContent(bitmap, faces);
69+
70+
// Although detector may be used multiple times for different images, it should be released
71+
// when it is no longer needed in order to free native resources.
72+
detector.release();
73+
}
74+
}
Loading
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:layout_width="match_parent"
4+
android:layout_height="match_parent" >
5+
6+
<com.google.android.gms.samples.vision.face.photo.FaceView
7+
android:id="@+id/faceView"
8+
android:layout_width="match_parent"
9+
android:layout_height="match_parent" />
10+
11+
</LinearLayout>
303 KB
Loading
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<resources>
2+
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
3+
(such as screen margins) for screens with more than 820dp of available width. This
4+
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
5+
<dimen name="activity_horizontal_margin">64dp</dimen>
6+
</resources>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<resources>
2+
<!-- Default screen margins, per the Android Design guidelines. -->
3+
<dimen name="activity_horizontal_margin">16dp</dimen>
4+
<dimen name="activity_vertical_margin">16dp</dimen>
5+
</resources>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<resources>
2+
<string name="app_name">Photo Demo</string>
3+
<string name="title_activity_photo_viewer">Photo Viewer</string>
4+
</resources>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<resources>
2+
<!-- Base application theme. -->
3+
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
4+
<!-- Customize your theme here. -->
5+
</style>
6+
</resources>

face/photo-demo/build.gradle

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Top-level build file where you can add configuration options common to all sub-projects/modules.
2+
3+
buildscript {
4+
repositories {
5+
jcenter()
6+
}
7+
dependencies {
8+
classpath 'com.android.tools.build:gradle:1.2.3'
9+
10+
// NOTE: Do not place your application dependencies here; they belong
11+
// in the individual module build.gradle files
12+
}
13+
}
14+
15+
allprojects {
16+
repositories {
17+
jcenter()
18+
}
19+
}

face/photo-demo/gradle.properties

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Project-wide Gradle settings.
2+
3+
# IDE (e.g. Android Studio) users:
4+
# Gradle settings configured through the IDE *will override*
5+
# any settings specified in this file.
6+
7+
# For more details on how to configure your build environment visit
8+
# http://www.gradle.org/docs/current/userguide/build_environment.html
9+
10+
# Specifies the JVM arguments used for the daemon process.
11+
# The setting is particularly useful for tweaking memory settings.
12+
# Default value: -Xmx10248m -XX:MaxPermSize=256m
13+
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14+
15+
# When configured, Gradle will run in incubating parallel mode.
16+
# This option should only be used with decoupled projects. More details, visit
17+
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18+
# org.gradle.parallel=true
Binary file not shown.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#Wed Apr 10 15:27:10 PDT 2013
2+
distributionBase=GRADLE_USER_HOME
3+
distributionPath=wrapper/dists
4+
zipStoreBase=GRADLE_USER_HOME
5+
zipStorePath=wrapper/dists
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip

0 commit comments

Comments
 (0)