KalidoKit seguimiento de rostro de código abierto

KalidoKit seguimiento de rostro de código abierto. Rostro, poses y manos. Además lo hace de forma divertida. El sistema de KalidoKit toma puntos de referencia 3D predefinidos y calcula rotaciones simples de Euler y valores faciales sencillos y algo más complejos.

He probado cómo funciona en su sitio web online, y resulta divertido, puedes optar por utilizar distintos personajes. Lo bueno del sistema es que al ser de código abierto puedes hacer con él lo que quieras.

Solución cinemática para el seguimiento

Kalidokit es una solución cinemática que mezcla técnicas Mediapipe/Tensorflow.js modelos de seguimiento de cara, ojos, posturas y mano; que es compatible con Facemesh, Blazepose, Handpose y Holistic. El desarrollador de la solución señala que toma puntos de referencia 3D predefinidos y calcula rotaciones simples de Euler y valores faciales.

KalidoKit seguimiento de rostro de código abierto
KalidoKit seguimiento de rostro de código abierto

Instalar KalidoKit a través de NPM

Código:

npm install kalidokit

Código:

import * as Kalidokit from "kalidokit";

// or only import the class you need

import { Face, Pose, Hand } from "kalidokit";

Instalar KalidoKit a través de CDN

Código:

<script src="https://cdn.jsdelivr.net/npm/kalidokit@1.0/dist/kalidokit.umd.js"></script>

Métodos de KalidoKit

KalidoKit se compone de tres formas distintas para hacer los cálculos de cara, pose y mano. Acepta resultados históricos de modelos como Facemesh, Blazepose, Handpose y Holistic.

Código:

// Accepts an array(468 or 478 with iris tracking) of vectors
Kalidokit.Face.solve(facelandmarkArray, {
    runtime: "tfjs", // `mediapipe` or `tfjs`
    video: HTMLVideoElement,
    imageSize: { height: 0, width: 0 },
    smoothBlink: false, // smooth left and right eye blink delays
    blinkSettings: [0.25, 0.75], // adjust upper and lower bound blink sensitivity
});

// Accepts arrays(33) of Pose keypoints and 3D Pose keypoints
Kalidokit.Pose.solve(poseWorld3DArray, poseLandmarkArray, {
    runtime: "tfjs", // `mediapipe` or `tfjs`
    video: HTMLVideoElement,
    imageSize: { height: 0, width: 0 },
    enableLegs: true,
});

// Accepts array(21) of hand landmark vectors; specify 'Right' or 'Left' side
Kalidokit.Hand.solve(handLandmarkArray, "Right");

// Using exported classes directly
Face.solve(facelandmarkArray);
Pose.solve(poseWorld3DArray, poseLandmarkArray);
Hand.solve(handLandmarkArray, "Right");

Utilidades adicionales de KalidoKit

Código:

// Stabilizes left/right blink delays + wink by providing blenshapes and head rotation
Kalidokit.Face.stabilizeBlink(
    { r: 0, l: 1 }, // left and right eye blendshape values
    headRotationY, // head rotation in radians
    {
        noWink = false, // disables winking
        maxRot = 0.5 // max head rotation in radians before interpolating obscured eyes
    });

// The internal vector math class
Kalidokit.Vector();

Plantilla VRM mezclada con KalidoKit

Inicia tu aplicación Vtuber con este sencillo ejemplo remezclable en Glitch. Seguimiento facial, de cuerpo completo y de mano, son menos de 350 líneas de javascript.

Esta demostración utiliza Mediapipe Holistic para el seguimiento del cuerpo, Three.js + Three-VRM para renderizar modelos y KalidoKit para los cálculos cinemáticos. Además está pensada para relajar y suavizar las animaciones.

La implementación puede variar según el modelo de detección de rostros y posturas que elijas utilizar, pero el principio sigue siendo el mismo. En este ejemplo se utiliza Mediapipe Holistic que los combina de manera precisa.

Código:

import * as Kalidokit from 'kalidokit'
import '@mediapipe/holistic/holistic';
import '@mediapipe/camera_utils/camera_utils';

let holistic = new Holistic({locateFile: (file) => {
    return `https://cdn.jsdelivr.net/npm/@mediapipe/holistic@0.4.1633559476/${file}`;
}});

holistic.onResults(results=>{
    // do something with prediction results
    // landmark names may change depending on TFJS/Mediapipe model version
    let facelm = results.faceLandmarks;
    let poselm = results.poseLandmarks;
    let poselm3D = results.ea;
    let rightHandlm = results.rightHandLandmarks;
    let leftHandlm = results.leftHandLandmarks;

    let faceRig = Kalidokit.Face.solve(facelm,{runtime:'mediapipe',video:HTMLVideoElement})
    let poseRig = Kalidokit.Pose.solve(poselm3d,poselm,{runtime:'mediapipe',video:HTMLVideoElement})
    let rightHandRig = Kalidokit.Hand.solve(rightHandlm,"Right")
    let leftHandRig = Kalidokit.Hand.solve(leftHandlm,"Left")

    };
});

