Theta UVC Blender もどき を作ってみたので、そのメモです。
#Theta UVC Blender ?
Theta UVC Blender は、RICOH THETA SからUSB出力されるライブストリーミング映像(Dual Fisheye)をつなぎ合わせEquirectangularにして、仮想カメラ映像として使うことができるRICOH さんのPCアプリです。
RICOH さんの本家はこちらです。
#目的
RICOH 公式で提供されてるものがあるのだから、自分で作るなんて無駄では?と思うかも知れませんが、シェーダーの勉強の題材が欲しかったのです(キッパリ)。
#必要な機能
- 仮想カメラ
- リアルタイムステッチング
#仮想カメラ
これは、今回の目的でないのと、自分の今の知識ではお手上げなので、ycapture(わいきゃぷちゃ)を使わせていただくことしました。感謝。
VisualStudioでのycaptureのbuild方法は下記を参考にしました。
#リアルタイムステッチング
ここでいうステッチングは、DualFishEye画像をつなぎ合わせてEquirectangularにすることです。
リアルタイム"でない"計算方法はすでにOpenCVで作ってあったので、それをGLSL(OpenGL Shading Language) で書き直すことにしました。
OpenGL, GLSLは下記を参考にさせていただきました。
- GLSL で画像処理 (1) 画像を取り込む
- GLFW による OpenGL 入門(pdf)
- OpenGL(GLSL)入門2 - はじめての三角形1
- [連載]やってみれば超簡単! WebGL と GLSL で始める、はじめてのシェーダコーディング(1)
ステッチングのための情報は下記を参考にさせていただきました。
射影方式が_立体射影_なのがポイント。
VisualStudio2013でビルドし、Windows8.1で動作確認した実行ファイルを下記に置きました。
theta_uvc_blender_mdk
取り扱いが少し面倒くさいですが興味があればお試しください。全部のソースは置いてないですが、座標変換処理を行うフラグメントシェーダ(DFE2EquiShader.fragmentshader)は置きました。
また、理由がよくわからないのですが、仮想カメラとして、theta_uv_blender_mdkを選択してもうまく見れない時があります。
(自分の環境では、FaceRigから開くと問題ないけど,VLCはたまに失敗して表示が更新されなくなります。)
フラグメントシェーダで実施しているステッチングの調整パラメータとしては下記6つあります。
float DFE_ALPHA_BLENDING_R_RATIO = 0.95; // 1.0=no alpha blending
float CAM_R = 283.0; // radius[pixel] @ 1280x720 DualFisyEye USB Streming input
float CAM1_CPX = 319.0; // x-coordinates of the center of 1st Fisyeye circle [pixel]
float CAM1_CPY = 319.0; // y-coordinates of the center of 1st Fisyeye circle [pixel]
float CAM2_CPX = 959.0; // x-coordinates of the center of 2nd Fisyeye circle [pixel]
float CAM2_CPY = 319.0; // y-coordinates of the center of 2nd Fisyeye circle [pixel]
FisyEyeの中心からCAM_R * DFE_ALPHA_BLENDING_R_RATIO以上の離れた座標を参照する場合は、2つのFisyeye画像をalpha blendingする処理を入れています。
座標変換は、基本的には下記の記事と同じと思います。
(2016/05/03追記:↓の記事は「立体射影」ではなく「等距離射影」のように見えるので自分の実装とは違いそう。射影方式の違いのリンク(射影方式のちがい - 屋根の上)も追加。)
THETAのDualfisheye動画をThree.jsで表示してみた
結果
- ステッチ性能はやっぱり本家に負けている感じ
- 表示遅延は(自分の環境では)少し短いようだ
最後に
処理速度に関しては、OpenCVでCPU処理で実装したときは、1fps以下しか出てなかったけど、今回はGLSLを書いてGPU処理にすることで15fpsが問題なく出せている。
OpenGLやシェーダ(GLSL)は、今まで手を付けてこなかったけど、少なくとも平面(画像)から平面(画像)への変換をGLSLでやるのはそんなに難しくない。ただ、今回GLSLのデバッグは全くやらなかった(OpenCVソースからGLSLへの書き換えのみなので、バグはtypoぐらい)ので、その辺のやりやすさはまだ不明。
でも、画像処理でゴリゴリ座標変換をやるときには、シェーダを書いてGPUの処理能力パワーを使わない手はないなぁと思う。(この分野の人には当たり前なのだろうが)