-upload AffdexMe folder to GitHub

-upload the AffdexMe project folder and corresponding README.md file
This commit is contained in:
acasallas 2015-06-23 16:44:24 -04:00
parent 082a13f0c0
commit b27245ea6a
52 changed files with 2155 additions and 0 deletions

7
AffdexMe/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures

1
AffdexMe/.idea/.name Normal file
View File

@ -0,0 +1 @@
AffdexMe

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
<entry name="!?*.aj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
</project>

View File

@ -0,0 +1,3 @@
<component name="CopyrightManager">
<settings default="" />
</component>

19
AffdexMe/.idea/gradle.xml Normal file
View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="LOCAL" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="C:\Program Files\Android\Android Studio\gradle\gradle-2.2.1" />
<option name="gradleJvm" value="1.7" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

19
AffdexMe/.idea/misc.xml Normal file
View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/AffdexMe.iml" filepath="$PROJECT_DIR$/AffdexMe.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
</modules>
</component>
</project>

6
AffdexMe/.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="" />
</component>
</project>

19
AffdexMe/AffdexMe.iml Normal file
View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="AffdexMe" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="AffdexMe_original" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

1
AffdexMe/app/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

101
AffdexMe/app/app.iml Normal file
View File

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="AffdexMe" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":app" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
<option name="TEST_SOURCE_GEN_TASK_NAME" value="generateDebugAndroidTestSources" />
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/22.1.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/22.1.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
<orderEntry type="jdk" jdkName="Android API 22 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="appcompat-v7-22.1.1" level="project" />
<orderEntry type="library" exported="" name="dagger-1.2.2" level="project" />
<orderEntry type="library" exported="" name="Affdex-sdk" level="project" />
<orderEntry type="library" exported="" name="javax.inject-1" level="project" />
<orderEntry type="library" exported="" name="support-v4-22.1.1" level="project" />
<orderEntry type="library" exported="" name="support-annotations-22.1.1" level="project" />
<orderEntry type="library" exported="" name="gson-2.3" level="project" />
<orderEntry type="library" exported="" name="Affdex-sdk-javadoc" level="project" />
<orderEntry type="library" exported="" name="flurry-analytics-4.1.0" level="project" />
</component>
</module>

38
AffdexMe/app/build.gradle Normal file
View File

@ -0,0 +1,38 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion '22.0.1'
defaultConfig {
applicationId "com.affectiva.affdexme"
minSdkVersion 16
targetSdkVersion 22
versionCode 11
versionName "1.0.844"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
//gson is necessary for the license to be parsed
compile 'com.google.code.gson:gson:2.3'
//include the Affdex SDK jars
compile files('libs/Affdex-sdk.jar')
compile files('libs/Affdex-sdk-javadoc.jar')
compile files('libs/dagger-1.2.2.jar')
compile files('libs/flurry-analytics-4.1.0.jar')
compile files('libs/javax.inject-1.jar')
//although the use of the CameraDetector class in this project does not require it, you may have to include
//the following dependencies if you use other features of the Affdex SDK
//compile 'com.android.support:support-v4:22.2.0'
//compile 'com.google.android.gms:play-services:7.5.0'
}

92
AffdexMe/app/build.xml Normal file
View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="AffdexMe" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: 1 -->
<import file="${sdk.dir}/tools/ant/build.xml" />
</project>

29
AffdexMe/app/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,29 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/AlanCasalas/Library/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
#prevent proguard from warning us about not including the GooglePlay dependency
-dontwarn **
#keep all classes (otherwise Proguard may remove classes that use reflection, injection, Gson, etc...)
-keep class sun.**
-keep class com.**
-keep class android.**
-keep class dagger.**
-keep class javax.**
#keep certain class members (otherwise Proguard would strip the members of these classes)
-keepclassmembers class com.affectiva.android.affdex.sdk.detector.License { *; }
-keepclassmembers class com.affectiva.android.affdex.sdk.detector.A* { *; }
-keepclassmembers class * {
@javax.inject.* *;
@dagger.* *;
<init>();
}

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.affectiva.affdexme" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="22" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
<uses-feature android:name="android.hardware.camera.front" android:required="false"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:configChanges="keyboardHidden|screenSize|orientation"
android:screenOrientation="sensorPortrait"
android:windowSoftInputMode="stateHidden"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

Binary file not shown.

View File

