Now using dots to show emos
This commit is contained in:
parent
f26802be79
commit
ffe51902a3
8 changed files with 200 additions and 38 deletions
|
@ -13,7 +13,8 @@
|
|||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
android:theme="@style/AppTheme"
|
||||
android:hardwareAccelerated="true">
|
||||
|
||||
<activity
|
||||
android:name=".GamingActivity"
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.rubenvandeven.emotionhero;
|
||||
|
||||
import android.graphics.Color;
|
||||
|
||||
import com.affectiva.android.affdex.sdk.detector.Face;
|
||||
|
||||
/**
|
||||
|
@ -35,4 +37,26 @@ public enum Emotion {
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getColor()
|
||||
{
|
||||
switch (this) {
|
||||
case ANGER:
|
||||
return Color.RED;
|
||||
case CONTEMPT:
|
||||
return Color.BLUE;
|
||||
case DISGUST:
|
||||
return Color.GREEN;
|
||||
case FEAR:
|
||||
return Color.MAGENTA;
|
||||
case JOY:
|
||||
return Color.YELLOW;
|
||||
case SADNESS:
|
||||
return Color.CYAN;
|
||||
case SURPRISE:
|
||||
return Color.LTGRAY;
|
||||
}
|
||||
|
||||
return Color.BLACK;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import android.view.MotionEvent;
|
|||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
@ -114,9 +115,14 @@ public class GamingActivity extends AppCompatActivity implements Detector.ImageL
|
|||
int previewHeight = 0;
|
||||
|
||||
Scenario currentScenario;
|
||||
ScenarioView scenarioView;
|
||||
|
||||
boolean has_camera_permission = false;
|
||||
|
||||
Button restartButton;
|
||||
|
||||
TextView paramText;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -128,6 +134,16 @@ public class GamingActivity extends AppCompatActivity implements Detector.ImageL
|
|||
mContentView = (TextView) findViewById(R.id.fullscreen_content);
|
||||
RelativeLayout videoLayout = (RelativeLayout) findViewById(R.id.video_layout);
|
||||
|
||||
// paramText = (TextView) findViewById(R.id.paramText);
|
||||
restartButton = (Button) findViewById(R.id.restartButton);
|
||||
restartButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
finish();
|
||||
startActivity(getIntent());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Set up the user interaction to manually show or hide the system UI.
|
||||
mContentView.setOnClickListener(new View.OnClickListener() {
|
||||
|
@ -169,6 +185,7 @@ public class GamingActivity extends AppCompatActivity implements Detector.ImageL
|
|||
}
|
||||
};
|
||||
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
// RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(1,1);
|
||||
params.addRule(RelativeLayout.CENTER_IN_PARENT,RelativeLayout.TRUE);
|
||||
cameraPreview.setLayoutParams(params);
|
||||
videoLayout.addView(cameraPreview,0);
|
||||
|
@ -176,7 +193,6 @@ public class GamingActivity extends AppCompatActivity implements Detector.ImageL
|
|||
|
||||
currentScenario = new ScenarioAnger();
|
||||
|
||||
ScenarioView scenarioView;
|
||||
scenarioView = new ScenarioView(this, currentScenario);
|
||||
RelativeLayout.LayoutParams scenarioViewParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
videoLayout.addView(scenarioView, 1, scenarioViewParams);
|
||||
|
@ -242,8 +258,14 @@ public class GamingActivity extends AppCompatActivity implements Detector.ImageL
|
|||
detector.setLicensePath("emotionhero_dev.license");
|
||||
detector.setMaxProcessRate(10);
|
||||
detector.setDetectAllEmotions(true);
|
||||
detector.setDetectAllAppearances(false);
|
||||
detector.setDetectAllEmojis(false);
|
||||
detector.setDetectAllExpressions(false);
|
||||
detector.setMaxProcessRate(12);
|
||||
|
||||
detector.setImageListener(this);
|
||||
detector.setOnCameraEventListener(this);
|
||||
detector.setFaceListener(this);
|
||||
}
|
||||
|
||||
detector.start();
|
||||
|
@ -304,6 +326,7 @@ public class GamingActivity extends AppCompatActivity implements Detector.ImageL
|
|||
{
|
||||
mContentView.setText(String.format("LEVEL ENDED\nScore: %.2f", currentScenario.getTotalScore()));
|
||||
stopDetector();
|
||||
restartButton.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
}
|
||||
if (list == null)
|
||||
|
@ -313,7 +336,19 @@ public class GamingActivity extends AppCompatActivity implements Detector.ImageL
|
|||
} else {
|
||||
Face face = list.get(0);
|
||||
currentScenario.validateFaceOnTime(face, timestamp);
|
||||
scenarioView.setCurrentAttributeScoresForFace(face);
|
||||
mContentView.setText(String.format("SCORE \n%.2f",currentScenario.getTotalScore()));
|
||||
|
||||
// String paramString = "";
|
||||
// paramString += "Anger " + String.format("%02.2f", face.emotions.getAnger()) + "%\n";
|
||||
// paramString += "Contempt " + String.format("%02.2f", face.emotions.getContempt()) + "%\n";
|
||||
// paramString += "Disgust " + String.format("%02.2f", face.emotions.getDisgust()) + "%\n";
|
||||
// paramString += "Fear " + String.format("%02.2f", face.emotions.getFear()) + "%\n";
|
||||
// paramString += "Joy " + String.format("%02.2f", face.emotions.getJoy()) + "%\n";
|
||||
// paramString += "Sadness " + String.format("%02.2f", face.emotions.getSadness()) + "%\n";
|
||||
// paramString += "Surprise " + String.format("%02.2f", face.emotions.getSurprise()) + "%\n";
|
||||
//
|
||||
// paramText.setText(paramString);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -360,11 +395,13 @@ public class GamingActivity extends AppCompatActivity implements Detector.ImageL
|
|||
public void onFaceDetectionStarted()
|
||||
{
|
||||
mContentView.setText("START!");
|
||||
currentScenario.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFaceDetectionStopped()
|
||||
{
|
||||
mContentView.setText("No face found...");
|
||||
// paramText.setText("No face found");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,42 +126,25 @@ abstract public class Scenario {
|
|||
return timestamp <= duration;
|
||||
}
|
||||
|
||||
public void drawOnCanvas(Canvas canvas) {
|
||||
// canvas;
|
||||
Paint paint = new Paint();
|
||||
paint.setColor(Color.RED);
|
||||
float height = (float) canvas.getHeight();
|
||||
float pix_per_sec = height / duration;
|
||||
public ArrayList<Target> getTargets() {
|
||||
return targets;
|
||||
}
|
||||
|
||||
float sec_height = canvas.getHeight() * (float) 0.2; // each second is 20% of canvas height
|
||||
|
||||
float diff_y;
|
||||
/**
|
||||
* Get the time within the scenario (so since start() has been called)
|
||||
*/
|
||||
public float getTime() {
|
||||
// if not started, don't move the labels, if started, move them by diff_y
|
||||
if(startTime == 0) {
|
||||
diff_y = 0;
|
||||
start();
|
||||
return 0;
|
||||
} else {
|
||||
float diff_t = ((System.currentTimeMillis() - startTime)) / (float) 1000;
|
||||
Log.d("TIME", Float.toString(diff_t));
|
||||
if(diff_t > duration) { // never larger than scenario duration
|
||||
diff_t = duration;
|
||||
return duration;
|
||||
}
|
||||
diff_y = sec_height * diff_t;
|
||||
return diff_t;
|
||||
}
|
||||
|
||||
// bottom at 80%;
|
||||
float bottomline_height = height * (float) 0.8;
|
||||
|
||||
canvas.drawLine(0, bottomline_height, canvas.getWidth(), bottomline_height, paint);
|
||||
canvas.drawLine(0, bottomline_height+1, canvas.getWidth(), bottomline_height+1, paint);
|
||||
|
||||
for(Target target: targets) {
|
||||
float y_pos = bottomline_height - (target.timestamp * sec_height);
|
||||
String target_text = target.emotion.toString() + " " + target.value + "%";
|
||||
canvas.drawText(target_text, canvas.getWidth()/2, y_pos + diff_y , paint);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void start()
|
||||
|
@ -169,6 +152,8 @@ abstract public class Scenario {
|
|||
startTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
// TODO: create a 'tick' that checks all current values with requirements and increases the timer etc
|
||||
// TODO: ... if scenario is running. This internal times makes it easier to pause etc.
|
||||
}
|
||||
|
||||
class ScenarioAnger extends Scenario{
|
||||
|
@ -180,5 +165,9 @@ class ScenarioAnger extends Scenario{
|
|||
setTarget(Emotion.ANGER, 40, 3);
|
||||
setTarget(Emotion.ANGER, 70, 4);
|
||||
setTarget(Emotion.ANGER, 100, 5);
|
||||
setTarget(Emotion.JOY, 100, 8);
|
||||
setTarget(Emotion.ANGER, 100, 10);
|
||||
setTarget(Emotion.JOY, 100, 15);
|
||||
setTarget(Emotion.ANGER, 100, 20);
|
||||
}
|
||||
}
|
|
@ -2,13 +2,20 @@ package com.rubenvandeven.emotionhero;
|
|||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
import com.affectiva.android.affdex.sdk.detector.Face;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by ruben on 16/08/16.
|
||||
*/
|
||||
|
@ -19,6 +26,12 @@ public class ScenarioView extends SurfaceView implements SurfaceHolder.Callback
|
|||
|
||||
private Scenario _scenario;
|
||||
|
||||
/**
|
||||
* The scorres in this moment, as to draw them on the screen.
|
||||
* Indexes are Emotion ordinals
|
||||
*/
|
||||
private Map<Emotion, Float> currentAttributeScores = new HashMap<>();
|
||||
|
||||
|
||||
// see: http://blog.danielnadeau.io/2012/01/android-canvas-beginners-tutorial.html
|
||||
class PanelThread extends Thread {
|
||||
|
@ -69,15 +82,92 @@ public class ScenarioView extends SurfaceView implements SurfaceHolder.Callback
|
|||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
//do drawing stuff here.
|
||||
// Log.e("TEST2", "Jaa!");
|
||||
_scenario.drawOnCanvas(canvas);
|
||||
|
||||
float height = canvas.getHeight();
|
||||
float width = canvas.getWidth();
|
||||
|
||||
// bottom at 80%;
|
||||
float bottomline_height = height * (float) 0.8;
|
||||
|
||||
|
||||
// draw current scores:
|
||||
float used_width = (float) 0.8; // 0.7: only use center
|
||||
float padding_left = canvas.getWidth() * (1-used_width) / 2;
|
||||
float step_y = (canvas.getWidth() * used_width) / Emotion.values().length;
|
||||
float max_ball_radius = step_y * (float) 0.8 / 2;
|
||||
|
||||
|
||||
// bottom at 80%;
|
||||
Paint mainPaint = new Paint();
|
||||
mainPaint.setColor(Color.GRAY);
|
||||
|
||||
|
||||
Paint linePaint = new Paint();
|
||||
linePaint.setColor(Color.GRAY);
|
||||
linePaint.setStrokeWidth(5);
|
||||
// canvas.drawLine(0, bottomline_height, width, bottomline_height, linePaint);
|
||||
|
||||
for(Emotion emotion: Emotion.values())
|
||||
{
|
||||
float value = 0;
|
||||
if(currentAttributeScores.containsKey(emotion)) {
|
||||
value = currentAttributeScores.get(emotion);
|
||||
}
|
||||
if(value < 5) {
|
||||
value = 5;
|
||||
}
|
||||
Paint emoPaint = new Paint();
|
||||
Paint emoPaintOutline = new Paint();
|
||||
emoPaint.setColor(emotion.getColor());
|
||||
emoPaintOutline.setColor(emotion.getColor());
|
||||
emoPaintOutline.setStyle(Paint.Style.STROKE);
|
||||
emoPaintOutline.setStrokeWidth(2);
|
||||
|
||||
float cx = padding_left + (step_y * emotion.ordinal() + step_y / 2);
|
||||
float cy = bottomline_height;
|
||||
|
||||
|
||||
canvas.drawCircle(cx, cy, max_ball_radius, mainPaint);
|
||||
canvas.drawCircle(cx, cy, max_ball_radius, emoPaintOutline);
|
||||
|
||||
canvas.drawCircle(cx, cy, max_ball_radius * value/100, emoPaint);
|
||||
|
||||
|
||||
canvas.drawText(emotion.toString(), cx, cy + max_ball_radius * (float) 1.3, emoPaint);
|
||||
}
|
||||
|
||||
// Draw targets:
|
||||
float sec_height = height * (float) 0.2; // each second is 20% of canvas height
|
||||
// current moved position
|
||||
float diff_y = sec_height * _scenario.getTime();
|
||||
|
||||
for(Scenario.Target target: _scenario.getTargets()) {
|
||||
Paint emoPaint = new Paint();
|
||||
emoPaint.setColor(target.emotion.getColor());
|
||||
|
||||
float cy = bottomline_height - (target.timestamp * sec_height) + diff_y;
|
||||
|
||||
float cx = padding_left + (step_y * target.emotion.ordinal() + step_y / 2);
|
||||
|
||||
canvas.drawCircle(cx, cy, max_ball_radius * target.value/100, emoPaint);
|
||||
|
||||
// String target_text = target.emotion.toString() + " " + target.value + "%";
|
||||
// canvas.drawText(target_text, cx, y_pos + diff_y , emoPaint);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setCurrentAttributeScoresForFace(Face face)
|
||||
{
|
||||
for(Emotion emotion: Emotion.values()) {
|
||||
currentAttributeScores.put(emotion, emotion.getValueFromFace(face));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -105,6 +195,4 @@ public class ScenarioView extends SurfaceView implements SurfaceHolder.Callback
|
|||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,16 @@
|
|||
<!--android:layout_height="match_parent" />-->
|
||||
|
||||
|
||||
<!--<TextView-->
|
||||
<!--android:text="No face found"-->
|
||||
<!--android:layout_width="wrap_content"-->
|
||||
<!--android:layout_height="wrap_content"-->
|
||||
<!--android:id="@+id/paramText"-->
|
||||
<!--android:textColor="@android:color/white"-->
|
||||
<!--android:layout_marginLeft="10dp"-->
|
||||
<!--android:layout_marginTop="10dp"-->
|
||||
<!--android:fontFamily="monospace" />-->
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
@ -62,10 +72,13 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<SurfaceView
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="1dp"
|
||||
android:id="@+id/surfaceView" />
|
||||
<Button
|
||||
android:text="@string/restart"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/restartButton"
|
||||
android:layout_gravity="center_vertical|center_horizontal"
|
||||
android:visibility="gone" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
|
|
|
@ -6,4 +6,13 @@
|
|||
<color name="colorScenarioLine">#FF0000</color>
|
||||
|
||||
<color name="black_overlay">#66000000</color>
|
||||
|
||||
<!--TODO: implement in Emotion.java-->
|
||||
<color name="emotion_anger">#ff0000</color>
|
||||
<color name="emotion_contempt">#0000ff</color>
|
||||
<color name="emotion_disgust">#009000</color>
|
||||
<color name="emotion_fear">#ffff00</color>
|
||||
<color name="emotion_joy">#ff00ff</color>
|
||||
<color name="emotion_sadness">#ff8c00</color>
|
||||
<color name="emotion_surprise">#00aaff</color>
|
||||
</resources>
|
||||
|
|
|
@ -4,4 +4,5 @@
|
|||
<string name="dummy_button">Dummy Button</string>
|
||||
<string name="dummy_content">initialising…</string>
|
||||
<string name="camera_required">The camera permission is required. Please start again</string>
|
||||
<string name="restart">Restart</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue