読者です 読者をやめる 読者になる 読者になる

はだしの元さん

プログラミングの技術的なことを忘備録かねて書いていこうと思っています。

MavericksでArduinoに書き込んでProcessing2と連携する

OS XがMavericksになったりProcessingが2.xになったりと環境が新しくなったことで、Arduinoにプログラムを書き込んだり、ProcessingとArduinoの連携ですこしはまったので解決方法書きます。

環境

  • OS X 10.9.1(Marvericks)
  • Processing 2.1.1
  • Arduino Duemilanove w ATmega 328
  • Arduino 1.0.5(エディタの方)

Arduinoに書き込む

MavericksのFTDIドライバに不具合があってそれで書き込みに失敗する見たいです。
なので公式のFTDICHIPが配布しているドライバに置き換えることで解決できました。

以下のサイトからドライバをダウンロードしインストールします。
http://www.ftdichip.com/Drivers/VCP.htm

ターミナルを開いて、以下のコマンドを実行します。

$ cd /System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns 
$ sudo mv AppleUSBFTDI.kext AppleUSBFTDI.disabled 
$ sudo touch /System/Library/Extensions

Macを再起動して以下のコマンドを実行してドライバが入っているか確認します。
成功していればArduinoに書き込めるようになっているはずです。

$ kextstat | grep FTDI

f:id:hadashi_gensan:20140216120317p:plain

Processing2と連携

まずProcessingにArduinoと連携できるようにするためのライブラリを導入します。
以下のサイトからProcessing2用のライブラリをダウンロードします。
http://playground.arduino.cc/Interfacing/Processing

解凍して出てくるarduinoというフォルダを、「Processing/libraries」にフォルダごと入れます。

次にArduinoのエディタを開きメニューから「ファイル>スケッチの例>Firmata>StandardFirmata」を開きArduinoに書き込みます。

Processingに戻り、以下のプログラムを実行します。

import processing.serial.*;
import cc.arduino.*;

Arduino arduino;

void setup() {
  println(Arduino.list());
  arduino = new Arduino(this, Arduino.list()[0], 57600);
}

void draw() {
}

このプログラムを実行するとコンソールにシリアルポートの一覧が表示されます。
f:id:hadashi_gensan:20140216121633p:plain
この一覧からどのシリアルポートを使うかをみて、先ほどのプログラムのArduino.list()[0]の部分を変更します。
例えば「/dev/tty.usbserial-A6008lAo」を使用する場合は6番目のシリアルポートなのでArduino.list()[5]とします。
あとはarduinoインスタンスからanalogReadやdigitalWriteなどのメソッドを呼べばArduinoと連携する事ができます。
ここまででProcessing2との連携は終わりです。

サンプル

Analog IN 1にボタンをつなげてON/OFFを検出するプログラムを作成したので参考までに。

import processing.serial.*;
import cc.arduino.*;

Arduino arduino;

int PIN = 1;

void setup() {
  println(Arduino.list());
  arduino = new Arduino(this, Arduino.list()[5], 57600);
  arduino.pinMode(PIN, Arduino.INPUT);
  frameRate(10);
}

void draw() {
  int sensorValue = arduino.analogRead(PIN);
  int ts = 20;
  if (sensorValue > ts) {
    background(color(231, 76, 60));
  } else {
    background(0);
  }
}

参考サイト

以下のサイトを参考にさせていただきました。
MacOSX10.9(Mavericks)とFTDIドライバについて : まごころせいじつ堂 (浜町庄金 研究開発)

Tesseract-OCRの学習

Tesseract-OCRはHPが開発し現在はGoogleが公開しているオープンソースOCRエンジンです。
オープンソースのOCRエンジン Tesseract-OCRでTesseeract-OCRで日本語の読み込みまでは説明しました。

今回はTesseract-OCR機械学習を行い精度を向上させるための方法を説明します。
僕は基本的に以下の公式のチュートリアルを読みながらやって行きました。

Tesseract Training Wiki
https://code.google.com/p/tesseract-ocr/wiki/TrainingTesseract3

大まかにやることは3つあります。

  1. boxファイルの作成 
  2. trファイルの作成
  3. トレーニングデータの作成

boxファイルの作成

まず学習したい画像ファイルを用意します。今回は以下の画像(train_img.png)を使用しました。
f:id:hadashi_gensan:20140115113722p:plain

次に以下のコマンドを実行します。

tesseract train_img.png jpn.hiragi.exp0 -l jpn batch.nochop makebox

ここでboxファイルのファイル名には以下のような命名規則があるので気をつけてください。

(3文字の言語名).(フォント名(任意)).exp(インデックス番号)

3文字の言語名は以下のサイトを参考して目的の言語を選んでください。日本はjpnです。
http://ja.wikipedia.org/wiki/ISO_639

インデックス番号はTesseract-OCRは同時に複数の画像を学習できるのでそのときに連番をつけて識別します。
今回は1枚の画像だけなので、0しか使いません。

成功するとjpn.hiragi.exp0.boxというファイルが出力されます。
テキストエディタで開くと以下のようになっていると思います。

M 4 6 22 30 0
u 23 5 39 23 0
C 42 5 57 24 0
i 59 6 73 31 0
n 77 6 93 24 0
t 95 5 111 28 0
0 112 5 130 24 0
S 132 5 147 24 0
h 149 6 165 30 0
ニ 172 5 178 24 0
0 184 5 202 24 0
p 203 0 219 24 0
e 221 5 237 24 0
n 239 6 255 24 0
C 258 5 273 24 0
V 274 6 292 23 0
y 310 0 328 23 0
q 329 5 345 24 0
m 346 6 364 24 0
G 365 5 381 24 0
伽 382 5 418 24 0
t 419 5 435 29 0
。 436 5 454 24 0

これは1行につき1文字文の情報が書かれています。
この情報の見方は以下の通りです。

読み込んだ文字 x1 y1 x2 y2 インデックス番号
M 4 6 22 30 0

f:id:hadashi_gensan:20140115150111p:plain

しかしこのデータをよく見てみると、実際の文字とは間違っているところがたくさんあると思います。
Tesseract-OCRの学習ではこの間違いを修正して、教える事で精度の向上ができます。
以下のように読み込んだ文字や座標の修正を行って保存します。

読み込んだ文字 左上のx座標 左上のy座標 右下のx座標 右下のy座標 インデックス番号
M 4 6 22 30 0
a 23 5 39 23 0

今回は一部しか示しませんが、実際は全ての文字と座標について修正を加えます。

trファイルの作成

次にtrファイルを作成します。
このときに使用していた画像のファイル名もboxファイルと同じ名前にする必要があります。
boxファイルの作成にしようした画像ファイルのファイル名を以下のように変更します。

jpn.hiragi.exp0.png

ファイル名を変更したら以下のコマンドを実行します。

tesseract jpn.hiragi.exp0.png jpn.hiragi.exp0 nobatch box.train.stderr

jpn.hiragi.exp0.trというファイルが出力されれば成功です。

トレーニングデータの作成

トレーニングを行う前に

  1. unicharsetファイル
  2. font_propertiesファイル

という2つのファイルを作成します。2つともTesseract-OCRに文字のフォント情報等を教えるために必要なファイルです。

unicharsetファイル

以下のコマンドを実行します。ここでboxファイルを指定するときにここでは拡張子を含む事に注意してください。

unicharset_extractor jpn.hiragi.exp0.box
font_propertiesファイル

このファイルは直接テキストエディタを使って作成します。
以下の1行だけからなる「font_properties(拡張子なし)」というテキストファイルを作成してください。

hiragi 0 0 0 0 0

このファイルは

フォント名(boxファイルのファイル名で指定した物と同名) italic bold fixed serif fraktur
hiragi 0 0 0 0 0

という順でデータが並んでいます。
italicなフォントを使用した場合は以下のようになるイメージです。

フォント名 italic bold fixed serif fraktur
hiragi 1 0 0 0 0
学習

unicharsetとfont_propertiesの2つのファイルを作ったら、以下のコマンドで学習を行います。

mftraining -F font_properties -U unicharset jpn.hiragi.exp0.tr 

成功すると以下のファイルが出力されます。

  • inttemp
  • shapetable
  • pffmtable

続いて次のコマンドを実行します。

 mftraining -F font_properties -U unicharset -O jpn.unicharset unicharset jpn.hiragi.exp0.tr

さらに次のコマンドを実行します。

cntraining jpn.hiragi.exp0.tr

このコマンドでnormprotoというファイルが作成されます。

次に今まで作成したファイルのファイル名を変更します。

  • inttemp
  • shapetable
  • pffmtable
  • normproto

というファイルの先頭に「jpn.」をつけます。
変更後

  • jpn.inttemp
  • jpn.shapetable
  • jpn.pffmtable
  • jpn.normproto

というファイル名に変更します。

ファイル名を変更したら以下のコマンドを実行します。

combine_tessdata jpn.

最後のドットを忘れないようにしてください。
成功するとjpn.traineddataというファイルが作られているはずです。

最後に以下のコマンドで「/usr/local/share/tessdata/」に生成したjpn.traineddataファイルをコピーしたら完了です。

cp jpn.traineddata /usr/local/share/tessdata/

以上でTesseract-OCRの簡単な学習方法の説明は完了です。
しかし今回はたった1枚の画像でしか学習していませんが、これを複数用意して学習させていく事で、精度の向上や新しい言語の対応などができます。

複数のファイルをやるときはtrファイルを作った段階で、catコマンドでそのファイルを結合することで対応できます。

AndroidAnnotaionsでよく使うアノテーション一覧

AndroidAnnotationsはAndroid開発でお決まりなめんどくさい処理をアノテーションをつけることで自動的にやってくれるライブラリです。

公式サイト
http://androidannotations.org/

アノテーションを一覧しているサイトが少なかったので、今回開発で使ったアノテーションをまとめてみました。

アノテーション 説明
@EActivity Activityにつけるアノテーション。@EActivity(R.layout.activity_main)とすることで自動的にそのレイアウトファイルを読み込んでくれる。
@ViewById(R.id.button) Button button = (Button) findViewById(R.id.button)を自動的にやってくれる。Buttonじゃなくても全部自動でやってくれる。
@Click(R.id.button) @ViewById(R.id.button)をしていればそのViewがクリックされたときに呼んでくれる。
@LongClick(R.id.button) @Click(R.id.button)のロングクリック版。
@AfterViews レイアウトの読み込みやfindViewByIdなどが終わったときに呼びたいメソッドにつける。
@Extra(value="extra1") intent.putExtra("extra1", value)で渡されたデータを自動的に取得してこのアノテーションをつけた変数に代入してくれる。
@EFragment @EActivityのフラグメント版。
@FragmentArg(value="arg1") setArguments()で渡されるデータを自動的に取得してくれる。指定したキーでデータを取得できなかった場合は代入は行われないので、宣言と同時に値をいれておけば見つからなかったときの初期値として使える。
@Background このアノテーションをつけたメソッドは必ずUIスレッド以外のスレッドで実行される。
@UiThread このアノテーションをつけたメソッドはかならずUIスレッドで実行される。
@SystemService LayoutInflater inflater;という変数宣言にこのアノテーションをつけるとgetSystemService(Context.LAYOUT_INFLATER_SERVICE)を自動的に呼んでinflaterに代入してくれる。特に引数を指定しなくても型から自動的に判別して取得してくれるのでLayoutInflaterに限らず何でも大丈夫。
@StringRes(R.string.appname) getString(R.string.appname)を自動的にしてくれる。
@StringArrayRes(R.array.texts) @StringResのArray版。
@EBean Activityなど以外の普通のクラスでもアノテーションを利用できるようになる。このアノテーションをつけたクラスを利用するときは@Beanをつけて変数を宣言する。

今回使ったのはこんな所でしょうか。
まだいっぱいあるので使う機会があったら使ってみたいですね。

CoffeeScriptのインストールからGruntを使って自動コンパイルするまで

最近数百行程度のJSを書いていて、そういえばCoffeeScriptって言うのがあったなぁっと思ったので、気分転換にやってみることにしました。

CoffeeScriptはJavaScriptにコンパイルすることのできる小さな言語で、純粋なJavaScriptのコードと比べて3分の1程度にコードを短縮できる(らしい)です。
また文法がRubyPythonに似ている(らしい)ことでも有名になった(らしい)です。

正直なところ数年前に何かの勉強会で聞きかじっただけなのでよくわかりません・・・
よくわからないので今回実際に開発に使って試してみたいと思います!

インストール

さっそくCoffeeScriptをインストールします。
CoffeeScriptはNode.jsを使用しているのでこれが既にインストールされている前提で説明します。

僕は既にNode.jsはインストール済みで、よく覚えていませんが多分以下のサイトをみてインストールしたような気がします。
http://qiita.com/dribble13/items/e895208727c85ef9bc52

CoffeeScriptのインストールは以下のコマンドで行います。

$ sudo npm install -g coffee-script

cofee -v とコマンドを入力してバージョンが表示されればインストールは成功です。

Hello World

次にHelloWorldをやってみます。
test.coffeeというファイルを作って以下のプログラムを書き込みます。

alert "Hello World!"

このコードがCoffeeScriptのコードになります。
CoffeeScriptは関数呼び出しの()を省略でき、また行末に「;」を入力しなくても大丈夫です。

次にこのプログラムをコンパイルします。
以下のコマンドを実行してください。

$ coffee -cb test.coffee

そうすると同じディレクトリにtest.jsが生成されます。任意のディレクトリに出力したい場合は-oオプションを用います。
コンパイルされたjsファイルは以下のようになっているはずです。

// Generated by CoffeeScript 1.6.3
alert('hello world');

よく見慣れたjsのコードになっている事がわかります。

これでもっとも基本的なCoffeeScriptの説明は終わりです。
ですが、コードを書く度に毎回ビルドしていては日が暮れてしまうことは想像に難くありません。
なので次にファイルを編集する度に自動的にCoffeeScriptのファイルをコンパイルすることのできるツールの「Grunt」を紹介します。

Grunt

Gruntは主にWeb制作においてCoffeeScriptnやLESSといったビルドが必要なものを自動的にビルドしてくれるツールです。
このGruntをつかってCoffeeScriptのコンパイルを自動的に行う方法を紹介します。
GruntもCoffeeScript同様にnpmを使ってインストールします。
以下のコマンドでインストールすることができます。

$ sudo npm install -g grunt-cli

次に自動化したいプロジェクトのルートディレクトリに移動します。
例としてcoffeeというディレクトリを作成し、cdコマンドでそこに移動します。
先ほどの例ではtest.coffeeというファイルはcoffee/test.coffeeという場所に作成したので
cd coffee/test.coffee
とします。

次にGruntを使用する上で必要な2つのファイルを作成します。

  • package.json
  • Grunt.coffee

この2つをプロジェクトのルートディレクトリに作成います。Grunt.coffeeはGrunt.jsでも大丈夫です。

package.jsonに以下の内容を書き込みます。

{
  "name": "coffee",
  "version": "0.0.0",
  "devDependencies": {
  },
}

次に必要なGruntモジュールをインストールします。
以下のコマンドを実行してください。

$ sudo npm install grunt --save-dev
$ sudo npm install grunt-contrib-watch --save-dev
$ sudo npm install grunt-contrib-coffee --save-dev

このコマンドを実行すると自動的にpackage.jsonが以下のように変更されているはずです。

{
  "name": "coffee",
  "version": "0.0.0",
  "devDependencies": {
    "grunt": "~0.4.2",
    "grunt-contrib-coffee": "~0.7.0",
    "grunt-contrib-watch": "~0.5.3"
  },
}

--save-devというオプションが自動的にpackage.jsonに必要な情報を書き込むようにするオプションです。

次にGrunt.coffeeについて説明します。
以下のようにGrunt.coffeeに書き込んでください。

module.exports = (grunt)->
    grunt.initConfig
        pkg : grunt.file.readJSON 'package.json'
            watch : 
	        files : ["./*.coffee"]
	        tasks : "coffee"
	     coffee : 
		compile : 
		    files : [
		        expand : true
			cwd : "./"
			src : "./*.coffee"
			dest : "./js/"
			ext : ".js"
		    ]
    grunt.loadNpmTasks 'grunt-contrib-coffee'
    grunt.loadNpmTasks 'grunt-contrib-watch'
    grunt.registerTask 'default', ['watch']

    return

