SyntaxHighlighter

2011-12-23

Interface1月号の内容を試してみた

12月18日にKinect(など)ハッカソンというのがあったので参加してきました。
ちょうどInterfaceの1月号にKinectの特集が掲載されていたので、それを読んで勉強していました。勉強したのは、「Kinectのマイクロホン・アレーによる音声信号処理」(p.112-116)です。まわり全員がほぼカメラと遊んでいる中、たぶん一人だけマイクと戯れたいたみたいです。。。自分は天邪鬼的性格らしい。

自分の能力不足でいろいろはまったけど、一応記録しておきます。


git

まず、サンプルをgitで取得、というところで躓いてしまいました。gitクライアントなど自分のWindowsに入っていません。てか、gitよく分かんない。。。
参照URLにはzip形式のファイルがあることにはあるけど、サンプルのVisual Studioのプロジェクトがないので、自分でプロジェクトの設定をしないといけない。

サンプルのコンパイル

Visual Studioのプロジェクトファイルを自分で作ることにしたけど、C/C++のプロジェクトの作り方をすっかり忘れてしまっていました。戒めのために、書いておくと、
  • ソリューションエクスプローラー内の対象のプロジェクトを選択して、プロパティを選ぶ
  • 構成プロパティ>C/C++>全体 の「追加のインクルードディレクトリ」で、openrafのヘッダファイルのあるincludeディレクトリを追加
  • 構成プロパティ>リンカー>全般 の「追加のライブラリディレクトリ」に、openrafのLibファイルのあるlibディレクトリを追加
  • 同じく、リンカー>入力 の「追加の依存ファイル」に、openraf.libを追加
  • ビルド後、実行前にexeファイルと同じディレクトリにopenraf/bin以下にあるdllファイルがあるか確認、なければコピー
リンカーの設定で、ずっとdllのディレクトリを選択していて、かなり詰まってました。。。

スピーカーの設定

入力としてKinectのみを使用するサンプルは動いたけど、出力側のスピーカーを使用するサンプル(raf_ds.cppとか)が最初うまく動かなかった。raf_openを実行しても認識してくれなかった(raf_valid_device(da)がfalseになる)。
どうやら、スピーカー>再生デバイス>構成>オーディオチャネル の値を4チャンネルにしていたのが悪さしていたらしい。設定をステレオにすると認識してくれるようになった。サンプルプログラムは2チャンネルの出力デバイスを検索しているみたい。

謎の実行時エラー

出力も使用してraf_enable_stftを使用するサンプルでたまに、libfftw3-3.dllでエラーが出てたり出なかったりした。理由は全く分からない。自分の環境がMacのBootCampを使用しているからかも???



ちょっとした音源定位

何はともあれ、Kinectの4つのマイクからデータが取得できるようになったらしいので(本当に正しくデータが取得できているのかは確認しようがないけど。。。)、最後に http://www.enjoy.ne.jp/~k-ichikawa/soundLoc3.html を参考に、相互相関を使った音源方向を推定するプログラムを書いてみました。既にKinect SDKにあるのに、完全に車輪の再発明状態です。
テストなので、normで割っているとか、かなり無駄も多いし、怪しいところ満載な感じですけど。。

/* pとかcは、openrafのサンプルコードから */
static double p[4][3] ={
 -0.115,0,0,
 0.035,0,0,
 0.075,0,0,
 0.115,0,0
};
static double T = 15; // 室温
static double c = 20.055*sqrt(T+273.15); // 音速

static double VOLUME_TH = 0.05; // 音源定位を実施する音の大きさのしきい値


double correlation(float* X, int N, int channel, int c1, int c2, int t) {
 double R = 0;
 for(int n=0;n<N;n++){
  int tmpT = t+n;
  if (t+n < 0) {
   tmpT = t+n + N;
  } else if (N < t+n) {
   tmpT = (t+n) - N;
  }
  R += X[channel * n + c1 ] * X[channel * (tmpT) + c2];
 }
 return R;
}

double calcTheta(int Tau, int c1, int c2, double* theta) {
 if (Tau == 0) {
  *theta = 0;
  return 1;
 }

 double diffTime = Tau / 16000.0;

 double delta = c * diffTime;
 double length = sqrt(pow((p[c2][0]-p[c1][0]), 2) + pow((p[c2][1]-p[c1][1]), 2) + pow((p[c2][2]-p[c1][2]), 2));
 if (length > fabs(delta)) {
  *theta = asin(delta/length) * 180.0/M_PI;
  return 1;
 } else {
  return 0;
 }
}

double calcLikelyTheta(float* X, int N, double* norm, int channel, int c1, int c2, double* theta) {
 double maxR = 0;
 int maxTau = -1000;
 for (int t=-N/2; t<=N/2; t++) {
  double R = correlation(X, N, channel, c1, c2, t)/(norm[c1]*norm[c2]);
  if (maxR < R) {
   maxR = R;
   maxTau = t;
  }
 }
 int ret = calcTheta(maxTau, c1, c2, theta);
 if (ret) {
  printf("R:%e, t:%2d theta: %5f Volume:%3f\n", maxR, maxTau, *theta, norm[c1]);
 } else {
  printf("R:%e, t:%2d theta: N/A Volume:%3f\n", maxR, maxTau, norm[c1]);
 }
 return ret;
}

/* フレーム処理を行うコールバック */
void callback(const raf_vector& input, raf_vector& output, void* info)
{
 float* X = (float*)input.data;
 float* Y = (float*)output.data;
 int channel=input.M; int N=input.N;

 double norm[4] = {0,0,0,0};
 for (int i=0; i<N; i++) {
  for (int j=0; j<4; j++) {
   norm[j] += pow(X[channel * i + j], 2);
  }
 }
 for (int j=0; j<4; j++) {
  norm[j] = sqrt(norm[j]);
 }

 if (norm[1] > VOLUME_TH) {
  int NumT = 3;
  double theta[3];
  int NumOK = 0;
  int chpair[3][2] = { {3, 0}, {2, 0}, {1, 0} };
  for (int i=0; i<NumT; i++) {
   int ret = calcLikelyTheta(X, N, norm, channel, chpair[i][0], chpair[i][1], &(theta[NumOK]));
   if (ret) {
    NumOK++;
   }
  }
  if (NumOK >= 2) {

   double meanT = 0;
   for (int i=0; i<NumOK; i++) {
    meanT += theta[i];
   }
   meanT /= (double)NumOK;
 
   double sigma = 0;
   for (int i=0; i<NumOK; i++) {
    sigma += pow(theta[i] - meanT, 2);
   }
   sigma /= (double)NumOK;
   printf("***** Theta mean:%f sigma:%f *****\n", meanT, sqrt(sigma));
  } else {
   printf("!!!!! not enough thetas !!!!!\n");
  }
 } else {
//  printf("!!!! too small volume !!!!\n");
 }

 /* ESCキーが押されたらコールバックを抜ける */
 if (kbhit()){
  if(getch()==0x1b) raf_cb_complete(info);
 }
}

書いたは良いけど、会場が静か過ぎて、音を出すのがはばかられて、テストできませんでした。。。

お家へ帰ってから確かめてみた結果は、下記のとおりです。まあ、動いていないこともないかなあ、という感じです。コマンドプロンプトなど貼り付けても理解されないだろうけど。



今回の感想

  • 音系の製作は、ハッカソンのような人が集まる場所でやるものではない。
  • 画像に比べると、音は扱いにくいかなあ、やっぱり。画像だとOpenCVという有名どころで簡単に扱えるようになっているし、応用もいっぱい考えられているけど、音だと、どんなライブラリが結局良いんだろうか??応用も音声認識と音源定位以外になにかあるのかしら?
  • OpenNIの方が発展性がありそうな気がしてきた。。

2011-12-09

「フィジカルコンピューティングを「仕事」にする」をよんだ

とにかく、イントロダクションの対談とケーススタディの内容が素晴らしかったと思う。
プロトタイプピングの重要性と、プロトタイピングから実際のプロダクトに落とし込むまでの大変さについて教えてくれたような気がする。
逆に、チュートリアルのWillリモコンやArduinoなどの使い方の部分はあまり必要性が感じられなかった(記事の内容が悪いわけではないのだけど・・・)。この節よりもケーススタディとかの実際の活用シーンをもっと充実してくれたら良かったのになあ、と贅沢な事を書いてみる。。。

2011-11-23

odstudy 2011.11 に行ってきた

odstudyという主にドキュメントに関するらしい勉強会に行ってきた。
現在、サーバ・インフラの仕事をしていながら、純粋なそっち系の勉強会に行ったのは実は初めてのような気がする。その世界にも神と呼ばれたり、仙人と呼ばれる方々がいらっしゃるらしい。。。

テーマは「属人化をなくすために」ということで、前半トークセッション(LT)、後半がディスカッション+その発表でした。まとめとかはtwitterで#odstudyで検索すればそのうち見つかる事でしょう。。。

ディスカッションとその発表が面白く、色々考えさせられました。いくつか覚えている範囲で、勘違いも多々あるかと思いますが。(書いている時点でまだまとめとかが無いので、うろ覚えだけで書いてます)

  • 自分はディスカッションに参加したチームの内容だけど、ドキュメントをwikiで管理すると、情報が分散される→情報が何れが最新かとかが分からなくなる→結局人に聞く→属人化orz。を防ぐために、wiki書き方にルールを設けましょう、システム的に制限を加えると効果的(運用部隊に開発出来る人が居ると良いなあ。。。)。全てのドキュメントを同じレベルで運用すると死ぬので、レベル分けして、内容の精査とかもレベルに応じて扱おう、というのが参考になりました。
  • ディスカッションの中で、システムの変更にあわせて、システムの監視とかが自動的に追加されるような構成管理があると良いし、ドキュメントも自動で最新に変更されると良いねえ、なんて話も。とんでもなく難しいかと思いますが。
  • 属人化を排除した方が良いものもあれば、属人化はそれなりにメリットもある(SPOFが倒れない限りは障害対応が早い、標準化する時間が必要ない、小さい案件なら特に)。
  • ドキュメントはどの程度のレベルの人にあわせて書かなければいけないのか?グッド○○○の人でも出来るようにしなければならないのか、運用する側にもそれなりに知識レベルが必要で、属人化は排除し無ければならないが、属グループ化ならそれなりに行けるのでは?
  • ドキュメント管理にPDCAサイクルの考え方を導入して、継続的なメンテナンス出来るようにしよう。
  • ドキュメントを書く事によって属人化は排除出来ない。あくまで属人化の問題を減らすために行っている。ドキュメントは手順書ではなく、教科書だと思って書け。またドキュメントはあくまで自分のために書くと思えば、モチベーションとかも上がるし、真面目に書く。ドキュメントを書く事自体は(会社的に)評価されないこともあるので開発部隊が運用のためにドキュメントを書こうとしても、モティベーションが上がらない。運用部隊が自分たちのために(ドキュメントが無いと自分たちの仕事が出来ないから)、開発部隊に協力してもらって書いた方が良いのでは?
もうちょっとあったような気がするけど、などなど。色々参考になりました。会社の人達にも共有したいなあ、と思える事も多々。

最後にとてつもなくとりとめの無い個人的感想を、、、

  • 人が介在する以上、属人化って言うのは完全排除は無理なのだろうなあ。理想は、工場とかの一通り訓練を受ければ誰でも作業可能な製造ラインなんだろうけど、、、
  • でも、その人が倒れた時に最低限の引き継ぎが行えるように、ドキュメントを残しておく事は意義があるし、特に長期間のシステム運用においては立ち上げの時のメンバーと現在運用中のメンバーは大半が入れ替わっていて、その際の引き継ぎコストを下げるためには不可欠だろうなあ。
  • 個人的なドキュメントと属人化の問題って、ドキュメントを如何にメンテナンスしていくか?かなあと思っています。
  • システム構成が変わってドキュメントも修正する必要があるし、時にはドキュメントのリファクタリングも必要だと思っていますが、特にPDCAのPとDは出来てもC以降が難しい。時間がないとか、現在うまく行っているものを何故あえてメンテナンスして修正する必要があるのか、という心理的不安。さらには、手順はあっても何故その手順になっているのか、なぜこのようなシステム構成なのかと言う歴史的経緯や思想的な部分が、必ずしも残っていなくて(それこそ口答伝承されている程度)、手順を直したくても直す拠り所となるものが無い、とか。
  • システム運用においては、属人化は絶対に排除出来ない、その上で、その人が倒れた時に被害を何れだけ最小限に留めるか、という想定で進めた方が良いのだろうなあ。


考え始めると難しいなあ、しかも明確な答えなんて多分無いと分かっているのに。。。

あと、システム運用側以上に属人的になっているのは営業サイドのような気がする。営業倒れたら代わり居なさそう。人とのコミュニケーションが発生する以上、これも仕方ないかなあww。

2011-11-14

国際ロボット展2011

今更感満載だけど、ロボット展へ行ってきましたので、記録に残しておきます。
ロボットとか、コンピュータビジョンの世界からかなり距離が離れてしまっているので、かなり付いていけない部分が多々ありました。。。

  • 相変わらず、産業用ロボットアームとかスライダーとかがメインで、ロボット産業の主力はやっぱり産業工作機械向けなんだなあ、
  • ビジョンシステムやモデリングを中心に扱っているゾーンが今までになく狭かった気がした。でも、産業用機械のブースで当然のごとく画像認識と組み合わせた、知能ロボット製品が展示されていて、この分野で画像処理、コンピュータビジョンは無くてはならないのだなあと、改めて思った。
  • Kinectにはまっている人的に気になったのが、DENSOで参考出品されていた、市販の距離計測カメラ(要するにKinect)を使って、工場を3次元撮影して、その結果をCADにインポート、その中で新しいロボットが導入出来るスペースがあるか検討したり、2次元マーカを使って、教示システムを構成したり、ARを利用したシミュレーションシステムを構成してました。骨格情報が取れて、楽しいな、的なものを通り過ぎて、かなり本格的な感じがしました。精度とか、3次元データの統合方法とか、気になる。。。
  • 未夢が歌って、挨拶してました。川田工業のブースにHRP-2とHRP-4が並んで展示されていたけど、4はスリムだなあ、という感じ。2は一時期いろんな研究室で使われていたみたいだけど、4はどうなんだろう。最近、愛知万博の頃と比べてヒューマノイドロボット下火な感じらしいから、頑張ってほしいなあ。。。


次回は2013年の秋の予定らしい。

2011-11-03

Web Audio API

会社でこっそりと(!?)GDDのセッションのストリーミングを見ていたら、ChromeのWeb Audio APIとやらが気になりました。

そしたらちょうど、HTML5 Rocks というページに、チュートリアルがあったので読んでみました。
音を鳴らすだけじゃなくて、ローパスフィルタとかもあって、凄いなあ。音を鳴らすコマンドがnoteOn, noteOffって、なんかMIDIっぽい。
でもゲーム以外の用途が思い浮かばないのは、自分の知恵が足りないせいかしら><


HTML5ってどこまで行くのだろう。そのうち付いていけない人が多発しそうな。

2011-10-22

DCEXPO行ってきた

(会社休んで!)21日(金)と 22日(土)に未来館でやっていたDCEXPOに行ってきました。会社休んでまで、どんだけハマってるんだ、ってツッコミが怖いですが、楽しかったです。
金曜日は、ブースを見て回って、Kinectの開発講座を聴きました。土曜日はセンターステージのイベントやシンポジウムを聞いてました。


