5

I am doing a sample work of handwritten letter detection through gestures of Android.It works well when I input 1 character at a time. That means when I write A on screen by gesture, the program recognizes it well(as I put it on gesture library earlier). As of now I code like this.

public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
    ArrayList<Prediction> predictions = gLib.recognize(gesture);

if (predictions.size() > 0 && predictions.get(0).score > 1.0) {

    String letter = predictions.get(0).name;  

    Toast.makeText(this, letter, Toast.LENGTH_SHORT).show();

    if(letter.contains("A"))  //when matches i print it to edittext
    edittext.setText("A");
    .
    .      //rest of stuff here like previous way
    .

    }
}

But my criteria isn't that. I want to recognize a word. I want to write a word at a time just like as. example

And during writing a word for each successful match the corresponding letter should be printed on edittext just like as.

A,N,D,R,O,I,D

So my question is how can I gain it? Is it possible to segment gestures(segment the word while writing)?Any working code example or links would be appreciated.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
ridoy
  • 6,274
  • 2
  • 29
  • 60

1 Answers1

4

If you write a word as separate letters (i.e. not cursive writing) as shown in the image given in the question. Then simply do this -

public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
    ArrayList<Prediction> predictions = gLib.recognize(gesture);

    if (predictions.size() > 0) {
        Prediction prediction = predictions.get(0);
        String letter = prediction.name;

        if (prediction.score > 1.0) {
            edittext.setText(edittext.getText().toString() + letter);
        }
    }
}

Which is essentially appending the new letter to the existing edittext string.

But if you are talking about cursive writing then it's a lot complicated. Here is some code which can track cursive writing.

public class MainActivity extends Activity {
    private Handler mHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @Override
    protected void onResume() {
        super.onResume();
        Tracker t = new Tracker();
        t.start();
    }

    @Override
    protected void onPause() {
        if (mHandler != null) 
            mHandler.getLooper().quit();
        super.onPause();
    }   

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_MOVE:
            if (mHandler != null) {
                Message msg = Message.obtain();
                msg.obj = event.getX() + "," + event.getY();
                mHandler.sendMessage(msg);
            }
            break;
        }
        return true;
    }

    private class Tracker extends Thread {
        private static final int LETTER_SIZE = 30;

        private GestureLibrary gLib;
        private ArrayList<GesturePoint> points;

        public Tracker() {
            points = new ArrayList<GesturePoint>();
            gLib = GestureLibraries.fromRawResource(MainActivity.this, R.raw.gestures);
            gLib.load();
        }

        @Override
        public void run() {
            Looper.prepare();
            mHandler = new Handler() {

                public void handleMessage(Message msg) {
                    String[] pos = String.valueOf(msg.obj).split(",");
                    points.add(new GesturePoint(Float.parseFloat(pos[0]), Float.parseFloat(pos[1]), System.currentTimeMillis()));

                    if (points.size() < LETTER_SIZE) return;

                    GestureStroke stroke = new GestureStroke(points);
                    Gesture gesture = new Gesture();
                    gesture.addStroke(stroke);

                    ArrayList<Prediction> predictions = gLib.recognize(gesture);
                    if (predictions.size() > 0) {
                        Prediction prediction = predictions.get(0);
                        String letter = prediction.name;

                        if (prediction.score > 1.0) {
                            Log.e("Found", letter);
                            points.clear();
                        }
                    }
                }
            };          
            Looper.loop();
        }
    }   
}

So basically we capture the touch positions and create a Gesture from it which pass to recognize() method of GestureLibrary. If a gesture is recognized then we print it and clear the touch positions so that a new letter can be recognized.

Sample Project: Cursive_eclipse_project.zip

appsroxcom
  • 2,821
  • 13
  • 17
  • I tried your code but nothing happens when i test it,so what wrong i am doing here?Do i need to add something with your 2nd code?I test this in emulator,not a real device,is it a problem?Moreover, there is no onGesturePerformed() in your 2nd code,so how the program recognize each letter when writing a word,can you please explain it clearly? – ridoy Apr 16 '13 at 20:21
  • I assume you have a gestures file in res/raw directory containing gestures for all the letters. The code doesn't use onGesturePerformed() since the gesture in our case is a word although R.raw.gestures only contains gestures for alphabets. So we create the Gesture ourselves based on the touch events and pass it to GestureLibrary.recognize(). The code works as i have tested it on emulator but make sure you have build a proper gestures file. Remember that you build the gestures using letters as you would write in cursive writing and not block letters. – appsroxcom Apr 17 '13 at 04:02
  • I think your solution is a good one,but perhaps i made a gamble there! Would you please mail me your test project? As it works right in your case,it will be very helpful for me if you send that. – ridoy Apr 17 '13 at 13:22
  • If you study the code you'll see there is no reason why it shouldn't work. Gesture recognition is done by GestureLibrary. We are just feeding it the Gestures manually instead of implementing OnGesturePerformedListener. I have provided a link to the eclipse project at the bottom of the answer. Run the application and check the Log for messages. – appsroxcom Apr 17 '13 at 14:51
  • Yes,it works now.A little thing,as you design it on a white layout,it will be good to give a color of the path when i write a word on the screen(currently it remains blank screen while i write),so where i need to change the code to give a color to better understand while writing? – ridoy Apr 17 '13 at 17:24
  • Awesome! For drawing of the path you may use the functionality of android.gesture.GestureOverlayView. But since we need to consume the touch events so you'll have to create a custom view inheriting from GestureOverlayView and override the dispatchTouchEvent(MotionEvent event). Then move all logic from Activity into the custom view and use this view in your layout file. – appsroxcom Apr 17 '13 at 19:24
  • If i use paint and canvas just like as http://stackoverflow.com/questions/12062497/drawing-to-canvas-ondraw-works-drawing-ontouchevent-doesnt ,does it work? – ridoy Apr 17 '13 at 20:19
  • Of course it will work. But again you have to create a custom view (i.e. DrawView) and implement its onDraw() and ... then use it in your layout. So why not just use GestureOverlayView? I thought of suggesting you the onDraw() approach which is the obvious choice but i guess using GestureOverlayView will be more neat. But it's up to you. – appsroxcom Apr 18 '13 at 04:10
  • Though i can't give colors on those path till now(as i am new in android),but i like your solution.So absolutely you are the bounty winner,i hope you will help if i can't make that color :) – ridoy Apr 22 '13 at 21:21
  • I have one more question, here you use touch points to recognize it by matching from library.But what happen if user writes a letter composed of 2/3 touch events?That means if i write letter A by 2 touch events,does your system works? – ridoy Apr 22 '13 at 21:32
  • I have updated the eclipse project so you may want to re-download it. Regarding your second question, that's the part for which you need to develop a heuristic algorithm for better gesture recognition. The current mechanism will return gestures continuously but your algorithm should be able to decide which one to accept. *LETTER_SIZE* and *points.clear()* are important parts of the equation. Btw, thanks for the bounty. – appsroxcom Apr 23 '13 at 03:43
  • hey appsroxcom,hope you are well..:),How can i show your Log.e("Found", letter) to a textview or an edittext? – ridoy Jun 25 '13 at 09:12