2012-01-29
エンジニアサポート新年会 CROSS 2012でEmotivについてLTをしました
日本ではあまり使っている人を見ない筋電/脳波ヘッドセットのEmotiv EPOC neuroheadsetを使ってみた。デモはNodejsでデータ飛ばしてCanvasに描画した。視線の位置のxyが取れるのでそれを使った方が面白かったかなぁ。
JavaのコードはSDKのサンプルをベースにJSON作っただけ。状態を取る部分のコードは次の通り。
JSONObject currentState = new JSONObject(); Edk.INSTANCE.EE_EmoEngineEventGetEmoState(eEvent, eState); float timestamp = EmoState.INSTANCE.ES_GetTimeFromStart(eState); JSONArray actions = new JSONArray(); if (EmoState.INSTANCE.ES_ExpressivIsBlink(eState) == 1) { actions.put("Blink"); } if (EmoState.INSTANCE.ES_ExpressivIsLeftWink(eState) == 1) { actions.put("Left Wink"); } if (EmoState.INSTANCE.ES_ExpressivIsRightWink(eState) == 1) { actions.put("Right Wink"); } if (EmoState.INSTANCE.ES_ExpressivIsLookingLeft(eState) == 1) { actions.put("Looking Left"); } if (EmoState.INSTANCE.ES_ExpressivIsLookingRight(eState) == 1) { actions.put("Looking Right"); } if (EmoState.INSTANCE.ES_ExpressivIsLookingDown(eState) == 1) { actions.put("Looking Down"); } currentState.put("actions", actions); currentState.put("Excitement ShortTerm", EmoState.INSTANCE.ES_AffectivGetExcitementShortTermScore(eState)); currentState.put("Excitement LongTerm", EmoState.INSTANCE.ES_AffectivGetExcitementLongTermScore(eState)); currentState.put("Engagement Boredom", EmoState.INSTANCE.ES_AffectivGetEngagementBoredomScore(eState)); currentState.put("Frustration", EmoState.INSTANCE.ES_AffectivGetFrustrationScore(eState)); currentState.put("Meditation", EmoState.INSTANCE.ES_AffectivGetMeditationScore(eState)); send("state", currentState.toString());
2012-01-08
キネクハトッカーズマニュアルのサポートページを更新しました。
サポートページ作成時点からかなり状況が変ったので、いろいろと修正しました。OpenNIの進化や、WebSocketでバイナリが使える様になった事など。半年も経てば随分と変る物ですね。
「キネクトハッカーズマニュアル」補足資料 ― Kinect Book Support v1.0 documentation
http://hagino3000.github.com/kinectbook/gen/html/appendix.html
2012-01-02
OpenNIをopenFrameworksから使う Advanced編
OpenNI Advent Calendarの20日目の記事です。
24日目の記事でもopenFrameworksについて書かれているので、内容がかぶらない様にしています。
OpenNIをOpenframeworksで使う
http://blog.hi-farm.net/2011/12/24/openni%E3%82%92openframeworks%E3%81%A7%E4%BD%BF%E3%81%86/
何故24日目の記事の方が先に公開されているかは気にしないでください。oFについて基本的な事は上記 @mmlemon_twitter さんの記事に書かれているので割愛します。あと、oFはMacユーザーが多いのでMacOSX + Xcode4の環境を前提に書きます。
ofxOpenNIについて
oFのaddonの一つ。OpenNIをoFっぽいインタフェースで扱える様にした物。誰のブランチを使っていいのかわからないけど、gameoverhack氏のブランチが一番forkされているので自分が使う時はそれを使っている。
gameoverhack/ofxOpenNI - GitHub
https://github.com/gameoverhack/ofxOpenNI
DepthGenerator, ImageGenerator, UserGenetator, HandGenerator, IRGenerator, GestureGeneratorの機能はカバーしていて、 exampleを見れば大体の使い方は掴めるはず。ofxOpenNIのジェネレータから得られるデータは、既に世界座標から表示座標系に変換されているため、そのまま表示に使う事ができる。
チルトモーターの首ふりも実装されているが、内部でlibusbを使っているためかMacOSでしか動作しない。Windowsでも首ふりしたかったらOpenNIのXnUSBを使う実装に書きかえれば良い。
リポジトリにある物はKinectで使う事が想定されているらしく、Xtion Proではそのまま使えない。SensorKinectの代りにSensorモジュールを自分でビルドして上書きすればいけそう。あとOpenNIのバージョンも古いので注意。今から使う場合は自分がメンテナになる勢いで使っていかないと厳しいだろう。
アドオンを使わない方法
さて、ofxOpenNIを紹介したが、現在自分の作業マシンにはKinectでは無くXtion Pro liveが接続されているのでofxOpenNIは動かない。なのでoFのプロジェクトにOpenNIを普通に追加して使う時に気にする事を書きます。
config.xmlがアプリケーションの内部に配置される様にする
Build Phasesで「Add Build Phase」してOpenNIの設定ファイルをビルドした.appファイルの中にコピーする。しておかないとHoge.app単体を配布して動作させた時にconfig.xmlが見つからない、とエラーになってしまう。
OpenNIの初期化コードは次の通りになる。
xn::EnumerationErrors ctxErrors; static string configFilePath = ofFilePath::getCurrentWorkingDirectory() + "../Resources/config.xml"; XnStatus rc = openNIContext.InitFromXmlFile(configFilePath.c_str(), &ctxErrors); if (rc != XN_STATUS_OK) { XnChar strError[1024]; ctxErrors.ToString(strError, 1024); throw std::runtime_error(strError); }
updateメソッドでfpsを落さないようにする
updateメソッドで注意しないといけないのは、WaitAndUpdata系のメソッドを毎回使うと、ofSetFrameRateでフレームレートを指定していてもブロックがかかりfps30程度に落ちてしまう。fpsに影響を与えたく無い場合はジェネレーターのWaitAndUpdateDataを呼ぶ前にIsNewDataAvailableで新しいデータが来ているかチェックする。ofxOpenNIではupdateメソッド内でWaitAndUpdateDataを呼んでいるため、フレームレートが30fpsに落ちてしまう。
コードは次の通り。
// 各種ジェネレータとOpenNIコンテキストはヘッダファイルでメンバとして定義してある。 void testApp::update(){ if (depthGen.IsNewDataAvailable()) { // 深度データの更新 depthGen.WaitAndUpdateData(); xn::DepthMetaData depthMetaData; depthGen.GetMetaData(depthMetaData); XnMapOutputMode mapMode; depthGen.GetMapOutputMode(mapMode); int width = mapMode.nXRes; int height = mapMode.nYRes; int numPixels = width * height; float* depthHist = createHist(&depthMetaData, numPixels); const XnDepthPixel* depthPixels = depthMetaData.Data(); for (XnUInt i = 0; i < numPixels; i++, ++depthPixels) { grayPixels[i] = depthHist[*depthPixels]; } grayImage.setFromPixels(grayPixels, width, height); } if (imageGen.IsNewDataAvailable()) { // ビデオカメラ画像の更新 imageGen.WaitAndUpdateData(); xn::ImageMetaData imageMetaData; imageGen.GetMetaData(imageMetaData); colorImage.setFromPixels((unsigned char*)imageMetaData.RGB24Data(), colorImage.width, colorImage.height); } if (audioGen.IsNewDataAvailable()) { // オーディオの更新 audioGen.WaitAndUpdateData(); ofLog(OF_LOG_NOTICE, "Audio data size:" + ofToString(audioGen.GetDataSize())); // doSomething } } void testApp::draw(){ ofScale(0.8, 0.8); // 深度画像の描画 grayImage.draw(0, 0); // ビデオカメラ画像の描画 colorImage.draw(640, 0); }
どうしてもupdateメソッド内がごちゃごちゃしてくるので、OpenNIの処理を分離するためのクラスを一つ作るのが良いだろう。Audioジェネレーターはこの記事のために初めて使ってみたが、安定して動作しなかったので特に何も処理は実装しなかった。*1
コード一式はgistにアップしてあります。
openFrameworks + OpenNI Sample ― Gist
https://gist.github.com/1547820
openFrameworks + Kinectな作品
Vimeoで検索するといろいろ見つかる。
自分のおきにいりはWebcam Piano 2.0 Teaserという作品 (Kinectは使っていないけど)
まとめ
android対応も進んでおり、openFrameworksも発展も楽しみなプラットフォームです。OpenNIと一緒に使えるようになっておくと良いかもしれません。openFrameworks + Kinectについての解説はキネクハッカーズマニュアルにもページを裂いて書いたので、興味のある方はチェックしてみてください。
- 書名
- キネクトハッカーズマニュアル
- 著者
- @hagino3000 + 小野 憲史
- 発売日
- 2011-08-26
- 価格
- 2,604 JPY (256ページ)
2011-12-19
OpenNI/NITEのボーントラッキングが劇的に進化していた件
第3回Kinectハッカソン無事に開催できました。レポートっぽい物はShibuya.NIのサイトにアップするとして、OpenNI + Xtion Pro liveで今日試した事など。
ポーズ不要
NITEを1.5.0 unstableにすると、ユーザー検出からポーズ検出をすっ飛ばしてボーントラッキングが開始できる様になった、以前まで必要だった学習データも不要。適当に動かしてみたら、たまたまその場にいた4人をいきなりトラッキングして普通に動いていた。重すぎて描画が遅れるという事も無かった。動画撮ればよかった。
Kinectポーズという単語は最早死語、「OpenNIはポーズを取らないと骨格取れないんですよ」とドヤ顔をする事はもうできませんね。
上半身のみボーントラッキングが動作した
トラッキング開始時にSkeletonCapabilityに渡すXnSkeletonProfileについて。大抵はXN_SKEL_PROFILE_ALLを渡して頭から足までのジョイントを得ると思うが、自分は 机に座る→作業→退席 の動作を正面からトラッキングしたかったので上半身だけで十分。下半身は見えないだろうし。
1.3.4: XnSkeletonProfile
http://openni.org/docs2/Reference/_xn_types_8h_a294999eabe6eeab319a61d3d0093b174.html
そこで、上半身のみのジョイントをトラッキングするXN_SKEL_PROFILE_UPPERを使うとこうなった。
頭と手だけもいける
頭の位置を取りたいだけならXN_SKEL_PROFILE_HEAD_HANDSで十分だった。ユーザー検出と同時に頭部の中心座標が取れるので、用途によっては顔認識よりも便利。横顔でも後ろ頭でもいける。始終静止状態の人は検出できないけど。つまり、全身を入れてポーズを取るのが不要になったおかげで、上半身のみや、下半身のみしか見えない状況においてジョイントのトラッキングが可能になった。
正面を向いてるかどうか
OpenCVの物体検出で正面顔の学習データを使ってみた。頭の位置は既にわかっているので、うまくやれば計算量は減らせるはず。cvHaarDetectObjectsに検索領域とか指定できればと思ったけど、そんなオプション無かった。
顔の向き
頭部の深度の平均値を使ってなんとなく傾きを得る方法を@molant3さんに教えてもらった。
Xtion Pro liveは家電量販店でも買えます
中の人曰くそういう事だった。輸入した時は190ドルだったけど、日本価格25,000円なり。
Kinectよりも高いけど、重くてでかいKinectを毎日持ち歩きたくはないので自分はXtion Pro liveを使っています。
Mac App StoreにKinectアプリが増えていた。
3D Scannerというアプリ。Kinectが接続されていない、とかいうエラーが出て動作しない!! 170JPYが無駄に……!!
2011-12-17
Kinectプログラミングをより楽しむための、新分野入門の勧め
この記事はOpenNI Advent Calendarの15日目の記事です。
さて、この記事をチェックされる様な方であれば、ある程度はKinectセンサーとそのドライバについて知識はあると思います。さらに、それらを使って何かを作りたいと考えている人も多いでしょう。Kinectはとても魅力的なデバイスです、ある程度のプログラミング経験があればモーションキャプチャセンサーとして使えてしまう環境が整っており、デバイスを使った開発などした事もない人間でも簡単に扱えます。
しかし、実際にアプリケーションを作ってみようとすると、全く未経験の領域に足を突っこむ事に気がつきます。画像処理、音声処理、機械学習、コンピュータインタラクション etc…。それらについて既に習熟していれば問題は無いのですが、私の様な大学で生物を専攻してしまった*1人間には全くもって未知の分野。ここからは、私の経験を元にKinectプログラミングに関係するいくつかの分野に足を踏みいれるのに役に立ちそうな書籍や情報源を紹介します。
画像処理
なにはともあれ最初は画像処理でしょう。Kinect SDKやNITEのボーントラッキング、ユーザー認識は高度な画像処理技術によって実現されています。深度画像を表示したい、加工したい、といった場合。Kinect SDKで深度画像とビデオカメラの像を合せたい、という時に必要になる知識です。
最初の本はこちら。画像データってコンピュータ上でどう表現されているの、という所から教えてくれるのがこの本。簡単なフィルタ(ぼかし、シャープネス、グレースケール化)のロジックの解説からフーリエ変換まで載っています。やさしい入門書。
次の本。上の本よりも多くのフィルタ、変換ロジックが詳細に解説されています。デバイスの話から始まり、画像の性質、フィルタ、変換、動画処理、キャリブレーション、パターン認識、画像符号化、と一通り学べる感じ。内容盛りだくさんなので、気になった所だけ目を通した。図が多めで読み易い。
他の本は読んでいないのでわかりませんが、CV界隈の偉い人がオススメしていたので良い本なんだろうなと。本と並行してOpenCVを触ってみると、動作イメージが掴めるかと。
音声処理
画像処理よりもさらに経験した事のある人は少ないであろう音声処理について。Kinectといえばボーントラッキングみたいな印象があるけど、Kinect SDKは録音、音声認識、ビームフォーミングといったAudio APIもあります。
ソフトバンククリエイティブ
売り上げランキング: 45778
OpenNIユーザー = Macユーザー = iOS開発者という偏見を私は持っているので、ここではiPhone Core Audioの本を紹介します。音声のデジタル化の基礎の所(サンプリング周波数、量子化ビット数の意味)から説明があったので助かりました。コードを書いて実際にiPhoneで動かしながらオーディオプログラミングの要領が掴めます。Core AudioはMacOSXでも使えるので、OpenNIのAudio Generatorが実装されたらCore Audioを使ってあれこれする事が増えるのではと予想しています。
表現
openFrameworksやProcessingといったヴィジュアルプログラミングフレームワークの使い方は、プログラミング経験があるのであれば本よりもネットに公開されている動画とコードを読むのがてっとり速いです。最初はパーティクル飛ばしから。
フィルムアート社
売り上げランキング: 230935
メディアアートっぽい物が作れたけど、そもそも「メディアアート」って何?? みたいな疑問を持ったらこの本。メディアアートの歴史を解説してくれる。デュシャンの泉はこの本で知りました。
コンピュータインタラクション
(Computer Science Library)
NUIっぽい物を作りたいという人に。コンピュータインタラクションはどうあるべきか。これからどうなるのか、という内容がざっくりと。Kinect発売よりも後に出た本なのでKinectについても少し言及があります。
(有斐閣アルマ―Specialized)
人間は世界をどう認識するのか、という所の話。UIデザインやインタラクション設計にも絡んでくる。
機械学習
Kinect SDKのボーントラッキングに使われているあれ。顔認識や手書き文字認識も機械学習で実装されます。
OpenCVだと学習データ作って何個かコマンドを打てば検出器ができてしまうのですが、それがどの様に実現されているのか知りたくもなります。
本は読んでいないのですが、スタンフォード大学のオンライン講義に機械学習のクラスがあったので受けています。3週目に手書き文字認識の実装という課題が出ました。来季も機械学習のコースはあります。
Machine Learning
http://jan2012.ml-class.org/
とにかく数式が出てくるので、数式アレルギーの荒治療としても効果的。
まとめ
これだけの分野を全て習得するのは難しいでしょうが、一つでも深くやりこめば相当面白い物が作れると思います。OpenNIの使い方を覚えたら、次は上のどれかの分野に足を突っ込んでみてはいかがでしょうか。
*1:今でも後悔している