@ -0,0 +1,271 @@
package com.affectiva.affdexme;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.os.Process;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
/**
* This class contains a SurfaceView and its own thread that draws to it.
* It is used to display the facial tracking dots over a user's face.
*/
public class DrawingView extends SurfaceView implements SurfaceHolder.Callback {
//Inner Thread class
class DrawingThread extends Thread{
private SurfaceHolder mSurfaceHolder;
private Paint circlePaint;
private Paint boxPaint;
private boolean stopFlag = false; //boolean to indicate when thread has been told to stop
private PointF[] nextPointsToDraw = null; //holds a reference to the most recent set of points returned by CameraDetector, passed in by main thread
boolean isDrawPointsEnabled = false; //saves whether user has selected dots to be drawn
float imageWidth = 0;
float imageHeight = 0;
float screenToImageRatio = 0;
float drawThickness = 0; //thickness with which dots and square will be drawn
private final long drawPeriod = 33; //draw at 30 fps
public DrawingThread(SurfaceHolder surfaceHolder, boolean drawPoints) {
mSurfaceHolder = surfaceHolder;
circlePaint = new Paint();
circlePaint.setColor(Color.WHITE);
boxPaint = new Paint();
boxPaint.setColor(Color.WHITE);
boxPaint.setStyle(Paint.Style.STROKE);
isDrawPointsEnabled = drawPoints;
}
/**
* Used to set the valence score, which determines the color of the bounding box.
* **/
void setScore(float s) {
if (s > 0) {
float colorScore = ((100f-s)/100f)*255;
boxPaint.setColor(Color.rgb((int)colorScore,255,(int)colorScore));
} else {
float colorScore = ((100f+s)/100f)*255;
boxPaint.setColor(Color.rgb(255,(int)colorScore,(int)colorScore));
}
}
public void stopThread() {
stopFlag = true;
}
public boolean isStopped() {
return stopFlag;
}
//Updates thread with latest points returned by the onImageResults() event.
public void updatePoints(PointF[] pointList) {
nextPointsToDraw = pointList;
}
//Sets measurements thread will use to draw facial tracking dots.
public void setDimen(int w, int h, float appToImageRatio, float thickness) {
imageWidth = w;
imageHeight = h;
screenToImageRatio = appToImageRatio;
drawThickness = thickness;
boxPaint.setStrokeWidth(thickness);
}
private void setDrawPointsEnabled(boolean b) {
isDrawPointsEnabled = b;
}
private boolean getDrawPointsEnabled() {
return isDrawPointsEnabled;
}
//Inform thread face detection has stopped, so array of points is no longer valid.
public void invalidatePoints() {
nextPointsToDraw = null;
}
@Override
public void run() {
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
while(!stopFlag) {
long startTime = SystemClock.elapsedRealtime(); //get time at the start of thread loop
/**
* We use SurfaceHolder.lockCanvas() to get the canvas that draws to the SurfaceView.
* After we are done drawing, we let go of the canvas using SurfaceHolder.unlockCanvasAndPost()
* **/
Canvas c = null;
try {
c = mSurfaceHolder.lockCanvas();
if (c!= null) {
synchronized (mSurfaceHolder) {
c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); //clear previous dots
if (isDrawPointsEnabled && (nextPointsToDraw != null) ) {
draw(c);
}
}
}
}
finally {
if (c!= null) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
//send thread to sleep so we don't draw faster than the requested 'drawPeriod'.
long sleepTime = drawPeriod - (SystemClock.elapsedRealtime() - startTime);
try {
if(sleepTime>0){
this.sleep(sleepTime);
}
} catch (InterruptedException ex) {
Log.e(LOG_TAG,ex.getMessage());
}
}
}
void draw(Canvas c) {
//Save our own reference to the list of points, in case the previous reference is overwritten by the main thread.
PointF[] points = nextPointsToDraw;
//Coordinates around which to draw bounding box.
float leftBx = imageWidth;
float rightBx = 0;
float topBx = imageHeight;
float botBx = 0;
//Iterate through all the points given to us by the CameraDetector object
for (int i = 0; i < points.length; i++) {
//We determine the left-most, top-most, right-most, and bottom-most points to draw the bounding box around.
if (points[i].x < leftBx)
leftBx = points[i].x;
if (points[i].x > rightBx)
rightBx = points[i].x;
if (points[i].y < topBx)
topBx = points[i].y;
if (points[i].y > botBx)
botBx = points[i].y;
//Draw facial tracking dots.
//The camera preview is displayed as a mirror, so X pts have to be reversed
c.drawCircle((imageWidth - points[i].x - 1) * screenToImageRatio, (points[i].y)* screenToImageRatio, drawThickness, circlePaint);
}
//Draw the bounding box.
c.drawRect((imageWidth - leftBx - 1) * screenToImageRatio, topBx * screenToImageRatio, (imageWidth - rightBx - 1) * screenToImageRatio, botBx * screenToImageRatio, boxPaint);
}
}
//Class variables of DrawingView class
private SurfaceHolder surfaceHolder;
private DrawingThread drawingThread; //DrawingThread object
private boolean isDimensionsNeeded = true;
private boolean isDrawPointsEnabled = true; //by default, start drawing thread without drawing points
private static String LOG_TAG = "AffdexMe";
//three constructors required of any custom view
public DrawingView(Context context) {
super(context);
initView();
}
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public DrawingView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView();
}
void initView(){
surfaceHolder = getHolder(); //The SurfaceHolder object will be used by the thread to request canvas to draw on SurfaceView
surfaceHolder.setFormat(PixelFormat.TRANSPARENT); //set to Transparent so this surfaceView does not obscure the one it is overlaying (the one displaying the camera).
surfaceHolder.addCallback(this); //become a Listener to the three events below that SurfaceView throws
drawingThread = new DrawingThread(surfaceHolder, isDrawPointsEnabled);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (drawingThread.isStopped()) {
drawingThread = new DrawingThread(surfaceHolder, isDrawPointsEnabled);
}
drawingThread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//command thread to stop, and wait until it stops
boolean retry = true;
drawingThread.stopThread();
while (retry) {
try {
drawingThread.join();
retry = false;
} catch (InterruptedException e) {
Log.e(LOG_TAG,e.getMessage());
}
}
isDimensionsNeeded = true; //Now that thread has been destroyed, we'll need dimensions to be recalculated if a new thread is later created.
}
public void setDimensions(int width, int height, float appToImageRatio, float radius) {
drawingThread.setDimen(width, height, appToImageRatio, radius);
isDimensionsNeeded = false;
}
public boolean isDimensionsNeeded() {
return isDimensionsNeeded;
}
public void setDrawPointsEnabled(boolean b){
isDrawPointsEnabled = b;
drawingThread.setDrawPointsEnabled(b);
}
public void invalidateDimensions() {
isDimensionsNeeded = true;
}
public boolean getDrawPointsEnabled() {
return isDrawPointsEnabled;
}
//The methods below simply delegate to the drawingThread object
public void setScore(float s) {
drawingThread.setScore(s);
}
public void updatePoints(PointF[] points) {
drawingThread.updatePoints(points);
}
public void invalidatePoints(){
drawingThread.invalidatePoints();
}
}

View File

