human/src/face/facemesh.js

59 lines
2.4 KiB
JavaScript
Raw Normal View History

2020-11-17 18:38:48 +01:00
import { tf } from '../../dist/tfjs.esm.js';
2020-11-12 20:52:32 +01:00
import * as blazeface from './blazeface.js';
import * as pipe from './facepipeline.js';
import * as coords from './coords.js';
2020-10-12 01:22:43 +02:00
class MediaPipeFaceMesh {
constructor(blazeFace, blazeMeshModel, irisModel, config) {
this.pipeline = new pipe.Pipeline(blazeFace, blazeMeshModel, irisModel, config);
2020-10-13 04:01:35 +02:00
if (config) this.config = config;
2020-10-12 01:22:43 +02:00
}
async estimateFaces(input, config) {
if (config) this.config = config;
const predictions = await this.pipeline.predict(input, config);
2020-10-13 04:01:35 +02:00
const results = [];
for (const prediction of (predictions || [])) {
2020-10-17 13:15:23 +02:00
// guard against disposed tensors on long running operations such as pause in middle of processing
if (prediction.isDisposedInternal) continue;
2020-11-06 19:50:16 +01:00
const mesh = prediction.coords ? prediction.coords.arraySync() : null;
const annotations = {};
if (mesh && mesh.length > 0) {
2020-11-12 20:52:32 +01:00
for (const key in coords.MESH_ANNOTATIONS) {
2020-11-06 19:50:16 +01:00
if (this.config.iris.enabled || key.includes('Iris') === false) {
2020-11-12 20:52:32 +01:00
annotations[key] = coords.MESH_ANNOTATIONS[key].map((index) => mesh[index]);
2020-10-12 01:22:43 +02:00
}
}
}
2020-11-06 19:50:16 +01:00
results.push({
confidence: prediction.confidence || 0,
box: prediction.box ? [prediction.box.startPoint[0], prediction.box.startPoint[1], prediction.box.endPoint[0] - prediction.box.startPoint[0], prediction.box.endPoint[1] - prediction.box.startPoint[1]] : 0,
mesh,
annotations,
image: prediction.image ? tf.clone(prediction.image) : null,
});
if (prediction.coords) prediction.coords.dispose();
if (prediction.image) prediction.image.dispose();
2020-10-12 01:22:43 +02:00
}
return results;
}
}
2020-10-13 04:01:35 +02:00
async function load(config) {
const models = await Promise.all([
blazeface.load(config),
2020-11-17 16:18:15 +01:00
tf.loadGraphModel(config.mesh.modelPath, { fromTFHub: config.mesh.modelPath.includes('tfhub.dev') }),
tf.loadGraphModel(config.iris.modelPath, { fromTFHub: config.iris.modelPath.includes('tfhub.dev') }),
2020-10-13 04:01:35 +02:00
]);
const faceMesh = new MediaPipeFaceMesh(models[0], models[1], models[2], config);
2020-11-07 16:37:19 +01:00
// eslint-disable-next-line no-console
console.log(`Human: load model: ${config.mesh.modelPath.match(/\/(.*)\./)[1]}`);
// eslint-disable-next-line no-console
console.log(`Human: load model: ${config.iris.modelPath.match(/\/(.*)\./)[1]}`);
2020-10-13 04:01:35 +02:00
return faceMesh;
}
exports.load = load;
2020-10-12 01:22:43 +02:00
exports.MediaPipeFaceMesh = MediaPipeFaceMesh;
2020-11-12 20:52:32 +01:00
exports.triangulation = coords.TRI468;