CoffeeScriptはインデントが大事なのでコピペでは多分上記のコードは動きません・・・
このプログラムはルートディレクトリにある「.coffee」ファイルが編集されたら自動的に「./js」ディレクトリに「.js」ファイルをコンパイルして出力するというものです。
実際の開発では「.coffee」ファイルは「./coffee/」といったディレクトリに保存すると思うので、「"./*.coffee"」となっている部分を「"./coffee/*.coffee"」というふうに変更することで対応できます。

package.jsonとGrunt.coffeeを作成したらgruntを以下のコマンドで実行します。

$ grunt

以下のようになっていれば成功です。
f:id:hadashi_gensan:20131215002636p:plain
先ほど作成したtest.coffeeを適当に編集してみましょう。
すると「./js/test.js」というファイルが自動的に作られているのがわかると思います。

これでCoffeeScriptをインストールしてGruntを使って自動的にコンパイルすることができました。
だいぶ開発が楽になったと思うのでもうちょっと本格的にCoffeeScriptの勉強をしていきたいと思います。
これで明日からマックでMac使ってコーヒー飲みながらCoffeeScriptが書ける!!!

enchant.jsで音をならす

enchant.jsで音をならす方法を紹介します。
と言ってもとても簡単で以下のようにするだけです。

$(function(){
    $(document).ready(function(){
        enchant();
	var game = new Core(320, 320);
		
        // サウンドファイルを読み込む
	game.preload("./sound/explosion01.mp3");
       
	game.onload = function () {
                // 音をならす
		game.assets["./sound/explosion01.mp3"].play();
	};
	game.start();
    });
});

画像と同様にpreload()メソッドで事前にファイルを読み込んでおき、そのデータに対して

game.assets["./sound/explosion01.mp3"].play();

というようにアクセスして、play()メソッドを呼ぶだけす。

ちなみに音データは以下のサイトから使わせてもらいました。
最近流行りの艦これにも使われている音を提供しているらしく、今日一番驚きましたw
http://taira-komori.jpn.org/freesound.html

Haar Likeの分類器を作成する

HaarLike

HaarLikeという手法はよく顔認識等で用いられる手法です。
ですが、独自でサンプル画像をたくさん用意して学習させる事で、任意のオブジェクトを見つける事ができるようになります。

今回はそのHaarLikeを学習して入力画像から「LAWSON」のロゴを見つける分類機を作成します。
またopencvが既にインストールされている前提で説明していきます。

学習

学習には正解画像(ポジティブサンプル)、非正解画像(ネガティブサンプル)を数千枚単位で用意する必要があります。
と言ってしまうと、ここで挫折しそうになりますが、精度を気にせずとりあえず動く物を作るだけなら数枚の画像でできます。

正解画像例
f:id:hadashi_gensan:20131211100214j:plain

非正解画像例
f:id:hadashi_gensan:20131211100145j:plain

サンプルデータ

opencvには1枚の画像から回転や変形などを加えて自動的に複数のサンプルデータを作成する「opencv_createsamples」というコマンドが用意されています。
このコマンドは以下のように使用する事ができます。

opencv_createsamples -img ./ok/ok0.jpg -vec lawson.vec -num 400
各パラメータの意味は以下の通りです。

  • img : 正解画像
  • vec : 出力されるサンプルデータの名前
  • num : 生成するサンプルデータの数

lawson.vecが生成されていれば成功です。

非正解画像のリストを作成

用意した非正解画像のパスを書いたテキストファイルが非正解画像のリストです。
以下のコマンドで一発で作成可能です。

find ng/ -name '*.jpg' > ng.txt
これで以下のようなテキストファイルが生成されます。

ng//ng0.jpg
ng//ng1.jpg
ng//ng2.jpg
ng//ng3.jpg
ng//ng4.jpg
ng//ng5.jpg
学習データの作成

学習データの作成にもopencv_traincascadeというコマンドを使用します。