@ -0,0 +1,48 @@
package com.affectiva.affdexme;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
/**
* GradientMetricView is used to display the valence metric and adds functionality of allowing
* the bar's shade of color to scale with the metric's value, rather than just being red or green.
*/
public class GradientMetricView extends MetricView {
//Three Constructors required of any custom view:
public GradientMetricView(Context context) {
super(context);
}
public GradientMetricView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public GradientMetricView(Context context, AttributeSet attrs, int styleID){
super(context, attrs, styleID);
}
/**
* As in MetricView, we set our text to display the score and size the colored bar appropriately.
* In this class, however, we let the score determine the color of the bar (shades of red for negative
* and shades of green for positive).
*/
@Override
public void setScore(float s) {
text = String.format("%d%%", (int)s);
if (s > 0) {
left = midX - (halfWidth * (s / 100));
right = midX + (halfWidth * (s / 100));
} else {
left = midX - (halfWidth * (-s / 100));
right = midX + (halfWidth * (-s / 100));
}
if (s > 0) {
float colorScore = ((100f-s)/100f)*255;
boxPaint.setColor(Color.rgb((int)colorScore,255,(int)colorScore));
} else {
float colorScore = ((100f+s)/100f)*255;
boxPaint.setColor(Color.rgb(255,(int)colorScore,(int)colorScore));
}
invalidate(); //instruct Android to re-draw our view, now that the text has changed
}
}

View File

