スポンサーサイト

--年--月--日 --:--

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

LIBSVM java版を使う

2012年02月20日 02:44

LIBSVM java版を使う

kinectを使ったアプリケーションで、決まった動きを検出するための一つの方法としてSVMを使う事を考えた。
現在は、OpenNI + java で kinect を使っているので、java言語で使えるsvmライブラリを探した。

以下が割と有名なようだったので使ってみた。

LIBSVM -- A Library for Support Vector Machines
http://www.csie.ntu.edu.tw/~cjlin/libsvm/


このページで、java実装は二つ紹介されている
・LIBSVMのjava実装(C++のコードをそのままjavaに変換した感じ)
 ・http://www.csie.ntu.edu.tw/~cjlin/libsvm/#download
・jlibsvm: LIBSVMをパフォーマンス、拡張性の観点からリファクタリングしたコード
 ・http://dev.davidsoergel.com/trac/jlibsvm/

このふたつのうち、説明だけ読むとjlibsvmの方がよく見えるが、実際使ってみると未実装部分が大杉だったので、上のLIBSVMのjava実装を使った。

・使い方

1.モデルの作成

1-1.元ネタファイルの作成

以下のような形式の元ネタファイルを作る


1 1:-0.0013786764705882354 2:0.0057157628676470585 3:4.5955882352941165E-4 4:0.00112655739379085 5:38.0 6:-83.0 7:236.0
1 1:-4.468958652830196E-4 2:0.001708883828216933 3:-0.0029316591163263133 4:-0.0029494415206854367 5:49.0 6:21.0 7:900.0
2 1:-8.053472566307697E-4 2:0.015825596141435506 3:6.725430580246377E-4 4:0.019385799543923065 5:196.0 6:-40.0 7:506.0
2 1:-1.7673336983657553E-4 2:0.021002586194578676 3:0.005701880761361455 4:0.00407827378102308 5:216.0 6:34.0 7:399.0
3 1:-8.170953867899441E-4 2:-0.0023765650581102004 3:0.0016513781990655056 4:0.011545796818632416 5:169.0 6:-149.0 7:1603.0
3 1:-0.011345886334911794 2:-0.004779992024791061 3:0.010344040288070138 4:0.015262516965389552 5:38.0 6:-84.0 7:700.0
4 1:-8.15206561207011E-4 2:-0.012176408105470035 3:-5.230214125755292E-4 4:0.014526629528803993 5:196.0 6:-118.0 7:533.0
4 1:-0.005219037617901608 2:-0.010753445963518873 3:0.005010016891373788 4:0.011383035605288017 5:100.0 6:-71.0 7:567.0
...



形式は

クラス名 パラメータ番号:値 パラメータ番号:値 パラメータ番号:値 ...

である必要がある。


1-2.svm_trainの実行


元ネタを例えばinput.txtという名前で保存した場合、

java svm_train -t 0 input.txt



を実行すると、input.txt.model というファイルが作成される。
なお、 -t でカーネル関数を選ぶ事ができる。0にすると線形カーネル,2にするとガウシアンカーネルになる。
(デフォルトはガウシアンカーネル)その他のパラメータなど詳しくは→http://www.csie.ntu.edu.tw/~cjlin/libsvm/

1-2.モデルの検証


モデルの検証を行うコマンドがある。とくに別途検証データがないので、入力データを食わせてみる。

java svm_predict input.txt input.txt.model output.txt



このコマンドの結果は以下のように出力される。

Accuracy = 70.1219512195122% (115/164) (classification)



Accuracyは、input.txtのデータ行に書かれたクラス名と生成されたモデルで判別されたクラス名が正しかった割合である。

(元ネタデータを使っているのに100%でないのは、モデルを作るときに外れ値が捨てられたのだろう、と今の所解釈している。)

output.txtは以下のように出力されている。

1.0
1.0
2.0
2.0
...


これは、モデルを使って判別された行ごとに出力されている。

2.判別


javaコードの中で、モデルのロード、判別対象にしたいデータの作成、判別を実行する。


// モデルのロード
svm_model model = svm.svm_load_model("input.txt.model");
...
// 判別対象にしたいデータ
svm_node[] input = new svm_node[7];
input[0] = new svm_node();
...
// ラベルをセット
input[0].index = 1;
input[1].index = 2;
...
// 値をセット
input[0].value = "ラベル1のデータ";
input[1].value = "ラベル2のデータ";
...
//判別の実行
double v = svm.svm_predict(model,input);



の様に実行する。

以上。

・感想


ツールとしては、簡単に使える。

しかし当然ながら入力データとして何を選ぶかが重要。現在あまり認識率をあげられてないので、別の入力データを選ぼうと考えている。

あと、ガウシアンカーネルで、gammaをデフォルトで使うと元ネタデータを再度svm_predictした際にAccuracy 100%となるモデルができたが、このモデルを実際に使って別の入力データを判別させるとある一つのクラスにしか分別しない分別器になってしまった。gammaの値を小さくするとこの現象はなくなった。この辺り、現在カーネル関数やカーネルパラメータの選定よりもまず入力データを再考する事が有効と考えて、まだあまり深追いはしていない。
スポンサーサイト

OpenNI Java を試す (2)

2012年01月09日 03:39

今日はHandsGeneratorというクラスを触ってみた。目標は、手の動きを追う方法を調べる事。