opencv_traincascade -data out/ -vec lawson.vec -bg ng.txt -numPos 350 -numNeg 5 -featureType HAAR -mode ALL
  • data : 学習データが出力されるディレクトリ
  • vec : 正解画像のサンプルデータ
  • bg : 非正解画像のリストファイル
  • numPos : 正解画像のサンプルデータの数
  • numNeg : 非正解画像の数
  • featureType : アルゴリズムを指定(LBP, HOG, HAARなどを選択できる)
  • mode : 使用する特徴量の種類

numPosについて、作成したデータ数ぴったりを指定してしまうと、エラーになるので
  データ数 * 0.9
くらいを指定します。

ここでデータ数が多いと何日単位という、ものすごい時間がかかります。
今回は正解画像400枚(自動生成したもの)、非正解画像5枚なので数分で終わると思います。

サンプルコード

作成した学習データを使ってLAWSONのロゴを発見するサンプルコードを以下に示します。

#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <iostream>
#include <stdio.h>

using namespace std;
using namespace cv;

int main (int argc, char** argv) {
	Mat receiptImg = imread(argv[1]);

	CascadeClassifier cascade;
	cascade.load("./out/cascade.xml");

	vector<Rect> rects;
	cascade.detectMultiScale(receiptImg, rects);

	for (vector<Rect>::iterator i=rects.begin(); i != rects.end(); ++i) {
		rectangle(receiptImg, 
			Rect(i->x, i->y, i->width, i->height),
			Scalar(0, 0, 255));
	}

	imwrite("result.jpg", receiptImg);

  	return 0;

}

サンプルデータがかなり少ないので精度はほとんどありませんが、とりあえず動くものは作れました。
サンプルデータをもっとたくさん集める事で精度をあげる事ができるのでがんばって集めていきます。

Rot.jsでRPGの「ターン」を管理する

今回紹介するRot.jsはマップの自動生成、最短距離検索やノイズの生成といったゲーム開発によく使われる機能を提供しているライブラリです。
いくつかある機能の中でも今回はドラクエやポケモンのようなターン管理機能を使ってみたいと思います。

ダウンロード

Rot.jsの公式サイト
http://ondras.github.io/rot.js/hp/

Rot.jsの使い方サイト
http://ondras.github.io/rot.js/manual/
ライブラリをダウンロードしてくるとhtmlファイルが入っていますが、「Cross origin requests are only supported for HTTP. 」というエラーで表示されませんでした・・・

公式サイトからzipをダウンロードしたら一番上の階層に入っているrot.min.jsを読み込めば利用できます。

ターン管理機能

ターンを管理する機能としていくつか提供されていますが、その中でも最も簡単で、ポケモンやドラクエのようなターン制を実装するのに使うであろう機能を紹介します。

ROT.Scheduler.Simpleでその簡単なターン管理機能を利用できます。

var scheduler = new ROT.Scheduler.Simple();
// 第2引数はターンを繰り返すかどうか。
//trueで永遠に登録したターンを繰り返す。
scheduler.add(function () {
    console.log("hello world");
}, true);

このようにしてScheduler.Simpleオブジェクトを生成し必要な値を追加していきます。
値ならなんでもいいのでfunctionや数値、文字列等々必要なものを追加します。

取り出す時は

for (var i=0; i<j10; i++){
     var current = scheduler.next();
     current();
}

先ほどの値を追加するときのように第2引数をtrueにすると、追加した値を繰り返し取得する事ができます。
この例では無名関数を一つ追加しているだけなので毎回同じ関数がcurrentに入ります。
つまり10回コンソールに「hello world」が出力されます。

サンプル

以下にもうちょっと実用的な例とプログラムの一部でなく全体を示します。
この例でも使用しているのですが、Rot.jsはゲーム開発に直接関係のある機能だけでなく、文字列のformatterも提供しています。

"hello %s".format(10);

というようにして使用します。

$(function(){
    $(document).ready(function(){
         var scheduler = new ROT.Scheduler.Simple();

            for (var i=1; i<=5; i++) {
                scheduler.add(
                     hello("hello %s".format(i)), true);
	    }

            for (var i=0; i<20; i++) {
                 var current = scheduler.next();
                 current();
             }
    });
     
     var hello = function (text) {
            return function () {
	         console.log(text);
            };
      };
});