javascriptでのAR
javascriptでのARをしてみたのでちょっとメモ。
サンプルはこちら
http://moeten.info/js/20140713_arTest/
上記ページをスマートフォンのChromeなどで表示して、下のマーカーを写すと認識されます。
ソースコードはこちら
index.html(ほとんどjs-aruco - JavaScript library for Augmented Reality applications - Google Project Hostingのソースのままです)
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <title></title> <script src="//code.jquery.com/jquery-1.11.0.min.js"></script> <script type="text/javascript" src="lib/jkl-dumper.js"></script> <script type="text/javascript" src="lib/polyfill.js"></script> <script type="text/javascript" src="lib/cv.js"></script> <script type="text/javascript" src="lib/aruco.js"></script> <script> $(function(){ var video, canvas, context, imageData, detector; var cameraData = []; function onLoad(){ // getCameraInfo(); } // function getCameraInfo(){ //カメラの情報を取得 MediaStreamTrack.getSources(function(data){ //カメラ情報を取得して、出力する var strCamera = ""; var len = data.length; for( var i = 0 ; i < len ; i ++ ){ if( data[i].kind == "video" ){ cameraData.push(data[i]); } } if( cameraData.length == 0 ){ alert("カメラが見つかりません"); return; } //カメラをセット setCamera(); }); } //カメラをセット //カメラを取得・切り替える var cnt = 0; var localStream = null; function setCamera(){ //カメラを順番に切り替える cnt++; if( cnt == cameraData.length ){ cnt = 0; } if( localStream ){ localStream.stop(); } navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia; if (navigator.getUserMedia){ function successCallback(stream){ localStream = stream; video = document.getElementById("video"); if (window.webkitURL) { video.src = window.webkitURL.createObjectURL(stream); } else if (video.mozSrcObject !== undefined) { video.mozSrcObject = stream; } else { video.src = stream; } canvas = document.getElementById("canvas"); context = canvas.getContext("2d"); canvas.width = $("#video").width();//parseInt(canvas.style.width); canvas.height = $("#video").width();//parseInt(canvas.style.height); } function errorCallback(error){ } navigator.getUserMedia({ video: { optional: [{sourceId: cameraData[cnt].id }] //カメラIDを直接指定する } }, successCallback, errorCallback); detector = new AR.Detector(); requestAnimationFrame(tick); } } function tick(){ requestAnimationFrame(tick); if (video.readyState === video.HAVE_ENOUGH_DATA){ snapshot(); var markers = detector.detect(imageData); drawCorners(markers); drawId(markers); } } function snapshot(){ context.drawImage(video, 0, 0, canvas.width, canvas.height); imageData = context.getImageData(0, 0, canvas.width, canvas.height); } function drawCorners(markers){ var corners, corner, i, j; context.lineWidth = 3; for (i = 0; i !== markers.length; ++ i){ corners = markers[i].corners; context.strokeStyle = "red"; context.beginPath(); for (j = 0; j !== corners.length; ++ j){ corner = corners[j]; context.moveTo(corner.x, corner.y); corner = corners[(j + 1) % corners.length]; context.lineTo(corner.x, corner.y); } context.stroke(); context.closePath(); context.strokeStyle = "green"; context.strokeRect(corners[0].x - 2, corners[0].y - 2, 4, 4); } } function drawId(markers){ var corners, corner, x, y, i, j; context.strokeStyle = "blue"; context.lineWidth = 1; for (i = 0; i !== markers.length; ++ i){ //$("#result").html("マーカーが" + markers.length + "個見つかりました。"); var dumper = new JKL.Dumper(); $("#result").html( dumper.dump( markers ) ); corners = markers[i].corners; x = Infinity; y = Infinity; for (j = 0; j !== corners.length; ++ j){ corner = corners[j]; x = Math.min(x, corner.x); y = Math.min(y, corner.y); } context.strokeText(markers[i].id, x, y) } } //カメラ切り替えボタンクリックイベント $("#changeButton").bind("click",function(){ setCamera(); }); onLoad(); }); </script> <style type="text/css"> *{ padding: 0; margin: 0; } body{ text-align: center; } #video{ width: 100%; height: 100%; margin: 10px; display: none; } #changeButton{ background: #7abcff; background: -moz-linear-gradient(top, #7abcff 0%, #60abf8 44%, #4096ee 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#7abcff), color-stop(44%,#60abf8), color-stop(100%,#4096ee)); background: -webkit-linear-gradient(top, #7abcff 0%,#60abf8 44%,#4096ee 100%); background: -o-linear-gradient(top, #7abcff 0%,#60abf8 44%,#4096ee 100%); background: -ms-linear-gradient(top, #7abcff 0%,#60abf8 44%,#4096ee 100%); background: linear-gradient(to bottom, #7abcff 0%,#60abf8 44%,#4096ee 100%); filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#7abcff', endColorstr='#4096ee',GradientType=0 ); padding: 5px 12px; font-weight: bold; border: 1px solid blue; font-size: 16px; text-shadow: 0 0 3px #fff; border-radius: 4px; margin-bottom: 13px; margin-top: 13px; } #result{ font-size: 12px;; color: gray; border:1px solid #aeaeae; border-radius: 5px; padding: 10px; margin-bottom: 13px; background: rgb(255, 251, 242); } </style> </head> <body> <video id="video" autoplay="true"></video> <canvas id="canvas"></canvas> <button id="changeButton">カメラ切り替え</button> <div id="result"></div> </body> </html>
速度もほぼリアルタイムで認識するので、いろいろとできそうです。