【Java】手書き文字を収集するアプリケーションの作成
隠れマルコフモデルによる手書き数字認識を実装する前に、手書き数字データを収集するアプリケーションを作成します。
いきなり余談ですが、手書き文字は採取時のデータの性質によってオンライン手書き文字とオフライン手書き文字に分けることが出来ます。
オフライン手書き文字は文字を見たままの画像として扱い、オンライン手書き文字は筆記時間毎のペンのX,Y座標や筆圧、移動速度や仰角等の時系列として扱います。
今回はHMMによる手書き数寺院式に適用する為、時系列データとして扱えるオンライン特徴量を採取します。
作成した筆跡収集アプリのコードは次のようになります。
HandWriting.java
package emoson.gui.handwriting; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.border.BevelBorder; public class HandWriting extends JFrame { public HandWriting(){ this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setBounds(100, 100, 500, 500); this.setLayout(new FlowLayout()); Note p1 = new Note(); p1.setPreferredSize(new Dimension(400, 400)); JPanel p2 = new JPanel(); p2.setPreferredSize(new Dimension(400, 50)); p2.setBackground(Color.BLUE); JButton ok_button = new JButton("OK"); ok_button.setBorderPainted(false); ok_button.setBackground(Color.WHITE); ok_button.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { p1.save(System.currentTimeMillis()+".txt"); }}); JButton cl_button = new JButton("Clear"); cl_button.setBorderPainted(false); cl_button.setBackground(Color.WHITE); cl_button.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { p1.clear(); }}); p2.add(ok_button); p2.add(cl_button); Container cont = this.getContentPane(); cont.add(p1); cont.add(p2); } public static void main(String[] args){ HandWriting app = new HandWriting(); app.setVisible(true); } }
Note.java
package emoson.gui.handwriting; import java.awt.Color; import java.awt.Graphics; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.swing.JPanel; public class Note extends JPanel implements MouseMotionListener{ private static final int size = 5; private List<Pos> posList; public Note(){ super(); this.posList = new ArrayList<Pos>(); addMouseMotionListener(this); } public void paintComponent(Graphics g){ g.setColor(Color.WHITE); g.fillRect(0, 0, this.getWidth(), this.getHeight()); g.setColor(Color.BLACK); for(Pos pos : this.posList){ g.fillOval((int)pos.X, (int)pos.Y, size, size); } } public void clear(){ this.posList.clear(); this.repaint(); } public void save(String fileName){ File file = new File(fileName); try { FileWriter fw = new FileWriter(file); for(Pos p : this.posList){ fw.write(p.X+","+p.Y+"\n"); } fw.close(); } catch (IOException e) { e.printStackTrace(); } this.clear(); } @Override public void mouseDragged(MouseEvent e) { posList.add(new Pos(e.getX(), e.getY())); this.repaint(); } @Override public void mouseMoved(MouseEvent e) { } }
Pos.java
package emoson.gui.handwriting; public class Pos { public float X; public float Y; public Pos(float X, float Y){ this.X = X; this.Y = Y; } }
実行すると次のようなGUIが起動します。
次のようにマウスで文字を筆記します
書き終えたらOKボタンを押します。
すると、プロジェクトのカレントディレクトリに次のようなファイルが生成されます
このファイルはサンプリング時間毎のマウスのX座標値とY座標値が神間で句切られています。
次回はこのプログラムをを用いて0から9までの手書き数字を採取し、隠れマルコフモデルを用いて手書き数字認識実験を行います。