自習室

こもります

openFrameworks で Kinect for Windows SDK 2.0 をまるっと利用する

はじめに

f:id:AMANE:20150201220035j:plain

この記事では、 ラッパなどを挟まず、 Kinect for Windows SDK 2.0 のフル機能を oF 内で直接利用する方法について調べた内容をまとめます。ラッパを利用しないのは、MSDN の公式リファレンスが非常にしっかりしているからです。ネットに転がっているKinect v2 がらみの情報も公式 SDK を直接たたくものが多いので、いまのとこは素で使った方がなにかと幸せな予感がしています。

oF 内で利用することで様々な機能をひっつけやすくなるので、アプリ全体としての構築も楽になると考えています。

環境

Visual Studio は Proの方が幸せですが、ここではExpressの前提ですすめます。

Visual Studio Community 2013 じゃだめか?

個人のデベロッパだと、Visual Studio Community 2013 を使ってアドオンうはうはしたいところです。しかし、公式には openFrameworks は、vs2013 をサポートしていません。そこで片手落ちではありますが以下の手順で ビルド環境としては2012ですが、エディタとしては VS Community 2013 を使って openFrameworks の開発 を行えるようになります。

  • VS Community 2013 とは別に VS2012 Express を入れておくと、VS2012 (v110) のビルドツールが使えるようになります。
  • oF の Project Generator でプロジェクトを作る
  • VS Community 2013 で開くと、通常だとソリューションのコンバートを勧められますが、これをキャンセルします

VS の Solution Explorer で下図のように表示されていたらできていると思います。

f:id:AMANE:20150127133522p:plain

このあたりは、@selflash 氏が説明してくださっているのでご参照ください。

使い方

プロジェクト設定

@kaorun55 先生の記事ではウィンドウズアプリの前提で説明されていますが、プロジェクト設定はoFでも同じです

Kinect for Windows SDK v2.0 で開発する環境を整える(C++編)

  • of の Project Generator でプロジェクトをじぇねれーーとする
  • 追加のインクルードディレクトリを設定する
    C:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\inc
  • 追加のライブラリディレクトリを設定する
    C:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\Lib\x86
  • 追加の依存ファイルに Kinect20.lib を設定する

シンプルにカラー画像の表示だけ

簡単な作例として、SDK をインストールしたらついてくる公式サンプル Color Basics-D2D をベースに、oFで動かしてみました。Kinect v2 からカラーのイメージをとってきて描画するだけ。

f:id:AMANE:20150201223037j:plain

ofImage か ofTexture か

oF 使い的にはきっと基本的すぎてあれですが、動画をoFで描画する際にどっちを使うといいのかわかりませんでした。

調べてみたところ、下記フォーラムで同様の質問がなされていました。

ofImage は ofTexture を内部で使っていて、メモリの確保なども含めてラップしているクラスなので、描画部分に関しては差はない、とのこと。今回のような Kinect との連携だと、ofTexture を使う場合でも、ColorFrame からpixel配列をいったん引っこ抜いてからそれを ofTextureにloadData する必要があるので、確保するメモリ量的にも差がなさそうです。

コードは #ifdef して両方試しています

あげてあります

Face Tracking も試してみた

つづけて、FaceBasics-D2D というサンプルから、顔認識に関する最低限野部分をoF向けに移植してみました。

f:id:AMANE:20150201223113j:plain

顔出しツラいっすね。写真は悪用厳禁っす。

一生懸命口角を上げたおかげで笑顔判定がYESなのと、(普段かけない)めがね判定がYESなのが確認できると思います。(^^;)

Kinect v2 はボーンやデプスも使って顔認識とトラッキングを行うので、かなりロバストです。本当は顔出し恥ずかしいですが、写真の印刷だとほとんど判定しないのですすすs… Kinect v2 すごいっす。

コード

追加のインポート

FaceTracking の機能は Kinect20.Face.lib という別のライブラリにまとめられているので、プロジェクトの設定でそれも追加する必要があります

  • Kinect.face.h を必要なコードでインクルードする
  • Project Properties 追加の依存ファイルに Kinect20.Face.lib を設定する
(追記しました) ポストビルドコマンドで、dll等必要なファイルを持ってくる

また、oFやKinectwindowsアプリは、VSのビルドコマンド内で、必要なdllなどのファイルをoFやKinectSDKのインストールディレクトリから自分の実行ディレクトリ(exeを出力するところ)にコピーしてきて、それを使ってexeを実行しています。

たとえば Kinect for Windows SDK 2.0 のサンプル FaceBasics-D2D では、下図のような指定で必要なdllなどを取ってきています。

f:id:AMANE:20150212081206p:plain

Visual Studio で oFアプリをビルドする場合は更に、oFアプリの実行に必要なdll等一式も持ってくる必要がありますが、これは、Visual Studio向けのProject Generator でアプリを作成すれば、自動的にコマンドがセットされています。正確には、oFのインストールディレクトリ中に定義されている、デフォルトのプロパティーシートを見ています。

(下図のプロパティシートは、 VIEW > OTHER WINDOW > PROPERTY MANAGER で開きます)

f:id:AMANE:20150212083706p:plain

したがって、今回のケースで言うと、 oF のデフォルトのポストビルドコマンドと、Kinect20.Face.dll 関連のポストビルドコマンドを同居させてあげる必要があります。

プロパティシートがプロジェクトに登録してあったら、その内容は継承されるのかと思ったのですが、どうもプロジェクト固有のプロパティに書いた内容で上書きされる仕様なようですので、すべて記入されてある必要があります。できあがりはこんな感じ。

