JavaScriptでヘッドトラッキング
Gunma.web #14で発表してきた内容の一つ、Canvasを使ったヘッドトラッキングライブラリを使って作成したデモです。
カメラに対する頭(顔)の位置で、地球儀の回転する方向(X軸)が変わります。
当然のことながらWebカメラがないPCでは動きません。また、Chromeでしか動作確認していません。
上記ページを開くと「Webカメラの使用」の許可/拒否を利かれるので、利用の際は許可を選択してください。
全てクライアントサイドで処理を行うため、サーバー側にデータを送ることはありませんが、気になる人はWebカメラ使用の許可を出す前にソースを調べてください。
上記ライブラリは、Webカメラからの入力されたデータを解析して顔の位置を検出します。ちなみに、正面でしか検出できません。
また、検出後のトラッキングはエッジと肌の色を元に追跡するようなので、肌の色と背景の色に差があまりないと見失うことが多いです。
また、部屋が暗すぎたりしても駄目。
クライアント端末のスペックによっては、顔座標を検出するまでに結構時間がかかります。
使いどころが難しいライブラリですが、簡単にヘッドトラッキングを実装できるので、試してみると面白いかもしれません。
地球儀自体はD3.jsを使って描画しています。
サンプル
headtrackr.jsを読み込みます。
1 |
<script src="../headtrackr.min.js"></script> |
input用・output用のキャンバスと、webカメラからデータを読み込むためのvideoタグを用意します。
1 2 3 |
<canvas id='ic' width="160" height="120" style="display:none" ></canvas> <video id="iv" autoplay loop></video> <canvas id='oc' width="160" height="120"></canvas> |
ヘッドトラッキング処理は以下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
var svg = d3.select('svg'); var rotateX = 0; //海 実はただのcircle svg.append('circle') .attr({ fill:"blue", cx:480, cy:250, r:245 }); var projection = d3.geo.orthographic() //投影法を指定 .scale(245) //大きさ .rotate([rotateX,0,0]) //x,y,z回転 .clipAngle(90); //表示する角度 180度を指定すると裏側の大陸まで表示される var path = d3.geo.path().projection(projection); d3.json("world.topojson", function(json){ //地図情報の読み込み var data = topojson.object(json, json.objects.conuntries); //topojson変換 svg.append("svg:g").attr({"class":"earth"}); //g要素追加(グループ化) //地図表示 map = svg .selectAll("path") .data(data.geometries) .enter() .append("svg:path") .style("background-color", "blue") .attr({ "class": "path tip", "d":path, "fill-opacity":1, "fill":"green", "stroke":"#222", 'data-tip':function(d){ return d.properties.sovereignt } }) .on("mouseover", function(){ d3.select(this).attr("fill", "red"); }) .on("mouseout", function(){ d3.select(this).transition().duration(500).attr("fill", "green"); }); map.append('title') //ツールチップ追加 .text(function(d){ return d.properties.sovereignt }); }); /* * ここから下がheadtrackr関連の処理 */ var vi = document.getElementById('iv'); var ci = document.getElementById('ic'); var co = document.getElementById('oc'); // output用キャンバスの位置設定 co.style.position = "absolute"; co.style.top = '0px'; co.style.zIndex = '999'; co.style.display = 'block'; //コンテクスト取得 var ctx = co.getContext('2d'); ctx.strokeStyle = "red"; var x = 0; var y = 0; var w = 0; var h = 0; // headtrackr読み込み var ht = new headtrackr.Tracker({ui : false}); console.log(ht.init(vi, ci)); // ヘッドトラッキング開始 ht.start(); //ヘッドトラッキング開始時のイベント document.addEventListener('headtrackrStatus', function (event) { switch (event.status) { case 'no camera': alert('WEBカメラが見つかりません');break; case 'no getUserMedia': alert('getUserMediaがサポートされていないブラウザです');break; } d3.select('#HSstatus').text("status:" + event.status); } ); // フェイストラッキングイベント document.addEventListener('facetrackingEvent', function (event) { d3.select('#FTEheight').text("height:" + event.height); d3.select('#FTEwidth').text("width:" + event.width); d3.select('#FTEangle').text("angle:" + event.angle); d3.select('#FTEx').text("x:" + event.x); d3.select('#FTEy').text("y:" + event.y); d3.select('#FTEy').text("y:" + event.y); d3.select('#FTEconfidence').text("confidence:" + event.confidence); d3.select('#FTEdetection').text("detection:" + event.detection); d3.select('#FTEtime').text("time:" + event.time); //前画面をクリア ctx.clearRect(0, 0, 160, 120); w = event.width; h = event.height; x = event.x - w/2; y = event.y - h/2; //顔の周りに四角を書き出す ctx.strokeRect(x, y, w, h); } ); // ヘッドトラッキングイベント document.addEventListener('headtrackingEvent', function (event) { d3.select('#HTEx').text("x:" + event.x); d3.select('#HTEy').text("y:" + event.y); d3.select('#HTEz').text("z:" + event.z); //地球儀回す処理 rotateX = rotateX + ~~event.x * -1; projection.rotate([rotateX, 0, 0]); //rotateの値を増やして path = d3.geo.path().projection(projection); //path関数をアップデート map.attr("d", path); //paht関数をmapオブジェクトに適用 } ); |
“JavaScriptでヘッドトラッキング” への1件の返信
現在コメントは受け付けていません。