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