xcopy /e /i /y "$(ProjectDir)..\..\..\export\vs\*.dll" "$(ProjectDir)bin"
xcopy "$(KINECTSDK20_DIR)Redist\Face\x86\NuiDatabase" "$(TargetDir)NuiDatabase" /e /y /i /r
xcopy "$(KINECTSDK20_DIR)Redist\Face\x86\Kinect20.Face.dll" "$(TargetDir)" /c /y

この状態でビルドすると、ビルド結果の出力で、exeがはき出された後にいろいろコピーしているのがわかると思います。

1>  KinectV2Sample.vcxproj -> F:\develop\of_v0.8.4_vs_release\apps\myApps\KinectV2Sample\bin\KinectV2Sample_debug.exe
1>  F:\develop\of_v0.8.4_vs_release\apps\myApps\KinectV2Sample\..\..\..\export\vs\Assimp32.dll
1>  F:\develop\of_v0.8.4_vs_release\apps\myApps\KinectV2Sample\..\..\..\export\vs\fmodex.dll
1>  F:\develop\of_v0.8.4_vs_release\apps\myApps\KinectV2Sample\..\..\..\export\vs\fmodexL.dll
1>  F:\develop\of_v0.8.4_vs_release\apps\myApps\KinectV2Sample\..\..\..\export\vs\FreeImage.dll
1>  F:\develop\of_v0.8.4_vs_release\apps\myApps\KinectV2Sample\..\..\..\export\vs\FreeType-6.dll
1>  F:\develop\of_v0.8.4_vs_release\apps\myApps\KinectV2Sample\..\..\..\export\vs\glut32.dll
1>  F:\develop\of_v0.8.4_vs_release\apps\myApps\KinectV2Sample\..\..\..\export\vs\libeay32.dll
1>  F:\develop\of_v0.8.4_vs_release\apps\myApps\KinectV2Sample\..\..\..\export\vs\ssleay32.dll
1>  F:\develop\of_v0.8.4_vs_release\apps\myApps\KinectV2Sample\..\..\..\export\vs\Zlib.dll
1>  9 個のファイルをコピーしました
1>  C:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\Redist\Face\x86\NuiDatabase\FaceAlignment.bin
1>  C:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\Redist\Face\x86\NuiDatabase\FaceAlignmentColor.bin
1>  C:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\Redist\Face\x86\NuiDatabase\FaceAlignmentColor27.bin

中略。この辺りは、顔発見のための辞書データなどをコピーしている

1>  C:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\Redist\Face\x86\NuiDatabase\HDFaceTracker\ViewModel\left.p.txt
1>  C:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\Redist\Face\x86\NuiDatabase\HDFaceTracker\ViewModel\right.mod.bin
1>  C:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\Redist\Face\x86\NuiDatabase\HDFaceTracker\ViewModel\right.p.txt
1>  C:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\Redist\Face\x86\NuiDatabase\HDFaceTracker\WholeHeadModel\FullHeadMaskVertexCorrespondence.txt
1>  C:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\Redist\Face\x86\NuiDatabase\HDFaceTracker\WholeHeadModel\fullMeanHead60_tri.ply
1>  57 個のファイルをコピーしました
1>  C:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\Redist\Face\x86\Kinect20.Face.dll
1>  1 個のファイルをコピーしました

これで実行可能です。

一応あげてあります

コードはかなりやっつけな感じで書いたので、一応上げますが、あまり参考にはされない方が良いかと思います(>_<)

先ほどのリポジトリにブランチとしてぶら下げています。

そのほかのアプローチ

以上のように使えることの確認をしましたが、ここに至る前に、いろいろ Kinect for Windows SDK 2.0 と oF のつなぎ方を調査したので、それもまとめておきます。

Kinect Common Bridge / ofxKinectv2

Kinect Common Bridge は、MSOpenTech コミュニティで開発されている Kinect for Windows SDK のラッパで、そのブランチとして 2.0 向けが開発されています。CinderやoFなどのクリエイティブコーダー向けに使いやすくするのが主目的のようです。

これを使ってoF向けにさらにラップしたのが ofxKinectv2 という addon です。これはまだ Face Tracking のフィーチャをサポートしていません。Color, Depth, Infrared, Body あたりの機能を簡単に使う分にはこれでも良さそうです。

Windows Store 向け

Channel9 (MSのデベロッパー向け広報ブログ) で、 Windows Store App 版での oF + Kinect v2 の記事が紹介されていました。この記事中で、MSOpenTech が Windows Store 向けアプリを生成する変更を加えた Project Generator 込みの oF Fork を紹介しています。もし必要があれば。

Mac

Mac + oF + Kinect v2 をやる場合は、 Theo 先生のこれが使えそうですが、試してはいません。名前かぶってますね。

Unity 使おうぜ Unity

このブログで過去に取り上げましたが、Unity Pro をお持ちならKinect v2 用の公式 UnityPackage がありますので、こちらを使うと楽ちんです。が、SDK 2.0 のフル機能を使えるわけではなさそうです(要調査) *1

さいごに

使えるようになったので、使っていきます。

*1:kaorun55 先生資料によると、FaceやSpeech、Gestureなど結構な部分が使えないようです http://www.slideshare.net/kaorun55/kinect-for-windows-v2-39610207

読書感想:融けるデザイン

はじめに

講演会や研究発表の場などで(一方的に)非常に注目しお世話になっている、インタラクション研究者、渡邊恵太先生の著作が出たので、発売日に買って読みました。

あまりに「はまった」ので、2周読んだところで読書感想ブログします。

融けるデザイン ―ハード×ソフト×ネット時代の新たな設計論

融けるデザイン ―ハード×ソフト×ネット時代の新たな設計論

渡邊恵太先生

の研究については、彼のホームページにきれいにまとめてあるので、そちらに目を通してから本を読まれると、より理解が進むかと思います。

サイト上で試すことのできる Visual Haptics や 味ペン は是非体験してみてください。

また、本書の中でも繰り返されている自己帰属感について、iPhoneを事例に紹介されている記事があり、わかりやすいので、本を読む前に読んでみると良いかと思います。

感動した一節集 兼 ざっくり要約

自分のためのメモと本書のイメージ紹介として、私が「なるほどー」とか「そうだ、その表現だ!」とか「この考え方は使える」と膝を打った文章を一部引用させていただきます。

この記事を書く前、2周目を読んでいるときに作ったメモは、この記事の10倍くらいあるのですが、何とか選抜して減らしてみました。(そのくらい、読み応えがあります!)

正しい切り出し方ができていなかったら渡邊先生に非常に申し訳ないので、少しでもご興味もたれた方は是非本を読んでください(^^;)

インターフェイス/インタラクションデザインとは

インターフェイスのデザインとは、コンピュータと人との関係性を設計し、人の行動や活動を作ること

コンピュータとインターネットで、なにやる?って考えたときに、ついうっかりスマートテレビとか作ってしまうと、思考の広がって無さが露呈して非常に残念な感じになるので、いま人は、何をするか何が起こるのか何を得て何を感じるのか、もっと自由にデザインしなければいけない。  

インターフェイスデザインとは、可能のデザイン。環境から人が何を知覚し、どんな行為を生むかをデザインすること。

現象レイヤの体験と自己帰属感

現象レイヤの体験(人の認知や心理な観点で見た人の知覚と行為)をデザインすることがいかに大切であるか、についての説明。

会社では当然「高いクオリティ」や「美しいビジュアル・アニメーション」を求めるけど、その具体的な評価指標を考える上で非常に参考になると思いました。

インターフェイス石器時代のような道具のあり方、原因と結果が直接的な関係になることを一つの目標とする。ハンマーという道具自体を意識せず、釘を打つこと(対象)に集中できるようなあり方が、道具が透明である、ということ。

パソコン操作中にカーソルを意識しないことや、iPhoneの体験の良さを例に、自己帰属感が説明されます。iPhoneを操作しているのではなく、その先の情報に直接触れているような感覚を得られるようになる。

(iPhoneが非常になめらかにさくさく動く意味は→) 指とグラフィックとの高い動きの連動性が道具的存在となり、自己帰属感をもたらす。そしてその結果、道具としての透明性を得る。

ユビキタスコンピューティングから、環境と知覚、ギブソンの話

人間と環境の間に、行為だけでなく、行為を拡張する道具が介入すれば、別の次元の「可能」を知覚し、また行為へつながる。良い道具は、特にこの可能の知覚が優れている。そして、環境と接続する知覚と行為は途切れることなく循環している。それが「体験」の正体であると思う

私がいすや丈夫な台を見れば「座れる」と思うのと同じ透明感で、コンピュータが人とインタラクションし機能する世界、ということか。

情報技術を中心としたインタラクションデザインの目標は、ユビキタスコンピューティングの流れをくめば、もはやパソコンやスマートフォンを使っていると言う意識がないまま直接コンピュータやインターネットの恩恵を受ける透明性をどうやって実現するか、ということなのだ

環境と知覚、という考え方からインタラクションを考えると

インタラクションは既にある人間の知覚行為を支えている環境の仕組みを活かしながら、コンピュータという異物をうまく馴染ませる。自然回帰ではなく、世界を拡張するために。

人と世界の拡張、については説明が繰り返されます

なぜ自己帰属感が大事か

目的行為への集中だけではなく、、、

自己帰属した道具は透明化し、意識されなくなる。すると何も感じない世界があるのだろうか。(中略) 自己帰属がもたらすのは、そこにある新しい知覚世界だ。(中略)道具はあなたを変えながら世界との接点を変える。自己が拡張される。

最近はやりの「拡張人間」も、ロボティクスとかセンシングとかV/M/A/R的な派手な側面ばかりではなく、渡邊先生の研究のように日々の体験を静かに変えるような側面からも考えて取り組んでいきたいです。

自己帰属感が高いと、自己感や「私が感」が生まれて「自分の体験」が立ち上がってくる。この体験こそが生きている実感、あるいは愉しさや喜びとも言える。生きている実感のようなものを、その道具/サービスを使う中で感じられる

ここまで来ると会社では説明しづらいですが(笑) 個人的には納得いったし、こういった観念を常に持って取り組んでいきたいです。

デザインへの取り組み方。体験の設計方法の具体的取り組み。意識すべきこと

これからのデザイン。画面のデザイン、モノの形のデザインにとどまらない。

インターネット + コンピュータのメタメディアの持つ、(既存のメタファに縛られない)表現の自由度と柔軟性の高さを最大限に生かし、新しい価値を生み出す

20世紀の技術は、人がこれまでやってきたことを効率よく代行するものであった。これからは知的創造行為も含まれる。本書が目指すのは、個人の能力拡張とそのデザインである

メタメディアのインターフェイスデザインの実例

実世界へ直接働きかけるインターフェイス。情報の道具化、情報自体を道具として利用する。人々が利用する道具自体にウェブ上のデータを結びつけ、物理的に制約を与えて、人の行動を直接的に支援する

それらの実例が、smoon, integlass, length printer などのプロジェクト。

パラレルインタラクションのすすめ

ユーザーインターフェイスの常識とは、「システムを使いたくて使っている人」や「目の前に居る人」を暗黙の内に前提としている。そのため操作を提供するデザインを「ユーザーインターフェイス」と呼んでいる。暗黙的にインタラクションの高速を前提に設計してしまっている 「私のシステムを使っている限り、私のシステムは使いやすい」

パラレルインタラクション。マルチデバイスの時代。「あなたのサービスはユーザーの生活のごく一部でしかない」

  • 文脈はデバイスから生活へ
  • 拘束性は配慮へ
  • 利用タイミングは集中から分散へ

(やや禁則事項ですが) これは、会社の上の人ほど逃れられない呪縛みたいになっているのをひしひしと感じています。「パラレルになるとしたら、プロダクト/コンテンツの価値が低い証拠だ」とか言われかねない勢いです。そういった文化を背景にビジネスをやってきた会社ですからそう考えてしまうのも仕方ないかもしれませんが、自分が関わるプロジェクトはそういうところを少しずつ変えていきたいと思っています。

さいごに

研究者の方の著作なのに、実際の生活に具体的な提案をしていかなければいけないメーカーの人間(私)に、かなりダイレクトに響く内容でした。

自己帰属感の話、iPhoneの例は非常にわかりやすく「そこのクオリティ上げたら、商品売れるの?」「それより機能を増やすべきじゃないの?」という「あるある」問答集に対する明確な答えになっており、これから積極的に同僚内で布教していきたいと考えています。

まずは、理解のありそうなデザイナさんやエンジニアさんに本書を布教して、こういったとこ大事にして企画とかインターフェイスデザインとかしていこうぜ!という雰囲気を作り出していきたいです。

Web Audio API の勉強 - グラフィックイコライザーを作る

はじめに

前回の記事で「Web Audio API はシンプルで使いやすいしパフォーマンスも問題なさそう」という予感を得たので、少し勉強してみることにしました。まずは基本的な使い方を勉強して、それから練習問題として、グラフィックイコライザーを作ってみます。

グラフィックイコライザー

iTunes でいうこいつ。ベースを聞きたいから低い周波数を強める(相対的に中高音を抑える)とか、シンバルの響きを感じたいから中高音を上げる(相対的に定温を抑える)とかするのに使うやつ。(俺氏曰く)

f:id:AMANE:20150124182347p:plain

完成品

今回は効果を分かりやすくするために「すべての周波数で同じ強度」となるホワイトノイズを生成し、それに対して周波数ごとの強弱をつけられるようなサンプルになっています。

使い方

  • Play でホワイトノイズが鳴ります(ボリューム注意!)
  • バーを動かすことで、指定周波数周辺を増減させます
  • グラフの下の"Log" "Linear" ボタンを押すと、グラフのx軸(音の周波数)を対数表示に切り替えられます

別ページで開く場合はこちらから > Web Audio Graphical Equalizer

このプログラムは g200kg.com さまの下記記事をベースに改変して作成いたしました。

基礎のお勉強

まずはWeb Audio APIの基本を勉強しました。参考にさせていただいた主なサイトは以下。

Getting Started with Web Audio API - HTML5 Rocks

"Web Audio API" でググるとトップに出るので、まずはここから。Googleのエンジニアによる記事。短い文量でWeb Audio APIの概要をつかむことが出来ました。

(電子書籍) O'Reilly Japan - Web Audio API

上の記事著者の著作、の邦訳。実質上の公式入門書。上の記事を拡張したような内容。この本のサポートページとして作られているサンプル集が非常に良い感じです。

また、上記サンプル集自体が、webaudioapi.com と言うサイトに含まれていて、ここから仕様書だったり、一般の方が作られている作例集に飛べたりします。

Web Audio API 解説 - 01.前説 | g200kg Music & Software

結論としては、このサイトだけで良かったです。Web Audio APIの基本から、細かい各ノードの使い方、それらの背景にあるデジタル音楽の理論まで、一通り学ぶことが出来ます。今回作成したグライコも、ここの記事中のコードをフォークして作らせていただきました。

Web Audio API (日本語訳)

上記サイトの方が、W3C の公式文書を邦訳してくださっています。ありがたすぎました。完璧でした。 Published Versionとしてはいまのところ W3C Working Draft 10 October 2013 が最新のようなので、邦訳も最新、と言うことになります。

Editors Draft としては、2015/1/6 に最新のものが提示されていました。

イコライザの実装

BiquadFilter "peaking" のチェーン

Web Audio API では sourceNode (音の発生源または音声データ)から destinationNode(最終的な出力先。端末のサウンドデバイスなど) までの間に、ゲイン調整や周波数領域でのフィルタリング、パンニングなどの効果をつけるノードを複数挟むことが出来ます。

ターゲット周波数の異なる複数ピーキングフィルタを通すことで、グライコ的な物が作れるだろうと予測をつけて調べて見たところ、似たようなやりとりがされているのを見つけました。これで行けそうな気がします。

操作する周波数は、冒頭にキャプチャを貼った iTunes のイコライザを参考に、 32kHz から 2倍ずつ上がっていく物にしました。

ホワイトノイズの発生と、可視化

この辺りは、参考にさせていただいた元記事様を参考になさってください

グラフのx軸を対数にする

イコライザーのバーは対数で並べているのに対し結果のグラフがリニアで表示されていると、低い周波数の左側の辺りが過密になって見にくかったので、x軸を対数表示と切り替えられるようにしました。

できあがりのルーティング

f:id:AMANE:20150124214154p:plain

(細かいところ)

縦向きのスライダーバーの作り方

さいごに

実装の詳細はコードをご覧下さい。

Web Audio API を使ってリッチな楽器を作っている作例なども勉強中に見かけました。自分もトライしてみたいですが、大変そうな予感。

前回今回試したように、入ってくる音に対してフィルタリングするような用途には、Web Audio APIはかなり答えてくれている印象を持ちました。今回も BiquadFilter を多段で挟んでも、特にパフォーマンスが悪くなったりはしていません。コードもかなりスッキリ書けるので良いですね。

積極的に使っていこうと思います。

マイク入力を WebAudio で加工して、ビデオと合流させた後 WebRTC で使う

はじめに

前の2記事ほど、ウェブカメラの映像を openFrameworks で加工してビデオデバイスに再度流し込むことで、WebRTC などで扱えるようにする方法について調査してきました。

音声も同様に加工して WebRTCで扱えるようにしたいなーと思いました。

完成品

f:id:AMANE:20150118110301p:plain

こちらで動かしています -> http://www.izmiz.me/mediaStreamMerging/

簡単に使い方
  • ウェブカムとマイクを持っている二台のPCで上記サイトにアクセスします
  • カメラとマイクの利用の許諾を問われるので、許可してください。
  • どちらかのPCで、相手の画面に表示されているIDを打ち込んで call すると、ウェブチャットが開始されます
  • Filter on にチェックして、 Frequency や Q値 を動かすと、相手側に伝える音声に ローパスがかかります
  • ハウリング注意。

検討した2手法

仮想サウンドドライバを使ってOSに流し込む方法 (不採用)

ycapture と同じ考え方で、作り上げた音声をOSの音声デバイスに再度流し込む手法を初めは検討しました。ドライバ相当のものを自力で書くのは面倒なので、有り物の組み合わせで何とか行きたいです。

と思って調べていたところ、ニコニコとかで実況をする方々が、自分の音声と音楽やら動画やらの音声を混ぜるのにOSのソフトウェアミキサー(Windowsのステレオミキサー)を使っていることを知りました。さらにその流れで、NETDUETTO というソフトに同梱されている仮想サウンドドライバを使うことで、コンピュータで再生している音声を音声デバイスとして再入力出来ることが分かりました。

となれば、oF なり Pure data なりで音声を加工してこの仕組みで音声デバイスに戻せば、WebRTCでも使えそうです。

f:id:AMANE:20150118104431p:plain

WebAudio と WebRTC を組み合わせる方法 (採用☆)

一方で、WebAudio API を使えば、jsの簡単なコードで音声にエフェクトを掛けられることも分かりました。ブラウザ内で完結するのもgoodです。

  • WebAudio APIの入力をマイクにする
  • WebAudio APIの出力を、mediaStream のビデオに合流させる

この2つが出来れば、目的は果たせます。そのためにちょいと調査をしました

こちらの記事様の時点では、AudioDestinationNode から mediaStream を引っこ抜くのは実装が不完全そう、という結果になっていました。しかし希望を持ったのでもう少し調べて見たところ、w3c の公式で「まさに」な内容が紹介されていました

The following examples illustrate WebRTC integration with the Web Audio API.

とのことです。このページの Example5 が、まさに今回の内容と同じになっています。図示すると下のような感じになります。これでいけそうです。

f:id:AMANE:20150118104440p:plain

今回は

ウェブカム映像へのエフェクトについては、パフォーマンスの観点から別アプリとの連携という形にしましたが、ちょっとWebAudio API を使ってみたところ、シンプルなフィルタリング等ならパフォーマンスに問題はなさそうでした。

システム構成もシンプルに出来るので、音声に関しては後者、ブラウザ内ですべてやる方式でトライしてみます。

音質

NETDUETTO の仮想デバイスをまたいで入ってきた音の音質が悪い印象もありました。これはもしかしたら私の設定の問題かもしれないのでここでは断言はしませんが、今のところ音質良くできている Web Audio API を利用する方向で行きます。

実装

映像のストリームも加える

最終的に「映像・音声共にエフェクトの掛けられるウェブチャットシステム」としたいので、上のExample 5に加えて、カメラ映像もmediaStreamに合流させる必要があります。

試行錯誤した結果、映像・音声で別々の mediaStream を作ったあと、片方をもう片方にマージ出来ることが分かりました。

// videoStream 映像のMediaStream
// audioDestNode WebAudio API の AudioDestinationNode

videoStream.addTrack(audioDestNode.stream.getAudioTracks()[0]);

// できあがったstream を、peerjs で使う

先の構成図にこの処理を加えて、最終的にはこんな感じになります

f:id:AMANE:20150118175140p:plain

完成品

今回は、下記二つのコードを合体させています

これに、上で述べた映像のストリームを追加する方法を加えて、音声加工可能なビデオチャットシステムとしています。

初めにも書きましたが、完成品はこちらで動いています。http://www.izmiz.me/mediaStreamMerging/

SkyWay サービス利用の注意点

上がっているコードには、SkyWayのAPI key が直打ちされています。この API key は私のドメイン(www.izmiz.me)からしか使えない物になっているので、ご自身で試される場合は、ご自身でSkyWayのアカウントを作成し、ご自身のドメインを適用して API key を取得してください。

さいごに

今回はWebRTC との組み合わせにフォーカスしてまとめました。

次はWebAudio API にフォーカスして、エフェクトの作り込みにトライしてみたいです。

CreateJS で背景前景ともに動かしながら曇りガラス的表現をする

はじめに

磨りガラスってこんなかんじ。

f:id:AMANE:20150113153912j:plain

photo by Johnny Jet

友人氏がそういうのをやりたい、と言っていたのを思い出してやってみました。

完成品はこちら

コード

あげてあります

環境

  • EaselJS 0.8.0

参考にしたもの

Cacheについて

DisplayObject.cache() は、オフスクリーンレンダリング用に document.createElement('canvas') して、そこにデータを書き込む操作で、そこに書き込んだ物をなんども使い回したり、できあがった画像全体にポストエフェクトを掛けたりするのに使います。

上記ブログでは、DisplayObject.cacheCanvas でオフスクリーンレンダされている画像にアクセスできることが説明されています。スーパーナイスです。

blurのかけ方、マスクの仕方

上で先に書いちゃいましたが、.cache() 関数でオフスクリーンレンダした結果に対して、ブラーをかけたりできます。

このサンプルではDisplayObject.maskcreatejs.Shape のオブジェクトを登録することで、Shapeの形状に切り抜いています。graphics.drawHOGE() で描ける単純な形状で抜きたい場合はこちら。

こちらの AlphaMaskFilter では、 フィルタになるアルファを持った絵を作り(最終的にcacheCanvasを入力に使うので、Shape等にかぎらない)、そのアルファチャネルを使って対象のDisplayObjectにマスクをかけます。アルファを持つ画像等をもとに複雑なマスキングをしたい場合はこちら。

最後に

今回やっていること図示するとこんな感じです。詳しくはコードをご参照ください。

f:id:AMANE:20150117214412p:plain

ブラー元の画像を作って cacheCanvas で引っこ抜くために 1キャッシュ, ブラーをかけてマスクで抜くためにもう1キャッシュ、計2キャッシュ使いそれらを毎フレーム更新するのでやや重いのが問題です。

どうにか改善したいのですが…

html から node.js を介して oF の画像処理をコントロールし、ブラウザ上で閲覧する

はじめに

前回の記事で ycapture を使って、oF の描画内容を Windows のビデオデバイスとして流すことで、ブラウザからも見ることが出来るようにする手法について紹介しました。

前回やったことを図でまとめるとこんな感じ(再掲)

f:id:AMANE:20150111151631p:plain

ブラウザからoFアプリをコントロールする

今回はそれを発展させて、HTML側からカメラエフェクトを変更・調整できるようにしてみます。

できあがりはこんな感じ。ブラウザから、ネイティブアプリ(oF)に指令を送って、エフェクトを調整しています。

完成時のシステムは以下の様になります。

f:id:AMANE:20150112093523p:plain

ブラウザで選んだエフェクトの種類や強度の情報をWebSocket で Node.js にわたし、 Node.js からは OSCでリレーしてエフェクトの種類の情報をoFに渡します

環境とつかったもの

  • Windows 7
  • Visual Studio Express 2012
  • openFrameworks v0.8.4
    • ofxOSC
    • ofxCv
    • ofxOpenCV
    • ycapture.dll
  • node.js v0.10.29
    • node-osc
    • express
    • socket.io

あげてあります

今回のコードは、 node.js(およびhtml) の部分と、 oFの部分で二つに分けてアップしてあります。 oFのプロジェクトは ycapture の存在を前提にしているので、前回の記事を参考に導入してみてください。

ycapture に関しては前回記事参照

ycapture をつかって画像処理の結果を windwos のビデオデバイスとして流すやり方については、前回から変わっていません。今回は、三つの登場人物間で増えた通信部についてメモをしておきます。

html - node.js 側

  • NORMAL(エフェクトなし)
  • CANNY (エッジ抽出)
  • BLUR (ぼかし)

ラジオボタンを選択すると、どれが選ばれたかをNode.js 側に伝えます。

また、CANNY と BLUR については、その効果の効きをレンジスライダーで調整してNode.js側に伝えます。

これらの通信には、エフェクトの効きをリアルタイムに反映させたかったので、WebSocket(Socket.io) を利用しています。Socket.io の使い方については特殊なことはしていないので、ソースコードをご参考下さい。

要素使いこなし

<p><label>THRESH1<input type="range" name="canny_thresh1" min ="1" max="400"></label></p>
// 1~400 の間を、1刻みで選択出来る。

<p><label>SIZE<input type="range" name="blur_size" min="1" max="201" step="2"></label></p>
// 1~201 の間を、2刻みで選択出来る

後者が特徴的です。ofxCv::blur は内部的に cv::GaussianBlur を呼んでいて、ガウシアンカーネルサイズは奇数で無くてはいけません。そこで、上記のような指定にすることで、<input> の出力を奇数に限定しています。

また、<input type="range"> 要素は、value が string となっているため、Socket.io で送り込む際に、number要素に変換しておきます。

document.cv_effect.blur_size.oninput = function() {
  // ドラッグ中も数値を取りたかったら oninputを使う
  // リリース時のみ取りたかったら onchange
  socket.emit('blur size', parseInt(this.value));
}

node.js - oF 側

node.js 側

Socket.io でブラウザから送られてくるメッセージをoscに載せ替えて送り出しています

  socket.on('blur size', function(value){
    oscclient.send('/blursize', value);
  });

oF 側

OSCのメッセージを受け取って、CVのエフェクトを切り替えたり、効果の強さを調整したりします

// ofApp.cpp

while(oscReceiver.hasWaitingMessages()){
  ofxOscMessage m;
  oscReceiver.getNextMessage(&m);

  std::string oscaddress = m.getAddress();

  if(oscaddress == "/changeeffect"){
    std::string typeStr = m.getArgAsString(0);
    if(typeStr == "non") {
      effectType = EffectType::NONE;
    } else if(typeStr == "canny" ) {
      effectType = EffectType::CANNY;
    } else if(typeStr == "blur" ) {
      effectType = EffectType::BLUR;
    } else {

    }
  } /*中略*/ else if(oscaddress == "/blursize") {
    blurSize = m.getArgAsInt32(0);
  }

  // このあと effectType や blurSize を使う
}

追記

本記事の投稿後、 凹先生から助言をいただきました。

ofxLibWebsockets 試してみたところ確かにお手軽に oF 上で WebSocket が扱えて、Node.js が不要になるので良いと思いました!

最後に

WebRTC を使ってビデオチャットにする

今回は扱っていませんが、今回の物に PeerJS (WebRTC)を加えると、画面エフェクトが可能なビデオチャットシステムが完成しますね。

他プラットフォーム

前回ご紹介した内容は、デバイスやOSの仕組みが関わるところだったので Windows 限定でしたが、今回ご紹介した内容は node.js と oFのaddonで出来るので、すべてのプラットフォームで実現可能です。 前回の記事で言う ycapture の仕事を linuxやMac OSX でやる手法についても、前回の記事の最後に調査だけしてあるので、それと組み合わせることで、他のプラットフォームでも同様の機能を実現できるのではと思います。

ycapture で OpenCV での処理結果を Windows のビデオソースとしてブラウザに流し込む

はじめに

WebRTC を使ってビデオチャットアプリを作る際に、ビデオ画像にエフェクトをかけたくなりました。モザイクとか、ブラーとか、漫画カメラとか。

ブラウザ上でJavaScriptでごりごり画像処理をするのはさすがに厳しそうですので、画像処理を行うのは別のアプリケーションで行うことにしました。

最終的に WebRTC で MediaStream として扱うことを考えると、画像処理の結果が通常のWebカメラと同様に navigator.getUserMedia() できれば一番手っ取り早いんじゃないかなーと思っていろいろ手法を探してみました。

便利なソフトを教えていただいた

しかし調べれば調べるほど、Windows上だと DirectShowのお勉強しなきゃとかつらそうな気配が漂っていたのですが、Twitterに泣きついたところ、@jnakano さんが ycapture(わいきゃぷちゃ) の存在を教えて下さいました。

ycapture(わいきゃぷちゃ)

説明から引用

ycaptureとは、WindowsのVideo Capture Sourceのような振る舞いをするDLL(の基本ソース)です。このDLLを使用すると、あたかもビデオキャプチャデバイスのように、任意のプログラムからビデオデータを供給することができます。

これだー!と言うことで、今回試してみました。開発者の谷沢さん、ありがとうございます。

開発の前に

今回やりたいこと

f:id:AMANE:20150111151631p:plain

  1. openFrameworks 上で、OpenCVを使ってカメラ画像を処理し、
  2. ycapture.dll からWindowsのビデオデバイスとして流します。
  3. ブラウザで navigator.getUserMedia() でストリームを取得します

注意

今回のアプローチがベストかどうかはケースバイケースだと思うので、手法の一つとしてご参考にしていただければと思います

環境

ycaptureのビルドは、

の2つの組み合わせで確認しています。openFrameworks に関しては、Visual Studio 版が 2012(v110) にしか対応していないため、今回のシステム全体としては、Visual Studio 2012 を利用しています。

ycapture の準備

公式に載っている利用法に従って下さい。公式ページでは VS2008で、と書いてありますが上記の通りの環境でもビルド & 利用可能でした。以下、ポイントだけメモっておきます。

Release か Debug か。ビルドの種類とパスの設定に注意。

Visual Studio は ライブラリ類のパスを通すのが面倒なので、私は Release ビルドに統一してやっています。Visual Studioのプロパティをいじる際は、毎回 Configuration の表示に気をつけましょう。

f:id:AMANE:20150111092217p:plain

Windows SDK を導入し、DirectShowの baseclasses をビルドして静的ライブラリを作る

Windows SDK アーカイブ – Windows デベロッパー センター

今回はこちらの Windows 7 および .NET Framework 3.5 SP1 用 Windows SDK を使っています。

baseclasses ライブラリのソリューションを Visual Studio 2012(2013) で開こうとすると、変換の際に大量の警告が出ますが、ビルドは出来ます。

配布されている ycapture プロジェクトのビルド準備

ycaptureプロジェクトのプロパティで、インクルードやリンクがうまくいくよう設定を変更します。先述の DirectShow/baseclasses の在処を教えてあげます(配布された状態だと、Windows SDKのバージョンが違ったりしています)

私の場合は以下の通り

  • 追加のインクルードディレクトリ
    C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\multimedia\directshow\baseclasses;

  • 追加のライブラリディレクトリ
    C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\multimedia\directshow\baseclasses\Release;

