2010年12月21日

Android で日本語読ませる実験中

Android 楽しいです。
手軽にアプリが作れるってところがいいですね。Java はあまり使ってなかったのですが、勉強しててよかったです。ほんとそう思います。

今は、とりあえず、Aquestalk2 で漢字を含んだ文章を読ませる実験をしています。辞書はSDカードに直接書き込んでいるので、これが自動化できたら誰でも使えるようになるので、そうなったら公開できると思います。

speak_cap.jpg

今回は GoSen を Android 向けに改造したものを使って日本語を解析しています。MeCab を元に Java で書き直した Sen。その Sen を補強した GoSen です。それを Android で動くように少し書き換えました。Android で GoSen を動かそうとしたら、どういうわけか XML で書かれた設定ファイルを読み込むところで止まってしまいました。そこでXML関連の部分を書き直してみました。別なシンプルな方法があったかもしれませんが、とりあえずこれでいいはずです。

具体的には下記のように、Configuration loadConfiguration(String configurationFilename) を次の二つのメソッドで置き換えました。そしてそれに伴い必要なimport文を追加しました。


  /**
* get a XML Text field
*
* @param XmlPullParser
* @param The Tag name String
* @return The Text String
*/
private static String getXMLText(XmlPullParser parser,String name) {
try {
if ( parser.next() == XmlPullParser.TEXT) {
String text = parser.getText();
if ( parser.next() == XmlPullParser.END_TAG && name.equals(parser.getName()) ) {
return text;
}
}
}catch(Exception e) {
}
throw new IllegalArgumentException( "element '" + name + "' is invalid");
}


/**
* Loads a tokenizer configuration file for Android
*
* @param configurationFilename The filename of the configuration to load
* @return The loaded configuration
*/
private static Configuration loadConfiguration(String configurationFilename) {

String dictionaryVersion = "";
Configuration configuration = new Configuration();

try {

File configurationFile = new File(configurationFilename);
String parentDirectory = configurationFile.getParent();
if (parentDirectory == null) {
parentDirectory = ".";
}
String separator = System.getProperty("file.separator");

configuration.connectionCostFilename = parentDirectory + separator + CONNECTION_COST_DATA_FILENAME;
configuration.partOfSpeechDataFilename = parentDirectory + separator + PART_OF_SPEECH_DATA_FILENAME;
configuration.tokenFilename = parentDirectory + separator + TOKEN_DATA_FILENAME;
configuration.trieFilename = parentDirectory + separator + TRIE_DATA_FILENAME;

XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
parser.setInput(new FileInputStream(configurationFilename),"UTF-8");
int eventType;
while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT){
if (eventType == XmlPullParser.START_TAG && parser.getDepth() == 1 ) {
if ( "configuration".equals(parser.getName()) ) {
while (true) {
eventType = parser.next();
if ( eventType == XmlPullParser.END_TAG ) {
if ( "configuration".equals(parser.getName() )) {
break;
} else {
throw new IllegalArgumentException( "invalid end tag");
}
}
if ( eventType == XmlPullParser.TEXT ) {
continue;
}
if ( eventType != XmlPullParser.START_TAG ) {
throw new IllegalArgumentException( "invalid event");
}
String name = parser.getName();
if (name.equals("dictionary-version")) {
dictionaryVersion = getXMLText(parser,name);
} else if (name.equals("tokenizer")) {
configuration.tokenizerClassName = getXMLText(parser,name);
} else if (name.equals("unknown-pos")) {
configuration.unknownPartOfSpeechDescription = getXMLText(parser,name);
} else {
throw new IllegalArgumentException( "unknown tag");
}
}
}
}
}
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
if (!dictionaryVersion.equals("1.0")) {
throw new IllegalArgumentException("Invalid dictionary version \"" + dictionaryVersion + "\"");
}
return configuration;
}



JARファイル
gosen-android-1.01.jar
このファイルのライセンスは LGPL です。
2011.01.06 更新
2.6.2以降のipadicにも対応させました。


関連ページ:
日本語形態素解析システムのJava実装SenをAndroid上で動かす
Sen Project
GoSen


GoSen を使うときに気をつけることは GoSen は LGPLライセンスだということです。GPL/LGPLライセンスのソフトは利用する分にはありがたいのですが、その反面、ソフトを書く側になると使いにくいのも事実です。ちゃんと理解しているか自信はありませんが、今回は LGPL のファイルからなる jar ファイルを利用するので、それを利用する側の本体のプログラムのソースを公開する義務は生じないと思います。間違っていたら指摘ください。

余計なことで悩まないように、誰かが現時点のトリプルライセンスになっている MeCab を元に、新しく Java で書き直して同じトリプルライセンスで公開してくれるとありがたいですね。そのときは是非 Man という名前で。


