kalidokit+live2dcubismcore+live2d+holistic实现摄像头捕获真人表情姿势及手指驱动三维数字人虚拟人动捕面捕效果代码
代码语言:html
所属分类:其他
代码描述:kalidokit+live2dcubismcore+live2d+holistic实现摄像头捕获真人表情姿势及手指驱动三维数字人虚拟人动捕面捕效果代码,结合了holistic及pixi-live2d-display等人工智能技术,可以用于数字人直播。
代码标签: kalidokit live2dcubismcore live2d face_mesh 摄像头 捕
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <style> h1 { font-family: "Jelly"; font-size: 32px; color: white; position: absolute; top: -12px; left: 16px; font-weight: normal; -webkit-font-feature-settings: "liga"; font-feature-settings: "liga"; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } h1:hover { color: #13a3f3; } a, a:visited, a:link { text-decoration: none; color: #222; display: inline-block; } a:hover, a:visited:hover, a:link:hover { color: #13a3f3; cursor: pointer; } .preview { display: flex; flex-direction: column; position: absolute; bottom: 16px; right: 16px; overflow: hidden; border-radius: 8px; background: #222; } video { max-width: 400px; height: auto; transform: scale(-1, 1); } .preview canvas { transform: scale(-1, 1); } body { margin: 0; } canvas { display: block; } .guides { position: absolute; bottom: 0; left: 0; height: auto; width: 100%; z-index: 1; } nav { position: absolute; top: 12px; right: 16px; display: flex; } nav img { width: 36px; height: auto; margin-left: 22px; } section { position: absolute; bottom: 0; right: 0; padding: 32px 0 16px 0; display: flex; justify-content: center; width: 100%; background: rgb(0, 0, 0); background: linear-gradient(0deg, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0) 100%); color: white; z-index: 2; /* border-radius: 40px; */ } p { color: white; padding: 8px 16px; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; margin: 0; } .preview a { border-radius: 24px; margin: 0 4px; } .preview a:hover { background: #ffffff20; } a.current { background: #13a3f3; pointer-events: none; } .linkOut { position: absolute; bottom: 16px; left: 16px; display: inline; color: black; padding: 0; } @media only screen and (max-width: 600px) { video { max-width: 160px; } } </style> </head> <body> <div class="preview"> <video class="input_video" width="1280px" height="720px" autoplay muted playsinline></video> <canvas class="guides"></canvas> <section> <a > <p>Live2D</p> </a> <a class="current" > <p>VRM</p> </a> </section> </div> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/three.133.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/GLTFLoader.133.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/OrbitControls.133.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/three-vrm.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/holistic.js"></script> <!-- Mediapipe or Tensorflow.js --> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/face_mesh.js"></script> <!-- Mediapipe Drawing Tools --> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/drawing_utils.js"></script> <!-- Mediapipe Camera Tools --> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/camera_utils.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/kalidokit.umd.js"></script> <script > //Import Helper Functions from Kalidokit const remap = Kalidokit.Utils.remap; const clamp = Kalidokit.Utils.clamp; const lerp = Kalidokit.Vector.lerp; /* THREEJS WORLD SETUP */ let currentVrm; // renderer const renderer = new THREE.WebGLRenderer({ alpha: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(window.devicePixelRatio); document.body.appendChild(renderer.domElement); // camera const orbitCamera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 0.1, 1000); orbitCamera.position.set(0.0, 1.4, 0.7); // controls const orbitControls = new THREE.OrbitControls(orbitCamera, renderer.domElement); orbitControls.screenSpacePanning = true; orbitControls.target.set(0.0, 1.4, 0.0); orbitControls.update(); // scene const scene = new THREE.Scene(); // light const light = new THREE.DirectionalLight(0xffffff); light.position.set(1.0, 1.0, 1.0).normalize(); scene.add(light); // Main Render Loop const clock = new THREE.Clock(); function animate() { requestAnimationFrame(animate); if (currentVrm) { // Update model to render physics currentVrm.update(clock.getDelta()); } renderer.render(scene, orbitCamera); } animate(); /* VRM CHARACTER SETUP */ // Import Character VRM const loader = new THREE.GLTFLoader(); loader.crossOrigin = "anonymous"; // Import model from URL, add your own model here loader.load( "//repo.bfw.wiki/bfwrepo/threemodel/Ashtra.vrm", gltf => { THREE.VRMUtils.removeUnnecessaryJoints(gltf.scene); THREE.VRM.from(gltf).then(vrm => { scene.add(vrm.scene); currentVrm = vrm; currentVrm.scene.rotation.y = Math.PI; // Rotate model 180deg to face camera }); }, (progress) => console.log( "Loading model...", 100.0 * (progress.loaded / progress.total), "%"), error => console.error(error)); // Animate Rotation Helper function const rigRotation = ( name, rotation = { x: 0, y: 0, z: 0 }, dampener = 1, lerpAmount = 0.3) => { if (!currentVrm) { return; } const Part = currentVrm.humanoid.getBoneNode( THREE.VRMSchema.HumanoidBoneName[name]); if (!Part) { return; } let euler = new THREE.Euler( rotation.x * dampener, rotation.y * dampener, rotation.z * dampener); let quaternion = new THREE.Quaternion().setFromEuler(euler); Part.quaternion.slerp(quaternion, lerpAmount); // interpolate }; // Animate Position Helper Function const rigPosition = ( name, position = { x: 0, y: 0, z: 0 }, dampener = 1, lerpAmount = 0.3) => { if (!currentVrm) { return; } const Part = currentVrm.humanoid.getBoneNode( THREE.VRMSchema.HumanoidBoneName[name]); if (!Part) { return; } let vector = new THREE.Vector3( position.x * dampener, position.y * dampener, position.z * dampener); Part.position.lerp(vector, lerpAmount); // interpolate }; let oldLookTarget = new THREE.Euler(); const rigFace = riggedFace => { if (!currentVrm) { return; } rigRotation("Neck", riggedFace.head, 0.7); // Blendshapes and Preset Name Schema const Blendshape = currentVrm.blendShapeProxy; const PresetName = THREE.VRMSchema.BlendShapePresetName; // Simple example without winking. Interpolate based on old blendshape, then stabilize blink with `Kalidokit` helper function. // for VRM, 1 is closed, 0 is open. riggedFace.eye.l = lerp( clamp(1 - riggedFace.eye.l, 0, 1), Blendshape.getValue(PresetName.Blink), 0.5); riggedFace.eye.r = lerp( clamp(1 - riggedFace.eye.r, 0, 1), Blendshape.getValue(PresetName.Blink), 0.5); riggedFace.eye = Kalidokit.Face.stabilizeBlink( riggedFace.eye, riggedFace.head.y); Blendshape.setValue(PresetName.Blink, riggedFace.eye.l); // Interpolate and set mouth blendshapes Blendshape.setValue( PresetName.I, lerp(riggedFace.mouth.shape.I, Blendshape.getValue(PresetName.I), 0.5)); Blendshape.setValue( PresetName.A, lerp(riggedFace.mouth.shape.A, Blendshape.getValue(PresetName.A), 0.5)); Blendshape.setValue( PresetName.E, lerp(riggedFace.mouth.shape.E, Blendshape.getValue(PresetName.E), 0.5)); Blendshape.setValue( PresetName.O, lerp(riggedFace.mouth.shape.O, Blendshape.getValue(PresetName.O), 0.5)); Blendshape.setValue( PresetName.U, lerp(riggedFace.mouth.shape.U, Blendshape.getValue(Pr.........完整代码请登录后点击上方下载按钮下载查看
网友评论0