// use Mediapipe's webcam utils to send video to holistic every frame
const camera = new Camera(HTMLVideoElement, {
  onFrame: async () => {
    await holistic.send({image: HTMLVideoElement});
  },
  width: 640,
  height: 480
});
camera.start();

Ligeras diferencias con Mediapipe y Tensorflow.js

Debido a las ligeras diferencias en los resultados de Mediapipe y Tensorflow.js, se recomienda especificar qué versión de tiempo de ejecución estás utilizando, así como el tamaño de entrada/imagen de video como referencia.

Código:

Kalidokit.Pose.solve(poselm3D,poselm,{
    runtime:'tfjs', // default is 'mediapipe'
    video: HTMLVideoElement,// specify an html video or manually set image size
    imageSize:{
        width: 640,
        height: 480,
    };
})

Kalidokit.Face.solve(facelm,{
    runtime:'mediapipe', // default is 'tfjs'
    video: HTMLVideoElement,// specify an html video or manually set image size
    imageSize:{
        width: 640,
        height: 480,
    };
})

Salidas de KalidoKit

A continuación se muestran los resultados esperados de los solucionadores kalidoKit.

Primer resultado:

// Kalidokit.Face.solve()
// Head rotations in radians
// Degrees and normalized rotations also available
{
    eye: {l: 1,r: 1},
    mouth: {
        x: 0,
        y: 0,
        shape: {A:0, E:0, I:0, O:0, U:0}
    },
    head: {
        x: 0,
        y: 0,
        z: 0,
        width: 0.3,
        height: 0.6,
        position: {x: 0.5, y: 0.5, z: 0}
    },
    brow: 0,
    pupil: {x: 0, y: 0}
}

Segundo resultado:

// Kalidokit.Pose.solve()
// Joint rotations in radians, leg calculators are a WIP
{
    RightUpperArm: {x: 0, y: 0, z: -1.25},
    LeftUpperArm: {x: 0, y: 0, z: 1.25},
    RightLowerArm: {x: 0, y: 0, z: 0},
    LeftLowerArm: {x: 0, y: 0, z: 0},
    LeftUpperLeg: {x: 0, y: 0, z: 0},
    RightUpperLeg: {x: 0, y: 0, z: 0},
    RightLowerLeg: {x: 0, y: 0, z: 0},
    LeftLowerLeg: {x: 0, y: 0, z: 0},
    LeftHand: {x: 0, y: 0, z: 0},
    RightHand: {x: 0, y: 0, z: 0},
    Spine: {x: 0, y: 0, z: 0},
    Hips: {
        worldPosition: {x: 0, y: 0, z: 0},
        position: {x: 0, y: 0, z: 0},
        rotation: {x: 0, y: 0, z: 0},
    }
}

Tercer resultado:

// Kalidokit.Hand.solve()
// Joint rotations in radians
// only wrist and thumb have 3 degrees of freedom
// all other finger joints move in the Z axis only
{
    RightWrist: {x: -0.13, y: -0.07, z: -1.04},
    RightRingProximal: {x: 0, y: 0, z: -0.13},
    RightRingIntermediate: {x: 0, y: 0, z: -0.4},
    RightRingDistal: {x: 0, y: 0, z: -0.04},
    RightIndexProximal: {x: 0, y: 0, z: -0.24},
    RightIndexIntermediate: {x: 0, y: 0, z: -0.25},
    RightIndexDistal: {x: 0, y: 0, z: -0.06},
    RightMiddleProximal: {x: 0, y: 0, z: -0.09},
    RightMiddleIntermediate: {x: 0, y: 0, z: -0.44},
    RightMiddleDistal: {x: 0, y: 0, z: -0.06},
    RightThumbProximal: {x: -0.23, y: -0.33, z: -0.12},
    RightThumbIntermediate: {x: -0.2, y: -0.19, z: -0.01},
    RightThumbDistal: {x: -0.2, y: 0.002, z: 0.15},
    RightLittleProximal: {x: 0, y: 0, z: -0.09},
    RightLittleIntermediate: {x: 0, y: 0, z: -0.22},
    RightLittleDistal: {x: 0, y: 0, z: -0.1}
}

Esta solución de código abierto está diseñada específicamente para rigging de modelos VRM 3D y avatares Live2D. Puedes encontrar el código en GitHub.

Hay una versión gratuita basada en la web, disponible si desea probar el sistema. Puedes encontrarlo aquí.