MeCab そのものを Android で使うというのもありだと思って、MeCab を JNI で動かせないかと模索もしています。既に ARM 向けにクロスコンパイルができることは確認できました。あとは、NDK の使い方を覚えたら何とかなるかもしれません。当然、それがうまくいけば次の段階として、内部で MeCab を使っている Open JTalk を Android でも使えるようにしたいと思っています。

最終的な目標は、Andorid で動く日本語のスクリーンリーダーです。Linux では Gnome Orca の続きをやらないといけないのに、NVDA もお手伝いしたいって気持ちはあるんですが、ちょっと今は、しばらくアンドロイドでいろいろプログラムを作ってみようと思います。



posted by takayan at 02:53 | Comment(0) | TrackBack(0) | Android | このブログの読者になる | 更新情報をチェックする

2011年01月06日

GoSen と Aquestalk2 を使って日本語をしゃべる Android アプリを作ってみた。

今年もよろしくお願いします。
さて、年末に作り始めたAndroidアプリを公開します。
仮公開先:[nihongoyomiagetest.apk]
(2011.01.09 19:20 数字・アルファベットに対応)
(2011.01.07 01:40 速度の情報が保存されない不具合修正)
(2011.01.07 01:12 再生ボタンの不具合修正)

まだテスト中ですので、不具合があるかもしれません。そのときは速やかにアンインストールしてください。

Aquestalk2の音声で日本語を読みます。
通常、Aquestalk2 は仮名文字しか読めませんが、GoSenを使って日本語の形態素解析をし、漢字仮名交じり文の読みを推定しています。機能そのものは入力されたテキストをただ変換し読み上げるだけのシンプルなものです。


辞書はとても巨大なので本体には同梱していません(50MB)。SDカード上に後述する専用のフォルダを作って、その中に配置してください。もしくは、このアプリのメニューに入れてあるネット上からダウンロードしてインストールする機能を使ってもよいです。ですが、スリープさせずに実行させて1時間近くかかってしまいます。スリープさせながらだと2時間以上かかります(IS03にて)。

そういうわけで、Java のプログラムに慣れた人ならば、辞書のインストールはパソコンでコンパイルした後SDカードにコピーしたほうが簡単です。パソコンでのコンパイルは1分ほどで終わります。そのかわり、ちょっと準備が必要です。

パソコンで辞書を作成するには、JDKantがインストールされている必要があります。そして GoSen のソースコードも必要です。GoSen のソースコードは svn を使って、https://itadaki.svn.sourceforge.net/svnroot/itadaki/GoSen からダウンロードしてください。
まず、ant を使って、GoSen をコンパイルします。その後、testdata/dictionary フォルダで、ant を実行すると、ipadic-2.6.0 の辞書データがコンパイルされます。GoSen は Sen よりは新しいですが、それでもやはり古いプログラムなので 2.6.2 以降のipadic 辞書にはそのままでは対応できません。今回のアプリで利用している jarでは、この対策を施していますが、パソコンで使うときの対策は次回詳しく説明します。
参考:GoSenのちょっとした改良

コンパイルが終われば辞書をSDカードに移します。Android本体をケーブルで繋ぐ方法でも、SDカードを外してパソコンに差す方法でも、 DropBox などパソコンからAndroid内にファイルを転送できるソフトやファイルマネージャーアプリを駆使する方法でもかません。SDカードの所定の場所(/sdcard/GoSen/ipadic-xxxxx/)にコピーしてください。/sdcard/GoSen/内に ipadic で始まるフォルダを見つけると、その中に ipadic の辞書データが入っていると判断するようにしています。

パソコンでコンパイルした場合、dictionary フォルダにはいくつかのファイルができていますが、コピーするのは dictionary.xml、connectionCost.sen、partOfSpeech.sen、token.sen、trie.sen の5つです。将来、辞書の再構築が Android 内でできるようになったらさらに二つのcsvファイルも必要になりますが、今はいりません。

JDK や ant の環境構築はプログラミングをやったことがない人にはハードルの高いものです。SDカードへのコピーも難しいかもしれません。そういう方はこのアプリで辞書をコンパイルしてください。時間はとってもかかってしまいますが。細かいことは何もせずにすみます。なお変換途中で終了すると、次回インストールでは展開するところからやり直します。



この GoSen の辞書は一度入れてしまえば、他のアプリからでも利用できます。今回作ったソフトの辞書関連のクラスを独立させて、辞書管理のアプリを別に作ってみようと思っています。単語を追加して、辞書を構築しなおすたびに一時間かかるような今の状況では使い物にはなりませんが。


今回公開するアプリにはアクエスト社のAndroid向けAquesTalk2ライブラリ、および音声Phontファイルが含まれています。このAquesTalk2ライブラリは非営利の個人利用に限り無償で使用できます。それ以外のご利用の場合はライセンスの購入が必要です。また、AquesTalk2ライブラリ単体での再配布はできません。


posted by takayan at 03:10 | Comment(2) | TrackBack(0) | Android | このブログの読者になる | 更新情報をチェックする