@ -0,0 +1,632 @@
package com.affectiva.affdexme;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.util.List;
import com.affectiva.android.affdex.sdk.Frame;
import com.affectiva.android.affdex.sdk.Frame.ROTATE;
import com.affectiva.android.affdex.sdk.detector.CameraDetector;
import com.affectiva.android.affdex.sdk.detector.Detector;
import com.affectiva.android.affdex.sdk.detector.Face;
/*
* AffdexMe is an app that demonstrates the use of the Affectiva Android SDK. It uses the
* front-facing camera on your Android device to view, process and analyze live video of your face.
* Start the app and you will see your own face on the screen and metrics describing your
* expressions.
*
* Tapping the screen will bring up a menu with options to display the Processed Frames Per Second metric,
* display facial tracking points, and control the rate at which frames are processed by the SDK.
*
* Most of the methods in this file control the application's UI. Therefore, if you are just interested in learning how the Affectiva SDK works,
* you will find the calls relevant to the use of the SDK in the startCamera() and stopCamera() methods, as well as the onImageResults() method.
*
* This class implements the Detector.ImageListener interface, allowing it to receive the onImageResults() event.
* This class implements the Detector.FaceListener interface, allowing it to receive the onFaceDetectionStarted() and
* onFaceDetectionStopped() events.
*
* In order to use this project, you will need to:
* - Obtain the SDK from Affectiva (visit http://www.affdex.com/mobile-sdk)
* - Copy the SDK assets folder contents into this project's assets folder
* - Copy the SDK libs folder contents into this project's libs folder
* - Copy the armeabi-v7a folder (found in the SDK libs folder) into this project's jniLibs folder
* - Add your license file to the /assets/Affdex folder and uncomment the line in the startCamera() method
* to type in your license file name
* - Build the project
* - Run the app on an Android device with a front-facing camera
*
* Copyright (c) 2014 Affectiva. All rights reserved.
*/
public class MainActivity extends Activity
implements Detector.FaceListener, Detector.ImageListener, TextView.OnEditorActionListener, View.OnTouchListener{
private static final String LOG_TAG = "AffdexMe";
//Affectiva SDK Object
private CameraDetector detector = null;
//Metrics View UI Objects
private RelativeLayout metricViewLayout;
private LinearLayout leftMetricsLayout;
private LinearLayout rightMetricsLayout;
private MetricView smilePct;
private MetricView browRaisePct;
private MetricView browFurrowPct;
private MetricView frownPct;
private MetricView valencePct;
private MetricView engagementPct;
private TextView fpsName;
private TextView fpsPct;
private TextView smileName;
private TextView browRaiseName;
private TextView browFurrowName;
private TextView frownName;
private TextView valenceName;
private TextView engagementName;
//Menu UI Objects
private RelativeLayout menuLayout;
private EditText fpsEditText;
private CheckBox fpsCheckbox;
private CheckBox trackingCheckbox;
private TextView fpsEditTextName;
//Other UI objects
private ViewGroup activityLayout; //top-most ViewGroup in which all content resides
private RelativeLayout mainLayout; //layout, to be resized, containing all UI elements
private RelativeLayout progressBarLayout; //layout used to show progress circle while camera is starting
private SurfaceView cameraView; //SurfaceView used to display camera images
private DrawingView drawingView; //SurfaceView containing its own thread, used to draw facial tracking dots
//The Shared Preferences object is used to restore/save settings when activity is created/destroyed
private final String PREFS_NAME = "AffdexMe";
SharedPreferences sharedPreferences;
//Application settings variables
private int detectorProcessRate = 20;
private boolean isMenuVisible = false;
private boolean isFPSVisible = false;
//Frames Per Second (FPS) variables
private long firstSystemTime = 0;
private float numberOfFrames = 0;
private long timeToUpdate = 0;
private boolean isFrontFacingCameraDetected = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); //To maximize UI space, we declare our app to be full-screen
setContentView(R.layout.activity_main);
/**
* We check to make sure the device has a front-facing camera.
* If it does not, we obscure the app with a notice informing the user they cannot
* use the app.
*/
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)) {
isFrontFacingCameraDetected = false;
TextView notFoundTextView = (TextView) findViewById(R.id.not_found_textview);
notFoundTextView.setVisibility(View.VISIBLE);
}
initializeUI();
}
void initializeUI() {
//Get handles to UI objects
activityLayout = (ViewGroup) findViewById(android.R.id.content);
progressBarLayout = (RelativeLayout) findViewById(R.id.progress_bar_cover);
metricViewLayout = (RelativeLayout) findViewById(R.id.metric_view_group);
leftMetricsLayout = (LinearLayout) findViewById(R.id.left_metrics);
rightMetricsLayout = (LinearLayout) findViewById(R.id.right_metrics);
mainLayout = (RelativeLayout) findViewById(R.id.main_layout);
menuLayout = (RelativeLayout) findViewById(R.id.affdexme_menu);
smilePct = (MetricView) findViewById(R.id.smile_pct);
browRaisePct = (MetricView) findViewById(R.id.brow_raise_pct);
browFurrowPct = (MetricView) findViewById(R.id.brow_furrow_pct);
frownPct = (MetricView) findViewById(R.id.frown_pct);
valencePct = (MetricView) findViewById(R.id.valence_pct);
engagementPct = (MetricView) findViewById(R.id.engagement_pct);
fpsPct = (TextView) findViewById(R.id.fps_value);
smileName = (TextView) findViewById(R.id.smile_name);
browRaiseName = (TextView) findViewById(R.id.brow_raise_name);
browFurrowName = (TextView) findViewById(R.id.brow_furrow_name);
frownName = (TextView) findViewById(R.id.frown_name);
valenceName = (TextView) findViewById(R.id.valence_name);
engagementName = (TextView) findViewById(R.id.engagement_name);
fpsName = (TextView) findViewById(R.id.fps_name);
fpsEditText = (EditText) findViewById(R.id.fps_edittext);
fpsEditTextName = (TextView) findViewById(R.id.fps_edittext_name);
fpsCheckbox = (CheckBox) findViewById(R.id.fps_checkbox);
trackingCheckbox = (CheckBox) findViewById(R.id.tracking_checkbox);
cameraView = (SurfaceView) findViewById(R.id.camera_preview);
drawingView = (DrawingView) findViewById(R.id.drawing_view);
//Load Application Font and set UI Elements to use it
Typeface face = Typeface.createFromAsset(getAssets(), "fonts/Square.ttf");
smilePct.setTypeface(face);
browRaisePct.setTypeface(face);
browFurrowPct.setTypeface(face);
frownPct.setTypeface(face);
valencePct.setTypeface(face);
engagementPct.setTypeface(face);
smileName.setTypeface(face);
browRaiseName.setTypeface(face);
browFurrowName.setTypeface(face);
frownName.setTypeface(face);
valenceName.setTypeface(face);
engagementName.setTypeface(face);
fpsPct.setTypeface(face);
fpsName.setTypeface(face);
fpsEditTextName.setTypeface(face);
fpsCheckbox.setTypeface(face);
trackingCheckbox.setTypeface(face);
//Hide left and right metrics by default (will be made visible when face detection starts)
leftMetricsLayout.setAlpha(0);
rightMetricsLayout.setAlpha(0);
/**
* This app uses two SurfaceView objects: one to display the camera image and the other to draw facial tracking dots.
* Since we want the tracking dots to appear over the camera image, we use SurfaceView.setZOrderMediaOverlay() to indicate that
* cameraView represents our 'media', and drawingView represents our 'overlay', so that Android will render them in the
* correct order.
*/
drawingView.setZOrderMediaOverlay(true);
cameraView.setZOrderMediaOverlay(false);
//Attach event listeners to the menu and edit box
activityLayout.setOnTouchListener(this);
menuLayout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
/**
* This method effectively blocks the mainLayout from receiving a touch event
* when the menu is pressed. This is to prevent the menu from closing if the user accidentally touches it
* when aiming for a checkbox or edit box.
*/
return true;
}
});
fpsEditText.setOnEditorActionListener(this);
/**
* This app sets the View.SYSTEM_UI_FLAG_HIDE_NAVIGATION flag. Unfortunately, this flag causes
* Android to steal the first touch event after the navigation bar has been hidden, a touch event
* which should be used to make our menu visible again. Therefore, we attach a listener to be notified
* when the navigation bar has been made visible again, which corresponds to the touch event that Android
* steals. If the menu bar was not visible, we make it visible.
*/
activityLayout.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
@Override
public void onSystemUiVisibilityChange(int uiCode) {
if ((uiCode == 0) && (isMenuVisible == false)) {
setMenuVisible(true);
}
}
});
}
/**
* We use onResume() to restore application settings using the SharedPreferences object and
* to indicate that dimensions should be recalculated.
*/
@Override
public void onResume() {
super.onResume();
restoreApplicationSettings();
drawingView.invalidateDimensions(); //set flag to have screen dimensions resized (usage appears in onImageResults())
setMenuVisible(false); //always make the menu invisible by default
}
/**
* We use the Shared Preferences object to restore application settings.
* **/
public void restoreApplicationSettings() {
sharedPreferences = getSharedPreferences(PREFS_NAME, 0);
detectorProcessRate = sharedPreferences.getInt("rate", detectorProcessRate); //restore camera processing rate
fpsEditText.setText(String.valueOf(detectorProcessRate));
if (sharedPreferences.getBoolean("fps",isFPSVisible)) { //restore isFPSMetricVisible
fpsCheckbox.setChecked(true);
setFPSVisible(true);
} else {
fpsCheckbox.setChecked(false);
setFPSVisible(false);
}
if (sharedPreferences.getBoolean("track",drawingView.getDrawPointsEnabled())) { //restore isTrackingDotsVisible
setTrackPoints(true);
trackingCheckbox.setChecked(true);
} else {
setTrackPoints(false);
trackingCheckbox.setChecked(false);
}
}
/**
* Reset the variables used to calculate processed frames per second.
* **/
public void resetFPSCalculations() {
firstSystemTime = SystemClock.elapsedRealtime();
timeToUpdate = firstSystemTime + 1000L;
numberOfFrames = 0;
}
/**
* We start the camera as soon as the application has been given focus, which occurs as soon as the application has
* been opened or reopened. Although this can also occur when the application regains focus after a dialog box has been closed,
* the camera will not be reinitialized because the detector object will not have been set to null during onPause().
* We also reset variables used to calculate the Processed Frames Per Second.
*/
@Override
public void onWindowFocusChanged(boolean hasFocus) {
if (hasFocus && isFrontFacingCameraDetected) {
startCamera();
resetFPSCalculations();
}
}
void startCamera() {
if (detector == null) {
/** Put the SDK in camera mode by using this constructor. The SDK will be in control of
* the camera. If a SurfaceView is passed in as the last argument to the constructor,
* that view will be painted with what the camera sees.
*/
detector = new CameraDetector(this, CameraDetector.CameraType.CAMERA_FRONT, cameraView);
// NOTE: uncomment the line below and replace "YourLicenseFile" with your license file, which should be stored in /assets/Affdex/
//detector.setLicensePath("YourLicenseFile");
// We want to detect all expressions, so turn on all classifiers.
detector.setDetectSmile(true);
detector.setDetectBrowFurrow(true);
detector.setDetectBrowRaise(true);
detector.setDetectEngagement(true);
detector.setDetectValence(true);
detector.setDetectLipCornerDepressor(true);
detector.setMaxProcessRate(detectorProcessRate);
detector.setImageListener(this);
detector.setFaceListener(this);
//now that the CameraDetector object has been set up, start the camera
try {
detector.start();
} catch (Exception e) {
Log.e(LOG_TAG, e.getMessage());
}
}
}
@Override
public void onFaceDetectionStarted() {
leftMetricsLayout.animate().alpha(1); //make left and right metrics appear
rightMetricsLayout.animate().alpha(1);
resetFPSCalculations(); //Since the FPS may be different whether a face is being tracked or not, reset variables.
}
@Override
public void onFaceDetectionStopped() {
performFaceDetectionStoppedTasks();
}
void performFaceDetectionStoppedTasks() {
leftMetricsLayout.animate().alpha(0); //make left and right metrics disappear
rightMetricsLayout.animate().alpha(0);
drawingView.invalidatePoints(); //inform the drawing thread that the latest facial tracking points are now invalid
resetFPSCalculations(); //Since the FPS may be different whether a face is being tracked or not, reset variables.
}
/**
* This event is received every time the SDK processes a frame.
*/
@Override
public void onImageResults(List<Face> faces, Frame image, float timeStamp) {
/**
* If the flag indicating that we need to size our layout is set, call calculateDimensions().
* The flag is a boolean stored in our drawingView object, retrieved through DrawingView.isDimensionsNeeded().
*/
if (drawingView.isDimensionsNeeded() ) {
calculateDimensions(image);
}
//If the faces object is null, we received an unprocessed frame
if (faces == null) {
return;
}
//At this point, we know the frame received was processed, so we perform our processed frames per second calculations
performFPSCalculations();
//If faces.size() is 0, we received a frame in which no face was detected
if (faces.size() == 0) {
return;
}
//The SDK currently detects one face at a time, so we recover it using .get(0).
//'0' indicates we are recovering the first face.
Face face = faces.get(0);
//update metrics with latest face information. The metrics are displayed on a MetricView, a custom view with a .setScore() method.
smilePct.setScore(face.getSmileScore());
browRaisePct.setScore(face.getBrowRaiseScore());
browFurrowPct.setScore(face.getBrowFurrowScore());
engagementPct.setScore(face.getEngagementScore());
frownPct.setScore(face.getLipCornerDepressorScore());
float valenceScore = face.getValenceScore();
valencePct.setScore(valenceScore);
/**
* If the user has selected to have facial tracking dots drawn, we use face.getFacePoints() to send those points
* to our drawing thread and also inform the thread what the valence score was, as that will determine the color
* of the bounding box.
*/
if (drawingView.getDrawPointsEnabled()) {
drawingView.setScore(valenceScore);
drawingView.updatePoints(face.getFacePoints());
}
}
/**
* This method serves two purposes:
* -It informs the drawing thread of the size of the frames passed by the CameraDetector object.
* -It corrects the dimensions of our mainLayout object to conform to the aspect ratio of the frames passed by the CameraDetector object.
*/
void calculateDimensions(Frame image){
//Log.i(LOG_TAG,"Dimensions being re-calculated");
float screenWidth = activityLayout.getWidth();
float screenHeight = activityLayout.getHeight();
float referenceDimension = screenHeight; //referenceDimension will be used to determine the size of the facial tracking dots
//get size of frames being passed by camera
float imageWidth = image.getWidth();
float imageHeight = image.getHeight();
/**
* If device is rotated vertically, reverse the width and height returned by the Frame object,
* and switch the dimension we consider to be the reference dimension.
*/
if ((ROTATE.BY_90_CW == image.getTargetRotation()) || (ROTATE.BY_90_CCW == image.getTargetRotation())) {
float temp = imageWidth;
imageWidth = imageHeight;
imageHeight = temp;
referenceDimension = screenWidth;
}
/**
* In this section, we resize our layouts so that the SurfaceView displaying the camera images to will have the same
* aspect ratio as the frames we are receiving from the camera.
* Since all elements in our app are inside 'mainLayout', we just have to adjust the height and width of this layout.
*/
//calculate aspect ratios of camera frames and screen
float imageAspectRatio = imageWidth/imageHeight;
float screenAspectRatio = screenWidth/screenHeight;
float screenToImageRatio = 0;
int newLayoutHeight = 0;
int newLayoutWidth = 0;
if (screenAspectRatio < imageAspectRatio) {
newLayoutHeight = (int) (screenWidth / imageAspectRatio);
screenToImageRatio = screenWidth / imageWidth;
newLayoutWidth = (int)screenWidth;
} else {
newLayoutWidth = (int) (screenHeight * imageAspectRatio);
screenToImageRatio = screenHeight/imageHeight;
newLayoutHeight = (int)screenHeight;
}
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mainLayout.getLayoutParams();
params.height = newLayoutHeight;
params.width = newLayoutWidth;
mainLayout.setLayoutParams(params);
/**
* Send necessary dimensions to the drawing thread.
* The dimensions are: width of frame, height of frame, ratio of screen to frame size, and thickness of facial tracking dots.
* This method will clear the flag that indicates whether we need to calculate dimensions, so this calculateDimensions()
* will not be continuously called.
*/
drawingView.setDimensions((int) imageWidth, (int) imageHeight, screenToImageRatio, referenceDimension / 160);
//Now that the aspect ratio has been corrected, remove the progress bar from obscuring the screen
progressBarLayout.setVisibility(View.GONE);
}
/**
* FPS measurement simply uses SystemClock to measure how many frames were processed since
* the FPS variables were last reset.
* The constants 1000L and 1000f appear because .elapsedRealtime() measures time in milliseconds.
* Note that if 20 frames per second are processed, this method could run for 1.5 years without being reset
* before numberOfFrames overflows.
*/
void performFPSCalculations() {
numberOfFrames += 1;
long currentTime = SystemClock.elapsedRealtime();
if (currentTime > timeToUpdate) {
float framesPerSecond = (numberOfFrames/(float)(currentTime - firstSystemTime))*1000f;
fpsPct.setText(String.format(" %.1f",framesPerSecond));
timeToUpdate = currentTime + 1000L;
}
}
/**
* Although we start the camera in onWindowFocusChanged(), we stop it in onPause(), and set detector to be null so that when onWindowFocusChanged()
* is called it restarts the camera. We also set the Progress Bar to be visible, so the camera (which may need resizing when the app
* is resumed) is obscured.
*/
@Override
public void onPause() {
super.onPause();
saveApplicationSettings();
progressBarLayout.setVisibility(View.VISIBLE);
stopCamera();
}
private void stopCamera() {
performFaceDetectionStoppedTasks();
if (null != detector) {
try {
detector.stop();
} catch (Exception e) {
Log.e("AffdexMe", e.getMessage());
}
}
detector = null; //setting detector to null will allow startCamera() to recreate the detector object when the application is reopened.
}
/**
* We use the SharedPreferences object to save application settings.
**/
public void saveApplicationSettings() {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean("fps", isFPSVisible);
editor.putBoolean("track", drawingView.getDrawPointsEnabled());
editor.putInt("rate", detectorProcessRate);
editor.commit();
}
public void fps_checkbox_click(View view) {
setFPSVisible(((CheckBox) view).isChecked());
}
public void tracking_checkbox_click(View view) {
setTrackPoints(((CheckBox) view).isChecked());
}
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
/**
* When a user has selected the Edit box to change the number of frames the detector processes per second
* and presses the 'DONE' button, the below block will be executed.
* */
if (actionId == EditorInfo.IME_ACTION_DONE) {
int parsedInt = 0;
try {
parsedInt = Integer.parseInt(v.getText().toString());
} catch (Exception e) {
v.setText(String.valueOf(detectorProcessRate));
return false;
}
if (parsedInt > 0) {
detectorProcessRate = parsedInt;
detector.setMaxProcessRate(detectorProcessRate);
resetFPSCalculations(); //reset FPS variables, since changing the process rate should change the FPS.
} else {
v.setText(String.valueOf(detectorProcessRate));
}
}
return false; //return false regardless, so Android closes the keyboard when user presses 'DONE'
}
/**
* When the user taps the screen, hide the menu if it is visible and show it if it is hidden.
* **/
void setMenuVisible(boolean b){
isMenuVisible = b;
if (b) {
menuLayout.setVisibility(View.VISIBLE);
//We display the navigation bar again
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
else {
InputMethodManager imm = (InputMethodManager)getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(fpsEditText.getWindowToken(), 0);
//We hide the navigation bar
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE);
menuLayout.setVisibility(View.INVISIBLE);
}
}
/**
* If a user has a phone with a physical menu button, they may expect it to toggle
* the menu, so we add that functionality.
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU) {
setMenuVisible(!isMenuVisible);
return true;
}
return super.onKeyDown(keyCode, event);
}
//If the user selects to have facial tracking dots drawn, inform our drawing thread.
void setTrackPoints(boolean b) {
drawingView.setDrawPointsEnabled(b);
}
void setFPSVisible(boolean b) {
isFPSVisible = b;
if (b) {
fpsName.setVisibility(View.VISIBLE);
fpsPct.setVisibility(View.VISIBLE);
} else {
fpsName.setVisibility(View.INVISIBLE);
fpsPct.setVisibility(View.INVISIBLE);
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
setMenuVisible(!isMenuVisible);
}
return false;
}
}

View File

@ -0,0 +1,115 @@
package com.affectiva.affdexme;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.View;
import java.lang.Math;
/**
* The MetricView class is used to display metric scores on top of colored bars whose color depend on the score.
*/
public class MetricView extends View {
float midX = 0; //coordinates of the center of the view
float midY = 0;
float halfWidth = 50;//default width and height of view
float height = 10;
String text = ""; //score in text format
Paint textPaint;
Paint boxPaint;
float left = 0; //colored bar is drawn using left,right,top, and height variables
float right = 0;
float top = 0;
float textBottom = 0; //tells our view where to draw the baseline of the font
public MetricView(Context context) {
super(context);
initResources(context,null);
}
public MetricView(Context context, AttributeSet attrs) {
super(context,attrs);
initResources(context,attrs);
}
public MetricView(Context context, AttributeSet attrs, int styleID){
super(context, attrs, styleID);
initResources(context,attrs);
}
void initResources(Context context, AttributeSet attrs) {
boxPaint = new Paint();
boxPaint.setColor(Color.GREEN);
textPaint = new Paint();
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextAlign(Paint.Align.CENTER);
int textSize = 15; //default text size value
//load and parse XML attributes
if (attrs != null) {
TypedArray a = getContext().obtainStyledAttributes(attrs,R.styleable.custom_attributes,0,0);
textPaint.setColor(a.getColor(R.styleable.custom_attributes_textColor, Color.BLACK));
textSize = a.getDimensionPixelSize(R.styleable.custom_attributes_textSize, textSize);
textPaint.setTextSize(textSize);
halfWidth = a.getDimensionPixelSize(R.styleable.custom_attributes_barLength,100)/2;
a.recycle();
} else {
textPaint.setColor(Color.BLACK);
textPaint.setTextSize(textSize);
}
/**
* We set the desired height of the view to be as large as our text.
* We also offset the bottom line at which our text is drawn, to give the appearance
* that the text is centered vertically.
*/
height = textSize;
textBottom = height - 5;
}
public void setTypeface(Typeface face) {
textPaint.setTypeface(face);
}
public void setScore(float s){
text = String.format("%.0f%%", s); //change the text of the view
left = midX - (halfWidth * (s / 100)); //change the coordinates at which the colored bar will be drawn
right = midX + (halfWidth * (s / 100));
invalidate(); //instruct Android to re-draw our view, now that the text has changed
}
/**
* set our view to be the minimum of the sizes that Android will allow and our desired sizes
* **/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension((int)Math.min(MeasureSpec.getSize(widthMeasureSpec), halfWidth *2), (int)Math.min(MeasureSpec.getSize(heightMeasureSpec),height));
}
@Override
protected void onSizeChanged(int w, int h, int oldW, int oldH) {
super.onSizeChanged(w,h,oldW,oldH);
midX = w/2;
midY = h/2;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//draws the colored bar that appears behind our score
canvas.drawRect(left,top,right,height, boxPaint);
//draws the score
canvas.drawText(text,midX , textBottom, textPaint);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -0,0 +1,51 @@
<RelativeLayout 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" tools:context=".MainActivity" android:focusable="true"
android:focusableInTouchMode="true"
android:id="@+id/main_layout"
android:keepScreenOn="true"
android:layout_gravity="center"
>
<SurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:id="@+id/camera_preview"
/>
<com.affectiva.affdexme.DrawingView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:id="@+id/drawing_view"/>
<include layout="@layout/metric_layout"
android:id="@+id/metric_view_group"
/>
<include layout="@layout/menu_layout"
android:layout_below="@id/metric_view_group"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/progress_bar_cover"
android:background="@color/black">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@android:style/Widget.DeviceDefault.ProgressBar"
android:layout_centerInParent="true"
android:indeterminate="true"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/not_found"
android:padding="20sp"
android:textColor="#CCCCCC"
android:background="@color/black"
android:gravity="center"
android:id="@+id/not_found_textview"
android:visibility="gone"
android:textSize="20sp"/>
</RelativeLayout>
</RelativeLayout>

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/affdexme_menu"
android:background="@color/transparent_overlay"
android:visibility="invisible"
>
<View
android:id="@+id/menu_border"
android:layout_width="fill_parent"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:layout_height="1dp"
android:background="@color/letter_gray"/>
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/menu_border"
android:id="@+id/menu_table_layout"
android:stretchColumns="0,1">
<TableRow>
<CheckBox
style="@style/optionsStyle"
android:layout_gravity="center"
android:text="@string/show_fps"
android:id="@+id/fps_checkbox"
android:onClick="fps_checkbox_click"
/>
<CheckBox
style="@style/optionsStyle"
android:layout_gravity="center"
android:text="@string/show_tracking"
android:id="@+id/tracking_checkbox"
android:onClick="tracking_checkbox_click"
/>
</TableRow>
</TableLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="@id/menu_table_layout">
<TextView
style="@style/optionsStyle"
android:text="@string/processed_frames_per_second"
android:id="@+id/fps_edittext_name"
/>
<EditText
style="@style/optionsStyle"
android:inputType="number"
android:ems="3"
android:maxLength="2"
android:id="@+id/fps_edittext"
android:imeOptions="actionDone" />
</LinearLayout>
</RelativeLayout>

View File

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:affdex="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:layout_height="@dimen/metric_viewgroup"
android:layout_width="match_parent"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:background="@color/transparent_overlay"
android:paddingBottom="@dimen/bottom_padding"
>
<!-- Logo-->
<ImageView
android:layout_height="wrap_content"
android:layout_width="@dimen/image_width"
android:layout_centerInParent="true"
android:src="@drawable/affectiva_logo_clear_background"
android:id="@+id/affectiva_logo" />
<!-- Left Metrics-->
<LinearLayout
android:orientation="vertical"
android:paddingLeft="@dimen/metric_panel_padding"
android:layout_alignParentLeft="true"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="@+id/left_metrics">
<TextView
style="@style/metricName"
android:text="@string/smile"
android:id="@+id/smile_name"
/>
<com.affectiva.affdexme.MetricView
style="@style/metricPct"
android:id="@+id/smile_pct" />
<TextView
style="@style/metricName"
android:text="@string/brow_raise"
android:id="@+id/brow_raise_name" />
<com.affectiva.affdexme.MetricView
style="@style/metricPct"
android:id="@+id/brow_raise_pct" />
<TextView
style="@style/metricName"
android:text="@string/brow_furrow"
android:id="@+id/brow_furrow_name" />
<com.affectiva.affdexme.MetricView
style="@style/metricPct"
android:id="@+id/brow_furrow_pct" />
</LinearLayout>
<!-- FPS Counter-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<TextView
style="@style/metricName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="right|bottom"
android:layout_weight="1"
android:id="@+id/fps_name"
android:text="@string/fps"
/>
<TextView
style="@style/metricPct"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left|bottom"
android:id="@+id/fps_value"
android:textSize="@dimen/pct_text_size"
android:layout_weight="1"
/>
</LinearLayout>
<!-- Right Metrics-->
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_alignParentRight="true"
android:paddingRight="@dimen/metric_panel_padding"
android:layout_height="match_parent"
android:id="@+id/right_metrics">
<TextView
style="@style/metricName"
android:text="@string/frown"
android:id="@+id/frown_name" />
<com.affectiva.affdexme.MetricView
style="@style/metricPct"
android:id="@+id/frown_pct" />
<TextView
style="@style/metricName"
android:text="@string/valence"
android:id="@+id/valence_name" />
<com.affectiva.affdexme.GradientMetricView
style="@style/metricPct"
android:id="@+id/valence_pct" />
<TextView
style="@style/metricName"
android:text="@string/engagement"
android:id="@+id/engagement_name" />
<com.affectiva.affdexme.MetricView
style="@style/metricPct"
android:id="@+id/engagement_pct" />
</LinearLayout>
</RelativeLayout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,10 @@
<resources>
<dimen name="name_text_size">24sp</dimen>
<dimen name="pct_text_size">14sp</dimen>
<dimen name="menu_text_size">18sp</dimen>
<dimen name="metric_view_bar_length">130dp</dimen>
<dimen name="bottom_padding">10dp</dimen>
<dimen name="metric_viewgroup">190dp</dimen>
<dimen name="image_width">180dp</dimen>
<dimen name="metric_panel_padding">15dp</dimen>
</resources>

View File

@ -0,0 +1,10 @@
<resources>
<dimen name="name_text_size">14sp</dimen>
<dimen name="pct_text_size">11sp</dimen>
<dimen name="menu_text_size">13sp</dimen>
<dimen name="metric_view_bar_length">80dp</dimen>
<dimen name="bottom_padding">5dp</dimen>
<dimen name="metric_viewgroup">130dp</dimen>
<dimen name="image_width">120dp</dimen>
<dimen name="metric_panel_padding">10dp</dimen>
</resources>

View File

@ -0,0 +1,10 @@
<resources>
<dimen name="name_text_size">12sp</dimen>
<dimen name="pct_text_size">9sp</dimen>
<dimen name="menu_text_size">12sp</dimen>
<dimen name="metric_view_bar_length">70dp</dimen>
<dimen name="bottom_padding">5dp</dimen>
<dimen name="metric_viewgroup">130dp</dimen>
<dimen name="image_width">100dp</dimen>
<dimen name="metric_panel_padding">8dp</dimen>
</resources>

View File

@ -0,0 +1,11 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="name_text_size">28sp</dimen>
<dimen name="pct_text_size">18sp</dimen>
<dimen name="menu_text_size">23sp</dimen>
<dimen name="metric_view_bar_length">140dp</dimen>
<dimen name="bottom_padding">15dp</dimen>
<dimen name="metric_viewgroup">220dp</dimen>
<dimen name="image_width">250dp</dimen>
<dimen name="metric_panel_padding">25dp</dimen>
</resources>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="custom_attributes">
<attr name="textSize" format="dimension" />
<attr name="textColor" format="color"/>
<attr name="barLength" format="dimension"/>
<attr name="textDepth" format="dimension"/>
</declare-styleable>
</resources>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="transparent_overlay">#55ffffff</color>
<color name="letter_gray">#514a40</color>
<color name="letter_orange">#ff8000</color>
<color name="black">#000000</color>
</resources>

View File

@ -0,0 +1,10 @@
<resources>
<dimen name="name_text_size">14sp</dimen>
<dimen name="pct_text_size">11sp</dimen>
<dimen name="menu_text_size">13sp</dimen>
<dimen name="metric_view_bar_length">80dp</dimen>
<dimen name="bottom_padding">5dp</dimen>
<dimen name="metric_viewgroup">140dp</dimen>
<dimen name="image_width">120dp</dimen>
<dimen name="metric_panel_padding">10dp</dimen>
</resources>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="metricName" >
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:gravity">center</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">@color/letter_orange</item>
<item name="android:shadowColor">#000000</item>
<item name="android:shadowDy">2</item>
<item name="android:shadowRadius">1</item>
<item name="android:layout_weight">1</item>
<item name="android:textSize">@dimen/name_text_size</item>
</style>
</resources>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="metricPct">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_gravity">center</item>
<item name="textColor">@color/letter_gray</item>
<item name="textSize">@dimen/pct_text_size</item>
<item name="barLength">@dimen/metric_view_bar_length</item>
</style>
</resources>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="optionsStyle" >
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">@color/letter_gray</item>
<item name="android:textSize">@dimen/menu_text_size</item>
<item name="android:textStyle">bold</item>
</style>
</resources>

View File

@ -0,0 +1,18 @@
<resources>
<string name="app_name">AffdexMe</string>
<string name="smile">SMILE</string>
<string name="brow_raise">BROW RAISE</string>
<string name="brow_furrow">BROW FURROW</string>
<string name="valence">VALENCE</string>
<string name="engagement">ENGAGEMENT</string>
<string name="frown">FROWN</string>
<string name="fps">FPS:</string>
<string name="show_fps">Show FPS</string>
<string name="show_tracking">Show Tracking</string>
<string name="processed_frames_per_second">Processed Frames Per Second: </string>
<string name="not_found">Sorry, AffdexMe requires the use of a front-facing camera, which was not found on your device.</string>
</resources>

View File

@ -0,0 +1,6 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="android:Theme.Holo.Light.NoActionBar">
<item name="android:windowBackground">@color/black</item>
</style>
</resources>

19
AffdexMe/build.gradle Normal file
View File

@ -0,0 +1,19 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}

