Skip to content

Commit

Permalink
Integrate with machine learning library [4-8h] elimu-ai#4
Browse files Browse the repository at this point in the history
Add activity for drawing numbers [8-16h] elimu-ai#13
  • Loading branch information
sladomic committed May 8, 2017
1 parent aee9579 commit fc6d547
Show file tree
Hide file tree
Showing 39 changed files with 1,342 additions and 1,246 deletions.
Binary file removed app/assets/engines/english
Binary file not shown.
Binary file removed app/assets/engines/numbers
Binary file not shown.
Binary file removed app/assets/engines/symbols
Binary file not shown.
21 changes: 8 additions & 13 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ android {
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}

compileOptions {
encoding = "UTF-8"
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}

buildTypes {
release {
minifyEnabled false
Expand All @@ -24,27 +30,16 @@ android {
}
}

repositories {
mavenLocal()
maven {
url "http://archiva.educativo.eu:8081/repository/internal/"
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})



compile 'org.literacyapp:literacyapp-model:1.1.33'
compile 'org.literacyapp:contentprovider:1.0.5'
compile 'org.tensorflow:libandroid_tensorflow_inference_java:1.0.1'
compile 'org.greenrobot:greendao:3.2.0'
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support:cardview-v7:23.4.0'
compile 'com.android.support:support-v4:23.4.0'
compile 'org.encog:encog-core:3.1.0'
testCompile 'junit:junit:4.12'
}
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package="org.literacyapp.handwriting">

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<application
android:name="HandwritingApplication"
Expand All @@ -21,6 +22,8 @@

<activity
android:name=".WriteLetterActivity" />
<activity
android:name=".WriteNumberActivity" />
<activity
android:name=".FinalActivity" />
</application>
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/assets/emnist_digits_labels.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
0
1
2
3
4
5
6
7
8
9
Binary file added app/src/main/assets/expert-graph.pb
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public void onCompletion(MediaPlayer mediaPlayer) {
HandwritingApplication handwritingApplication = (HandwritingApplication) getApplicationContext();
handwritingApplication.setCompletionCounter(handwritingApplication.getCompletionCounter() + 1);
if (handwritingApplication.getCompletionCounter() < 5){
Intent intent = new Intent(getApplicationContext(), WriteLetterActivity.class);
Intent intent = new Intent(getApplicationContext(), WriteNumberActivity.class);
startActivity(intent);
} else {
finishAffinity();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ protected void onStart() {

ContentProvider.initializeDb(this);

Intent intent = new Intent(this, WriteLetterActivity.class);
Intent intent = new Intent(this, WriteNumberActivity.class);
startActivity(intent);

finish();
Expand Down
103 changes: 60 additions & 43 deletions app/src/main/java/org/literacyapp/handwriting/WriteLetterActivity.java
Original file line number Diff line number Diff line change
@@ -1,50 +1,54 @@
package org.literacyapp.handwriting;

import android.content.res.Resources;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;

import org.literacyapp.contentprovider.ContentProvider;
import org.literacyapp.contentprovider.dao.AudioDao;
import org.literacyapp.contentprovider.dao.DaoSession;
import org.literacyapp.contentprovider.dao.LetterDao;
import org.literacyapp.contentprovider.model.content.Letter;
import org.literacyapp.contentprovider.model.content.multimedia.Audio;
import org.literacyapp.contentprovider.util.MultimediaHelper;
import org.literacyapp.handwriting.entity.Engine;
import org.literacyapp.handwriting.entity.LanguageProcessor;
import org.literacyapp.handwriting.entity.LetterBuffer;
import org.literacyapp.handwriting.lang.EnglishProcessor;
import org.literacyapp.handwriting.ocr.Ocr;
import org.literacyapp.handwriting.ocr.Classifier;
import org.literacyapp.handwriting.ocr.TensorFlowImageClassifier;
import org.literacyapp.handwriting.util.MediaPlayerHelper;
import org.literacyapp.handwriting.view.DrawModel;
import org.literacyapp.handwriting.view.DrawView;
import org.literacyapp.handwriting.view.DrawViewOnTouchListener;

import java.io.File;
import java.lang.reflect.Constructor;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class WriteLetterActivity extends AppCompatActivity {
public class WriteLetterActivity extends AppCompatActivity implements View.OnTouchListener {

private Ocr ocr;
private AudioDao audioDao;
private Letter letter;

private LanguageProcessor langProc;
private static final int PIXEL_WIDTH = 28;

private LetterBuffer lBuffer;
private DrawModel mModel;
private DrawView mDrawView;

private AudioDao audioDao;
private Letter letter;
private static final int INPUT_SIZE = 28;
private static final String INPUT_NAME = "input";
private static final String OUTPUT_NAME = "output";

private static final String MODEL_FILE = "file:///android_asset/letters.pb";
private static final String LABEL_FILE =
"file:///android_asset/letters.txt";

private Classifier classifier;

@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i(getClass().getName(), "onCreate");
super.onCreate(savedInstanceState);

setContentView(R.layout.activity_write_letter);

ocr = (Ocr) findViewById(R.id.writePad);
setContentView(R.layout.activity_write);

DaoSession daoSession = ContentProvider.getDaoSession();
audioDao = daoSession.getAudioDao();
Expand All @@ -54,27 +58,43 @@ protected void onCreate(Bundle savedInstanceState) {
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(letter.getText());
Log.i(getClass().getName(), "letter: " + letter);
// Set on listener to restart the drawing with a blank screen
textView.setOnTouchListener(this);

initTensorFlowAndLoadModel();

mModel = new DrawModel(PIXEL_WIDTH, PIXEL_WIDTH);

mDrawView = (DrawView) findViewById(R.id.view_draw);
mDrawView.setModel(mModel);
DrawViewOnTouchListener listener = new DrawViewOnTouchListener(mDrawView, mModel, classifier, letter.getText(), getApplicationContext());
mDrawView.setOnTouchListener(listener);
}

@Override
protected void onStart() {
Log.i(getClass().getName(), "onStart");
super.onStart();
private void initTensorFlowAndLoadModel() {
Log.i(getClass().getName(), "initTensorFlowAndLoadModel");

try {
loadProcessor(EnglishProcessor.class.getName());
} catch (Exception e) {
Log.e(getClass().getName(), null, e);
classifier = TensorFlowImageClassifier.create(
getAssets(),
MODEL_FILE,
LABEL_FILE,
INPUT_SIZE,
INPUT_NAME,
OUTPUT_NAME);
Log.d(getClass().getName(), "Load Success");
} catch (final Exception e) {
throw new RuntimeException("Error initializing TensorFlow!", e);
}

setDelay(500);
}

@Override
protected void onResume() {
Log.i(getClass().getName(), "onResume");
super.onResume();

mDrawView.onResume();

MediaPlayer mediaPlayer = MediaPlayerHelper.playInstructionSound(getApplicationContext());
if (mediaPlayer != null){
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
Expand All @@ -86,20 +106,17 @@ public void onCompletion(MediaPlayer mediaPlayer) {
}
}

private void loadProcessor(String classname) throws Exception {
Log.i(getClass().getName(), "loadProcessor");

Class<LanguageProcessor> c = (Class<LanguageProcessor>) Class.forName(classname);
Constructor<LanguageProcessor> ct = c.getConstructor(Engine.class);

langProc = ct.newInstance(ocr.getEngine());
lBuffer = new LetterBuffer(langProc);
ocr.loadEngine(langProc, lBuffer);
@Override
protected void onPause() {
super.onPause();
mDrawView.onPause();
}

private void setDelay(long delay) {
Log.i(getClass().getName(), "setDelay");

ocr.setDelay(delay);
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
mModel.clear();
mDrawView.reset();
mDrawView.invalidate();
return true;
}
}
119 changes: 119 additions & 0 deletions app/src/main/java/org/literacyapp/handwriting/WriteNumberActivity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package org.literacyapp.handwriting;

import android.media.MediaPlayer;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;

import org.literacyapp.contentprovider.ContentProvider;
import org.literacyapp.contentprovider.dao.AudioDao;
import org.literacyapp.contentprovider.dao.DaoSession;
import org.literacyapp.contentprovider.model.content.Number;
import org.literacyapp.handwriting.ocr.Classifier;
import org.literacyapp.handwriting.ocr.TensorFlowImageClassifier;
import org.literacyapp.handwriting.util.MediaPlayerHelper;
import org.literacyapp.handwriting.view.DrawModel;
import org.literacyapp.handwriting.view.DrawView;
import org.literacyapp.handwriting.view.DrawViewOnTouchListener;

import java.util.List;

public class WriteNumberActivity extends AppCompatActivity implements View.OnTouchListener {

private AudioDao audioDao;
private Number number;

private static final int PIXEL_WIDTH = 28;

private DrawModel mModel;
private DrawView mDrawView;

private static final int INPUT_SIZE = 28;
private static final String INPUT_NAME = "input";
private static final String OUTPUT_NAME = "output";

private static final String MODEL_FILE = "file:///android_asset/expert-graph.pb";
private static final String LABEL_FILE =
"file:///android_asset/emnist_digits_labels.txt";

private Classifier classifier;

@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i(getClass().getName(), "onCreate");
super.onCreate(savedInstanceState);

setContentView(R.layout.activity_write);

DaoSession daoSession = ContentProvider.getDaoSession();
audioDao = daoSession.getAudioDao();

List<Number> unlockedNumbers = ContentProvider.getUnlockedNumbers();
number = unlockedNumbers.get((int)(Math.random() * unlockedNumbers.size()));
Log.i(getClass().getName(), "number: " + number);
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(number.getValue().toString());
// Set on listener to restart the drawing with a blank screen
textView.setOnTouchListener(this);

initTensorFlowAndLoadModel();

mModel = new DrawModel(PIXEL_WIDTH, PIXEL_WIDTH);

mDrawView = (DrawView) findViewById(R.id.view_draw);
mDrawView.setModel(mModel);
DrawViewOnTouchListener listener = new DrawViewOnTouchListener(mDrawView, mModel, classifier, number.getValue().toString(), getApplicationContext());
mDrawView.setOnTouchListener(listener);
}

private void initTensorFlowAndLoadModel() {
Log.i(getClass().getName(), "initTensorFlowAndLoadModel");
try {
classifier = TensorFlowImageClassifier.create(
getAssets(),
MODEL_FILE,
LABEL_FILE,
INPUT_SIZE,
INPUT_NAME,
OUTPUT_NAME);
Log.d(getClass().getName(), "Load Success");
} catch (final Exception e) {
throw new RuntimeException("Error initializing TensorFlow!", e);
}
}

@Override
protected void onResume() {
Log.i(getClass().getName(), "onResume");
super.onResume();

mDrawView.onResume();

MediaPlayer mediaPlayer = MediaPlayerHelper.playInstructionSound(getApplicationContext());
if (mediaPlayer != null){
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
MediaPlayerHelper.playNumberSound(getApplicationContext(), audioDao, number);
}
});
}
}

@Override
protected void onPause() {
super.onPause();
mDrawView.onPause();
}

@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
mModel.clear();
mDrawView.reset();
mDrawView.invalidate();
return true;
}
}
Loading

0 comments on commit fc6d547

Please sign in to comment.