34 lines
1.8 KiB
JavaScript
34 lines
1.8 KiB
JavaScript
'use strict';
|
|
let face = null, hands = null, vision = null;
|
|
let lastTime = 0;
|
|
async function prepare(c) {
|
|
if (!vision) {
|
|
const module = await import('/vendor/mediapipe/vision_bundle.mjs');
|
|
const files = await module.FilesetResolver.forVisionTasks('/vendor/mediapipe/wasm');
|
|
vision = {module,files};
|
|
}
|
|
if (c.rosto && !face) face = await vision.module.FaceDetector.createFromOptions(vision.files, {
|
|
baseOptions:{modelAssetPath:'/vendor/mediapipe/face.tflite',delegate:'CPU'},runningMode:'VIDEO',minDetectionConfidence:.6});
|
|
if (c.maos && !hands) hands = await vision.module.HandLandmarker.createFromOptions(vision.files, {
|
|
baseOptions:{modelAssetPath:'/vendor/mediapipe/hands.task',delegate:'CPU'},runningMode:'VIDEO',numHands:2,
|
|
minHandDetectionConfidence:.6,minHandPresenceConfidence:.6,minTrackingConfidence:.5});
|
|
}
|
|
self.onmessage = async ({data}) => {
|
|
const bitmap = data.bitmap;
|
|
try {
|
|
await prepare(data.config);
|
|
if (!bitmap) { self.postMessage({tipo:'pronto'}); return; }
|
|
const began = performance.now();
|
|
const stamp = Math.max(data.timestamp,lastTime+1); lastTime=stamp;
|
|
const faces = data.config.rosto ? face.detectForVideo(bitmap,stamp).detections.map(d=>({
|
|
x:d.boundingBox.originX/bitmap.width,y:d.boundingBox.originY/bitmap.height,
|
|
w:d.boundingBox.width/bitmap.width,h:d.boundingBox.height/bitmap.height,
|
|
score:d.categories[0]?.score || 0,pontos:d.keypoints.map(p=>({x:p.x,y:p.y}))
|
|
})) : [];
|
|
const result = data.config.maos ? hands.detectForVideo(bitmap,stamp) : {landmarks:[]};
|
|
self.postMessage({tipo:'resultado',faces,hands:result.landmarks.map(h=>h.map(p=>({x:p.x,y:p.y}))),
|
|
ms:performance.now()-began,timestamp:data.timestamp});
|
|
} catch(e) { self.postMessage({tipo:'erro',erro:e.message || String(e)}); }
|
|
finally { if (bitmap) bitmap.close(); }
|
|
};
|