Three.jsに入門+手を検出してAR.jsと組み合わせてみた
はじめに
こんにちは、速水です。
普段は弊社サービスのConnectのフロントエンドを担当してます。
KabukuといえばThree.js(?)ということで、業務とは全く関係ないのですが今回はかねてより興味のあったWebARにThree.jsで入門した話とそこに手の検出を組み合わせてみた話をしたいと思います。やってみた系の記事です。
入門ということなので何が参考になったのかも含めてやってみたことを説明したいと思います。
この記事を書く1週間前に参加を決めたのでそこから全てへの挑戦は始まりました。
今回使ったライブラリは以下の通りです。
このライブラリの中で今まで使ったことのあるライブラリは0です。3D系の開発経験も0です。
このような状態で全て知らないライブラリをどうして混ぜようと考えてしまったのでしょうか・・・
入門を考えている人は絶対に1個ずつ学んでいった方がよいと思います。ほんとに。
Handtrack.jsというライブラリを使ったのですが、この中身はTensorFlow.jsを使って手がどこにあるのかを検知するライブラリになっています。
手の検出をいれた理由としては、ARなどで表示したコンテンツに対して手などでインタラクションを行えた方が楽しいという思いつきからです。
最初はAR.jsではなくThree.jsのARButtonを使っていこうと考えていたのですが、カメラ画像を他のライブラリ(Handtrack.js)に渡す方法がわからなかった(多分できない?)ので挫折して、途中で急遽AR.jsに切り替えました。
やりたかったこと
私はゲームが大好きでよくやり込んでいるのですが、ARでゲーム内の一部の要素を再現できたら絶対面白いと常日頃思ってました。
せっかくAdventCalenderに参加するので上記の思いをThree.jsに叶えてもらいました。
やりたかったこととしてはマゾゲーで高難易度で有名な某ソウルゲームに存在している篝火を再現することです。
これは何かと言うとゲームのセーブポイントのようなものでキャラクターが手をかざすことで火がともりセーブポイントとなるゲーム内で重要かつ心休まる地点です。
今回はHandtrack.jsを使って手を検知し、手をかざした際にAR上の消えた篝火に火を取り戻し、そこで休息することで心の安寧を取り戻そうと思います。
できたもの
こんな感じになりました。
このURLから試すことができます。
カメラの許可を求められるので許可を押して、HIROのマーカーを写すことでオブジェクトが現れるようになってます。地面にマーカーを置くとちょうど良い感じで表示されます。(ブラウザ上だけで処理しており、サーバーに取得される心配はありません)
画面内で手を検知したら炎がともされて、Bornfire lit!な気分が味わえます。
想定よりも若干重たくカクツク点が気になっていますが、一応動いたのでとりあえず今はよしとしました。
あと、処理が重たいのでスマホが熱くなってしまい、ある意味炎をリアルに感じられます・・・
一応コードも置いておきます。ただ割とサンプルを持ってきたりしてちぐはぐな感じになっていて参考になるとはお世辞にも言えない状態です。いずれちゃんと直したいです・・・。
手の検出について
Three.jsについては他の方がたくさん説明してくれているので、一点だけここでは手の検出について説明しておきます。
ここで苦労するかと思ったのですが意外とすんなりと使うことができました。
なので、あまり有益な情報はないのですが一応何したかを書きます。
やったこととしてはHandtrack.jsを独立して動かして手の検出を行なってました。
Handtrack.jsの中身としてはTensorFlow.jsを使って映像などから推測しているライブラリです。このライブラリ自体はその結果を使いやすくしてくれるものとなっています。
下記のようなコードでMediaStreamを取得してきてそれをHandtrack.jsに渡して、手が画面内に存在しているかどうかをみていました。
Handtrack.jsにもカメラ画像を取得する関数が用意されていたのですが、そこはfacingModeがuser
と指定されていて背面カメラの映像が取得できなかったので自分で用意して使いました。
下記のコードは説明用に切り抜いて編集したコードなので動作はしないものです。
const model = await handTrack.load(modelParams);
const video = document.getElementById("arjs-video"); //AR.jsによって追加された要素
const stream = await navigator.mediaDevices
.getUserMedia({
audio: false,
video: {
facingMode: "environment"
}
});
video.srcObject = stream
const predictions = await model.detect(video) // 認識結果
console.log(predictions);
/*
こんなデータが出力されます。
[{
bbox: [x, y, width, height],
class: "hand",
score: 0.8380282521247864
}, {
bbox: [x, y, width, height],
class: "hand",
score: 0.74644153267145157
}]
*/
今回は時間がなく手でオブジェクトの操作などは行なっていないのですが、カメラ画像内の手の位置が取得できるのでうまくやればできるのではないかと思ってます。
入門してみて
3Dモデル何それ?っていう状態から開始したのですが、位置の指定や回転・スケール・3Dモデルの読み込みをある程度雰囲気でやってできたのでThree.jsの実力を味わうことができました。
今回時間が足りなくてできなかったのですが、手の位置に応じてオブジェクトを配置や配置されているオブジェクトへのアクションもできそうでもっと面白いことができそうだと感じています。
samplesの中身も一部しか見れてないので、中身を見てどんなのがあるのかを見て他に何ができそうか検討してみたいところです。
Three.jsだいぶ面白くなってきたのでもう少しやり込んでみたいと思いました。
参考になったサイト
下記のサイトが特に参考になりました!
* AR.js doc
* three.js samples
* three.js超入門
* Kabukuの開発者ブログ!!
* three.ar.jsを使ったスマホAR入門
* WebXR AR Paint その2
もう少しあった気がしたのですがとりあえず思い出せたところまで
色々なサイトをみて四苦八苦してたのですが、three.jsのsamplesがかなり参考になりました。
炎を表現したくて色々検索して試しては失敗してたんですが、ふとsamplesを見てみたらwebgl_fire.htmlを発見して思わずおるやんけ!ってなってしまいました。
ここで使われていたFireはmoduleとして利用でき、オプションをうまく設定することで狙った効果をすぐに表示できる優れものでした。samplesにはこれ以外にも参考になりそうなものがたくさんあって充実してるなって感じました。
あとThree.js+AR関係で調べるとかなりの確率でKabukuの開発者ブログが現れるのでかなりオススメのサイトです!!
その他の記事
Other Articles
関連職種
Recruit