他の○○Generatorと同様にcontextを与えて生成。

handsGen = HandsGenerator.create(context);

それぞれのイベントのオブザーバーの実装クラスを渡しておく。

handsGen.getHandCreateEvent().addObserver(...)
handsGen.getHandDestroyEvent().addObserver(...)
handsGen.getHandUpdateEvent().addObserver(...)

これだけでは何も起こらない。どっかでhandsGen.startTracking(Point3D)しないとトラッキングが始まらない。

(ここはサンプルのUserTrackerのままだが)まず、UserGeneratorを生成し、userGeneratorからskeltonCapabikityを取得する。skeltonCapabilityのCalibrationCompleteイベントのオブザーバを登録し、

userGen = UserGenerator.create(context);
skeletonCap = userGen.getSkeletonCapability();
skeletonCap.getCalibrationCompleteEvent().addObserver(...);


そのオブザーバーの中は次のような処理にする。キャリブレーションがOKだったら、SkeltonCapabilityのトラッキングを開始し、その後に右手のトラッキングを開始する。

if (args.getStatus() == CalibrationProgressStatus.OK)
{
skeletonCap.startTracking(args.getUser());
handsGen.StartTracking(skeletonCap.getSkeletonJointPosition(
args.getUser(), SkeletonJoint.RIGHT_HAND).getPosition());
}

以上で、何となく手の動きが追えるようになった。ただし、「RIGHT_HAND」と書いてあるのにどうしても左手をトラッキングしているように見える・・。

OpenNI Java を試す

2012年01月04日 03:18

先日Blogに書いた通り、Kinectを動かすためのJava環境を作ったので、OpenNIのお試しとして以前から作りたかった疑似3Dビューワー的な物(Kinectカメラ一個で取った3D画像の視点を変えられるやつ)をとりあえず作ってみた。

前回全く言及しなかったが、それぞれ以下のようなバージョンを使っている。

OS:Mac OS X 10.6.8
Java:1.6.0_29
Eclipse:3.7.1
OpenNI:MacOSX-v1.5.2.7

サンプルの作成には、OpenNIのSampleに入っていた、Java版SimpleViewerのソースコードを使い回す。

1.Depthを取得する
DepthGenerator depthGen = DepthGenerator.create(context);
DepthMetaData depthMD = depthGen.getMetaData();
ShortBuffer depth = depthMD.getData().createShortBuffer();

depthというShortBufferの中に 640 * 480 の長さで 0 から 10000の
short値が入ってる。(測定不能の場合0が入っているっぽいので、除外した方がよい)


2.カメラ画像(Image)を取得する
ImageGenerator imageGen = ImageGenerator.create(context);
ImageMetaData imageMD = imageGen.getMetaData();
ByteBuffer image = imageMD.getData().createByteBuffer();

imageというByteBufferの中に 640 * 480 * 3 の長さでRGB値が入ってる。
Color オブジェクトを作るには、以下のようにする。

Color color = new Color(image.get() & 0xff, image.get() & 0xff, image.get() & 0xff);

3.グルグルまわす部分を作る。
グルグルまわす機構は、とくにOpenNIは関係ないので省略。座標を再計算してimageに書き出して、Graphicsにpaintしているだけ。今回は20秒で鉛直方向を軸にしてくるくる周り続ける機構を作った。


以上、画像を貼りたいが家が汚いので貼らないことにする。

---
疑似3Dビューワーとして格好いいのは
Kinect RGBDemo v0.6.1
などがある。

Mac と Eclipse で Kinect を使う

2011年12月29日 23:49

Kinect発売から一年以上 経ちましたが、最近家族用にXBOX360 Kinect パックを買ったのでとりあえず Macに繋いでみるまでやってみました。あと、あまり敢えてJava版使っている人多くないような気がしたので使ってみました。

1.Kinect用ACアダプタを買う
XBOX360 Kinect パックを買うと、USB変換アダプタ付きACアダプタが同梱されていません。楽天で売ってたので購入。

2.Macにlibusbをインストール
MacPorts で libusb-devel+universal をインストール。
(+universal本当に必要だったのかは不明)

MacPortsでうまくいかない事があったら、とりあえず

sudo port -v selfupdate

sudo port -v upgrade outdated

してみてから考えよう。

個人的には、OS10.5から使ってるMacports環境だったので、arch ppc というエントリが残っててglib2のインストールでハマった。

3.OpenNI, KInectドライバのインストール

Opien NI は以下のサイトから

http://www.openni.org/Downloads/OpenNIModules.aspx

-OpenNI Binariesを選択するとOSごとのバイナリが出てくるので、MacOS用を選択しダウンロードボタンを押す。その後、install.shを実行

-ドライバは

https://github.com/avin2/SensorKinect/tree/master

からダウンロードして、MacOS用フォ
ルダを取得、その後、install.shを実行

4.Java版サンプルの実行

Eclipseのワークスペースに次のようなディレクトリ構造を作成(例)
libにあるdylibはOpenNIのLIBフォルダからコピーする。org.OpenNI.jarもOpenNIのJarフォルダからコピーする。

Eclipse

上記ディレクトリ構造の場合、Eclipseからサンプルアプリケーションを実行する際には、Run CofiguraionでJVMパラメータとして -Djava.library.path=lib を渡せば良い。


以上です。やっぱりJavaだと起動に少し時間かかかりますね。



上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。