View File

@ -0,0 +1,18 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

Binary file not shown.

View File

@ -0,0 +1,6 @@
#Wed Apr 10 15:27:10 PDT 2013
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip

164
AffdexMe/gradlew vendored Normal file
View File

@ -0,0 +1,164 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

90
AffdexMe/gradlew.bat vendored Normal file
View File

@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

1
AffdexMe/settings.gradle Normal file
View File

@ -0,0 +1 @@
include ':app'

28
README.md Normal file
View File

@ -0,0 +1,28 @@
#Sample App for Affdex SDK for Android
Welcome to our repository on GitHub! Here you will find example code to get you started with our Affdex SDK for Android and begin emotion-enabling you own app!
AffdexMe
--------
*Dependencies*
- Affectiva Android SDK (visit http://www.affectiva.com/solutions/apis-sdks/)
**AffdexMe** is an app that demonstrates the use of the Affectiva Android SDK. It uses the front-facing camera on your Android device to view, process and analyze live video of your face. Start the app and you will see your own face on the screen and metrics describing your expressions. Tapping the screen will bring up a menu with options to display the Processed Frames Per Second metric, display facial tracking points, and control the rate at which frames are processed by the SDK.
Most of the methods in this file control the application's UI. Therefore, if you are just interested in learning how the Affectiva SDK works, you will find the calls relevant to the use of the SDK in the startCamera() and stopCamera() methods, as well as the onImageResults() method.
In order to use this project, you will need to:
- Obtain the Affectiva Android SDK
- Copy the contents of the SDK's assets folder into this project's assets folder
- Copy the contents of the SDK's libs folder into this project's libs folder
- Copy the armeabi-v7a folder (found in the SDK libs folder) into this project's jniLibs folder
- Add your license file to the /assets/Affdex folder and uncomment the line in the startCamera() method which specifies your license file path
- Build the project
- Run the app on an Android device with a front-facing camera
Copyright (c) 2014 Affectiva. All rights reserved.
See the comment section at the top of the MainActivity.java file for more information.