展示ブースで気になったもの
  • Kinectで取得したdepth情報を表示して、棒で粘土のように押しつぶす事が出来るVR体験システム、面白かった、押しつぶすモノによってはストレス発散にもなりそうww
  • テレビの世界遺産の3D。これは是非3Dで見たい

    センターステージ・シンポジウム
    • 球形飛行体:コンテンツの世界に防衛省!という自体そのものが驚きだけど、デモしていた球形飛行体自体も衝撃でした。お話も明朗で聞いていて楽しかったです(飛行理論云々や兵器の種類なんてさっぱりだけど)。アメリカの犬型(?)ロボットと、どっちがブットんだ開発か、競って頂きたい気がする。。。
    • Kinect開発講座:前半はマイクロソフトの方自らが、Kinectの概要とライブコーディングを行って、Kinect開発(の取っ掛かり)が如何に簡単であるかを紹介されていました。
      後半は大学の白井先生という方の講演で、これからKinectのような体を使ったゲームや操作が世界的に流行るという話を、歴史的経緯を交えながらお話しされていました。そして、実際使い物になるNUIを実現するのは難しい、いろんな人達が模索中で、解決策を見いだすと、学会で評価されたり特許ができる、というようなお話でした。前半は何度か聞いた事があるので、後半の講義が大変為になりました。ただ、この辺も特許合戦が始まっちゃうと、弱小開発者は立場が辛いなあと言うのも正直なところです。
    • 音手パフォーマンス:拍手する機械。自動拍手機能と、遠隔拍手機能があるらしい。○○するための機械と聞くと、明和電機の笑う機械を思い出すなあ。。。
    • シンポジウム ソーシャルコンテンツ大爆発うんぬんかんぬん:チームラボの猪子さん、IAMASの小林さん、FabLabの田中さんと、個人的にはそうそうたるメンバーと思ったシンポジウムでした。FabLabあたりの話から、展開が何やら、大量生産とカスタム生産についてがメイントピックになっていたような気がします。
      大量生産vs.カスタム生産と構図を促したいわけではなく(小林さんのおっしゃる通り、大量生産あってこそのカスタム生産と言う部分もあるので、この2つは対立構造ではない)、ソフトウェアがオープンソースという(ソーシャルな)ネットワークで発達したのと同様に、物理的なものをつくることもこれから同様な経緯をもって広まるだろう、ような話だったと思います。
      それに対して、そのパーソナルファブリケーションという運動の恩恵をアメリカは受けるだろうけど、日本は個人的なものつくりをしなくとも、下町工場(?)のような手取り足取り(格安で)作ってくれるプロフェッショナルな方々が沢山居るので(例えばこんなの?)、個人で一から作る事がそれほど広まるのか?と言うような、話もあり、興味深かったです。個人的には興味ある分野で、注視していきたいなあと思います。
      ゲーミフィケーションの話も聞きたかったなあ〜。
      あと、個人的にはフィジカルコンピューティングもARも(インタフェースの拡張という意味では)同じようなものじゃない?って思ってるんですけど、違うんですかねえ??
    • Tokyo AR Show:先生と名の付く職業に就く方々は歴史から入るのが好きらしいw(ペッパーの幽霊という元祖ARが紹介されていました)。Kinect使ってARDroneを操縦したり、ARマーカーをうまく使ってタッチパネルからロボットを操作するデモや、AR三兄弟の仕事内容とかが紹介されていました。
      一時期、そこら中で(企画やマーケティングを中心に)ARうんぬんと言われていた時期があって、消化不良気味だったけど、このステージはARっていろいろな可能性があるのね!って思わされました。
      球形飛行体のデモ
      音手のデモ
      その他の感想
      • そこら中でKinect登場し過ぎw。3D技術が多いのは、「国際3D FAIR」がDCEXPOの一部なのだから、当然なのだけど、それにも匹敵するKinect利用率である。14800円(小売り希望価格)は伊達じゃない!ってことか。この傾向が続くのなら、来年は協賛なり後援にMicrosoftが入って、「日本Kinect FAIR」がプログラムに追加されそうな気がする。
      • 先生と言う名の付く職業の方は、流行だけを追わずに、やはり考えている事が2歩3歩先を見ているなあ、というのをシンポジウムやブースを見て思いました。企業が何も考えていないと言うわけでは決してないのだけど、企業系のブースと大学のブースではちょっと見ている先が異なるのかな、と感じました。。。具体的に何処が?とは、言えるほどはっきりした考えではないのですが、ただ感じただけです。

      DCEXPOを見た後、森美術館でメタボリズムの未来都市展とドラゴンクエスト展を見に行くような人は、観客多しといえども、自分くらいのような気がする。。。
      でもこれも良かった。前者はいろいろ考えさせられましたし、後者は懐かしい!!、です。

      2011-10-16

      KinectのViewerとMercurial

      Kinectを触っていると、.Netが楽しくなってくる。とりあえずVisual Studioが便利で、.Netの豊富なライブラリがすばらしいと思えてくる。普段、自分が、ゴージャスな環境で、オブジェクト指向なプログラムを書いていないだけなのかも知れないけど。。。MicroSoftはKinectという餌で、Visual Studioユーザを増やそうというのが魂胆なのではないかとすら思えてくる。

      Kinect SDKのサンプルでSkeletonデータをCanvas上で2次元に投影して描写するというものがあったけど、任意の視点から表示できないかと考えてて、すると、3Dモデルが扱えないといけないわけで、OpenGLとかWindowsだったらDirectXか、で面倒だなあ(特にDirectXなんて触ったことすらない)と思っていたら、Viewport3DなんていうWPFのクラスが在りやがりました。.Net恐るべし。
      GUIのツールボックスには見当たらないのだけど(私は2010 Expressを使っているので、別バージョンだとあるのかも。。。)、XAMLのテキスト編集には直接書けるみたい。

      書き方はリンク参照のこと、だけど、OpenGLのコードを一度書いたことある人なら、それほど違和感なくかける感じです。とってもオブジェクト指向だから書き方は全く違うのだけど、雰囲気というか、考え方は一緒みたい。きっと実体はグラフィックライブラリのラッパなのでしょうね。

      めでたく.Netで3Dを描写する方法が分かったので、任意視点のSkeletonデータ表示が作れました。この程度の3Dなら問題なく動くようです。
      上から、のつもり。。。(左はいつもの2D投影、右が任意視点)

      横から、のつもり。。。(画像説明は上と同じ)

      各セグメントモデルは直方体としているので、もう少し色を変えるなり、幅を変えればもう少し、見栄えが良くなるかも。間接角度等を追加で表示させられたら、プログラムでデバックの一助になるかも知れない。
      ただ、素の.Netだけで頑張ろうとしている人ってどれ位居るんだろう・・・?


      で、話がガラッと変わって、先日(15日)にPython Developers Festaというかなり異業種交流会的な勉強会で、Mercurialという分散バージョン管理システムのハンズオンを受けて、Mercurial派の軍門に下ってきました(ちなみにまだgitは触ったことありません)。
      そして、bitbucketというサービスで(無料で)使えるということで、せっかくなので初めて登録して使ってみました(ソース暴露デビュー??)。
      https://bitbucket.org/ffuyyo/kinect_skeleton_viewer
      と言いつつ、まだbitbucket使い方とか全然わかってません。ハンズオンはMacだったのでコマンドラインも楽だったけど、WindowsでTortoiseHgを使ってみたけどよく分からない。やっぱりWindowsで開発は難しい、、、あれっ????
      こういう使い方で良いのか?とか、こんなファイルを登録して大丈夫?とかとっても気になるけど、まあ、まだこれしか登録していないので、失うものは何もない。。。(多分)


      この記事の内容が異種格闘技戦っぽくなってきた、、、

      2011-10-10

      「アジャイルサムライ」をよんだ

      最近、開発方法というか、仕事の方法にいろいろ思うことがあって、アジャイルとか勉強したくなったので、読んでみた。
      教科書的な難しい用語の解説とかは特になく、アジャイルと言う考え方をどうやって使っていくかと言う実践的な内容のようです。

      素直な感想としては、「明日からあなたの仕事が劇的に変わる」的ではないのだなあと思った。銀の弾丸なんてないのだからしようがないのだけど。本に書いてあることを素直に導入できれば良いのだけど、環境によって適用できるものが違うので、ここの環境に合わせてみんなで考えて、実践していく必要があるらしい。
      もし、仕事にこの考え方が取り入れていけたら、今の状況より改善しそうな気はするけど、実際実践するのはとっても大変で、発想の転換が必要で、勇気のいることだなあと思った。

      機会があったら、実際に実践している人達の、ビフォー・アフター的な話が聞いてみたいなあ、と。

      2011-10-08

      CEATEC行ってきた

      デバイス・部品系は商談スペースもあったりしてビジネスっぽいのだけど、ネットワークとかパーソナル系は例のごとく文化祭っぽい雰囲気で、業務時間中に行きにくいのよねっ、ましてやサーバ屋さんが業務として行くのは許可されなさそうなので、土曜日に行ってます。

      ただ何年も行っていると、去年も見たなあ〜、ってやつや他のブースとの違いが分からない(エコXXXXとかホームネットワークとか裸眼立体視とか・・・)のが多くなってきて、数年前に初めて行った時の驚きが少なくなるのはしようがないところかなあと。。。細かい違いが分かるほど勉強・情報収集がなってないだけなんでしょうけど。

      以下つまみ食い感想
      • KDDIの新感覚スマートフォン ボタン押してる感が出て面白かったけど、今までのタッチパネルに慣れきってしまうと、逆に違和感を感じるかも・・・
      • KDDIの自由視点コンサート コンセプト自体はお台場のsonyのエクスプローラサイエンスで似たようなものを見たことがあるような気がするけど、映像をプラスして、商品一歩手前まで持ってきたのが凄いところなのかなあ
      • sharpの超高精細な液晶テレビ 中途半端な3D映像よりも映像酔いしそう。。。それだけ綺麗ってことだけど
      • IntelでARとかロボットスーツとか とっても違和感を覚えつつも、いろんな技術でインテルはいってるってことらしい
      • コンテンツエクスペリエンスゾーンの研究紹介 自由視点生成の研究で、あらこんなところにもKinectが。この撮像装置は研究の分野にも大きな影響を及ぼしているらしい感じがする。
      • CEATECで発表されて実際製品化されたものってどれ位あるんだろう???
      そして最後に本の即売会(10%off)でアジャイルサムライを買ってみた。いつもの展示会的展開。。。

      2011-09-07

      kinect勉強会vol.3 に行ってきた

      昨日ありましたので、行ってきました。名だたるマイクロソフトセミナールームでMac, iPad率の高さに、かなり、挑戦的な勉強会だったような気がします。そして、セッション内容もMS Kinect SDKをまともに扱ったのはマイクロソフトの方の発表のみという。。。
      そんな状況でも天下のマイクロソフトさまは寛大な心で見て見ぬ振りをしてくださったことでしょう。

      既に良質なまとめブログとかがあるようですので、あんまり細かいことは書きませんが、Kinectのドライバだけでなく、Kinect自体にもライセンスと言うか、使用を制限する文言があるってことは驚きでした。罠は思わぬところに張ってあるのだなあ。

      あと、NUIって何ぞや、的な話が出てきて、PCはNUIに向かないということらしい。まあ、キーボードとマウスを使うことを前提に今まで発展してきたものだから、同然っちゃ当然なのかも。これから出てくる、新しいデバイスやらなんやらのためのUIなのかも。安直に考えるとSignageとか??
      個人的には、NUIとは、人々の普段行っている自然な動作を、情報システム(上述のごとく、NUIの文脈でPCはそぐわない?)にアクセスにマッピングする行為、的な考えを推したいところだけど。Content Awarenessだったっけ?、を言い換えただけだけど。。。

      この辺も勉強し直すかな。。

      2011-09-05

      「キネクトハッカーズマニュアル」を読んだ

      タイトル通り。斜め読みした感じですが。全文カラー、素晴らしい。

      内容は、Kinectに関する内容が幅広〜く取り扱われていて、メインはKinectハックのやり方が書かれている感じです。特定のフレームワークに限定せずに、OpenNIとかMicrosoftのSDKだとか、それらを便利に使うためのopenFrameworksを使った方法などが紹介されていました。また、Kinectで画像を扱う場合はほぼお世話になるだろう、OpenCVは一章設けてありました。
      そうは言いつつ、それぞれのフレームワークの(一部を除いて)細かいところは深入りせず、とりあえず使えるようになって、簡単なサンプルが作れるところまでを重点的に示されているようです。使い方以上に突っ込んだ内容は、各種専門のドキュメントを参考にする必要があるかと。Kinectハック初めての人や、今までOpenNIなど特定のフレームワークしか使ったことがなかったけど、他のSDKとかどうなんだろう?という人向けなのだと思います。

      KinectやOpenCV以外の、node.jsやらHTML5関連の技術がほぼ説明なしで使われているところは、普段Web開発している人向けに書かれているためかなあ(何故かは知らないけど、Kinect界隈で遊んでいる人達は、Web技術者が多いらしい。勉強会とか見てると。。。)。普段C++も書かない、Web開発にも関わっていない(私みたいな)人だと、特に後半ちょっと辛い部分があるかも。。。

      あと、個人的な感想:
      • 所々に書いてあるコラム的な、KinectのSDK等に使われている技術や、NUIに関する話題が楽しく読めました。
      • 一つに縛られない、ある意味発散系な内容で、個人的には好きです。
      • 認識系のOpenCVが書かれているなら、折角だから、表示系に関するOpenGLとかも書かれていたらなあ、と思います。認識系はそこそこにインタラクティブに魅せる作品が多いことを鑑みると、需要は多いはず。
      • 真面目に読み解いていないけど、ソースコードが場所によって雰囲気が違ってる。書いた時期が異なるだけなんだろうけど。そんなものなのかしら。
      • これを読むとKinectとか使って何か作りたくなる気分になる
      だれか、音声系もレクチャーしてくれないかな。。。

      2011-08-29

      KinectでFFT

      注)β時代のSDKを使っていた頃の記事です。最新版では動かないと思います。。。

      KinectのマイクロフォンからのデータをFFTできたら面白いかなあと思った続き。

      いろいろあって、すごく時間が空いてしまったような気がするけど、とりあえず、kinectのマイクロフォンのデータを取得する関数からの出力を使って、FFTができるようになった。

      いろいろ変なところもあろうが、該当部分のソースを晒してみることにした。

      • FFTの本体
      const int fftLength = 1024;
      byte[] rawData;
      const int rawDataLength = 1024 * 2;
      AForge.Math.Complex[] fftBuf;
      
      public void doFFT(Stream audioStream)
      {
        int recordLength = rawDataLength;
        while (recordLength > 0)
        {
          int count = audioStream.Read(rawData, 0, recordLength);
          recordLength -= count;
        }
        for (int i = 0; i < fftLength; i++)
        {
          fftBuf[i].Re = (rawData[2 * i + 1] << 8 | rawData[2 * i]);
          fftBuf[i].Im = 0;
        }
        AForge.Math.FourierTransform.FFT(fftBuf, AForge.Math.FourierTransform.Direction.Forward);
      }
      
      • 使う側
      using (var source = new KinectAudioSource())
       {
         source.SystemMode = SystemMode.OptibeamArrayOnly;
         using (var audioStream = source.Start())
         {
           while (true)
           {
             doFFT(audioStream);
           }
         }
      }
      

      ぶっちゃけ、これだけ。あとは枝葉末節(AForgeライブラリに関しては、以前の記事を参照のこと)。


      スピードは、FFTの処理自体は付いてきてくれているはずだけど。。。この後、前回記事のように、FFTの結果をスペクトルっぽく表示しているのだけど、ちょっと遅れているように感じる。。。どこか悪いのだろうか??
      あと、関数から取得できるデータって、1入力だけなのかしら。マイク4つあるはずだから、4入力取得できる方法があるのかしら(しっかりマニュアル読んでないだけだけど)。


      しかし、慣れてないせいもあって、C#、というよりWindowsで図とか表示するの難しいなあ。KinectやらFFTで悩んでいる時間より、画面に図形とかを表示する方法が分からなくて悩んでいる時間のほうが長いや。。。


      2011-08-21

      勉強会2連戦

      この土日に勉強会と言うか、カンファレンスと言うか、に連続して参加してみた。これこれ(全くアクセサビリティのない書き方。。。)。普段の会社の仕事よりも頭使ったんじゃないかなあとすら思えます。。。

      どちらも、熱い内容で(天候は寒いくらいだったけど)、大いに刺激を受けました。

      Javascriptが今流行ってるということで、ちゃんと勉強して、技術をキャッチアップしていく必要があるなあと改に思いました。

      HTML5に関して思ったことが、まだ勧告という形で標準化されていないから様子見、ではなくて、まだ標準化に至ってないからこそ、どんどん使って広めていくべきものなのかなあと。。。多分、積極的に使用しているところはそんな心意気でやっているのかも??

      技術面だけでなく、コミュニケーションとか、考え方とか、それ以外の部分も大切だなあと思う次第です。どちらか一方が欠けても駄目なんだろうなあ。。。とか言って経験とかないうちに思想とか語っても空しいだけだけど。

      普段、サーバ管理とかのインフラ寄りの仕事をしている人間が、Javascriptとかの開発系のイベントに行くのは、とってもアウェー感漂って、参加している方と話す時に、話があうのかなあと尻込みしてしまうのが、いつも思うことなんだなあ。。。どうなんだろう。でも開発楽しそうなんだよねえ。。。

      あとは、色々勉強会とか行くとどれも面白そうで目移りしてしまって、結局何れも中途半端になりがちなので気をつけないと。

      なんかとっても日記っぽいブログになった。多分理解できる人はいない。(未来の自分も含めて)

      2011-08-13

      横浜トリエンナーレ

      に行ってきました。暑かった。

      前回(2007年?っだったけ?)に比べると、会場が集められているためかどうかは分からないが、こぢんまりした印象を受けた。ただ、個人的には、前回は全く意味が分からなくて、置いていかれている感満載だったったのに対して、今回はぶっとんてる感は小さいけど、あまりアートとか分からない自分でも楽しめました、と思います。

      本展は回れたけど、特別共催部分は全く見てないので、涼しくなったらまた行こうかしら。。

      2011-08-08

      バイオリン発表会

      8月6日にバイオリンの発表会で発表してきました。2回目です。
      今年は、葉加瀬太郎のエトピリカを弾きました。会社で得意先でプレゼンしたり、普段人前で話したりとかが全くないので、かなり緊張しました。ただ、去年の足がガクブルというような最悪状況に比べれば、今年は手の震えだけで済んだので、まだましかなあ、、、と。
      緊張なんて場数を踏むしかないのでしょうね。

      曲自体は、最初は2ページだけの短い2分ぐらい(になるように編集された)の譜面を渡されたのですが、その後、1枚追加(アドリブ部分でこれがとっても難しかった!!)されてしまいました。。。。
      そこで、何とか譜面を2枚に収めようと、MuseScoreというフリーの楽譜作成アプリを使って譜面を清書しました。このアプリ、所々バギーな部分はあるにせよ、なかなか便利で、PDFやサウンドファイルとして保存が出来ます。これをiTunesのライブラリに登録して、毎日通勤途中でイメージトレーニングしてました(保存形式にmp3もあったらより便利なのに。。。)。
      クラスの人たちとあわせる時も、ピアノは弾けないけど、このサウンドファイルがあることで合わせる練習がスムーズに進めることができました。音源自体は、YouTubeとかにごまんと転がっているけど、同一のアドリブ分なんて見つからないので、重宝です。
      なんかとっても現代風な練習っぽい???

      ただ、過信は禁物で、本番は当然生ピアノが伴奏にありますし、弾いている人は当然人間(しかもピアノの先生)。楽譜通り弾いてたまるもんですか的なところがあったり、バイオリンを弾いている人達のレベルや曲の難易度に合わせて、スピードを変えて下さるのでした。
      機械的に作った音で練習する時は、参考程度に留めよう、というのが教訓です。。。


      その打ち上げの席で、ビブラートが出来るようになるにはまだ、一年くらいかかると言われてしまいました、まだ先は長い。。。

      2011-07-10

      FFT

      MSのKinect SDK betaで取得できるマイクからのデータを、フーリエ変換できたら面白そうだなあと思いつきで、C#でFFTが行えるライブラリを探していました。そしたら、AForge というライブラリを見つけた。あまり日本語解説が見当たらないけど、ページを軽く見てみると、NeuroとかMachineLearningとかが見えてなかなか面白そうと思う機会があったら別の関数も試してみたい。
      ただ今回はFFTがしたいだけなので、AForge.Mathだけが必要のようだ。
      ほかにもC#でFFTができるライブラリはあるらしいけど、とりあえずやってみる用途だと、これが一番簡単そう、ということで、とりあえず使ってみた。(FFTなんて学生時代のプログラム課題以来だなあ・・・)

      Kinectとかとりあえず忘れて、難しいことはすべて置いておいて、単純にwavファイルからFFTを実施した結果。何とか窓関数はまったく使ってないです。
      ちゃんとそれらしいグラフが得られているような気がするけど、確かめる術はないなあ。。。

      FFTより画面に描写している時間のほうが長いような。。。

      でもって、ここから先に進める日は何時のことだろうか???(きっとそのうち忘れそう・・・)

      2011-06-29

      ウェブオペレーションという本を読んだ

      ウェブオペレーションという本を、見た目的に興味深かったので読んでみました。

      開発者と運用者の壁というかいがみ合いというか、お互いがお互いの足を引っ張りあっているというか、お互いがお互いを、アイツ使えね〜と思っていると言うのは、どこにでもあるのだな〜と思えてきます。
      特に興味深かったのは、4章と10章と16章あたり。アジャイルとかも言葉ぐらいしか知らずに、分かったような分からないような知識しかないので、これを気に少し勉強してみようかな〜と、思ったりもするのでした。

      ちなみに、本を読んだ時に、次これ読みたいと思ったり、これ勉強してみたいと思わせる本が、自分の中で良い本の一つの定義だったりしてます、、、、全然関係ないですが

      2011-06-04

      kinect勉強会に行ってきた

      今更だけど、kinect勉強会vol.2 に行ってきました。とても参考になる面白い会でした、主催者さま、発表者さま、事務局のみなさま、ありがとうございました。
      ただ、平日夜(しかも金曜日じゃない)、大森、遠い。


      勉強会のUstとすばらしいまとめが、Team-lablogにあるので、とくに自分なりのまとめをするつもりはなくて、例によって感想をつらつらと書くだけです。

      「ちょっと深いOpenNIとNITEの話(でも初心者歓迎!!) 」
      OpenNI、NITEとは何ぞやと、その中身について、でした。OpenNIをようやく、発表者さまの本を買って勉強し始めたところなので、どういうものなのか今ひとつ理解してませんでしたが、いろいろなことが難しい画像処理をすることなく実現できそうで、使いこなせるようになると楽しいなあと思いました。

      「OpenCVとKinect」
      こっちは反対に、OpenCVを使って画像処理をごりごり頑張っていく話でした。色々な開発事例が紹介されてどれも興味深かったです。チームラボにはコンピュータビジョンを使った案件を色々行われているようで、大変うらやましく思います。。。

      「NUI(Natural User Interface)とKinect」
      kinectを使って、どのようにNUIを行えば良いのか検討していました。学習データを作る方法は大変参考になりました。脳波センサーも興味深い。
      質問で、既に発表者さまが説明していたのに、自分が、あまりしっかり聞いておらず、あまりに低レベルな質問をしてしまいました。申し訳ない気持ちで一杯です。以後気をつけます。

      (LT)「kinect on HTML5へぇ~」
      発表者さまが操作すると、みんなのPCのブラウザ上に表示されたスライドが同期して動く、さらにkinectのスケルトン情報を表示させる、というものすごい発表でした。HTML5すげえなあ。。。

      (LT)「SPECIFICITY チームラボ」
      是非、体験してみたい。

      (LT)「Kinectゲームつくってます」
      kinectで対戦ゲームを作ってる(アメーバピグのキャラクターで)、ってお話。普通にXBOXのゲームで出てきそうです。。。
      #ああそうか、kinectって今のところゲームで遊ぶ用の機器なんだよね。。。

      (LT)「MSのくせになまいきだ チームラボ」
      kinect->MAC->arduino->willリモコンをつないで、カービィーで遊ぶ、というお話。こういう話大好きです!!

      全体の感想

      • ある程度高度なことをしようとすると、機械学習等を使用したちゃんとした物体認識が必須みたいだなあ。すると、個人で遊ぶレベルを超え始めているような。。。その意味では学習データの作り方はとても参考になりました。
      • カメラ間のキャリブレーションはちゃんと勉強しておきたい。
      • でもって、発表者さま、参加者さまのレベルが高くて、それに比べて(比べるのもおこがましい)自分のやっていることがしょぼいなあ、萎えそう。。。

      2011-05-29

      WebSocket勉強会に行ってきた

      タイトル通り、5/28に開催されたWebSocket勉強会に行ってきました。内容自体は、リンク先の発表資料(29日時点では歯抜け状態ですけど)やUstの録画、はたまたTogetterを見れば良いとして、折角なので自分なりの感想を書いておくことにしよう。

      • 最初のコマにWebSocketのプロトコル内容を中心とた発表がありました。どんどん内容が変わっているようで、いつ策定されるんだろうというのがとにかく気になります。自分アプリケーションの開発屋さんじゃなくて、サーバとかインフラ寄りの人なので、プロトコルは気になるところです。とりあえず時間のある時にプロトコルの仕様書に挑戦してみようかと思いました。
      • その後いくつか事例紹介が続きましたが(と一括りにしてしまって、発表者さんごめんなさい><)、よく出てくる組み合わせがnode.jsとさくらのVPS。
        • HTML5とかに興味ある人って基本Javascript好きな人っていう勝手な先入観があるので、サーバのjavascriptで書きたいのかなあ。まあ単純にWebSocketと相性が良いのかも知れない(その辺がよく分からない)。C10Kってのも話は聞いたことあるだけで細かいことは知らないので、この辺も勉強しておきたいところ。サーバ関係の仕事してるなら、知っとけって言われるかも知れないし。
        • node.jsも折角なんで使ってみたい。
        • さくらのVPSは個人ユーザ向けサーバでは鉄板なのだろうか。確かに1ヶ月1000円未満でサーバ使えるのは魅力。
      • ブラウザとハードウェアをつなげる話も出てきました。ブラウザでハードウェア操作は自分も興味ある部分です。遠い過去の昔に対抗心だけでこんなブログも書いたことあるし。。。そういう自分も今や完全にkinectの軍門に下ったわけだけど。
        • node.jsがあれば、機器がTCPを喋れれば(喋れなかったらさらにプロキシ 見たいなものを挟む)websocketで通信が出来るらしい。面白い。
        • しかし、@ndrugerさんのこの分野への投資額は相当なものだなあ。kinectにHMD、しかも対戦ゲームを作ってるってことなので、もう一セットあるのかしら。。。
      • 最後の方は、どちらかと言うとサーバに寄った話だったような気がする。node.js以外にJetttyという選択肢もあるとか。
        • 数あるHTML5関係の機能の中でWebSocketはサーバ機能が必須、というのが敷居を高くしている要因の一つらしい。アプリケーションの仕様や設計に依ることが大きいと思うけど、クライアント側のコードを書くよりサーバ側のコードを書く方が圧倒的に難しい気がする。単純なウェブアプリケーションではなくて、コネクションを管理したりと正にサーバを作成するような感じな気がする(まあ、実際はWebSocketサーバがその辺よしなにやってくれるとは思うけど)。個人的には、サーバ側の開発パターンが確立、整理されるようになると、もう少し敷居が下がるのかなあと思ったりします。
        • まあ、WebSocketが使えるサーバのサービスがほとんどない(だからさくらVPSが流行る)っていう状況も何とかなると、って思います。クライアント側のネットワーク(プロキシとかプロキシとかプロキシとか。。。)とサーバ側のネットワーク(通信に影響を与えるかも知れない機能を許可するのは、インフラ屋さん的にはとっても嫌がるってのは、身にしみて感じております。。。)がネックになりそう。
        • あと、WebSocketのサーバサービスが増えるにはWebSocketは儲かる匂いがしないと、、、そんな匂いを漂わせるにはWebSocket対応サービスが増えないと、、、というジレンマ。
        • だからしばらくはLAN内での使用に限定されるのかも。
        • iPhoneで操作できるプレゼン機能、欲しい。。。
      なかなか、濃縮されて深い勉強会だったと思いました。次回までにもう少しWebSocketについて勉強して、参加できればなあと思いました。
      なんか、勉強したいことがどんどん増えていくな、時間は有限なのに。。。

      # WebSocketなのかWebsocketなのかwebsocketなのか、正式名はなんでしょう。。。?

      2011-05-06

      kinectで遊んでみる 再び

      大型連休にも関わらず、自分は何やっているんだろうと思いつつ、またkinectを触っています。
      今回はARっぽいものを作ろうとしたけど、結論から言うと、(例によって)あまり実りの無い実装をしてしまったようです。なので、反面教師的な意味を込めて記録しておきます。

      内容は4月にあったkinectハッカソンvol.2 +そのとき構想だけのことろを実際に作ってみたらこうなった、という部分です。

      やろうとしたこと
      ちょっと前に(今も??)ARってのが流行ってたけど、基本、画像にとあるモデルをオーバーラップさせて表示させているけど、kinect使うと3次元空間上(細かい人だと2.5次元と言ったりするらしい。。。)に(3次元復元した)画像データとモデルを(比較的簡単に、というか、先人たちの情報を使って)表示出来そうなので、頑張ってみようと思いました。
      従って、やるべきことは、RGB画像からモデルを表示する領域(以下対象領域)を取得して、その点を3次元上にプロットして、そこにOpenGLでモデルを表示させる、と言うことになります。

      まあ、誰かがどこかでやってそうな内容だけど、気にしない、気にしない(あまりそういう調査をしない人なので)。。。

      構成
      流れはこんな感じ。
      1. RGB画像から、モデルを表示する対象領域を切り出す(手とか、方眼紙とか。。。)
      2. 1.で求めた領域に対応するdepth画像の領域を取り出す
      3. 2.で取り出した領域を3D点に復元する
      4. 3D点から平面を推定して、位置とx,y,z軸を頑張って計算する
      5. 4.で求めた座標上にモデルを表示する
      6. その他の領域を3Dに復元して表示する
      使ったツールは、kinect制御にlibfreenect、画像処理ツールとしてOpenCV2.2、描写にOpenGLを使った。言語はCです。

      RGB画像の領域を切り出す
      調べていないので、とっても推測ですけど、OpenNIとかのボーン検出って、depth画像を元にやっていそうな気がするけど、あまのじゃくな自分としては、RGB画像から領域を取得することにしました。単純しごくな方法で、kinectのRGBカメラ画像から色情報(HSV)を使って切り出すことにしました。
      1. RGBからHSVに変換
      2. 各ピクセルについてしきい値内にあるものを取得
      3. オープニングとクロージングを使ってノイズを削減
      4. 輪郭抽出をして、最も面積が大きいものを対象領域とする
      あまりに単純なため、色の明るさが自動で調節されてしまう上に、パラメータが職人的でそのわりに、精度も良くない。あくまでkinectのRGBカメラは表示用なんだなあと思います。
      RGB画像
      対象領域候補の抽出:上のパラメータを変えて色の範囲を決めます。。。

      depth画像の領域を切り出す
      RGB画像から取得した対象領域を3次元上に表示する為には、対象領域の対応するdepth画像上の点を取得する必要があります。
      そのやり方は単純に、
      img_rgb.x = img_depth.x, img_rgb.y = img_depth.y
      では無いです。depth画像のある(dx, dy)に対応するRGB画像の(cx, cy)を求める計算方法は、http://nicolas.burrus.name/index.php/Research/KinectCalibration とか http://graphics.stanford.edu/~mdfisher/Kinect.html に詳しいです。これをパラメータ値も含めて、参考にしました。本当はキャリブレーションしないといけないところなんですが、、、

      3次元点の復元
      depth画像から3次元点の復元が出来ます。これも、上記の2つのリンクに詳しいです。libfreenectのサンプルコードや、ofxKinectにもやり方があります。

      抜粋:
       img_depth : depth画像のなまデータ
       mask_hand : RGB画像から抽出した対象領域(名前は昔の名残。。。)
       img_targetarea : RGB画像から抽出した対象領域に対応したdepth領域
       map_3d : depth画像の各点の3次元点を記憶
       map_image : depth画像の各点に対応するRGB画像の座標値を記憶 

      cvSetZero(img_targetarea);
       cvSetZero(map_3d);
       cvSetZero(map_image);
       for (int i=0; i<DISPLAY_SIZE_H; i++) {
        for (int j=0; j<DISPLAY_SIZE_W; j++) {
         float tx, ty, tz;
         float w, h;
         uint16_t d = CV_IMAGE_ELEM(img_depth, uint16_t, i, j);
         if (0 < d && d < 2047) {
          transformDepthTo3D(j, i, d, &tx, &ty, &tz);
          CV_IMAGE_ELEM(map_3d, float, i, j*3)     = tx;
          CV_IMAGE_ELEM(map_3d, float, i, j*3 + 1) = ty;
          CV_IMAGE_ELEM(map_3d, float, i, j*3 + 2) = tz;
          transform3DToRGBImage(tx, ty, tz, &w, &h);
          CV_IMAGE_ELEM(map_image, float, i, j*2)     = w;
          CV_IMAGE_ELEM(map_image, float, i, j*2 + 1) = h;
          int rw = cvRound(w);
          int rh = cvRound(h);
          if (0<= rw && rw<DISPLAY_SIZE_W && 0 <= rh && rh < DISPLAY_SIZE_H) {
           uint8_t c = CV_IMAGE_ELEM(mask_hand, uint8_t, rh, rw);
           if (c > 0) {
            // 対象領域
            CV_IMAGE_ELEM(img_targetarea, uint8_t, i, j) = 255;
           }
          }
         }
        }
       }
      

      この辺のコードが出てきたから、自分のやり方がどうもうまく行かない気がしてきました。。。
      四角い青いカード
      四角い青いカードに対応するdepth画像を切り出したところ

      前段の画像処理がうまくないせいか、プログラムが間違っているせいか、キャリブレーションをちゃんとやっていないせいか、はずれ値データが沢山取れてしまいます(そもそも構想から問題があった、が正解のような気がします)。

      対象領域の位置とx,y,z軸を計算する
      モデル表示の為に、対象領域の3次元上の位置と3軸が必要になります。そのために対象領域の3次元上の平面推定をします(平面が推定できればあとは適当な条件をつけてやれば、位置と3軸が求まります、きっと。。。)。
      ところで、3次元点列からの平面推定ってどうやるんでしょう。私は一般的な方法を知りません。あったとしてもとても面倒そう。
      z軸の誤差を最小にするする方法なら、例えばこんな感じらしいけど、ある点から平面への垂線の距離を最小にする場合、面倒らしい。このQAページによると、主成分分析を使うといいらしい、とのことで、OpenCVの cvCalcPCA 関数を使って、固有値の大きい順にx, y, z軸を決めることにしました(位置も一緒に求められます)。なので頑張らなくても計算できました。

      でも、計算した軸はかなりふらついてしまって、その結果、きれいに物体が表示できないのが正直なところです(主成分分析のせいではなくて、前段の画像処理の部分の制度の問題と思われます)。あまりのふらつき具合に、座標軸なんて推定するだけ無駄のような気になってきます。

      座標上にモデルを表示する
      対象領域の3次元上の位置と軸を求めたので、そこから、OpenGL上でのMODEL_VIEW変換行列が計算できます。座標変換してお望みのモデルなり何なりを表示出来ます。
      抜粋:
       hand_X_axis : 対象領域の各軸
       hand_center : 対象領域の中心

      void loadHandPositionMatrix() {
       GLfloat mat[16] = {
        hand_x_axis[0], hand_x_axis[1], hand_x_axis[2], 0,
        hand_y_axis[0], hand_y_axis[1], hand_y_axis[2], 0,
        hand_z_axis[0], hand_z_axis[1], hand_z_axis[2], 0,
        hand_center[0], hand_center[1], hand_center[2], 1
       };
       glMultMatrixf(mat);
      

      その他の領域を3次元に復元して表示
      3次元上に生成した点にRGB画像をテクスチャとして貼る方法も、libfreenectのサンプルコードにあります。

      結果
      対象領域の3次元点
      対象領域にモデル表示、その他領域も表示
      ちなみに処理の速度を測ってみると、7FPSくらい。かなり微妙。。。

      感想と反省
      • RGB画像上で画像処理するのはやはり、あまり賢い選択ではないようです。折角のdepth画像を有効に使って領域を取得した方がいいんだなあと思います。
      • となると、RGBの画像処理を使わずに、OpenNIのボーン検出をして、そこから特徴点の3次元を取得、3次元点を使ってモデルを表示した方が精度が高くなるような気がします。また、きっとそっちの方がkinectらしい気もします。。。
      • あくまでRGB画像処理派なら、ARToolkitを使うということも考えられます。それはどこかの誰かがやっていたような気がしますが。。。
      • OpenCV1.xを少し触ったことあるけど、2x、ヘッダファイルとか変わり過ぎでしょ。関数はそれほど変わってないけど、引数の増えた関数もあった。ウェブ上にもまだあまり日本語情報が無い。。。
      • OpenCVもC++の方が情報が多いような気がするので、C++使えるならそっちを使った方が良いのでしょう(今更勉強する気にはあまりなれないけど)。
      • まあOpenCVとかOpenGLの勉強になったので良しとしよう。。。
      • 例によって自己満足な誰得?な内容です。

      2011-04-06

      オライリーの電子書籍を買う

      この前、オライリーでチャリティとしてebook半額セールをしていたので、つられて買ってしまった。
      で、初めて電子書籍というものを買ってみたことになるのだが、これを機に電子書籍リーダを!と思うこのごろだけど、iPad2もいつになるのか分からないので、とりあえずiPhone(3GS)で見ようとしたところ、ebookの実態はpdfでiBookアプリで見ようとすると、とても見づらい。。。
      GoodReader(Lite)を使うと、テキストだけを抽出してくれて、文字サイズを変更できるので多少は見やすくなる。幸いに文字主体の本だったので、今回はこれで良さそうだけど、やっぱり電子書籍リーダが欲しくなってきた。。。

      2011-04-03

      花見

      新宿御苑で花見がありました。メンバーが会社の動機とその友人の友人、、、みたいな、伊文化交流な感じのメンバーでした。。。

      人はまだそれほど多くなかったけど、一部の木やソメイヨシノじゃない別の種類を除いて、まだ満開にはほど遠かった。来週が満開らしいので、きっと来週は凄い人でしょう。あと、とても寒かった。御苑を出た後のカフェの暖かさが幸せでした。。。なんか、寒い花見を去年も経験しているような気がして、とってもデジャブです。


      咲いている木もある

      これは桜じゃない。。。何??

      2011-03-13

      kinectと戯れてみた

      この前、金がないとか書いておきながら、結局kinectを買ってしまって、3/6にkinectハッカソンに行ってきました。我ながら回りに流されやすい性質である。まあ元々ユーザインターフェイス系に興味がある人なので、問題はないのだが。

      で、そのハッカソンで、手振り(指揮の手振り)に応じて音が鳴るものを作ってみたので、少しここで内容を保存しておく。

      こんな感じ:


      概要

      こんな感じ。


      我ながら回りくどい面倒な事をしている。なんでこんなに面倒かと言うと、macとC++でMIDIを生成する方法が分からなかったから。。。

      1. kinectで人物撮影
      2. openfremeworksのOpenNIプラグインを使って、人体のボーンを取得
      3. ボーンから手の位置等を取得して領域を作成
      4. 手を動かして、特定の領域に入ったら、oscでPureDataにデータ生成
      5. PureDataは受け取ったoscデータを元にMIDI生成
      6. GarageBandがMIDIを受信して音を鳴らす



      kinect

      言わずと知れた、本来はXBOXのコントローラ。3/6のkinectハッカソンでは、20人くらいいて、XBOX+kinectで遊んだ事ある人はほとんど居なかった。。。

      Xbox 360 Kinect センサーXbox 360 Kinect センサー
      価格:¥ 14,800(税込)
      発売日:2010-11-20


      openFrameworks + OpenNI

      openFrameworksについては、本家サイト参照の事。Processingを何度か触った事があるので、使い方は何となく分かるが、C++という存在故、敷居は高い。。。(画像処理とかごりごりやりたい場合は、openFrameworksを使う事になるのだろうか?)

      kinectを使う場合はOpenNIを使うと便利らしいよ、とのこと。これを使えば色やdepthだけでなく、ボーンと呼ばれる、人物を認識して首や腕等のデータを抽出してくれる。という事しか私は知らない。。。きっとそのうち勉強する。

      そのOpenNIのopenFrameworksプラグインの導入方法については、http://d.hatena.ne.jp/ke_takahashi/20110107/p1を参照しました。簡単には入ってくれなくて、色々手順が必要です。。。


      で、肝心のアプリケーションは、下記の用に領域を分割します。


      右手を順番にconduct.TopArea → conduct.BottomArea → conduct.BottomAreaから離す → conduct.RightArea → conduct.TopAreaに動かす事(結局、4拍子っぽい手の動きをします)で「MIDIを出力するために」oscを発行します。。。oscの形式は、
      
      /sound <midi note number>
      


      oscの使い方はhttp://yoppa.org/ma2_10/2279.htmlを参照にしました。

      左手をpitch.TopArea, pitch.MiddleArea, pitch.BottomAreaに動かす事で音程(オクターブ)を変えます。


      PureData

      本家サイト。oscを使うためにはextendedを使う必要があるそうです。内容はopenFrameworksから送られてきたoscをデコードして、midi形式で送り出すだけです。
      midiを実際に送り出すためには、Preference -> MIDI Settings からMIDI outをnone以外に選択する必要があるようです(none以外表示されないじゃないか?かも知れませんが、私の場合、文字が一切出てこない選択肢があってそれを選択できるみたい)。Media -> Test Audio and MIDIという項目があるので、これで確認することができます。

      見た目とかは、問わないでください。。。。

      なんで、わざわざoscを経由してPureDataなのか?という事ですが、書いたように、macでMIDIを生成する方法が分からなかったからです;-)。C++から出力する方法は当然あるようですが、それを読み解く気力がありませんでした。。。まあでもC++で自力で書くと大変そうだし、音のon/offタイミングをうまくするにはスレッドとか考えないといけなさそうなので、それを考えると、こちらの方が楽かと、自分を無理矢理納得させてみた。


      GarageBand

      少なくとも、私はmacを買った時に付いてきました。新しいプロジェクトを作成して、音源追加(「+」)ボタンをおして、ソフトウェア音源を選択すると、音が鳴るようになりました。これならピアノ以外の音も選べるので便利かと。。。


      自己突っ込みと感想

      • キラキラ星って4拍子じゃなくて2拍子説?
      • 音出すのって難しいよね
      • kinectらしさが見当たらない?
      • openFrameworks便利(描画が)
      • やはりC++は難敵だ(MSが春に出すSDKに期待するのか・・・?)
      • openFrameworksのopenNIプラグインはもう少し改良の余地がありそうな・・・?
      • 次機会があったら、画像処理とか取り入れてみたい

      2011-02-26

      本「プログラマが知るべき97のこと」

      まともな開発なんてやった事の無い人間ですが、イベント会場で安く売っていたので買ってしまいました。

      人によっては食い違ってる気がする部分もあるけど(例えば、ある人は、既に動いているプログラムを軽々しく変更すべきではない、というような事を言っていて、別のある人は、プログラムの修正を躊躇うな的な事を言っているような)、直接、プログラムを書いていない人間でも為になる事があるような気がしました。

      まわりにあまりプログラマが居ないので、彼らはどういう事を考えているんだろうなあと気になります。

      読むと、テスト駆動開発やアジャイル開発とかいうものに入信したくなる、かも????



      プログラマが知るべき97のことプログラマが知るべき97のこと
      価格:¥ 1,995(税込)
      発売日:2010-12-18

      2011-02-20

      gaeからpicasaに画像を登録する

      WebGLでシェーダーの勉強をしていたら、ふと、canvas上のデータを画像として取り出すにはどうしたら良いのだろうと思いました。調べてみると、toDataURL()という関数を使用すると、DataURLという形式で得られるという事を知りました
      toDataURL()で得られた値を、imgタグのsrcに設定すれば、そのまま画像が表示されて、右クリックなりで画像を保存を選択すれば、canvasで描写された画像をローカルに保存できるようです。
      とすると、今度はこの画像をどこかイメージ保存サービスに楽に保存するにはどうしようかという事が気になってきましたので、ちょっとやってみました。(ちょっとと言っても、結構時間がかかりましたけど)

      https://nekonekopic.appspot.com/
      ※今うまく動きません。。。

      • 動かなかったらすいません。特に認証部分が不思議動作するかも、です
      • アプリが信用できないなら、Picasa登録部分は使用しない方が良いです。画像表示までなら、ログインなしでも遊べます


      google app engineとpicasa

      とりあえずWebサーバをgaeとして、そこからpicasaに保存する、という方法にしました。

      picasaに保存する理由は、gaeで画像データを持つと、あっという間に容量がいっぱいになりそうだったし、そもそもデータをずっと保存しておく自身なんて全くないです。最終データをpicasaに保存しておけば、いつでもこのアプリケーションを消すことができます(gaeのアプリって消せましたっけ??gaeアプリは消せます。。。)。なので多分必要以上に苦労してます。。。

      蛇足ですが、アプリのイメージ図。


      picasaとかgoogleサービスのAPIを利用するために、ライブラリが提供されているみたいです。これを使えば、生々しくテキストデータを扱わずに済むようです。
      このライブラリを使ってpicasaのAPIを使うチュートリアルがあるので、これを参考にして、アルバムやイメージの登録など、基本的に動作できました。

      厄介なのが、picasaへの認証方法でした。AuthSubを使いましたが、この部分が動くようになるまでが一番時間がかかったような気がします。。。正しいTokenじゃないとか、Tokenのスコープが違うと何度も怒られたり。。。

      AuthSubを頑張っている部分。これが本当に良いのか全く想像がつきません。。。。
      
      def getClient(uri):
      user = users.get_current_user()
      if user:
      gd_client = gdata.photos.service.PhotosService(email=user.email())
      # workaround http://code.google.com/p/gdata-python-client/issues/detail?id=184
      else:
      gd_client = gdata.photos.service.PhotosService()
      
      gdata.alt.appengine.run_on_appengine(gd_client)
      
      session_token = None
      authsub_token = gdata.auth.extract_auth_sub_token_from_url(uri)
      if authsub_token:
      session_token = gd_client.upgrade_to_session_token(authsub_token)
      logging.info("session_token=%s" % (session_token))
      if session_token and user:
      gd_client.token_store.remove_all_tokens()
      gd_client.token_store.add_token(session_token)
      logging.info("Already login")
      elif session_token:
      gd_client.current_token = session_token
      logging.info("Not Login")
      
      logging.info("AuthSubToken=%s", gd_client.GetAuthSubToken())
      if gd_client.GetAuthSubToken():
      return gd_client
      else:
      return None
      


      画像アップロード

      ブラウザからは、画像がdataURL形式と呼ばれる、テキストデータで送られてくるので、バイナリに変換する必要があります(多分・・・)。画像本体部分は、Base64エンコードされているようなので、以下の通りに解析しました。全パターン対応していないみたいですけど。

      
      def convertDataURL(self, url):
      m = re.match(r'data:(.*);base64,(.*)', url)
      if m:
      imagedata = {'type':m.group(1), 'data':base64.b64decode(m.group(2))}
      return imagedata
      return None
      


      Picasaへの画像アップロードはこんな感じ。
      
      def insertPhoto(self, client, albumid, title, image, image_type):
      try:
      albumurl = "/data/feed/api/user/default/albumid/%s" % (albumid)
      photo = client.InsertPhotoSimple(albumurl, albumurl, title, StringIO(image), image_type)
      return photo
      except  gdata.photos.service.GooglePhotosException:
      logging.info(traceback.format_exc())
      self.redirect(PicasaAuth.originalURL)
      


      Picasaへの画像登録方法は、このサイトも参考になりました。


      セッション中の画像の渡し方

      意外に悩んだのがこれ。いくつかページ遷移する間にどうやって画像を渡していこうかと悩んで、必要になるまでサーバ側に画像を送りたくないなあとか、cookieでセッションとか難しいなあ、memcacheオプション使った方が良いのかなあ、等等考えて、結局、一番後腐れが無いだろうという事で、sessionStorageを使う事にしました。画像がdataURLというテキスト形式になっている事も好都合!

      コード自体は、練習問題レベルで、
      画像を登録
      
      function uploadToAlbum(canvas, url) {
      if (!sessionStorage) {
      alert("No SessionStorage");
      return;
      } else {
      sessionStorage.setItem("photo", canvas.toDataURL());
      window.open(url, null);
      }
      }
      


      画像をhiddenパラメータに設定、またはimgタグに設定
      
      function setPhoto() {
      var input = document.getElementById("photo");
      input.value = sessionStorage.getItem("photo");
      
      var img = document.getElementById("capture");
      img.src = sessionStorage.getItem("photo");
      
      }
      


      今回思った事。
      • ここまで書いておいてなんですが、このアプリオリジナルって訳ではなくて、似たような事をしているアプリケーションをつい最近、developer summitのHTML5グループの展示でありました。。。
      • 実はPicasaに直接アクセスできるjavascriptがあります、って話になると、この苦労はなんだろうって気になります。
      • 認証系は、場当たり的にやったので怖いです。ちゃんと勉強してからつかいませう。へたにライブラリがあると、よく分からなくても使えてしまうので、危険だなあ・・・
      • 相当我流なので、これが正しいアプリケーションの作り方なのかさっぱり分かりません。ちゃんと勉強しましょう
      • そろそろ3次元も勉強・・・

      2011-02-07

      webgl+websocket+arduino

      先日、webglの勉強会で、kinectをインターフェイスとしてwebglを動かすというデモを見て、感動しました。node.jsやwebsocketを使うと、外部機器からのデータをブラウザに取得出来るようだという事を知ったので、自分も試してみようと思いました。

      ここは是非、自分もkinectを!と言いたいところだけど、現在kinectを買うだけの持ち合わせが無いので、とりあえず手元にあるもので、何となく外部機器をwebglを連携してみようかと考え、結局今手元にあるのが、
      ・Arduino
      ・ArduinoのEthernetシールド
      ・ずっと前MTMで買った脈拍センサー
      #これ全部そろえると、kinectの半分の値段にはなりそうなんだけどね〜〜〜

      とりあえず、今回はこれを使ってみる事にしました。

      [Arduino+Ethernetシールド]
      node.jsを使ってみようかと思っていたけど、きっとArduino用websocketライブラリがあるに違いないと、探してみたら、cwebsocketというモノが見つかりました。このライブラリのサンプル(echo.pde)を見て、使い方を確認してみた。
      120行目あたりにある、

      while (!client.available() && client.connected())

      が、websocketをopenした後の、クライアントからのデータ待ちを表しているようなので、この部分に、サーバからクライアントへのデータ出力を実施すれば、一方的にクライアントにArduinoが取得したセンサデータを垂れ流せるよう、という事で、以下のようなコードを作成。
      while (!client.available() && client.connected()) {
      char data[BUF_LEN];
      size_t data_len = BUF_LEN;
      out_len = BUF_LEN;
      
      HB_GetNextData(&beat_mean, &beat_isbeat, &beat_rate);
      HB_toString(beat_mean, beat_isbeat, beat_rate, data, &data_len);
      frame_type = ws_make_frame((uint8_t*)data, data_len, buffer, &out_len, WS_TEXT_FRAME);
      if (frame_type != WS_TEXT_FRAME) {
      terminate();
      }
      client.write(buffer, out_len);
      //        delay(1000);
      
      }; // wait for data
      


      HB_GetNextDataは脈拍センサからデータを取得する(以前自分が勝手に作ったものを少し手直ししただけ)関数で、過去データの平均値と、データが大きく変化したかを表すboolean、計算した心拍数を返します。HB_toStringはそれらデータを文字列に変換する関数でJSON形式にする。以下のような感じになります。

      { "mean":300,"isbeat":false,"rate":60}

      これを、websocketで送ります。

      このライブラリで複数クライアントへのブロードキャストとかどうするんだろうと気になりますが、気が向いたらやってみたいなあ。。。

      [websocket+webgl]

      websocketデータの取得は、よくあるサンプルコードそのままです。
      var ws;
      var heartData;
      function initWS() {
      ws = new WebSocket("ws://xxx.xxx.xxx.xxx:8080/echo");  #websocketライブラリのechoサンプルを少し改造しただけなので、こんなURLに。。。
      
      ws.onopen = function() {
      console.log("Open ws");
      };
      
      ws.onmessage = function(evt) {
      heartData = JSON.parse(evt.data);
      var node = document.getElementById("mean");
      node.replaceChild(document.createTextNode(heartData.mean), node.childNodes[0]);
      var node = document.getElementById("beat");
      node.replaceChild(document.createTextNode(heartData.isbeat), node.childNodes[0]);
      var node = document.getElementById("rate");
      node.replaceChild(document.createTextNode(heartData.rate), node.childNodes[0]);
      }
      }
      


      Arduinoからは色々データを送ってみたものの、今回は平均値(mean)に応じて、モデルの大きさを変えるだけの単純なものにしてみました。モデルは単純な球でwebglのプログラムや使用したツール、モデル作成法は以前の記事と大して変わりません。サイズ変更は、球のレンダリングの前に、
      function valuemap(value, low1, high1, low2, high2) {
      if (value <= low1) return low2;
      if (value >= high1) return high2;
      return (high2-low2)/(high1-low1) * (value - low1) + low2;
      }
      
      if (heartData) {
      var s = valuemap(heartData.mean, 200, 700, 0.3, 3);
      mvMatrix.scale([s,s,s]);  #現在のモデル行列をスケールするオレオレ関数です。
      }
      

      を実行するだけです。heartData.mean値に比例して球のサイズが変わります。

      下記のような動画の通り動きます。iPhoneで撮ったので幅が狭いとか、脈拍数低過ぎとか、突っ込みどころは満載ですが。。。



      やってみての感想として、Arduino自体がwebsocketのサーバになる今回の構成だとあまり使い道と言うか発展性が無い気がしてます。node.jsとかでサーバを立てておいた方が、細かい事が簡単にできるだろうし(Cはやっぱり文字列とか面倒だし・・・)、複数のArduinoを使いたいとなった場合に、データを集約するサーバにいったん送信して、そのサーバに対してクライアントはアクセスした方が良いんだろうなあと思った次第です。

      という事で何の役に立つか分かりませんが、参考までに。

      2011-01-31

      映画「ソーシャルネットワーク」を観てきた

      テレビとかネットとかで面白いという話を聞いて、まわりでも面白かったと言っている人が居たので見てきた。

      まず、少なからずIT系に関わる身としては、いくつか散りばめられたコンピュータネタが面白かった。字幕では訳しきれていない部分で、emacsとか聞こえてきたのが気になったりした。
      あとは、最初に主人公が使っていたPCがvaioだったのは配給会社の関係か????

      別に、良いとか悪いとか言うつもりは無いけど、
      映画の内容自体は、マーク・ザッカーバーグが何を思っているのかが、あまり理解できなかった。まあ、凡人たる自分に天才の考えたる事は理解できない、というステレオタイプ的な事を言ってしまえばそれまでですが。。。
      なので、映画の構図的に、主人公の周りの人々が色々悲喜劇を演じて、中心に居るはずの主人公はその一連の出来事にあまり興味ない、我関せずなように見えてしまった。主人公が周りの人に振り回されている印象を受けた。。。いうなれば天才を利用しようとする人々の群像劇(喜劇?)。。。かなりドロドロした内容だなあ。

      2011-01-15

      本「クラウド大全」

      を、読んでみた。1年くらい前の本なので、ちょいと情報が古いところがある(1年あれば古くなる世界なんだなあ、、、としみじみ)けど、クラウドと呼ばれる存在の概要と、有名サービスの概要が知れるので、入門書としてはちょうど良いのかなと思った。これで読んで、興味持ったサービスや技術を突っ込んで調べていく、という使い方だと思う。

      目から鱗
      本文中のとある章にに書いてあった内容として、クラウドとは無料消費者向けのweb2.0のサービスで培った技術を企業に有償で使ってもらうものだ、云々、あたり。(本当かどうかは置いておいて)なるほどなあと、感心しました。

      にしても、興味深い技術があるなあ、自分も触ってみたい。。。


      クラウド大全 第2版 サービス詳細から基盤技術までクラウド大全 第2版 サービス詳細から基盤技術まで
      価格:¥ 2,520(税込)
      発売日:2010-04-22

      2011-01-01

      webglで年賀状っぽいものを作ってみた

      2011年ってことで、年賀状っぽいwebページを。
      このページです。
      webglが動くブラウザじゃないと見えません(開発版chromeとか、webkitとか)、データ量が多いのでパワーのあるマシンじゃないと動かないかも。動かなかったらごめんなさい。

      雪だるまのつもりなんだけど、色合いがどうも泥だるまのようだ。
      手袋はガクガクだし・・・(モデリングをほとんどやった事がないのですよね、実は)。

      参考ページ、ツール
      Learning WebGL javascriptの書き方から教えてくれる丁寧なページで、一通り勉強できました。
      Hack The WebGL ためになるコードがあります。かなり参考にさせていただきました。
      ・特にモデルの作成にBlenderのプラグインを使わせていただきました。
      glmatrix 行列計算用のjavascriptを使わせていただきました。速いらしい。

      その他
      ・背景画像
       canvasタグを2つ使用してスタイルシートを使用して重ねて表示させてます。
       一つのcanvasでwebgl、もう一つのcanvasに画像を書き出してます。
       chromeで試すと、webglを初期化するところで、gl.clearColor(0.0, 0.0, 0.0, 0.0)と設定すると、背景が透過されるらしい。
       ほかに良い方法ありそうな気がするけど。


      1/30追記:

      Light Ambient Colorのパラメータ値に応じて、背景画像の色も変更できるようにしてみた。
      最初、canvasの2Dnコンテキストから一画素ずつ色を変えていこうとしたけど、処理時間がかかるようなので、背景画像の色変更もwebGLのシェーディングを使用した。確かにスピードは速くなったけど、欠点は、テクスチャを使用しているので、画像のサイズが限られしまう、という事。

      背景画像をwebGLで変更する部分だけを切り出したものが、
      http://www3.ocn.ne.jp/~nnffuyyo/imagerendering/imagetest.html
      このページ中のuse Lightingをチェックすると、同じくAmbient Colorのパラメータ値に応じて、画像の色が変わります。画像の縦横サイズが2の指数乗でないと、画像は表示されません。ドラッグアンドドロップインターフェイスがあるので、適当な画像を使用して確認できるかと。
      Related Posts Plugin for WordPress, Blogger...