mirror of https://github.com/vladmandic/human
add extra face rotation prior to mesh
parent
57f6262d38
commit
be8b532cb9
|
@ -9,8 +9,9 @@
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
### **HEAD -> main** 2021/11/14 mandic00@live.com
|
### **release 2.5.2** 2021/11/15 mandic00@live.com
|
||||||
|
|
||||||
|
- improve error handling
|
||||||
|
|
||||||
### **2.5.2** 2021/11/14 mandic00@live.com
|
### **2.5.2** 2021/11/14 mandic00@live.com
|
||||||
|
|
||||||
|
|
9
TODO.md
9
TODO.md
|
@ -6,9 +6,9 @@
|
||||||
|
|
||||||
### Exploring
|
### Exploring
|
||||||
|
|
||||||
- Optical Flow: <https://docs.opencv.org/3.3.1/db/d7f/tutorial_js_lucas_kanade.html>
|
- Optical flow: <https://docs.opencv.org/3.3.1/db/d7f/tutorial_js_lucas_kanade.html>
|
||||||
- Histogram Equalization: Regular, Adaptive, Contrast Limited, CLAHE
|
- Advanced histogram equalization: Adaptive, Contrast Limited, CLAHE
|
||||||
- TFLite Models: <https://js.tensorflow.org/api_tflite/0.0.1-alpha.4/>
|
- TFLite models: <https://js.tensorflow.org/api_tflite/0.0.1-alpha.4/>
|
||||||
- Body segmentation: `robust-video-matting`
|
- Body segmentation: `robust-video-matting`
|
||||||
- TFJS incompatibility with latest `long.js` 5.0.0 due to CJS to ESM switch
|
- TFJS incompatibility with latest `long.js` 5.0.0 due to CJS to ESM switch
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
||||||
#### WebGPU
|
#### WebGPU
|
||||||
|
|
||||||
Experimental support only until support is officially added in Chromium
|
Experimental support only until support is officially added in Chromium
|
||||||
|
|
||||||
- Performance issues:
|
- Performance issues:
|
||||||
<https://github.com/tensorflow/tfjs/issues/5689>
|
<https://github.com/tensorflow/tfjs/issues/5689>
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@ MoveNet MultiPose model does not work with WASM backend due to missing F32 broad
|
||||||
|
|
||||||
<br><hr><br>
|
<br><hr><br>
|
||||||
|
|
||||||
## Pending release notes:
|
## Pending Release Notes
|
||||||
|
|
||||||
New:
|
New:
|
||||||
- new demo `demos/faceid` that utilizes multiple algorithm to validate input before triggering face recognition
|
- new demo `demos/faceid` that utilizes multiple algorithm to validate input before triggering face recognition
|
||||||
|
|
|
@ -32,3 +32,10 @@ designed to serve as a quick check when used together with other indicators:
|
||||||
- Checks if input has obvious artifacts due to recording (e.g. playing back phone recording of a face)
|
- Checks if input has obvious artifacts due to recording (e.g. playing back phone recording of a face)
|
||||||
- Configuration: `human.config.face.liveness`.enabled
|
- Configuration: `human.config.face.liveness`.enabled
|
||||||
- Result: `human.result.face[0].live` as score
|
- Result: `human.result.face[0].live` as score
|
||||||
|
|
||||||
|
### Models
|
||||||
|
|
||||||
|
**FaceID** is compatible with
|
||||||
|
- `faceres.json` (default) perfoms combined age/gender/descriptor analysis
|
||||||
|
- `faceres-deep.json` higher resolution variation of `faceres`
|
||||||
|
- `mobilefacenet` alternative model for face descriptor analysis
|
||||||
|
|
|
@ -19,10 +19,12 @@ const userConfig = {
|
||||||
filter: {
|
filter: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
equalization: true,
|
equalization: true,
|
||||||
|
width: 0,
|
||||||
},
|
},
|
||||||
face: {
|
face: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
detector: { rotation: true, return: true, maxDetected: 50 },
|
// detector: { rotation: false, return: true, maxDetected: 50, iouThreshold: 0.206, minConfidence: 0.122 },
|
||||||
|
detector: { return: true, rotation: true, maxDetected: 50, iouThreshold: 0.01, minConfidence: 0.2 },
|
||||||
mesh: { enabled: true },
|
mesh: { enabled: true },
|
||||||
iris: { enabled: false },
|
iris: { enabled: false },
|
||||||
emotion: { enabled: true },
|
emotion: { enabled: true },
|
||||||
|
@ -138,7 +140,8 @@ async function SelectFaceCanvas(face) {
|
||||||
async function AddFaceCanvas(index, res, fileName) {
|
async function AddFaceCanvas(index, res, fileName) {
|
||||||
all[index] = res.face;
|
all[index] = res.face;
|
||||||
for (const i in res.face) {
|
for (const i in res.face) {
|
||||||
if (res.face[i].mesh.length === 0 || !res.face[i].tensor) continue; // did not get valid results
|
if (!res.face[i].tensor) continue; // did not get valid results
|
||||||
|
if ((res.face[i].faceScore || 0) < human.config.face.detector.minConfidence) continue; // face analysis score too low
|
||||||
all[index][i].fileName = fileName;
|
all[index][i].fileName = fileName;
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
canvas.tag = { sample: index, face: i, source: fileName };
|
canvas.tag = { sample: index, face: i, source: fileName };
|
||||||
|
@ -177,9 +180,9 @@ async function AddImageElement(index, image, length) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const img = new Image(128, 128);
|
const img = new Image(128, 128);
|
||||||
img.onload = () => { // must wait until image is loaded
|
img.onload = () => { // must wait until image is loaded
|
||||||
|
document.getElementById('images').appendChild(img); // and finally we can add it
|
||||||
human.detect(img, userConfig).then((res) => {
|
human.detect(img, userConfig).then((res) => {
|
||||||
AddFaceCanvas(index, res, image); // then wait until image is analyzed
|
AddFaceCanvas(index, res, image); // then wait until image is analyzed
|
||||||
document.getElementById('images').appendChild(img); // and finally we can add it
|
|
||||||
resolve(true);
|
resolve(true);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -236,12 +239,8 @@ async function main() {
|
||||||
log('Discovered images:', images);
|
log('Discovered images:', images);
|
||||||
}
|
}
|
||||||
|
|
||||||
// images = ['/samples/in/solvay1927.jpg'];
|
// images = ['/samples/in/person-lexi.jpg', '/samples/in/person-carolina.jpg', '/samples/in/solvay1927.jpg'];
|
||||||
|
|
||||||
// download and analyze all images
|
|
||||||
// const promises = [];
|
|
||||||
// for (let i = 0; i < images.length; i++) promises.push(AddImageElement(i, images[i], images.length));
|
|
||||||
// await Promise.all(promises);
|
|
||||||
const t0 = human.now();
|
const t0 = human.now();
|
||||||
for (let i = 0; i < images.length; i++) await AddImageElement(i, images[i], images.length);
|
for (let i = 0; i < images.length; i++) await AddImageElement(i, images[i], images.length);
|
||||||
const t1 = human.now();
|
const t1 = human.now();
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
import { Human } from "../../dist/human.esm.js";
|
import { Human } from "../../dist/human.esm.js";
|
||||||
var humanConfig = {
|
var humanConfig = {
|
||||||
modelBasePath: "../../models",
|
modelBasePath: "../../models",
|
||||||
filter: { equalization: false }
|
filter: { equalization: true }
|
||||||
};
|
};
|
||||||
var human = new Human(humanConfig);
|
var human = new Human(humanConfig);
|
||||||
human.env["perfadd"] = false;
|
human.env["perfadd"] = false;
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -11,8 +11,8 @@ import { Human } from '../../dist/human.esm.js'; // equivalent of @vladmandic/Hu
|
||||||
|
|
||||||
const humanConfig = { // user configuration for human, used to fine-tune behavior
|
const humanConfig = { // user configuration for human, used to fine-tune behavior
|
||||||
modelBasePath: '../../models',
|
modelBasePath: '../../models',
|
||||||
filter: { equalization: false },
|
filter: { equalization: true },
|
||||||
// backend: 'webgpu',
|
// backend: 'webgpu' as 'webgpu,
|
||||||
// async: true,
|
// async: true,
|
||||||
// face: { enabled: false, detector: { rotation: true }, iris: { enabled: false }, description: { enabled: false }, emotion: { enabled: false } },
|
// face: { enabled: false, detector: { rotation: true }, iris: { enabled: false }, description: { enabled: false }, emotion: { enabled: false } },
|
||||||
// body: { enabled: false },
|
// body: { enabled: false },
|
||||||
|
|
|
@ -1213,7 +1213,7 @@ async function process2(input, config3, getTensor = true) {
|
||||||
}
|
}
|
||||||
async function skip(config3, input) {
|
async function skip(config3, input) {
|
||||||
let skipFrame = false;
|
let skipFrame = false;
|
||||||
if (config3.cacheSensitivity === 0)
|
if (config3.cacheSensitivity === 0 || !input.shape || input.shape.length !== 4 || input.shape[1] > 2048 || input.shape[2] > 2048)
|
||||||
return skipFrame;
|
return skipFrame;
|
||||||
if (!last.inputTensor) {
|
if (!last.inputTensor) {
|
||||||
last.inputTensor = tfjs_esm_exports.clone(input);
|
last.inputTensor = tfjs_esm_exports.clone(input);
|
||||||
|
@ -5027,7 +5027,6 @@ function correctFaceRotation(rotate, box4, input, inputSize8) {
|
||||||
// src/face/blazeface.ts
|
// src/face/blazeface.ts
|
||||||
var keypointsCount = 6;
|
var keypointsCount = 6;
|
||||||
var model5;
|
var model5;
|
||||||
var anchorsData = [];
|
|
||||||
var anchors = null;
|
var anchors = null;
|
||||||
var inputSize = 0;
|
var inputSize = 0;
|
||||||
var size = () => inputSize;
|
var size = () => inputSize;
|
||||||
|
@ -5044,10 +5043,7 @@ async function load5(config3) {
|
||||||
} else if (config3.debug)
|
} else if (config3.debug)
|
||||||
log("cached model:", model5["modelUrl"]);
|
log("cached model:", model5["modelUrl"]);
|
||||||
inputSize = model5.inputs[0].shape ? model5.inputs[0].shape[2] : 0;
|
inputSize = model5.inputs[0].shape ? model5.inputs[0].shape[2] : 0;
|
||||||
if (inputSize === -1)
|
anchors = tfjs_esm_exports.tensor2d(generateAnchors(inputSize));
|
||||||
inputSize = 64;
|
|
||||||
anchorsData = generateAnchors(inputSize);
|
|
||||||
anchors = tfjs_esm_exports.tensor2d(anchorsData);
|
|
||||||
return model5;
|
return model5;
|
||||||
}
|
}
|
||||||
function decodeBounds(boxOutputs) {
|
function decodeBounds(boxOutputs) {
|
||||||
|
@ -5101,12 +5097,11 @@ async function getBoxes(inputImage, config3) {
|
||||||
b.slice = tfjs_esm_exports.slice(t.batch, [nms[i], keypointsCount - 1], [1, -1]);
|
b.slice = tfjs_esm_exports.slice(t.batch, [nms[i], keypointsCount - 1], [1, -1]);
|
||||||
b.squeeze = tfjs_esm_exports.squeeze(b.slice);
|
b.squeeze = tfjs_esm_exports.squeeze(b.slice);
|
||||||
b.landmarks = tfjs_esm_exports.reshape(b.squeeze, [keypointsCount, -1]);
|
b.landmarks = tfjs_esm_exports.reshape(b.squeeze, [keypointsCount, -1]);
|
||||||
b.startPoint = tfjs_esm_exports.slice(b.bbox, [0, 0], [-1, 2]);
|
const points = await b.bbox.data();
|
||||||
b.endPoint = tfjs_esm_exports.slice(b.bbox, [0, 2], [-1, 2]);
|
|
||||||
boxes.push({
|
boxes.push({
|
||||||
box: {
|
box: {
|
||||||
startPoint: await b.startPoint.data(),
|
startPoint: [points[0], points[1]],
|
||||||
endPoint: await b.endPoint.data()
|
endPoint: [points[2], points[3]]
|
||||||
},
|
},
|
||||||
landmarks: await b.landmarks.array(),
|
landmarks: await b.landmarks.array(),
|
||||||
confidence
|
confidence
|
||||||
|
@ -5879,7 +5874,7 @@ var inputSize5 = 0;
|
||||||
var skipped10 = Number.MAX_SAFE_INTEGER;
|
var skipped10 = Number.MAX_SAFE_INTEGER;
|
||||||
var lastTime10 = 0;
|
var lastTime10 = 0;
|
||||||
async function predict10(input, config3) {
|
async function predict10(input, config3) {
|
||||||
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
||||||
const skipTime = (((_a = config3.face.detector) == null ? void 0 : _a.skipTime) || 0) > now() - lastTime10;
|
const skipTime = (((_a = config3.face.detector) == null ? void 0 : _a.skipTime) || 0) > now() - lastTime10;
|
||||||
const skipFrame = skipped10 < (((_b = config3.face.detector) == null ? void 0 : _b.skipFrames) || 0);
|
const skipFrame = skipped10 < (((_b = config3.face.detector) == null ? void 0 : _b.skipFrames) || 0);
|
||||||
if (!config3.skipAllowed || !skipTime || !skipFrame || boxCache.length === 0) {
|
if (!config3.skipAllowed || !skipTime || !skipFrame || boxCache.length === 0) {
|
||||||
|
@ -5893,7 +5888,10 @@ async function predict10(input, config3) {
|
||||||
landmarks: possible.landmarks,
|
landmarks: possible.landmarks,
|
||||||
confidence: possible.confidence
|
confidence: possible.confidence
|
||||||
};
|
};
|
||||||
boxCache.push(squarifyBox(enlargeBox(scaleBoxCoordinates(box4, possibleBoxes.scaleFactor), Math.sqrt(((_c = config3.face.detector) == null ? void 0 : _c.cropFactor) || 1.6))));
|
const boxScaled = scaleBoxCoordinates(box4, possibleBoxes.scaleFactor);
|
||||||
|
const boxEnlarged = enlargeBox(boxScaled, Math.sqrt(((_c = config3.face.detector) == null ? void 0 : _c.cropFactor) || 1.6));
|
||||||
|
const boxSquared = squarifyBox(boxEnlarged);
|
||||||
|
boxCache.push(boxSquared);
|
||||||
}
|
}
|
||||||
skipped10 = 0;
|
skipped10 = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -5917,14 +5915,14 @@ async function predict10(input, config3) {
|
||||||
faceScore: 0,
|
faceScore: 0,
|
||||||
annotations: {}
|
annotations: {}
|
||||||
};
|
};
|
||||||
[angle, rotationMatrix, face5.tensor] = correctFaceRotation(!((_d = config3.face.mesh) == null ? void 0 : _d.enabled) && ((_e = config3.face.detector) == null ? void 0 : _e.rotation), box4, input, ((_f = config3.face.mesh) == null ? void 0 : _f.enabled) ? inputSize5 : size());
|
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_d = config3.face.detector) == null ? void 0 : _d.rotation, box4, input, ((_e = config3.face.mesh) == null ? void 0 : _e.enabled) ? inputSize5 : size());
|
||||||
if ((_g = config3 == null ? void 0 : config3.filter) == null ? void 0 : _g.equalization) {
|
if ((_f = config3 == null ? void 0 : config3.filter) == null ? void 0 : _f.equalization) {
|
||||||
const equilized = await histogramEqualization(face5.tensor);
|
const equilized = await histogramEqualization(face5.tensor);
|
||||||
tfjs_esm_exports.dispose(face5.tensor);
|
tfjs_esm_exports.dispose(face5.tensor);
|
||||||
face5.tensor = equilized;
|
face5.tensor = equilized;
|
||||||
}
|
}
|
||||||
face5.boxScore = Math.round(100 * box4.confidence) / 100;
|
face5.boxScore = Math.round(100 * box4.confidence) / 100;
|
||||||
if (!((_h = config3.face.mesh) == null ? void 0 : _h.enabled)) {
|
if (!((_g = config3.face.mesh) == null ? void 0 : _g.enabled)) {
|
||||||
face5.box = getClampedBox(box4, input);
|
face5.box = getClampedBox(box4, input);
|
||||||
face5.boxRaw = getRawBox(box4, input);
|
face5.boxRaw = getRawBox(box4, input);
|
||||||
face5.score = face5.boxScore;
|
face5.score = face5.boxScore;
|
||||||
|
@ -5945,22 +5943,22 @@ async function predict10(input, config3) {
|
||||||
const coordsReshaped = tfjs_esm_exports.reshape(contourCoords, [-1, 3]);
|
const coordsReshaped = tfjs_esm_exports.reshape(contourCoords, [-1, 3]);
|
||||||
let rawCoords = await coordsReshaped.array();
|
let rawCoords = await coordsReshaped.array();
|
||||||
tfjs_esm_exports.dispose([contourCoords, coordsReshaped, confidence, contours]);
|
tfjs_esm_exports.dispose([contourCoords, coordsReshaped, confidence, contours]);
|
||||||
if (face5.faceScore < (((_i = config3.face.detector) == null ? void 0 : _i.minConfidence) || 1)) {
|
if (face5.faceScore < (((_h = config3.face.detector) == null ? void 0 : _h.minConfidence) || 1)) {
|
||||||
box4.confidence = face5.faceScore;
|
box4.confidence = face5.faceScore;
|
||||||
} else {
|
} else {
|
||||||
if ((_j = config3.face.iris) == null ? void 0 : _j.enabled)
|
if ((_i = config3.face.iris) == null ? void 0 : _i.enabled)
|
||||||
rawCoords = await augmentIris(rawCoords, face5.tensor, config3, inputSize5);
|
rawCoords = await augmentIris(rawCoords, face5.tensor, config3, inputSize5);
|
||||||
face5.mesh = transformRawCoords(rawCoords, box4, angle, rotationMatrix, inputSize5);
|
face5.mesh = transformRawCoords(rawCoords, box4, angle, rotationMatrix, inputSize5);
|
||||||
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize5]);
|
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize5]);
|
||||||
for (const key of Object.keys(meshAnnotations))
|
for (const key of Object.keys(meshAnnotations))
|
||||||
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
|
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
|
||||||
box4 = squarifyBox({ ...enlargeBox(calculateLandmarksBoundingBox(face5.mesh), ((_k = config3.face.detector) == null ? void 0 : _k.cropFactor) || 1.6), confidence: box4.confidence });
|
box4 = squarifyBox({ ...enlargeBox(calculateLandmarksBoundingBox(face5.mesh), ((_j = config3.face.detector) == null ? void 0 : _j.cropFactor) || 1.6), confidence: box4.confidence });
|
||||||
face5.box = getClampedBox(box4, input);
|
face5.box = getClampedBox(box4, input);
|
||||||
face5.boxRaw = getRawBox(box4, input);
|
face5.boxRaw = getRawBox(box4, input);
|
||||||
face5.score = face5.faceScore;
|
face5.score = face5.faceScore;
|
||||||
newCache.push(box4);
|
newCache.push(box4);
|
||||||
tfjs_esm_exports.dispose(face5.tensor);
|
tfjs_esm_exports.dispose(face5.tensor);
|
||||||
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_l = config3.face.detector) == null ? void 0 : _l.rotation, box4, input, inputSize5);
|
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_k = config3.face.detector) == null ? void 0 : _k.rotation, box4, input, inputSize5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
faces.push(face5);
|
faces.push(face5);
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -14194,7 +14194,8 @@ function intersectionOverUnion(boxes, i, j) {
|
||||||
const intersectionYmax = Math.min(ymaxI, ymaxJ);
|
const intersectionYmax = Math.min(ymaxI, ymaxJ);
|
||||||
const intersectionXmax = Math.min(xmaxI, xmaxJ);
|
const intersectionXmax = Math.min(xmaxI, xmaxJ);
|
||||||
const intersectionArea = Math.max(intersectionYmax - intersectionYmin, 0) * Math.max(intersectionXmax - intersectionXmin, 0);
|
const intersectionArea = Math.max(intersectionYmax - intersectionYmin, 0) * Math.max(intersectionXmax - intersectionXmin, 0);
|
||||||
return intersectionArea / (areaI + areaJ - intersectionArea);
|
const iou = intersectionArea / (areaI + areaJ - intersectionArea);
|
||||||
|
return iou;
|
||||||
}
|
}
|
||||||
function suppressWeight(iouThreshold, scale22, iou) {
|
function suppressWeight(iouThreshold, scale22, iou) {
|
||||||
const weight = Math.exp(scale22 * iou * iou);
|
const weight = Math.exp(scale22 * iou * iou);
|
||||||
|
@ -71538,7 +71539,7 @@ async function process2(input2, config3, getTensor2 = true) {
|
||||||
}
|
}
|
||||||
async function skip(config3, input2) {
|
async function skip(config3, input2) {
|
||||||
let skipFrame = false;
|
let skipFrame = false;
|
||||||
if (config3.cacheSensitivity === 0)
|
if (config3.cacheSensitivity === 0 || !input2.shape || input2.shape.length !== 4 || input2.shape[1] > 2048 || input2.shape[2] > 2048)
|
||||||
return skipFrame;
|
return skipFrame;
|
||||||
if (!last.inputTensor) {
|
if (!last.inputTensor) {
|
||||||
last.inputTensor = clone(input2);
|
last.inputTensor = clone(input2);
|
||||||
|
@ -75352,7 +75353,6 @@ function correctFaceRotation(rotate, box4, input2, inputSize8) {
|
||||||
// src/face/blazeface.ts
|
// src/face/blazeface.ts
|
||||||
var keypointsCount = 6;
|
var keypointsCount = 6;
|
||||||
var model6;
|
var model6;
|
||||||
var anchorsData = [];
|
|
||||||
var anchors = null;
|
var anchors = null;
|
||||||
var inputSize = 0;
|
var inputSize = 0;
|
||||||
var size = () => inputSize;
|
var size = () => inputSize;
|
||||||
|
@ -75369,10 +75369,7 @@ async function load5(config3) {
|
||||||
} else if (config3.debug)
|
} else if (config3.debug)
|
||||||
log("cached model:", model6["modelUrl"]);
|
log("cached model:", model6["modelUrl"]);
|
||||||
inputSize = model6.inputs[0].shape ? model6.inputs[0].shape[2] : 0;
|
inputSize = model6.inputs[0].shape ? model6.inputs[0].shape[2] : 0;
|
||||||
if (inputSize === -1)
|
anchors = tensor2d(generateAnchors(inputSize));
|
||||||
inputSize = 64;
|
|
||||||
anchorsData = generateAnchors(inputSize);
|
|
||||||
anchors = tensor2d(anchorsData);
|
|
||||||
return model6;
|
return model6;
|
||||||
}
|
}
|
||||||
function decodeBounds(boxOutputs) {
|
function decodeBounds(boxOutputs) {
|
||||||
|
@ -75426,12 +75423,11 @@ async function getBoxes(inputImage, config3) {
|
||||||
b.slice = slice(t.batch, [nms[i], keypointsCount - 1], [1, -1]);
|
b.slice = slice(t.batch, [nms[i], keypointsCount - 1], [1, -1]);
|
||||||
b.squeeze = squeeze(b.slice);
|
b.squeeze = squeeze(b.slice);
|
||||||
b.landmarks = reshape(b.squeeze, [keypointsCount, -1]);
|
b.landmarks = reshape(b.squeeze, [keypointsCount, -1]);
|
||||||
b.startPoint = slice(b.bbox, [0, 0], [-1, 2]);
|
const points = await b.bbox.data();
|
||||||
b.endPoint = slice(b.bbox, [0, 2], [-1, 2]);
|
|
||||||
boxes.push({
|
boxes.push({
|
||||||
box: {
|
box: {
|
||||||
startPoint: await b.startPoint.data(),
|
startPoint: [points[0], points[1]],
|
||||||
endPoint: await b.endPoint.data()
|
endPoint: [points[2], points[3]]
|
||||||
},
|
},
|
||||||
landmarks: await b.landmarks.array(),
|
landmarks: await b.landmarks.array(),
|
||||||
confidence
|
confidence
|
||||||
|
@ -76204,7 +76200,7 @@ var inputSize5 = 0;
|
||||||
var skipped10 = Number.MAX_SAFE_INTEGER;
|
var skipped10 = Number.MAX_SAFE_INTEGER;
|
||||||
var lastTime10 = 0;
|
var lastTime10 = 0;
|
||||||
async function predict10(input2, config3) {
|
async function predict10(input2, config3) {
|
||||||
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
||||||
const skipTime = (((_a = config3.face.detector) == null ? void 0 : _a.skipTime) || 0) > now() - lastTime10;
|
const skipTime = (((_a = config3.face.detector) == null ? void 0 : _a.skipTime) || 0) > now() - lastTime10;
|
||||||
const skipFrame = skipped10 < (((_b = config3.face.detector) == null ? void 0 : _b.skipFrames) || 0);
|
const skipFrame = skipped10 < (((_b = config3.face.detector) == null ? void 0 : _b.skipFrames) || 0);
|
||||||
if (!config3.skipAllowed || !skipTime || !skipFrame || boxCache.length === 0) {
|
if (!config3.skipAllowed || !skipTime || !skipFrame || boxCache.length === 0) {
|
||||||
|
@ -76218,7 +76214,10 @@ async function predict10(input2, config3) {
|
||||||
landmarks: possible.landmarks,
|
landmarks: possible.landmarks,
|
||||||
confidence: possible.confidence
|
confidence: possible.confidence
|
||||||
};
|
};
|
||||||
boxCache.push(squarifyBox(enlargeBox(scaleBoxCoordinates(box4, possibleBoxes.scaleFactor), Math.sqrt(((_c = config3.face.detector) == null ? void 0 : _c.cropFactor) || 1.6))));
|
const boxScaled = scaleBoxCoordinates(box4, possibleBoxes.scaleFactor);
|
||||||
|
const boxEnlarged = enlargeBox(boxScaled, Math.sqrt(((_c = config3.face.detector) == null ? void 0 : _c.cropFactor) || 1.6));
|
||||||
|
const boxSquared = squarifyBox(boxEnlarged);
|
||||||
|
boxCache.push(boxSquared);
|
||||||
}
|
}
|
||||||
skipped10 = 0;
|
skipped10 = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -76242,14 +76241,14 @@ async function predict10(input2, config3) {
|
||||||
faceScore: 0,
|
faceScore: 0,
|
||||||
annotations: {}
|
annotations: {}
|
||||||
};
|
};
|
||||||
[angle, rotationMatrix, face5.tensor] = correctFaceRotation(!((_d = config3.face.mesh) == null ? void 0 : _d.enabled) && ((_e = config3.face.detector) == null ? void 0 : _e.rotation), box4, input2, ((_f = config3.face.mesh) == null ? void 0 : _f.enabled) ? inputSize5 : size());
|
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_d = config3.face.detector) == null ? void 0 : _d.rotation, box4, input2, ((_e = config3.face.mesh) == null ? void 0 : _e.enabled) ? inputSize5 : size());
|
||||||
if ((_g = config3 == null ? void 0 : config3.filter) == null ? void 0 : _g.equalization) {
|
if ((_f = config3 == null ? void 0 : config3.filter) == null ? void 0 : _f.equalization) {
|
||||||
const equilized = await histogramEqualization(face5.tensor);
|
const equilized = await histogramEqualization(face5.tensor);
|
||||||
dispose(face5.tensor);
|
dispose(face5.tensor);
|
||||||
face5.tensor = equilized;
|
face5.tensor = equilized;
|
||||||
}
|
}
|
||||||
face5.boxScore = Math.round(100 * box4.confidence) / 100;
|
face5.boxScore = Math.round(100 * box4.confidence) / 100;
|
||||||
if (!((_h = config3.face.mesh) == null ? void 0 : _h.enabled)) {
|
if (!((_g = config3.face.mesh) == null ? void 0 : _g.enabled)) {
|
||||||
face5.box = getClampedBox(box4, input2);
|
face5.box = getClampedBox(box4, input2);
|
||||||
face5.boxRaw = getRawBox(box4, input2);
|
face5.boxRaw = getRawBox(box4, input2);
|
||||||
face5.score = face5.boxScore;
|
face5.score = face5.boxScore;
|
||||||
|
@ -76270,22 +76269,22 @@ async function predict10(input2, config3) {
|
||||||
const coordsReshaped = reshape(contourCoords, [-1, 3]);
|
const coordsReshaped = reshape(contourCoords, [-1, 3]);
|
||||||
let rawCoords = await coordsReshaped.array();
|
let rawCoords = await coordsReshaped.array();
|
||||||
dispose([contourCoords, coordsReshaped, confidence, contours]);
|
dispose([contourCoords, coordsReshaped, confidence, contours]);
|
||||||
if (face5.faceScore < (((_i = config3.face.detector) == null ? void 0 : _i.minConfidence) || 1)) {
|
if (face5.faceScore < (((_h = config3.face.detector) == null ? void 0 : _h.minConfidence) || 1)) {
|
||||||
box4.confidence = face5.faceScore;
|
box4.confidence = face5.faceScore;
|
||||||
} else {
|
} else {
|
||||||
if ((_j = config3.face.iris) == null ? void 0 : _j.enabled)
|
if ((_i = config3.face.iris) == null ? void 0 : _i.enabled)
|
||||||
rawCoords = await augmentIris(rawCoords, face5.tensor, config3, inputSize5);
|
rawCoords = await augmentIris(rawCoords, face5.tensor, config3, inputSize5);
|
||||||
face5.mesh = transformRawCoords(rawCoords, box4, angle, rotationMatrix, inputSize5);
|
face5.mesh = transformRawCoords(rawCoords, box4, angle, rotationMatrix, inputSize5);
|
||||||
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input2.shape[2] || 0), pt[1] / (input2.shape[1] || 0), (pt[2] || 0) / inputSize5]);
|
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input2.shape[2] || 0), pt[1] / (input2.shape[1] || 0), (pt[2] || 0) / inputSize5]);
|
||||||
for (const key of Object.keys(meshAnnotations))
|
for (const key of Object.keys(meshAnnotations))
|
||||||
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
|
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
|
||||||
box4 = squarifyBox({ ...enlargeBox(calculateLandmarksBoundingBox(face5.mesh), ((_k = config3.face.detector) == null ? void 0 : _k.cropFactor) || 1.6), confidence: box4.confidence });
|
box4 = squarifyBox({ ...enlargeBox(calculateLandmarksBoundingBox(face5.mesh), ((_j = config3.face.detector) == null ? void 0 : _j.cropFactor) || 1.6), confidence: box4.confidence });
|
||||||
face5.box = getClampedBox(box4, input2);
|
face5.box = getClampedBox(box4, input2);
|
||||||
face5.boxRaw = getRawBox(box4, input2);
|
face5.boxRaw = getRawBox(box4, input2);
|
||||||
face5.score = face5.faceScore;
|
face5.score = face5.faceScore;
|
||||||
newCache.push(box4);
|
newCache.push(box4);
|
||||||
dispose(face5.tensor);
|
dispose(face5.tensor);
|
||||||
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_l = config3.face.detector) == null ? void 0 : _l.rotation, box4, input2, inputSize5);
|
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_k = config3.face.detector) == null ? void 0 : _k.rotation, box4, input2, inputSize5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
faces.push(face5);
|
faces.push(face5);
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1223,7 +1223,7 @@ async function process2(input, config3, getTensor = true) {
|
||||||
}
|
}
|
||||||
async function skip(config3, input) {
|
async function skip(config3, input) {
|
||||||
let skipFrame = false;
|
let skipFrame = false;
|
||||||
if (config3.cacheSensitivity === 0)
|
if (config3.cacheSensitivity === 0 || !input.shape || input.shape.length !== 4 || input.shape[1] > 2048 || input.shape[2] > 2048)
|
||||||
return skipFrame;
|
return skipFrame;
|
||||||
if (!last.inputTensor) {
|
if (!last.inputTensor) {
|
||||||
last.inputTensor = tf2.clone(input);
|
last.inputTensor = tf2.clone(input);
|
||||||
|
@ -5053,7 +5053,6 @@ function correctFaceRotation(rotate, box4, input, inputSize8) {
|
||||||
// src/face/blazeface.ts
|
// src/face/blazeface.ts
|
||||||
var keypointsCount = 6;
|
var keypointsCount = 6;
|
||||||
var model5;
|
var model5;
|
||||||
var anchorsData = [];
|
|
||||||
var anchors = null;
|
var anchors = null;
|
||||||
var inputSize = 0;
|
var inputSize = 0;
|
||||||
var size = () => inputSize;
|
var size = () => inputSize;
|
||||||
|
@ -5070,10 +5069,7 @@ async function load5(config3) {
|
||||||
} else if (config3.debug)
|
} else if (config3.debug)
|
||||||
log("cached model:", model5["modelUrl"]);
|
log("cached model:", model5["modelUrl"]);
|
||||||
inputSize = model5.inputs[0].shape ? model5.inputs[0].shape[2] : 0;
|
inputSize = model5.inputs[0].shape ? model5.inputs[0].shape[2] : 0;
|
||||||
if (inputSize === -1)
|
anchors = tf9.tensor2d(generateAnchors(inputSize));
|
||||||
inputSize = 64;
|
|
||||||
anchorsData = generateAnchors(inputSize);
|
|
||||||
anchors = tf9.tensor2d(anchorsData);
|
|
||||||
return model5;
|
return model5;
|
||||||
}
|
}
|
||||||
function decodeBounds(boxOutputs) {
|
function decodeBounds(boxOutputs) {
|
||||||
|
@ -5127,12 +5123,11 @@ async function getBoxes(inputImage, config3) {
|
||||||
b.slice = tf9.slice(t.batch, [nms[i], keypointsCount - 1], [1, -1]);
|
b.slice = tf9.slice(t.batch, [nms[i], keypointsCount - 1], [1, -1]);
|
||||||
b.squeeze = tf9.squeeze(b.slice);
|
b.squeeze = tf9.squeeze(b.slice);
|
||||||
b.landmarks = tf9.reshape(b.squeeze, [keypointsCount, -1]);
|
b.landmarks = tf9.reshape(b.squeeze, [keypointsCount, -1]);
|
||||||
b.startPoint = tf9.slice(b.bbox, [0, 0], [-1, 2]);
|
const points = await b.bbox.data();
|
||||||
b.endPoint = tf9.slice(b.bbox, [0, 2], [-1, 2]);
|
|
||||||
boxes.push({
|
boxes.push({
|
||||||
box: {
|
box: {
|
||||||
startPoint: await b.startPoint.data(),
|
startPoint: [points[0], points[1]],
|
||||||
endPoint: await b.endPoint.data()
|
endPoint: [points[2], points[3]]
|
||||||
},
|
},
|
||||||
landmarks: await b.landmarks.array(),
|
landmarks: await b.landmarks.array(),
|
||||||
confidence
|
confidence
|
||||||
|
@ -5920,7 +5915,7 @@ var inputSize5 = 0;
|
||||||
var skipped10 = Number.MAX_SAFE_INTEGER;
|
var skipped10 = Number.MAX_SAFE_INTEGER;
|
||||||
var lastTime10 = 0;
|
var lastTime10 = 0;
|
||||||
async function predict10(input, config3) {
|
async function predict10(input, config3) {
|
||||||
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
||||||
const skipTime = (((_a = config3.face.detector) == null ? void 0 : _a.skipTime) || 0) > now() - lastTime10;
|
const skipTime = (((_a = config3.face.detector) == null ? void 0 : _a.skipTime) || 0) > now() - lastTime10;
|
||||||
const skipFrame = skipped10 < (((_b = config3.face.detector) == null ? void 0 : _b.skipFrames) || 0);
|
const skipFrame = skipped10 < (((_b = config3.face.detector) == null ? void 0 : _b.skipFrames) || 0);
|
||||||
if (!config3.skipAllowed || !skipTime || !skipFrame || boxCache.length === 0) {
|
if (!config3.skipAllowed || !skipTime || !skipFrame || boxCache.length === 0) {
|
||||||
|
@ -5934,7 +5929,10 @@ async function predict10(input, config3) {
|
||||||
landmarks: possible.landmarks,
|
landmarks: possible.landmarks,
|
||||||
confidence: possible.confidence
|
confidence: possible.confidence
|
||||||
};
|
};
|
||||||
boxCache.push(squarifyBox(enlargeBox(scaleBoxCoordinates(box4, possibleBoxes.scaleFactor), Math.sqrt(((_c = config3.face.detector) == null ? void 0 : _c.cropFactor) || 1.6))));
|
const boxScaled = scaleBoxCoordinates(box4, possibleBoxes.scaleFactor);
|
||||||
|
const boxEnlarged = enlargeBox(boxScaled, Math.sqrt(((_c = config3.face.detector) == null ? void 0 : _c.cropFactor) || 1.6));
|
||||||
|
const boxSquared = squarifyBox(boxEnlarged);
|
||||||
|
boxCache.push(boxSquared);
|
||||||
}
|
}
|
||||||
skipped10 = 0;
|
skipped10 = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -5958,14 +5956,14 @@ async function predict10(input, config3) {
|
||||||
faceScore: 0,
|
faceScore: 0,
|
||||||
annotations: {}
|
annotations: {}
|
||||||
};
|
};
|
||||||
[angle, rotationMatrix, face5.tensor] = correctFaceRotation(!((_d = config3.face.mesh) == null ? void 0 : _d.enabled) && ((_e = config3.face.detector) == null ? void 0 : _e.rotation), box4, input, ((_f = config3.face.mesh) == null ? void 0 : _f.enabled) ? inputSize5 : size());
|
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_d = config3.face.detector) == null ? void 0 : _d.rotation, box4, input, ((_e = config3.face.mesh) == null ? void 0 : _e.enabled) ? inputSize5 : size());
|
||||||
if ((_g = config3 == null ? void 0 : config3.filter) == null ? void 0 : _g.equalization) {
|
if ((_f = config3 == null ? void 0 : config3.filter) == null ? void 0 : _f.equalization) {
|
||||||
const equilized = await histogramEqualization(face5.tensor);
|
const equilized = await histogramEqualization(face5.tensor);
|
||||||
tf16.dispose(face5.tensor);
|
tf16.dispose(face5.tensor);
|
||||||
face5.tensor = equilized;
|
face5.tensor = equilized;
|
||||||
}
|
}
|
||||||
face5.boxScore = Math.round(100 * box4.confidence) / 100;
|
face5.boxScore = Math.round(100 * box4.confidence) / 100;
|
||||||
if (!((_h = config3.face.mesh) == null ? void 0 : _h.enabled)) {
|
if (!((_g = config3.face.mesh) == null ? void 0 : _g.enabled)) {
|
||||||
face5.box = getClampedBox(box4, input);
|
face5.box = getClampedBox(box4, input);
|
||||||
face5.boxRaw = getRawBox(box4, input);
|
face5.boxRaw = getRawBox(box4, input);
|
||||||
face5.score = face5.boxScore;
|
face5.score = face5.boxScore;
|
||||||
|
@ -5986,22 +5984,22 @@ async function predict10(input, config3) {
|
||||||
const coordsReshaped = tf16.reshape(contourCoords, [-1, 3]);
|
const coordsReshaped = tf16.reshape(contourCoords, [-1, 3]);
|
||||||
let rawCoords = await coordsReshaped.array();
|
let rawCoords = await coordsReshaped.array();
|
||||||
tf16.dispose([contourCoords, coordsReshaped, confidence, contours]);
|
tf16.dispose([contourCoords, coordsReshaped, confidence, contours]);
|
||||||
if (face5.faceScore < (((_i = config3.face.detector) == null ? void 0 : _i.minConfidence) || 1)) {
|
if (face5.faceScore < (((_h = config3.face.detector) == null ? void 0 : _h.minConfidence) || 1)) {
|
||||||
box4.confidence = face5.faceScore;
|
box4.confidence = face5.faceScore;
|
||||||
} else {
|
} else {
|
||||||
if ((_j = config3.face.iris) == null ? void 0 : _j.enabled)
|
if ((_i = config3.face.iris) == null ? void 0 : _i.enabled)
|
||||||
rawCoords = await augmentIris(rawCoords, face5.tensor, config3, inputSize5);
|
rawCoords = await augmentIris(rawCoords, face5.tensor, config3, inputSize5);
|
||||||
face5.mesh = transformRawCoords(rawCoords, box4, angle, rotationMatrix, inputSize5);
|
face5.mesh = transformRawCoords(rawCoords, box4, angle, rotationMatrix, inputSize5);
|
||||||
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize5]);
|
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize5]);
|
||||||
for (const key of Object.keys(meshAnnotations))
|
for (const key of Object.keys(meshAnnotations))
|
||||||
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
|
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
|
||||||
box4 = squarifyBox({ ...enlargeBox(calculateLandmarksBoundingBox(face5.mesh), ((_k = config3.face.detector) == null ? void 0 : _k.cropFactor) || 1.6), confidence: box4.confidence });
|
box4 = squarifyBox({ ...enlargeBox(calculateLandmarksBoundingBox(face5.mesh), ((_j = config3.face.detector) == null ? void 0 : _j.cropFactor) || 1.6), confidence: box4.confidence });
|
||||||
face5.box = getClampedBox(box4, input);
|
face5.box = getClampedBox(box4, input);
|
||||||
face5.boxRaw = getRawBox(box4, input);
|
face5.boxRaw = getRawBox(box4, input);
|
||||||
face5.score = face5.faceScore;
|
face5.score = face5.faceScore;
|
||||||
newCache.push(box4);
|
newCache.push(box4);
|
||||||
tf16.dispose(face5.tensor);
|
tf16.dispose(face5.tensor);
|
||||||
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_l = config3.face.detector) == null ? void 0 : _l.rotation, box4, input, inputSize5);
|
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_k = config3.face.detector) == null ? void 0 : _k.rotation, box4, input, inputSize5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
faces.push(face5);
|
faces.push(face5);
|
||||||
|
|
|
@ -1224,7 +1224,7 @@ async function process2(input, config3, getTensor = true) {
|
||||||
}
|
}
|
||||||
async function skip(config3, input) {
|
async function skip(config3, input) {
|
||||||
let skipFrame = false;
|
let skipFrame = false;
|
||||||
if (config3.cacheSensitivity === 0)
|
if (config3.cacheSensitivity === 0 || !input.shape || input.shape.length !== 4 || input.shape[1] > 2048 || input.shape[2] > 2048)
|
||||||
return skipFrame;
|
return skipFrame;
|
||||||
if (!last.inputTensor) {
|
if (!last.inputTensor) {
|
||||||
last.inputTensor = tf2.clone(input);
|
last.inputTensor = tf2.clone(input);
|
||||||
|
@ -5054,7 +5054,6 @@ function correctFaceRotation(rotate, box4, input, inputSize8) {
|
||||||
// src/face/blazeface.ts
|
// src/face/blazeface.ts
|
||||||
var keypointsCount = 6;
|
var keypointsCount = 6;
|
||||||
var model5;
|
var model5;
|
||||||
var anchorsData = [];
|
|
||||||
var anchors = null;
|
var anchors = null;
|
||||||
var inputSize = 0;
|
var inputSize = 0;
|
||||||
var size = () => inputSize;
|
var size = () => inputSize;
|
||||||
|
@ -5071,10 +5070,7 @@ async function load5(config3) {
|
||||||
} else if (config3.debug)
|
} else if (config3.debug)
|
||||||
log("cached model:", model5["modelUrl"]);
|
log("cached model:", model5["modelUrl"]);
|
||||||
inputSize = model5.inputs[0].shape ? model5.inputs[0].shape[2] : 0;
|
inputSize = model5.inputs[0].shape ? model5.inputs[0].shape[2] : 0;
|
||||||
if (inputSize === -1)
|
anchors = tf9.tensor2d(generateAnchors(inputSize));
|
||||||
inputSize = 64;
|
|
||||||
anchorsData = generateAnchors(inputSize);
|
|
||||||
anchors = tf9.tensor2d(anchorsData);
|
|
||||||
return model5;
|
return model5;
|
||||||
}
|
}
|
||||||
function decodeBounds(boxOutputs) {
|
function decodeBounds(boxOutputs) {
|
||||||
|
@ -5128,12 +5124,11 @@ async function getBoxes(inputImage, config3) {
|
||||||
b.slice = tf9.slice(t.batch, [nms[i], keypointsCount - 1], [1, -1]);
|
b.slice = tf9.slice(t.batch, [nms[i], keypointsCount - 1], [1, -1]);
|
||||||
b.squeeze = tf9.squeeze(b.slice);
|
b.squeeze = tf9.squeeze(b.slice);
|
||||||
b.landmarks = tf9.reshape(b.squeeze, [keypointsCount, -1]);
|
b.landmarks = tf9.reshape(b.squeeze, [keypointsCount, -1]);
|
||||||
b.startPoint = tf9.slice(b.bbox, [0, 0], [-1, 2]);
|
const points = await b.bbox.data();
|
||||||
b.endPoint = tf9.slice(b.bbox, [0, 2], [-1, 2]);
|
|
||||||
boxes.push({
|
boxes.push({
|
||||||
box: {
|
box: {
|
||||||
startPoint: await b.startPoint.data(),
|
startPoint: [points[0], points[1]],
|
||||||
endPoint: await b.endPoint.data()
|
endPoint: [points[2], points[3]]
|
||||||
},
|
},
|
||||||
landmarks: await b.landmarks.array(),
|
landmarks: await b.landmarks.array(),
|
||||||
confidence
|
confidence
|
||||||
|
@ -5921,7 +5916,7 @@ var inputSize5 = 0;
|
||||||
var skipped10 = Number.MAX_SAFE_INTEGER;
|
var skipped10 = Number.MAX_SAFE_INTEGER;
|
||||||
var lastTime10 = 0;
|
var lastTime10 = 0;
|
||||||
async function predict10(input, config3) {
|
async function predict10(input, config3) {
|
||||||
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
||||||
const skipTime = (((_a = config3.face.detector) == null ? void 0 : _a.skipTime) || 0) > now() - lastTime10;
|
const skipTime = (((_a = config3.face.detector) == null ? void 0 : _a.skipTime) || 0) > now() - lastTime10;
|
||||||
const skipFrame = skipped10 < (((_b = config3.face.detector) == null ? void 0 : _b.skipFrames) || 0);
|
const skipFrame = skipped10 < (((_b = config3.face.detector) == null ? void 0 : _b.skipFrames) || 0);
|
||||||
if (!config3.skipAllowed || !skipTime || !skipFrame || boxCache.length === 0) {
|
if (!config3.skipAllowed || !skipTime || !skipFrame || boxCache.length === 0) {
|
||||||
|
@ -5935,7 +5930,10 @@ async function predict10(input, config3) {
|
||||||
landmarks: possible.landmarks,
|
landmarks: possible.landmarks,
|
||||||
confidence: possible.confidence
|
confidence: possible.confidence
|
||||||
};
|
};
|
||||||
boxCache.push(squarifyBox(enlargeBox(scaleBoxCoordinates(box4, possibleBoxes.scaleFactor), Math.sqrt(((_c = config3.face.detector) == null ? void 0 : _c.cropFactor) || 1.6))));
|
const boxScaled = scaleBoxCoordinates(box4, possibleBoxes.scaleFactor);
|
||||||
|
const boxEnlarged = enlargeBox(boxScaled, Math.sqrt(((_c = config3.face.detector) == null ? void 0 : _c.cropFactor) || 1.6));
|
||||||
|
const boxSquared = squarifyBox(boxEnlarged);
|
||||||
|
boxCache.push(boxSquared);
|
||||||
}
|
}
|
||||||
skipped10 = 0;
|
skipped10 = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -5959,14 +5957,14 @@ async function predict10(input, config3) {
|
||||||
faceScore: 0,
|
faceScore: 0,
|
||||||
annotations: {}
|
annotations: {}
|
||||||
};
|
};
|
||||||
[angle, rotationMatrix, face5.tensor] = correctFaceRotation(!((_d = config3.face.mesh) == null ? void 0 : _d.enabled) && ((_e = config3.face.detector) == null ? void 0 : _e.rotation), box4, input, ((_f = config3.face.mesh) == null ? void 0 : _f.enabled) ? inputSize5 : size());
|
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_d = config3.face.detector) == null ? void 0 : _d.rotation, box4, input, ((_e = config3.face.mesh) == null ? void 0 : _e.enabled) ? inputSize5 : size());
|
||||||
if ((_g = config3 == null ? void 0 : config3.filter) == null ? void 0 : _g.equalization) {
|
if ((_f = config3 == null ? void 0 : config3.filter) == null ? void 0 : _f.equalization) {
|
||||||
const equilized = await histogramEqualization(face5.tensor);
|
const equilized = await histogramEqualization(face5.tensor);
|
||||||
tf16.dispose(face5.tensor);
|
tf16.dispose(face5.tensor);
|
||||||
face5.tensor = equilized;
|
face5.tensor = equilized;
|
||||||
}
|
}
|
||||||
face5.boxScore = Math.round(100 * box4.confidence) / 100;
|
face5.boxScore = Math.round(100 * box4.confidence) / 100;
|
||||||
if (!((_h = config3.face.mesh) == null ? void 0 : _h.enabled)) {
|
if (!((_g = config3.face.mesh) == null ? void 0 : _g.enabled)) {
|
||||||
face5.box = getClampedBox(box4, input);
|
face5.box = getClampedBox(box4, input);
|
||||||
face5.boxRaw = getRawBox(box4, input);
|
face5.boxRaw = getRawBox(box4, input);
|
||||||
face5.score = face5.boxScore;
|
face5.score = face5.boxScore;
|
||||||
|
@ -5987,22 +5985,22 @@ async function predict10(input, config3) {
|
||||||
const coordsReshaped = tf16.reshape(contourCoords, [-1, 3]);
|
const coordsReshaped = tf16.reshape(contourCoords, [-1, 3]);
|
||||||
let rawCoords = await coordsReshaped.array();
|
let rawCoords = await coordsReshaped.array();
|
||||||
tf16.dispose([contourCoords, coordsReshaped, confidence, contours]);
|
tf16.dispose([contourCoords, coordsReshaped, confidence, contours]);
|
||||||
if (face5.faceScore < (((_i = config3.face.detector) == null ? void 0 : _i.minConfidence) || 1)) {
|
if (face5.faceScore < (((_h = config3.face.detector) == null ? void 0 : _h.minConfidence) || 1)) {
|
||||||
box4.confidence = face5.faceScore;
|
box4.confidence = face5.faceScore;
|
||||||
} else {
|
} else {
|
||||||
if ((_j = config3.face.iris) == null ? void 0 : _j.enabled)
|
if ((_i = config3.face.iris) == null ? void 0 : _i.enabled)
|
||||||
rawCoords = await augmentIris(rawCoords, face5.tensor, config3, inputSize5);
|
rawCoords = await augmentIris(rawCoords, face5.tensor, config3, inputSize5);
|
||||||
face5.mesh = transformRawCoords(rawCoords, box4, angle, rotationMatrix, inputSize5);
|
face5.mesh = transformRawCoords(rawCoords, box4, angle, rotationMatrix, inputSize5);
|
||||||
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize5]);
|
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize5]);
|
||||||
for (const key of Object.keys(meshAnnotations))
|
for (const key of Object.keys(meshAnnotations))
|
||||||
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
|
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
|
||||||
box4 = squarifyBox({ ...enlargeBox(calculateLandmarksBoundingBox(face5.mesh), ((_k = config3.face.detector) == null ? void 0 : _k.cropFactor) || 1.6), confidence: box4.confidence });
|
box4 = squarifyBox({ ...enlargeBox(calculateLandmarksBoundingBox(face5.mesh), ((_j = config3.face.detector) == null ? void 0 : _j.cropFactor) || 1.6), confidence: box4.confidence });
|
||||||
face5.box = getClampedBox(box4, input);
|
face5.box = getClampedBox(box4, input);
|
||||||
face5.boxRaw = getRawBox(box4, input);
|
face5.boxRaw = getRawBox(box4, input);
|
||||||
face5.score = face5.faceScore;
|
face5.score = face5.faceScore;
|
||||||
newCache.push(box4);
|
newCache.push(box4);
|
||||||
tf16.dispose(face5.tensor);
|
tf16.dispose(face5.tensor);
|
||||||
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_l = config3.face.detector) == null ? void 0 : _l.rotation, box4, input, inputSize5);
|
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_k = config3.face.detector) == null ? void 0 : _k.rotation, box4, input, inputSize5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
faces.push(face5);
|
faces.push(face5);
|
||||||
|
|
|
@ -1223,7 +1223,7 @@ async function process2(input, config3, getTensor = true) {
|
||||||
}
|
}
|
||||||
async function skip(config3, input) {
|
async function skip(config3, input) {
|
||||||
let skipFrame = false;
|
let skipFrame = false;
|
||||||
if (config3.cacheSensitivity === 0)
|
if (config3.cacheSensitivity === 0 || !input.shape || input.shape.length !== 4 || input.shape[1] > 2048 || input.shape[2] > 2048)
|
||||||
return skipFrame;
|
return skipFrame;
|
||||||
if (!last.inputTensor) {
|
if (!last.inputTensor) {
|
||||||
last.inputTensor = tf2.clone(input);
|
last.inputTensor = tf2.clone(input);
|
||||||
|
@ -5053,7 +5053,6 @@ function correctFaceRotation(rotate, box4, input, inputSize8) {
|
||||||
// src/face/blazeface.ts
|
// src/face/blazeface.ts
|
||||||
var keypointsCount = 6;
|
var keypointsCount = 6;
|
||||||
var model5;
|
var model5;
|
||||||
var anchorsData = [];
|
|
||||||
var anchors = null;
|
var anchors = null;
|
||||||
var inputSize = 0;
|
var inputSize = 0;
|
||||||
var size = () => inputSize;
|
var size = () => inputSize;
|
||||||
|
@ -5070,10 +5069,7 @@ async function load5(config3) {
|
||||||
} else if (config3.debug)
|
} else if (config3.debug)
|
||||||
log("cached model:", model5["modelUrl"]);
|
log("cached model:", model5["modelUrl"]);
|
||||||
inputSize = model5.inputs[0].shape ? model5.inputs[0].shape[2] : 0;
|
inputSize = model5.inputs[0].shape ? model5.inputs[0].shape[2] : 0;
|
||||||
if (inputSize === -1)
|
anchors = tf9.tensor2d(generateAnchors(inputSize));
|
||||||
inputSize = 64;
|
|
||||||
anchorsData = generateAnchors(inputSize);
|
|
||||||
anchors = tf9.tensor2d(anchorsData);
|
|
||||||
return model5;
|
return model5;
|
||||||
}
|
}
|
||||||
function decodeBounds(boxOutputs) {
|
function decodeBounds(boxOutputs) {
|
||||||
|
@ -5127,12 +5123,11 @@ async function getBoxes(inputImage, config3) {
|
||||||
b.slice = tf9.slice(t.batch, [nms[i], keypointsCount - 1], [1, -1]);
|
b.slice = tf9.slice(t.batch, [nms[i], keypointsCount - 1], [1, -1]);
|
||||||
b.squeeze = tf9.squeeze(b.slice);
|
b.squeeze = tf9.squeeze(b.slice);
|
||||||
b.landmarks = tf9.reshape(b.squeeze, [keypointsCount, -1]);
|
b.landmarks = tf9.reshape(b.squeeze, [keypointsCount, -1]);
|
||||||
b.startPoint = tf9.slice(b.bbox, [0, 0], [-1, 2]);
|
const points = await b.bbox.data();
|
||||||
b.endPoint = tf9.slice(b.bbox, [0, 2], [-1, 2]);
|
|
||||||
boxes.push({
|
boxes.push({
|
||||||
box: {
|
box: {
|
||||||
startPoint: await b.startPoint.data(),
|
startPoint: [points[0], points[1]],
|
||||||
endPoint: await b.endPoint.data()
|
endPoint: [points[2], points[3]]
|
||||||
},
|
},
|
||||||
landmarks: await b.landmarks.array(),
|
landmarks: await b.landmarks.array(),
|
||||||
confidence
|
confidence
|
||||||
|
@ -5920,7 +5915,7 @@ var inputSize5 = 0;
|
||||||
var skipped10 = Number.MAX_SAFE_INTEGER;
|
var skipped10 = Number.MAX_SAFE_INTEGER;
|
||||||
var lastTime10 = 0;
|
var lastTime10 = 0;
|
||||||
async function predict10(input, config3) {
|
async function predict10(input, config3) {
|
||||||
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
||||||
const skipTime = (((_a = config3.face.detector) == null ? void 0 : _a.skipTime) || 0) > now() - lastTime10;
|
const skipTime = (((_a = config3.face.detector) == null ? void 0 : _a.skipTime) || 0) > now() - lastTime10;
|
||||||
const skipFrame = skipped10 < (((_b = config3.face.detector) == null ? void 0 : _b.skipFrames) || 0);
|
const skipFrame = skipped10 < (((_b = config3.face.detector) == null ? void 0 : _b.skipFrames) || 0);
|
||||||
if (!config3.skipAllowed || !skipTime || !skipFrame || boxCache.length === 0) {
|
if (!config3.skipAllowed || !skipTime || !skipFrame || boxCache.length === 0) {
|
||||||
|
@ -5934,7 +5929,10 @@ async function predict10(input, config3) {
|
||||||
landmarks: possible.landmarks,
|
landmarks: possible.landmarks,
|
||||||
confidence: possible.confidence
|
confidence: possible.confidence
|
||||||
};
|
};
|
||||||
boxCache.push(squarifyBox(enlargeBox(scaleBoxCoordinates(box4, possibleBoxes.scaleFactor), Math.sqrt(((_c = config3.face.detector) == null ? void 0 : _c.cropFactor) || 1.6))));
|
const boxScaled = scaleBoxCoordinates(box4, possibleBoxes.scaleFactor);
|
||||||
|
const boxEnlarged = enlargeBox(boxScaled, Math.sqrt(((_c = config3.face.detector) == null ? void 0 : _c.cropFactor) || 1.6));
|
||||||
|
const boxSquared = squarifyBox(boxEnlarged);
|
||||||
|
boxCache.push(boxSquared);
|
||||||
}
|
}
|
||||||
skipped10 = 0;
|
skipped10 = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -5958,14 +5956,14 @@ async function predict10(input, config3) {
|
||||||
faceScore: 0,
|
faceScore: 0,
|
||||||
annotations: {}
|
annotations: {}
|
||||||
};
|
};
|
||||||
[angle, rotationMatrix, face5.tensor] = correctFaceRotation(!((_d = config3.face.mesh) == null ? void 0 : _d.enabled) && ((_e = config3.face.detector) == null ? void 0 : _e.rotation), box4, input, ((_f = config3.face.mesh) == null ? void 0 : _f.enabled) ? inputSize5 : size());
|
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_d = config3.face.detector) == null ? void 0 : _d.rotation, box4, input, ((_e = config3.face.mesh) == null ? void 0 : _e.enabled) ? inputSize5 : size());
|
||||||
if ((_g = config3 == null ? void 0 : config3.filter) == null ? void 0 : _g.equalization) {
|
if ((_f = config3 == null ? void 0 : config3.filter) == null ? void 0 : _f.equalization) {
|
||||||
const equilized = await histogramEqualization(face5.tensor);
|
const equilized = await histogramEqualization(face5.tensor);
|
||||||
tf16.dispose(face5.tensor);
|
tf16.dispose(face5.tensor);
|
||||||
face5.tensor = equilized;
|
face5.tensor = equilized;
|
||||||
}
|
}
|
||||||
face5.boxScore = Math.round(100 * box4.confidence) / 100;
|
face5.boxScore = Math.round(100 * box4.confidence) / 100;
|
||||||
if (!((_h = config3.face.mesh) == null ? void 0 : _h.enabled)) {
|
if (!((_g = config3.face.mesh) == null ? void 0 : _g.enabled)) {
|
||||||
face5.box = getClampedBox(box4, input);
|
face5.box = getClampedBox(box4, input);
|
||||||
face5.boxRaw = getRawBox(box4, input);
|
face5.boxRaw = getRawBox(box4, input);
|
||||||
face5.score = face5.boxScore;
|
face5.score = face5.boxScore;
|
||||||
|
@ -5986,22 +5984,22 @@ async function predict10(input, config3) {
|
||||||
const coordsReshaped = tf16.reshape(contourCoords, [-1, 3]);
|
const coordsReshaped = tf16.reshape(contourCoords, [-1, 3]);
|
||||||
let rawCoords = await coordsReshaped.array();
|
let rawCoords = await coordsReshaped.array();
|
||||||
tf16.dispose([contourCoords, coordsReshaped, confidence, contours]);
|
tf16.dispose([contourCoords, coordsReshaped, confidence, contours]);
|
||||||
if (face5.faceScore < (((_i = config3.face.detector) == null ? void 0 : _i.minConfidence) || 1)) {
|
if (face5.faceScore < (((_h = config3.face.detector) == null ? void 0 : _h.minConfidence) || 1)) {
|
||||||
box4.confidence = face5.faceScore;
|
box4.confidence = face5.faceScore;
|
||||||
} else {
|
} else {
|
||||||
if ((_j = config3.face.iris) == null ? void 0 : _j.enabled)
|
if ((_i = config3.face.iris) == null ? void 0 : _i.enabled)
|
||||||
rawCoords = await augmentIris(rawCoords, face5.tensor, config3, inputSize5);
|
rawCoords = await augmentIris(rawCoords, face5.tensor, config3, inputSize5);
|
||||||
face5.mesh = transformRawCoords(rawCoords, box4, angle, rotationMatrix, inputSize5);
|
face5.mesh = transformRawCoords(rawCoords, box4, angle, rotationMatrix, inputSize5);
|
||||||
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize5]);
|
face5.meshRaw = face5.mesh.map((pt) => [pt[0] / (input.shape[2] || 0), pt[1] / (input.shape[1] || 0), (pt[2] || 0) / inputSize5]);
|
||||||
for (const key of Object.keys(meshAnnotations))
|
for (const key of Object.keys(meshAnnotations))
|
||||||
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
|
face5.annotations[key] = meshAnnotations[key].map((index2) => face5.mesh[index2]);
|
||||||
box4 = squarifyBox({ ...enlargeBox(calculateLandmarksBoundingBox(face5.mesh), ((_k = config3.face.detector) == null ? void 0 : _k.cropFactor) || 1.6), confidence: box4.confidence });
|
box4 = squarifyBox({ ...enlargeBox(calculateLandmarksBoundingBox(face5.mesh), ((_j = config3.face.detector) == null ? void 0 : _j.cropFactor) || 1.6), confidence: box4.confidence });
|
||||||
face5.box = getClampedBox(box4, input);
|
face5.box = getClampedBox(box4, input);
|
||||||
face5.boxRaw = getRawBox(box4, input);
|
face5.boxRaw = getRawBox(box4, input);
|
||||||
face5.score = face5.faceScore;
|
face5.score = face5.faceScore;
|
||||||
newCache.push(box4);
|
newCache.push(box4);
|
||||||
tf16.dispose(face5.tensor);
|
tf16.dispose(face5.tensor);
|
||||||
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_l = config3.face.detector) == null ? void 0 : _l.rotation, box4, input, inputSize5);
|
[angle, rotationMatrix, face5.tensor] = correctFaceRotation((_k = config3.face.detector) == null ? void 0 : _k.rotation, box4, input, inputSize5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
faces.push(face5);
|
faces.push(face5);
|
||||||
|
|
|
@ -13480,7 +13480,8 @@ function intersectionOverUnion(boxes, i, j) {
|
||||||
const intersectionYmax = Math.min(ymaxI, ymaxJ);
|
const intersectionYmax = Math.min(ymaxI, ymaxJ);
|
||||||
const intersectionXmax = Math.min(xmaxI, xmaxJ);
|
const intersectionXmax = Math.min(xmaxI, xmaxJ);
|
||||||
const intersectionArea = Math.max(intersectionYmax - intersectionYmin, 0) * Math.max(intersectionXmax - intersectionXmin, 0);
|
const intersectionArea = Math.max(intersectionYmax - intersectionYmin, 0) * Math.max(intersectionXmax - intersectionXmin, 0);
|
||||||
return intersectionArea / (areaI + areaJ - intersectionArea);
|
const iou = intersectionArea / (areaI + areaJ - intersectionArea);
|
||||||
|
return iou;
|
||||||
}
|
}
|
||||||
function suppressWeight(iouThreshold, scale2, iou) {
|
function suppressWeight(iouThreshold, scale2, iou) {
|
||||||
const weight = Math.exp(scale2 * iou * iou);
|
const weight = Math.exp(scale2 * iou * iou);
|
||||||
|
|
|
@ -13,7 +13,6 @@ import type { Point } from '../result';
|
||||||
|
|
||||||
const keypointsCount = 6;
|
const keypointsCount = 6;
|
||||||
let model: GraphModel | null;
|
let model: GraphModel | null;
|
||||||
let anchorsData: [number, number][] = [];
|
|
||||||
let anchors: Tensor | null = null;
|
let anchors: Tensor | null = null;
|
||||||
let inputSize = 0;
|
let inputSize = 0;
|
||||||
|
|
||||||
|
@ -27,9 +26,7 @@ export async function load(config: Config): Promise<GraphModel> {
|
||||||
else if (config.debug) log('load model:', model['modelUrl']);
|
else if (config.debug) log('load model:', model['modelUrl']);
|
||||||
} else if (config.debug) log('cached model:', model['modelUrl']);
|
} else if (config.debug) log('cached model:', model['modelUrl']);
|
||||||
inputSize = model.inputs[0].shape ? model.inputs[0].shape[2] : 0;
|
inputSize = model.inputs[0].shape ? model.inputs[0].shape[2] : 0;
|
||||||
if (inputSize === -1) inputSize = 64;
|
anchors = tf.tensor2d(util.generateAnchors(inputSize));
|
||||||
anchorsData = util.generateAnchors(inputSize);
|
|
||||||
anchors = tf.tensor2d(anchorsData);
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +70,6 @@ export async function getBoxes(inputImage: Tensor, config: Config) {
|
||||||
t.logits = tf.slice(t.batch, [0, 0], [-1, 1]);
|
t.logits = tf.slice(t.batch, [0, 0], [-1, 1]);
|
||||||
t.sigmoid = tf.sigmoid(t.logits);
|
t.sigmoid = tf.sigmoid(t.logits);
|
||||||
t.scores = tf.squeeze(t.sigmoid);
|
t.scores = tf.squeeze(t.sigmoid);
|
||||||
|
|
||||||
t.nms = await tf.image.nonMaxSuppressionAsync(t.boxes, t.scores, (config.face.detector?.maxDetected || 0), (config.face.detector?.iouThreshold || 0), (config.face.detector?.minConfidence || 0));
|
t.nms = await tf.image.nonMaxSuppressionAsync(t.boxes, t.scores, (config.face.detector?.maxDetected || 0), (config.face.detector?.iouThreshold || 0), (config.face.detector?.minConfidence || 0));
|
||||||
const nms = await t.nms.array() as number[];
|
const nms = await t.nms.array() as number[];
|
||||||
const boxes: Array<{ box: { startPoint: Point, endPoint: Point }, landmarks: Point[], confidence: number }> = [];
|
const boxes: Array<{ box: { startPoint: Point, endPoint: Point }, landmarks: Point[], confidence: number }> = [];
|
||||||
|
@ -86,12 +82,11 @@ export async function getBoxes(inputImage: Tensor, config: Config) {
|
||||||
b.slice = tf.slice(t.batch, [nms[i], keypointsCount - 1], [1, -1]);
|
b.slice = tf.slice(t.batch, [nms[i], keypointsCount - 1], [1, -1]);
|
||||||
b.squeeze = tf.squeeze(b.slice);
|
b.squeeze = tf.squeeze(b.slice);
|
||||||
b.landmarks = tf.reshape(b.squeeze, [keypointsCount, -1]);
|
b.landmarks = tf.reshape(b.squeeze, [keypointsCount, -1]);
|
||||||
b.startPoint = tf.slice(b.bbox, [0, 0], [-1, 2]);
|
const points = await b.bbox.data();
|
||||||
b.endPoint = tf.slice(b.bbox, [0, 2], [-1, 2]);
|
|
||||||
boxes.push({
|
boxes.push({
|
||||||
box: {
|
box: {
|
||||||
startPoint: (await b.startPoint.data()) as unknown as Point,
|
startPoint: [points[0], points[1]] as Point,
|
||||||
endPoint: (await b.endPoint.data()) as unknown as Point,
|
endPoint: [points[2], points[3]] as Point,
|
||||||
},
|
},
|
||||||
landmarks: (await b.landmarks.array()) as Point[],
|
landmarks: (await b.landmarks.array()) as Point[],
|
||||||
confidence,
|
confidence,
|
||||||
|
|
|
@ -41,7 +41,10 @@ export async function predict(input: Tensor, config: Config): Promise<FaceResult
|
||||||
landmarks: possible.landmarks,
|
landmarks: possible.landmarks,
|
||||||
confidence: possible.confidence,
|
confidence: possible.confidence,
|
||||||
};
|
};
|
||||||
boxCache.push(util.squarifyBox(util.enlargeBox(util.scaleBoxCoordinates(box, possibleBoxes.scaleFactor), Math.sqrt(config.face.detector?.cropFactor || 1.6))));
|
const boxScaled = util.scaleBoxCoordinates(box, possibleBoxes.scaleFactor);
|
||||||
|
const boxEnlarged = util.enlargeBox(boxScaled, Math.sqrt(config.face.detector?.cropFactor || 1.6));
|
||||||
|
const boxSquared = util.squarifyBox(boxEnlarged);
|
||||||
|
boxCache.push(boxSquared);
|
||||||
}
|
}
|
||||||
skipped = 0;
|
skipped = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -67,7 +70,7 @@ export async function predict(input: Tensor, config: Config): Promise<FaceResult
|
||||||
};
|
};
|
||||||
|
|
||||||
// optional rotation correction based on detector data only if mesh is disabled otherwise perform it later when we have more accurate mesh data. if no rotation correction this function performs crop
|
// optional rotation correction based on detector data only if mesh is disabled otherwise perform it later when we have more accurate mesh data. if no rotation correction this function performs crop
|
||||||
[angle, rotationMatrix, face.tensor] = util.correctFaceRotation(!config.face.mesh?.enabled && config.face.detector?.rotation, box, input, config.face.mesh?.enabled ? inputSize : blazeface.size());
|
[angle, rotationMatrix, face.tensor] = util.correctFaceRotation(config.face.detector?.rotation, box, input, config.face.mesh?.enabled ? inputSize : blazeface.size());
|
||||||
if (config?.filter?.equalization) {
|
if (config?.filter?.equalization) {
|
||||||
const equilized = await histogramEqualization(face.tensor as Tensor);
|
const equilized = await histogramEqualization(face.tensor as Tensor);
|
||||||
tf.dispose(face.tensor);
|
tf.dispose(face.tensor);
|
||||||
|
|
|
@ -31,8 +31,8 @@ export const getRawBox = (box, input): Box => (box ? [
|
||||||
] : [0, 0, 0, 0]);
|
] : [0, 0, 0, 0]);
|
||||||
|
|
||||||
export const scaleBoxCoordinates = (box, factor) => {
|
export const scaleBoxCoordinates = (box, factor) => {
|
||||||
const startPoint = [box.startPoint[0] * factor[0], box.startPoint[1] * factor[1]];
|
const startPoint: Point = [box.startPoint[0] * factor[0], box.startPoint[1] * factor[1]];
|
||||||
const endPoint = [box.endPoint[0] * factor[0], box.endPoint[1] * factor[1]];
|
const endPoint: Point = [box.endPoint[0] * factor[0], box.endPoint[1] * factor[1]];
|
||||||
return { startPoint, endPoint, landmarks: box.landmarks, confidence: box.confidence };
|
return { startPoint, endPoint, landmarks: box.landmarks, confidence: box.confidence };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -262,7 +262,7 @@ const checksum = async (input: Tensor): Promise<number> => { // use tf sum or js
|
||||||
|
|
||||||
export async function skip(config, input: Tensor) {
|
export async function skip(config, input: Tensor) {
|
||||||
let skipFrame = false;
|
let skipFrame = false;
|
||||||
if (config.cacheSensitivity === 0) return skipFrame;
|
if (config.cacheSensitivity === 0 || !input.shape || input.shape.length !== 4 || input.shape[1] > 2048 || input.shape[2] > 2048) return skipFrame; // cache disabled or input is invalid or too large for cache analysis
|
||||||
|
|
||||||
/*
|
/*
|
||||||
const checkSum = await checksum(input);
|
const checkSum = await checksum(input);
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
2021-11-15 09:19:13 [36mINFO: [39m @vladmandic/human version 2.5.2
|
2021-11-16 12:51:36 [36mINFO: [39m @vladmandic/human version 2.5.2
|
||||||
2021-11-15 09:19:13 [36mINFO: [39m User: vlado Platform: linux Arch: x64 Node: v17.0.1
|
2021-11-16 12:51:36 [36mINFO: [39m User: vlado Platform: linux Arch: x64 Node: v17.0.1
|
||||||
2021-11-15 09:19:13 [36mINFO: [39m Application: {"name":"@vladmandic/human","version":"2.5.2"}
|
2021-11-16 12:51:36 [36mINFO: [39m Application: {"name":"@vladmandic/human","version":"2.5.2"}
|
||||||
2021-11-15 09:19:13 [36mINFO: [39m Environment: {"profile":"production","config":".build.json","package":"package.json","tsconfig":true,"eslintrc":true,"git":true}
|
2021-11-16 12:51:36 [36mINFO: [39m Environment: {"profile":"production","config":".build.json","package":"package.json","tsconfig":true,"eslintrc":true,"git":true}
|
||||||
2021-11-15 09:19:13 [36mINFO: [39m Toolchain: {"build":"0.6.4","esbuild":"0.13.13","typescript":"4.4.4","typedoc":"0.22.9","eslint":"8.2.0"}
|
2021-11-16 12:51:36 [36mINFO: [39m Toolchain: {"build":"0.6.4","esbuild":"0.13.13","typescript":"4.4.4","typedoc":"0.22.9","eslint":"8.2.0"}
|
||||||
2021-11-15 09:19:13 [36mINFO: [39m Build: {"profile":"production","steps":["clean","compile","typings","typedoc","lint","changelog"]}
|
2021-11-16 12:51:36 [36mINFO: [39m Build: {"profile":"production","steps":["clean","compile","typings","typedoc","lint","changelog"]}
|
||||||
2021-11-15 09:19:13 [35mSTATE:[39m Clean: {"locations":["dist/*","types/*","typedoc/*"]}
|
2021-11-16 12:51:36 [35mSTATE:[39m Clean: {"locations":["dist/*","types/*","typedoc/*"]}
|
||||||
2021-11-15 09:19:13 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/cpu","format":"cjs","platform":"node","input":"tfjs/tf-node.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":102,"outputBytes":1275}
|
2021-11-16 12:51:36 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/cpu","format":"cjs","platform":"node","input":"tfjs/tf-node.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":102,"outputBytes":1275}
|
||||||
2021-11-15 09:19:13 [35mSTATE:[39m Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":61,"inputBytes":545714,"outputBytes":462580}
|
2021-11-16 12:51:36 [35mSTATE:[39m Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":61,"inputBytes":545763,"outputBytes":462549}
|
||||||
2021-11-15 09:19:13 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/gpu","format":"cjs","platform":"node","input":"tfjs/tf-node-gpu.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":110,"outputBytes":1283}
|
2021-11-16 12:51:36 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/gpu","format":"cjs","platform":"node","input":"tfjs/tf-node-gpu.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":110,"outputBytes":1283}
|
||||||
2021-11-15 09:19:13 [35mSTATE:[39m Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":61,"inputBytes":545722,"outputBytes":462584}
|
2021-11-16 12:51:36 [35mSTATE:[39m Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":61,"inputBytes":545771,"outputBytes":462553}
|
||||||
2021-11-15 09:19:13 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/wasm","format":"cjs","platform":"node","input":"tfjs/tf-node-wasm.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":149,"outputBytes":1350}
|
2021-11-16 12:51:36 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/wasm","format":"cjs","platform":"node","input":"tfjs/tf-node-wasm.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":149,"outputBytes":1350}
|
||||||
2021-11-15 09:19:13 [35mSTATE:[39m Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":61,"inputBytes":545789,"outputBytes":462656}
|
2021-11-16 12:51:36 [35mSTATE:[39m Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":61,"inputBytes":545838,"outputBytes":462625}
|
||||||
2021-11-15 09:19:13 [35mSTATE:[39m Compile: {"name":"tfjs/browser/version","format":"esm","platform":"browser","input":"tfjs/tf-version.ts","output":"dist/tfjs.version.js","files":1,"inputBytes":1063,"outputBytes":1652}
|
2021-11-16 12:51:36 [35mSTATE:[39m Compile: {"name":"tfjs/browser/version","format":"esm","platform":"browser","input":"tfjs/tf-version.ts","output":"dist/tfjs.version.js","files":1,"inputBytes":1063,"outputBytes":1652}
|
||||||
2021-11-15 09:19:13 [35mSTATE:[39m Compile: {"name":"tfjs/browser/esm/nobundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":2326,"outputBytes":912}
|
2021-11-16 12:51:36 [35mSTATE:[39m Compile: {"name":"tfjs/browser/esm/nobundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":2326,"outputBytes":912}
|
||||||
2021-11-15 09:19:13 [35mSTATE:[39m Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":61,"inputBytes":545351,"outputBytes":464846}
|
2021-11-16 12:51:37 [35mSTATE:[39m Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":61,"inputBytes":545400,"outputBytes":464789}
|
||||||
2021-11-15 09:19:13 [35mSTATE:[39m Compile: {"name":"tfjs/browser/esm/custom","format":"esm","platform":"browser","input":"tfjs/tf-custom.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":307,"outputBytes":2497761}
|
2021-11-16 12:51:37 [35mSTATE:[39m Compile: {"name":"tfjs/browser/esm/custom","format":"esm","platform":"browser","input":"tfjs/tf-custom.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":307,"outputBytes":2497780}
|
||||||
2021-11-15 09:19:14 [35mSTATE:[39m Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":61,"inputBytes":3042200,"outputBytes":1624010}
|
2021-11-16 12:51:37 [35mSTATE:[39m Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":61,"inputBytes":3042268,"outputBytes":1623936}
|
||||||
2021-11-15 09:19:14 [35mSTATE:[39m Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":61,"inputBytes":3042200,"outputBytes":2967931}
|
2021-11-16 12:51:38 [35mSTATE:[39m Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":61,"inputBytes":3042268,"outputBytes":2967931}
|
||||||
2021-11-15 09:19:33 [35mSTATE:[39m Typings: {"input":"src/human.ts","output":"types","files":53}
|
2021-11-16 12:52:01 [35mSTATE:[39m Typings: {"input":"src/human.ts","output":"types","files":53}
|
||||||
2021-11-15 09:19:40 [35mSTATE:[39m TypeDoc: {"input":"src/human.ts","output":"typedoc","objects":51,"generated":true}
|
2021-11-16 12:52:08 [35mSTATE:[39m TypeDoc: {"input":"src/human.ts","output":"typedoc","objects":51,"generated":true}
|
||||||
2021-11-15 09:19:40 [35mSTATE:[39m Compile: {"name":"demo/typescript","format":"esm","platform":"browser","input":"demo/typescript/index.ts","output":"demo/typescript/index.js","files":1,"inputBytes":5801,"outputBytes":3822}
|
2021-11-16 12:52:08 [35mSTATE:[39m Compile: {"name":"demo/typescript","format":"esm","platform":"browser","input":"demo/typescript/index.ts","output":"demo/typescript/index.js","files":1,"inputBytes":5811,"outputBytes":3821}
|
||||||
2021-11-15 09:19:40 [35mSTATE:[39m Compile: {"name":"demo/faceid","format":"esm","platform":"browser","input":"demo/faceid/index.ts","output":"demo/faceid/index.js","files":2,"inputBytes":15166,"outputBytes":11786}
|
2021-11-16 12:52:08 [35mSTATE:[39m Compile: {"name":"demo/faceid","format":"esm","platform":"browser","input":"demo/faceid/index.ts","output":"demo/faceid/index.js","files":2,"inputBytes":15166,"outputBytes":11786}
|
||||||
2021-11-15 09:20:19 [35mSTATE:[39m Lint: {"locations":["*.json","src/**/*.ts","test/**/*.js","demo/**/*.js"],"files":92,"errors":0,"warnings":0}
|
2021-11-16 12:52:49 [35mSTATE:[39m Lint: {"locations":["*.json","src/**/*.ts","test/**/*.js","demo/**/*.js"],"files":92,"errors":0,"warnings":0}
|
||||||
2021-11-15 09:20:20 [35mSTATE:[39m ChangeLog: {"repository":"https://github.com/vladmandic/human","branch":"main","output":"CHANGELOG.md"}
|
2021-11-16 12:52:50 [35mSTATE:[39m ChangeLog: {"repository":"https://github.com/vladmandic/human","branch":"main","output":"CHANGELOG.md"}
|
||||||
2021-11-15 09:20:20 [36mINFO: [39m Done...
|
2021-11-16 12:52:50 [36mINFO: [39m Done...
|
||||||
|
|
1352
test/test.log
1352
test/test.log
File diff suppressed because it is too large
Load Diff
|
@ -13,8 +13,8 @@ export declare const getBoxCenter: (box: any) => [number, number];
|
||||||
export declare const getClampedBox: (box: any, input: any) => Box;
|
export declare const getClampedBox: (box: any, input: any) => Box;
|
||||||
export declare const getRawBox: (box: any, input: any) => Box;
|
export declare const getRawBox: (box: any, input: any) => Box;
|
||||||
export declare const scaleBoxCoordinates: (box: any, factor: any) => {
|
export declare const scaleBoxCoordinates: (box: any, factor: any) => {
|
||||||
startPoint: number[];
|
startPoint: Point;
|
||||||
endPoint: number[];
|
endPoint: Point;
|
||||||
landmarks: any;
|
landmarks: any;
|
||||||
confidence: any;
|
confidence: any;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue