html から node.js を介して oF の画像処理をコントロールし、ブラウザ上で閲覧する
はじめに
前回の記事で ycapture を使って、oF の描画内容を Windows のビデオデバイスとして流すことで、ブラウザからも見ることが出来るようにする手法について紹介しました。
前回やったことを図でまとめるとこんな感じ(再掲)
ブラウザからoFアプリをコントロールする
今回はそれを発展させて、HTML側からカメラエフェクトを変更・調整できるようにしてみます。
できあがりはこんな感じ。ブラウザから、ネイティブアプリ(oF)に指令を送って、エフェクトを調整しています。
完成時のシステムは以下の様になります。
ブラウザで選んだエフェクトの種類や強度の情報を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 を使う }
追記
本記事の投稿後、 凹先生から助言をいただきました。
@izmhrats あと、この構成なら C++ で websocket 使ったほうがクールかもと思った(https://t.co/0U6ohrlwnF)。
— 凹 (@hecomi) 2015, 1月 13
ofxLibWebsockets 試してみたところ確かにお手軽に oF 上で WebSocket が扱えて、Node.js が不要になるので良いと思いました!
最後に
WebRTC を使ってビデオチャットにする
今回は扱っていませんが、今回の物に PeerJS (WebRTC)を加えると、画面エフェクトが可能なビデオチャットシステムが完成しますね。
他プラットフォーム
前回ご紹介した内容は、デバイスやOSの仕組みが関わるところだったので Windows 限定でしたが、今回ご紹介した内容は node.js と oFのaddonで出来るので、すべてのプラットフォームで実現可能です。 前回の記事で言う ycapture の仕事を linuxやMac OSX でやる手法についても、前回の記事の最後に調査だけしてあるので、それと組み合わせることで、他のプラットフォームでも同様の機能を実現できるのではと思います。