これでビルドが出来ます。

ycaptureclient と testclienet のビルド

この二つは、配布状態のままでビルド可能です。

testclientは、ソリューション内でycaptureclientに対してプロジェクトの依存関係が組まれているので、特にライブラリの場所とか気にしなくて大丈夫なようです。

ycapture.dll の登録

regsvr32.exe を使ってdllを登録する際は、 powershell/cmd を管理者権限で立ち上げないと怒られます。

>regsvr32.exe ycapture.dll

サンプルを試す

ycapture で配布されている testclient で、以下の流れが確認出来ます。

  1. testclient を起動します。
  2. 受け側として、ブラウザで https://simpl.info/getusermedia/sources/ を開きます。 navigator.getUserMedia のサンプルアプリです。
    受け側はSkypeなどのアプリでももちろん大丈夫です。
  3. 画面に、testclientが流している赤い帯が表示されれば成功です

f:id:AMANE:20150111151857p:plain

testclient が生成するカメラが見つからないときがある

ドライバの読み込み順の関係かキャッシュか正確なことは分かりませんが、作った仮想カメラがクライアントから見つからないことがあります。こういうときは、ページのリロードや、既に刺さっているウェブカムの抜き差しなどをすると、見つかるようになります。

ycapture を oF 内で利用する

ycapture を oF 内で利用する事で、oF での描画結果やCVを使った画像処理の結果を、仮想カメラデバイスとして流すことが出来るようになります。

プロジェクトの準備

ここでは Visual Studio での oF プロジェクトの生成等については割愛いたします。

以下の点をプロジェクトのプロパティに設定していきます

  • baseclasses/ycapture のビルドにあわせて、configuration を Release にする
  • 追加のインクルードディレクトリに、ycaptureとycaptureclient のソースコードがある場所を追加する
<ycaptureをおいた場所>\ycapture-src-0.1.1\ycapture\ycaptureclient
<ycaptureをおいた場所>\ycapture-src-0.1.1\ycapture\ycapture
  • 追加のライブラリディレクトリに、ycapture/ycaptureclientのビルド結果がある場所を追加する
<ycaptureをおいた場所>\ycapture-src-0.1.1\ycapture\Release
  • ライブラリの入力に、以下の物を追加する
ycapture.lib
ycaptureclient.lib

コード

ycapture さんで配布されているtestclient を参考に書いていきます。

// ofApp.h

// 前略
#include "ofxCv.h"
#include "CaptureSender.h"
#include "ycapture.h"

class ofApp : public ofBaseApp {

public:
  // 中略
  ofVideoGrabber cam;
  ofImage raw;
  ofImage blur;
  CaptureSender *sender;  // ycaptureのオブジェクト
};
// ofApp.cpp
int CAM_WIDTH = 640;
int CAM_HEIGHT = 480;
unsigned long avgTimePF = 1000 / 30;    // 30fps ストリームのタイミングを作るのに使うらしいが詳細不明

void ofApp:setup(){
  cam.initGrabber(CAM_WIDTH, CAM_HEIGHT); // カメラの初期化
  sender = new CaptureSender(CS_SHARED_PATH, CS_EVENT_WRITE, CS_EVENT_READ); // ycaptureのセットアップ
  // 後略
}

void ofApp::update(){
  cam.update();

  if(cam.isFrameNew()){
    raw.setFromPixels(cam.getPixels(), CAM_WIDTH, CAM_HEIGHT, OF_IMAGE_COLOR); // カメラ画像をコピー
    raw.mirror(1, 0); // そのまま送るとブラウザ側で垂直方向に反転する
  
    ofxCv::blur(raw, blur, 51); // ブラーをかけてみるテスト
    HRESULT hr = sender->Send(counter * avgTimePF, CAM_WIDTH, CAM_HEIGHT, blur.getPixels() ); //★★ここがポイント★★
    // 後略
  }
}

void ofApp::draw() {
  cam.draw(0, 0);
}

要するに、何かしらの方法で画像を作った後、 RGBの順の unsigned char 配列にして、sender->Send() すれば良いようです。oFやCVには、RGBの順の unsigned char 配列 への変換関数が用意されているので楽ちんです。

さいごに

ウェブブラウザ上で、oFで処理した結果の画像が見られれば完成です。oFのウィンドウに表示されているカメラのスルー画と並べて見ても、遅れは感じられません。良い感じ。

f:id:AMANE:20150111104337j:plain

次は、せっかくブラウザ上でやっているので、ブラウザでのユーザの入力を受け付けて、エフェクトを変更したりする仕組みを作ってみようと思います。

他プラットフォーム

Linuxの場合

余り詳しくないので間違いがあるといけないのですが、、Linux環境だと、gstreamer や V4L2loopback といったモジュールを使うと、割と簡単に動画ストリームをビデオデバイスとして取り扱うことが出来るようです。実際、openFrameworksの addons に arturoc/ofxGstV4L2Sink · GitHub と言う物があって、リポジトリのREADMEによれば、

Uses v4l2sink gst element to create a virtual device which can be used as a camera in any application that supports v4l2

とのことで、今回狙っていることが出来そうです。ただし私は試していません。

Mac OSX の場合

rsodre/ofxFakam · GitHub と言う物があり、これも

ofxFakam is an Open Frameworks addon that streams screen data to a fake camera driver.

ということで、狙っていることが出来そうです。ただし私は試していません。