Kinectronを使って見る
kinectronというプロジェクトがある
ElectronクライアントでAzureKinectとかKinect v2のセンサーデータをブロードキャストして
SDKを使ったWebクライアントで受信できるらしい
送信クライアントに使っているのはkinect-azureというnpmパッケージらしい
通信はPeer.jsを使ったWebRTCらしい
kinectronのGithubはこちら
もしかしてjsしかサポートしていない?
なんとなくやってみたいのが、babylon.jsでkinectronから受信した深度情報や色情報から点群を生成したい
ん-できるのかな
そのためにはまず、kinectron serverからColorとdepthを送信して
それをクライアントで取得して
それらのデータから点群を生成して
その点群をパーティクルなりシェーダなりで表示しなくてはいけない
というのをまとめる
- Kinectron serverからColorとdepthを送信(もしかしたらFOVとかXYTableが必要かも)
- colorとdepthを受信
- 点群を生成
- 点群を表示
kinectron server試してみた
単体動作はこんな感じ
ところでKinectronサーバー、GitHubじゃなくてなんでDropBoxで配布するんだとおもったら
バイナリ3.6GBあって草
どんなデータが送信できるのか、colorとdepth、RawDepth 、RGBD
RGBDってどんな感じだろうと思ったら、
Alphaに8bitでdepthが入ってる、depthにアラインされたcolorらしい
でも8bitってどういうことだ......
流石に256mmだけしか測れないことはなさそうなので、16bit→8bitにマップされてるはずなんだけど
これがsqrtなのか線形補完なのかワカラン
AzureKinectのWFOV 2x2Binnedは512x512でFOVが120d x 120dのdepthカメラ
おそらくこれにマッピングされているんだろう
xytableとかは取得できなさそうだし、z値から自前計算で点群復元かな
ここにAzureKinectの場合のWebクライアントのサンプルが載っている
three.jsのpoint cloudではただzの値をパーティクルに設定しているだけなので
FoVを考慮していないっぽいが、
それでも使い方は何となくわかって良い
DepthとRawDepthとDepthKeyという3つのDepthデータがある
まずDepthの説明
"Depth" returns a webp of the depth mapped to a grayscale (0-255) image.
次にRawDepth
"Raw Depth" returns an array of values ranging from 0 - 3860. The values correspond to depth in millimeters. It displays a lossless webp image in the application for testing and feedback.
そしてDepthKey
"Depth Key" returns an array of raw depth values corresponding to the tracked bodies. The values range from 0 - 3860. The values correspond to depth in millimeters. It displays a lossless webp image in the application for testing and feedback.
Depthは画像化するために0-255にマッピングされたデータらしい
白黒の画像になっている
RawDepthはそのままの値?(でも上限は65,536ではないっぽい)の配列らしい
DepthKeyはボディトラッキングの文脈も絡んでくるんだとか
本当はRGBDを使いたいんだけど、なんとなくrawDepth or DepthKeyが扱いやすそうな気がしてきた
AzureKinectの深度カメラのハードウェア仕様
RawDepthの時、枠が丸ではなく六角形だった
ということはRGBDとは異なりDepthのモードはNFOVということになり、
またexampleを見た感じだと、NFOV 2x2 binnedだと思われる
とりあえずViteのvanillajsでKinectronのらwdepthを受信するところまでできた
本当はtsで書きたいけど......まぁ動くだけましか
depthデータから点群復元の式、こんな感じだろうか
(y座標とz座標の)導出の流れとしては、
- まずFOVから焦点距離(相対値)
が分かる。これは定数f - 同時に投影面座標系における位置(UV座標っぽいもの)である
が分かる(x_f,y_f) - すると、投影面までの距離が
とわかるd_f=\sqrt{x_f^2+y_f^2} はピクセルごとの定数なので最初だけ計算すればよいd_f - 次に相似によって焦点から
までの距離が(0,y,z) だとわかる。ここでd_y=d \frac{d_{fy}}{d_f} であるd_{fy}=\sqrt{f^2+y_f^2} - 最後に相似によって
とわかるy=y_f \frac{d_y}{d_{fy}}, z=f \frac{d_y}{d_{fy}} - 同様にx座標も計算できる
お風呂に入りながら間違えを発見した
検算として
多分このままだとならない
理由は
としてしまっていたらしい
今思ったけど、これ前提として縦横のサイズが違った場合にも[-1, 1]に正規化してるので
なんか縮尺変じゃね......?
どうすればよいんだろ、-1,1を縦に適用して、横は横長の場合1.2とかそういう感じでやるのがいいのかな
それでいい気がしてきた
縮尺が違うのが問題なのであって、数値的にはもともとピクセル単位でもよかったわけだし
プロジェクト、Kinectronを考慮してjsで書いてたけど、
流石にやってられなくなっちゃったのでtsを導入
jsからtsをimportするぶんには拡張子を忘れないようにすれば問題ないし
eslint+perttierも問題なく動作した
いつもお世話になっているZenn記事
js も混みのプロジェクトだからか、なぜかts→tsでのimportでなぜかunable to resolve path的な奴が出てきたが、こちらで解決
やっとtsでいい感じに組んだproviderでもKinectron受信できた......
ちょっと詰まったけど、無事depth maoからpoint cloudにするためのコアロジックも実装できた
コード書きながら思ったのが、今回は画像の縦幅を基準に正規化しているので、
焦点距離を求める時も鉛直方向のFoVから計算しないとおかしくなるよなぁと思った
最終的に、思っていたようなものができました
点群構成のロジックもあってたみたいで:嬉しい:
GitHubはこちら