HTML 代码部分非常简单。我们只是在这里引入了库,并添加了 div 元素来在浏览器中渲染摄像头画面:
<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"/><metaname="viewport"content="width=device-width, initial-scale=1.0"/><metahttp-equiv="X-UA-Compatible"content="ie=edge"/><title>The Hand Trick</title><linkrel="stylesheet"href="css/style.css"/></head><body><!-- Video for handtracker --><divclass="tracker"><videoid="myvideo"></video><canvasid="canvas"class="border"></canvas><buttonid="trackbutton"disabledonclick="toggleVideo()">Button</button><divid="updatenote">hello</div></div><divclass="data"><divclass="hand-1"><pid="hand-x">X: <span>0</span></p><pid="hand-y">Y: <span>0</span></p></div></div><script src="js/three.js"></script><script src="https://cdn.jsdelivr.net/npm/handtrackjs/dist/handtrack.min.js"></script><script src="js/scene.js"></script></body></html>
// Setting scene for 3D Objectvarscene=newTHREE.Scene();varcamera=newTHREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);varvector=newTHREE.Vector3();varrenderer=newTHREE.WebGLRenderer();renderer.setSize(window.innerWidth,window.innerHeight);document.body.appendChild(renderer.domElement);
接下来,我们创建一个3D对象来渲染到场景中。这里我们将定义盒子的几何形状和网格材质类型。
// Creating 3D objectvargeometry=newTHREE.BoxGeometry(1,2,1);varmaterial=newTHREE.MeshBasicMaterial({color:"rgba(3, 197, 221, 0.81)",wireframe:true,wireframeLinewidth:1});varcube=newTHREE.Mesh(geometry,material);scene.add(cube);camera.position.z=5;
如果你想让物体在三维空间中旋转,这一步是可选的。只是这样看起来更酷。
// Optional animation to rotate the elementvaranimate=function(){requestAnimationFrame(animate);cube.rotation.x+=0.01;cube.rotation.y+=0.01;renderer.render(scene,camera);};animate();
这就是使用 Three.js 需要做的全部工作。现在让我们来体验一下 Handtrack.js。
// Creating Canavs for video Inputconstvideo=document.getElementById("myvideo");consthandimg=document.getElementById("handimage");constcanvas=document.getElementById("canvas");constcontext=canvas.getContext("2d");lettrackButton=document.getElementById("trackbutton");letupdateNote=document.getElementById("updatenote");letimgindex=1;letisVideo=false;letmodel=null;// Params to initialize Handtracking jsconstmodelParams={flipHorizontal:true,maxNumBoxes:1,iouThreshold:0.5,scoreThreshold:0.7};handTrack.load(modelParams).then(lmodel=>{model=lmodel;updateNote.innerText="Loaded Model!";trackButton.disabled=false;});
我们在这里定义加载 Handtrack.js 的参数,但这一步是可选的;您也可以传递一个空对象。该handTrack.load()方法将帮助您加载模型。Handtrack.js 加载完成后,让我们编写函数来将视频流加载到 HTML 中定义的 canvas 元素中。为此,我们将使用该handTrack.startVideo()方法。
// Method to start a videofunctionstartVideo(){handTrack.startVideo(video).then(function(status){if (status){updateNote.innerText="Video started. Now tracking";isVideo=true;runDetection();}else{updateNote.innerText="Please enable video";}});}// Method to toggle a videofunctiontoggleVideo(){if (!isVideo){updateNote.innerText="Starting video";startVideo();}else{updateNote.innerText="Stopping video";handTrack.stopVideo(video);isVideo=false;updateNote.innerText="Video stopped";}}
现在我们可以编写代码,从handtrack.js获取预测数据。
//Method to detect movementfunctionrunDetection(){model.detect(video).then(predictions=>{model.renderPredictions(predictions,canvas,context,video);if (isVideo){requestAnimationFrame(runDetection);}});}
//Method to detect movementfunctionrunDetection(){model.detect(video).then(predictions=>{model.renderPredictions(predictions,canvas,context,video);if (isVideo){requestAnimationFrame(runDetection);}if (predictions.length>0){changeData(predictions[0].bbox);}});}//Method to Change prediction data into useful informationfunctionchangeData(value){letmidvalX=value[0]+value[2]/2;letmidvalY=value[1]+value[3]/2;document.querySelector(".hand-1 #hand-x span").innerHTML=midvalX;document.querySelector(".hand-1 #hand-y span").innerHTML=midvalY;moveTheBox({x:(midvalX-300)/600,y:(midvalY-250)/500});}//Method to use prediction data to render cube accordinglyfunctionmoveTheBox(value){cube.position.x=((window.innerWidth*value.x)/window.innerWidth)*5;cube.position.y=-((window.innerHeight*value.y)/window.innerHeight)*5;renderer.render(scene,camera);}