mirror of https://github.com/vladmandic/human
convert to typescript
parent
ea9847927b
commit
6fb133b55e
|
@ -46,7 +46,7 @@ Compatible with *Browser*, *WebWorker* and *NodeJS* execution on both Windows an
|
|||
|
||||
<br>
|
||||
|
||||
*This is a pre-release project, see [issues](https://github.com/vladmandic/human/issues) for list of known limitations and planned enhancements*
|
||||
*See [issues](https://github.com/vladmandic/human/issues?q=) and [discussions](https://github.com/vladmandic/human/discussions) for list of known limitations and planned enhancements*
|
||||
|
||||
*Suggestions are welcome!*
|
||||
|
||||
|
|
|
@ -56,14 +56,19 @@ async function detect(input) {
|
|||
}
|
||||
|
||||
async function test() {
|
||||
// test with embedded face image
|
||||
log.state('Processing embedded warmup image: face');
|
||||
myConfig.warmup = 'face';
|
||||
const resultFace = await human.warmup(myConfig);
|
||||
log.data(resultFace);
|
||||
log.data('Face: ', resultFace.face);
|
||||
|
||||
// test with embedded full body image
|
||||
log.state('Processing embedded warmup image: full');
|
||||
myConfig.warmup = 'full';
|
||||
const resultFull = await human.warmup(myConfig);
|
||||
log.data(resultFull);
|
||||
log.data('Body:', resultFull.body);
|
||||
log.data('Hand:', resultFull.hand);
|
||||
log.data('Gesture:', resultFull.gesture);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"inputs": {
|
||||
"dist/human.esm.js": {
|
||||
"bytes": 1349003,
|
||||
"bytes": 1343005,
|
||||
"imports": []
|
||||
},
|
||||
"demo/draw.js": {
|
||||
|
@ -43,14 +43,14 @@
|
|||
"imports": [],
|
||||
"exports": [],
|
||||
"inputs": {},
|
||||
"bytes": 2028101
|
||||
"bytes": 2018414
|
||||
},
|
||||
"dist/demo-browser-index.js": {
|
||||
"imports": [],
|
||||
"exports": [],
|
||||
"inputs": {
|
||||
"dist/human.esm.js": {
|
||||
"bytesInOutput": 1340450
|
||||
"bytesInOutput": 1335513
|
||||
},
|
||||
"demo/draw.js": {
|
||||
"bytesInOutput": 6204
|
||||
|
@ -65,7 +65,7 @@
|
|||
"bytesInOutput": 16815
|
||||
}
|
||||
},
|
||||
"bytes": 1388309
|
||||
"bytes": 1383372
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,18 +1,18 @@
|
|||
{
|
||||
"inputs": {
|
||||
"src/log.js": {
|
||||
"src/log.ts": {
|
||||
"bytes": 401,
|
||||
"imports": []
|
||||
},
|
||||
"dist/tfjs.esm.js": {
|
||||
"bytes": 1071833,
|
||||
"bytes": 1071825,
|
||||
"imports": []
|
||||
},
|
||||
"src/tfjs/backend.js": {
|
||||
"bytes": 2171,
|
||||
"src/tfjs/backend.ts": {
|
||||
"bytes": 2168,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -21,11 +21,11 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"src/blazeface/blazeface.js": {
|
||||
"bytes": 7024,
|
||||
"src/blazeface/blazeface.ts": {
|
||||
"bytes": 6024,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -34,8 +34,8 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"src/blazeface/box.js": {
|
||||
"bytes": 1935,
|
||||
"src/blazeface/box.ts": {
|
||||
"bytes": 1727,
|
||||
"imports": [
|
||||
{
|
||||
"path": "dist/tfjs.esm.js",
|
||||
|
@ -43,44 +43,40 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"src/blazeface/util.js": {
|
||||
"bytes": 3087,
|
||||
"src/blazeface/util.ts": {
|
||||
"bytes": 2777,
|
||||
"imports": []
|
||||
},
|
||||
"src/blazeface/coords.js": {
|
||||
"bytes": 37915,
|
||||
"src/blazeface/coords.ts": {
|
||||
"bytes": 37783,
|
||||
"imports": []
|
||||
},
|
||||
"src/blazeface/facepipeline.js": {
|
||||
"bytes": 14275,
|
||||
"src/blazeface/facepipeline.ts": {
|
||||
"bytes": 14254,
|
||||
"imports": [
|
||||
{
|
||||
"path": "dist/tfjs.esm.js",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/blazeface/box.js",
|
||||
"path": "src/blazeface/box.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/blazeface/util.js",
|
||||
"path": "src/blazeface/util.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/blazeface/coords.js",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/blazeface/coords.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/blazeface/facemesh.js": {
|
||||
"bytes": 2973,
|
||||
"src/blazeface/facemesh.ts": {
|
||||
"bytes": 2935,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -88,33 +84,33 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/blazeface/blazeface.js",
|
||||
"path": "src/blazeface/blazeface.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/blazeface/facepipeline.js",
|
||||
"path": "src/blazeface/facepipeline.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/blazeface/coords.js",
|
||||
"path": "src/blazeface/coords.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/profile.js": {
|
||||
"bytes": 1045,
|
||||
"src/profile.ts": {
|
||||
"bytes": 1004,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/faceboxes/faceboxes.js": {
|
||||
"bytes": 2612,
|
||||
"src/faceboxes/faceboxes.ts": {
|
||||
"bytes": 2852,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -122,16 +118,16 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js",
|
||||
"path": "src/profile.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/age/age.js": {
|
||||
"bytes": 2037,
|
||||
"src/age/age.ts": {
|
||||
"bytes": 2064,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -139,16 +135,16 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js",
|
||||
"path": "src/profile.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/gender/gender.js": {
|
||||
"bytes": 2906,
|
||||
"src/gender/gender.ts": {
|
||||
"bytes": 2904,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -156,16 +152,16 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js",
|
||||
"path": "src/profile.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/emotion/emotion.js": {
|
||||
"bytes": 3056,
|
||||
"src/emotion/emotion.ts": {
|
||||
"bytes": 3033,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -173,16 +169,16 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js",
|
||||
"path": "src/profile.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/embedding/embedding.js": {
|
||||
"bytes": 2063,
|
||||
"src/embedding/embedding.ts": {
|
||||
"bytes": 1992,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -190,13 +186,13 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js",
|
||||
"path": "src/profile.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/modelBase.js": {
|
||||
"bytes": 1343,
|
||||
"src/posenet/modelBase.ts": {
|
||||
"bytes": 1333,
|
||||
"imports": [
|
||||
{
|
||||
"path": "dist/tfjs.esm.js",
|
||||
|
@ -204,93 +200,93 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/heapSort.js": {
|
||||
"bytes": 1590,
|
||||
"src/posenet/heapSort.ts": {
|
||||
"bytes": 1645,
|
||||
"imports": []
|
||||
},
|
||||
"src/posenet/buildParts.js": {
|
||||
"bytes": 1775,
|
||||
"src/posenet/buildParts.ts": {
|
||||
"bytes": 1723,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/posenet/heapSort.js",
|
||||
"path": "src/posenet/heapSort.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/keypoints.js": {
|
||||
"bytes": 2011,
|
||||
"src/posenet/keypoints.ts": {
|
||||
"bytes": 2025,
|
||||
"imports": []
|
||||
},
|
||||
"src/posenet/vectors.js": {
|
||||
"bytes": 1273,
|
||||
"src/posenet/vectors.ts": {
|
||||
"bytes": 1075,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/posenet/keypoints.js",
|
||||
"path": "src/posenet/keypoints.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/decoders.js": {
|
||||
"bytes": 2083,
|
||||
"src/posenet/decoders.ts": {
|
||||
"bytes": 1943,
|
||||
"imports": [
|
||||
{
|
||||
"path": "dist/tfjs.esm.js",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/keypoints.js",
|
||||
"path": "src/posenet/keypoints.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/decodePose.js": {
|
||||
"bytes": 5368,
|
||||
"src/posenet/decodePose.ts": {
|
||||
"bytes": 5152,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/posenet/keypoints.js",
|
||||
"path": "src/posenet/keypoints.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/vectors.js",
|
||||
"path": "src/posenet/vectors.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/decoders.js",
|
||||
"path": "src/posenet/decoders.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/decodeMultiple.js": {
|
||||
"bytes": 2373,
|
||||
"src/posenet/decodeMultiple.ts": {
|
||||
"bytes": 2259,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/posenet/buildParts.js",
|
||||
"path": "src/posenet/buildParts.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/decodePose.js",
|
||||
"path": "src/posenet/decodePose.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/vectors.js",
|
||||
"path": "src/posenet/vectors.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/util.js": {
|
||||
"bytes": 2262,
|
||||
"src/posenet/util.ts": {
|
||||
"bytes": 2017,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/posenet/keypoints.js",
|
||||
"path": "src/posenet/keypoints.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/modelPoseNet.js": {
|
||||
"bytes": 2519,
|
||||
"src/posenet/posenet.ts": {
|
||||
"bytes": 2376,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -298,42 +294,25 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/modelBase.js",
|
||||
"path": "src/posenet/modelBase.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/decodeMultiple.js",
|
||||
"path": "src/posenet/decodeMultiple.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/decodePose.js",
|
||||
"path": "src/posenet/decodePose.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/util.js",
|
||||
"path": "src/posenet/util.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/posenet.js": {
|
||||
"bytes": 712,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/posenet/modelPoseNet.js",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/keypoints.js",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/util.js",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/handpose/box.js": {
|
||||
"bytes": 2522,
|
||||
"src/handpose/box.ts": {
|
||||
"bytes": 2443,
|
||||
"imports": [
|
||||
{
|
||||
"path": "dist/tfjs.esm.js",
|
||||
|
@ -341,53 +320,49 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"src/handpose/handdetector.js": {
|
||||
"bytes": 3548,
|
||||
"src/handpose/handdetector.ts": {
|
||||
"bytes": 3627,
|
||||
"imports": [
|
||||
{
|
||||
"path": "dist/tfjs.esm.js",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/handpose/box.js",
|
||||
"path": "src/handpose/box.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/handpose/util.js": {
|
||||
"bytes": 2346,
|
||||
"src/handpose/util.ts": {
|
||||
"bytes": 2254,
|
||||
"imports": []
|
||||
},
|
||||
"src/handpose/handpipeline.js": {
|
||||
"bytes": 7246,
|
||||
"src/handpose/handpipeline.ts": {
|
||||
"bytes": 7344,
|
||||
"imports": [
|
||||
{
|
||||
"path": "dist/tfjs.esm.js",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/handpose/box.js",
|
||||
"path": "src/handpose/box.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/handpose/util.js",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/handpose/util.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/handpose/anchors.js": {
|
||||
"bytes": 224151,
|
||||
"src/handpose/anchors.ts": {
|
||||
"bytes": 224156,
|
||||
"imports": []
|
||||
},
|
||||
"src/handpose/handpose.js": {
|
||||
"bytes": 2578,
|
||||
"src/handpose/handpose.ts": {
|
||||
"bytes": 2529,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -395,32 +370,32 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/handpose/handdetector.js",
|
||||
"path": "src/handpose/handdetector.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/handpose/handpipeline.js",
|
||||
"path": "src/handpose/handpipeline.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/handpose/anchors.js",
|
||||
"path": "src/handpose/anchors.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/gesture/gesture.js": {
|
||||
"bytes": 4245,
|
||||
"src/gesture/gesture.ts": {
|
||||
"bytes": 4265,
|
||||
"imports": []
|
||||
},
|
||||
"src/imagefx.js": {
|
||||
"bytes": 19445,
|
||||
"bytes": 19447,
|
||||
"imports": []
|
||||
},
|
||||
"src/image.js": {
|
||||
"bytes": 5871,
|
||||
"src/image.ts": {
|
||||
"bytes": 5851,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -437,19 +412,19 @@
|
|||
"bytes": 9786,
|
||||
"imports": []
|
||||
},
|
||||
"src/sample.js": {
|
||||
"src/sample.ts": {
|
||||
"bytes": 55382,
|
||||
"imports": []
|
||||
},
|
||||
"package.json": {
|
||||
"bytes": 2321,
|
||||
"bytes": 2344,
|
||||
"imports": []
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytes": 18962,
|
||||
"src/human.ts": {
|
||||
"bytes": 19393,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -457,51 +432,51 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/tfjs/backend.js",
|
||||
"path": "src/tfjs/backend.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/blazeface/facemesh.js",
|
||||
"path": "src/blazeface/facemesh.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/faceboxes/faceboxes.js",
|
||||
"path": "src/faceboxes/faceboxes.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/age/age.js",
|
||||
"path": "src/age/age.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/gender/gender.js",
|
||||
"path": "src/gender/gender.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/emotion/emotion.js",
|
||||
"path": "src/emotion/emotion.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/embedding/embedding.js",
|
||||
"path": "src/embedding/embedding.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/posenet.js",
|
||||
"path": "src/posenet/posenet.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/handpose/handpose.js",
|
||||
"path": "src/handpose/handpose.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/gesture/gesture.js",
|
||||
"path": "src/gesture/gesture.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/image.js",
|
||||
"path": "src/image.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js",
|
||||
"path": "src/profile.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -509,7 +484,7 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/sample.js",
|
||||
"path": "src/sample.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -524,7 +499,7 @@
|
|||
"imports": [],
|
||||
"exports": [],
|
||||
"inputs": {},
|
||||
"bytes": 1932071
|
||||
"bytes": 1923046
|
||||
},
|
||||
"dist/human.esm.js": {
|
||||
"imports": [],
|
||||
|
@ -532,125 +507,122 @@
|
|||
"default"
|
||||
],
|
||||
"inputs": {
|
||||
"src/blazeface/blazeface.js": {
|
||||
"bytesInOutput": 2915
|
||||
"src/blazeface/facemesh.ts": {
|
||||
"bytesInOutput": 1445
|
||||
},
|
||||
"src/blazeface/box.js": {
|
||||
"bytesInOutput": 987
|
||||
},
|
||||
"src/blazeface/util.js": {
|
||||
"bytesInOutput": 1197
|
||||
},
|
||||
"src/blazeface/coords.js": {
|
||||
"bytesInOutput": 30534
|
||||
},
|
||||
"src/blazeface/facepipeline.js": {
|
||||
"bytesInOutput": 5578
|
||||
},
|
||||
"src/blazeface/facemesh.js": {
|
||||
"bytesInOutput": 1518
|
||||
},
|
||||
"src/profile.js": {
|
||||
"bytesInOutput": 637
|
||||
},
|
||||
"src/faceboxes/faceboxes.js": {
|
||||
"bytesInOutput": 1387
|
||||
},
|
||||
"src/age/age.js": {
|
||||
"bytesInOutput": 813
|
||||
},
|
||||
"src/gender/gender.js": {
|
||||
"bytesInOutput": 1283
|
||||
},
|
||||
"src/emotion/emotion.js": {
|
||||
"bytesInOutput": 1247
|
||||
},
|
||||
"src/embedding/embedding.js": {
|
||||
"bytesInOutput": 870
|
||||
},
|
||||
"src/posenet/modelBase.js": {
|
||||
"bytesInOutput": 679
|
||||
},
|
||||
"src/posenet/heapSort.js": {
|
||||
"bytesInOutput": 1048
|
||||
},
|
||||
"src/posenet/buildParts.js": {
|
||||
"bytesInOutput": 529
|
||||
},
|
||||
"src/posenet/keypoints.js": {
|
||||
"bytesInOutput": 1638
|
||||
},
|
||||
"src/posenet/vectors.js": {
|
||||
"bytesInOutput": 627
|
||||
},
|
||||
"src/posenet/decoders.js": {
|
||||
"bytesInOutput": 875
|
||||
},
|
||||
"src/posenet/decodePose.js": {
|
||||
"bytesInOutput": 1482
|
||||
},
|
||||
"src/posenet/decodeMultiple.js": {
|
||||
"bytesInOutput": 704
|
||||
},
|
||||
"src/posenet/util.js": {
|
||||
"bytesInOutput": 1065
|
||||
},
|
||||
"src/posenet/modelPoseNet.js": {
|
||||
"bytesInOutput": 1167
|
||||
},
|
||||
"src/posenet/posenet.js": {
|
||||
"bytesInOutput": 401
|
||||
},
|
||||
"src/handpose/handdetector.js": {
|
||||
"bytesInOutput": 1704
|
||||
},
|
||||
"src/handpose/handpipeline.js": {
|
||||
"bytesInOutput": 2485
|
||||
},
|
||||
"src/handpose/anchors.js": {
|
||||
"bytesInOutput": 127006
|
||||
},
|
||||
"src/handpose/handpose.js": {
|
||||
"bytesInOutput": 1331
|
||||
},
|
||||
"src/gesture/gesture.js": {
|
||||
"bytesInOutput": 2424
|
||||
"src/posenet/keypoints.ts": {
|
||||
"bytesInOutput": 1690
|
||||
},
|
||||
"src/imagefx.js": {
|
||||
"bytesInOutput": 11004
|
||||
"bytesInOutput": 11016
|
||||
},
|
||||
"src/image.js": {
|
||||
"bytesInOutput": 2480
|
||||
},
|
||||
"src/log.js": {
|
||||
"src/log.ts": {
|
||||
"bytesInOutput": 252
|
||||
},
|
||||
"dist/tfjs.esm.js": {
|
||||
"bytesInOutput": 1062888
|
||||
"bytesInOutput": 1062782
|
||||
},
|
||||
"src/tfjs/backend.js": {
|
||||
"src/tfjs/backend.ts": {
|
||||
"bytesInOutput": 1205
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 10537
|
||||
"src/blazeface/blazeface.ts": {
|
||||
"bytesInOutput": 2185
|
||||
},
|
||||
"src/handpose/box.js": {
|
||||
"src/blazeface/box.ts": {
|
||||
"bytesInOutput": 834
|
||||
},
|
||||
"src/blazeface/util.ts": {
|
||||
"bytesInOutput": 858
|
||||
},
|
||||
"src/blazeface/coords.ts": {
|
||||
"bytesInOutput": 28983
|
||||
},
|
||||
"src/blazeface/facepipeline.ts": {
|
||||
"bytesInOutput": 5046
|
||||
},
|
||||
"src/human.ts": {
|
||||
"bytesInOutput": 10223
|
||||
},
|
||||
"src/faceboxes/faceboxes.ts": {
|
||||
"bytesInOutput": 1549
|
||||
},
|
||||
"src/profile.ts": {
|
||||
"bytesInOutput": 606
|
||||
},
|
||||
"src/age/age.ts": {
|
||||
"bytesInOutput": 826
|
||||
},
|
||||
"src/gender/gender.ts": {
|
||||
"bytesInOutput": 1309
|
||||
},
|
||||
"src/emotion/emotion.ts": {
|
||||
"bytesInOutput": 1243
|
||||
},
|
||||
"src/embedding/embedding.ts": {
|
||||
"bytesInOutput": 802
|
||||
},
|
||||
"src/posenet/posenet.ts": {
|
||||
"bytesInOutput": 1007
|
||||
},
|
||||
"src/posenet/modelBase.ts": {
|
||||
"bytesInOutput": 646
|
||||
},
|
||||
"src/posenet/heapSort.ts": {
|
||||
"bytesInOutput": 1017
|
||||
},
|
||||
"src/posenet/buildParts.ts": {
|
||||
"bytesInOutput": 456
|
||||
},
|
||||
"src/posenet/decodePose.ts": {
|
||||
"bytesInOutput": 1292
|
||||
},
|
||||
"src/posenet/vectors.ts": {
|
||||
"bytesInOutput": 346
|
||||
},
|
||||
"src/posenet/decoders.ts": {
|
||||
"bytesInOutput": 768
|
||||
},
|
||||
"src/posenet/decodeMultiple.ts": {
|
||||
"bytesInOutput": 557
|
||||
},
|
||||
"src/posenet/util.ts": {
|
||||
"bytesInOutput": 354
|
||||
},
|
||||
"src/handpose/handpose.ts": {
|
||||
"bytesInOutput": 1263
|
||||
},
|
||||
"src/handpose/box.ts": {
|
||||
"bytesInOutput": 938
|
||||
},
|
||||
"src/handpose/util.js": {
|
||||
"src/handpose/handdetector.ts": {
|
||||
"bytesInOutput": 1668
|
||||
},
|
||||
"src/handpose/util.ts": {
|
||||
"bytesInOutput": 816
|
||||
},
|
||||
"src/handpose/handpipeline.ts": {
|
||||
"bytesInOutput": 2449
|
||||
},
|
||||
"src/handpose/anchors.ts": {
|
||||
"bytesInOutput": 126985
|
||||
},
|
||||
"src/gesture/gesture.ts": {
|
||||
"bytesInOutput": 2391
|
||||
},
|
||||
"src/image.ts": {
|
||||
"bytesInOutput": 2454
|
||||
},
|
||||
"config.js": {
|
||||
"bytesInOutput": 1426
|
||||
},
|
||||
"src/sample.js": {
|
||||
"src/sample.ts": {
|
||||
"bytesInOutput": 55295
|
||||
},
|
||||
"package.json": {
|
||||
"bytesInOutput": 16
|
||||
}
|
||||
},
|
||||
"bytes": 1349003
|
||||
"bytes": 1343005
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,18 +1,18 @@
|
|||
{
|
||||
"inputs": {
|
||||
"src/log.js": {
|
||||
"src/log.ts": {
|
||||
"bytes": 401,
|
||||
"imports": []
|
||||
},
|
||||
"dist/tfjs.esm.js": {
|
||||
"bytes": 681,
|
||||
"bytes": 690,
|
||||
"imports": []
|
||||
},
|
||||
"src/tfjs/backend.js": {
|
||||
"bytes": 2171,
|
||||
"src/tfjs/backend.ts": {
|
||||
"bytes": 2168,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -22,10 +22,10 @@
|
|||
]
|
||||
},
|
||||
"src/blazeface/blazeface.js": {
|
||||
"bytes": 7024,
|
||||
"bytes": 6983,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -52,7 +52,7 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/blazeface/facepipeline.js": {
|
||||
"bytes": 14275,
|
||||
"bytes": 14028,
|
||||
"imports": [
|
||||
{
|
||||
"path": "dist/tfjs.esm.js",
|
||||
|
@ -71,16 +71,16 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/blazeface/facemesh.js": {
|
||||
"bytes": 2973,
|
||||
"bytes": 2898,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -101,20 +101,20 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"src/profile.js": {
|
||||
"bytes": 1045,
|
||||
"src/profile.ts": {
|
||||
"bytes": 1004,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/faceboxes/faceboxes.js": {
|
||||
"bytes": 2612,
|
||||
"src/faceboxes/faceboxes.ts": {
|
||||
"bytes": 2852,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -122,16 +122,16 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js",
|
||||
"path": "src/profile.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/age/age.js": {
|
||||
"bytes": 2037,
|
||||
"src/age/age.ts": {
|
||||
"bytes": 2064,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -139,16 +139,16 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js",
|
||||
"path": "src/profile.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/gender/gender.js": {
|
||||
"bytes": 2906,
|
||||
"src/gender/gender.ts": {
|
||||
"bytes": 2904,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -156,16 +156,16 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js",
|
||||
"path": "src/profile.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/emotion/emotion.js": {
|
||||
"bytes": 3056,
|
||||
"src/emotion/emotion.ts": {
|
||||
"bytes": 3033,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -173,16 +173,16 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js",
|
||||
"path": "src/profile.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/embedding/embedding.js": {
|
||||
"bytes": 2063,
|
||||
"src/embedding/embedding.ts": {
|
||||
"bytes": 1992,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -190,7 +190,7 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js",
|
||||
"path": "src/profile.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
|
@ -244,7 +244,7 @@
|
|||
]
|
||||
},
|
||||
"src/posenet/decodePose.js": {
|
||||
"bytes": 5368,
|
||||
"bytes": 5216,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/posenet/keypoints.js",
|
||||
|
@ -261,7 +261,7 @@
|
|||
]
|
||||
},
|
||||
"src/posenet/decodeMultiple.js": {
|
||||
"bytes": 2373,
|
||||
"bytes": 2303,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/posenet/buildParts.js",
|
||||
|
@ -286,11 +286,11 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/modelPoseNet.js": {
|
||||
"bytes": 2519,
|
||||
"src/posenet/posenet.js": {
|
||||
"bytes": 2406,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -315,23 +315,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/posenet.js": {
|
||||
"bytes": 712,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/posenet/modelPoseNet.js",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/keypoints.js",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/util.js",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/handpose/box.js": {
|
||||
"bytes": 2522,
|
||||
"imports": [
|
||||
|
@ -355,11 +338,11 @@
|
|||
]
|
||||
},
|
||||
"src/handpose/util.js": {
|
||||
"bytes": 2346,
|
||||
"bytes": 2326,
|
||||
"imports": []
|
||||
},
|
||||
"src/handpose/handpipeline.js": {
|
||||
"bytes": 7246,
|
||||
"bytes": 7243,
|
||||
"imports": [
|
||||
{
|
||||
"path": "dist/tfjs.esm.js",
|
||||
|
@ -374,7 +357,7 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
|
@ -384,10 +367,10 @@
|
|||
"imports": []
|
||||
},
|
||||
"src/handpose/handpose.js": {
|
||||
"bytes": 2578,
|
||||
"bytes": 2536,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -408,19 +391,19 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"src/gesture/gesture.js": {
|
||||
"bytes": 4245,
|
||||
"src/gesture/gesture.ts": {
|
||||
"bytes": 4265,
|
||||
"imports": []
|
||||
},
|
||||
"src/imagefx.js": {
|
||||
"bytes": 19445,
|
||||
"bytes": 19311,
|
||||
"imports": []
|
||||
},
|
||||
"src/image.js": {
|
||||
"bytes": 5871,
|
||||
"src/image.ts": {
|
||||
"bytes": 5851,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -437,7 +420,7 @@
|
|||
"bytes": 9786,
|
||||
"imports": []
|
||||
},
|
||||
"src/sample.js": {
|
||||
"src/sample.ts": {
|
||||
"bytes": 55382,
|
||||
"imports": []
|
||||
},
|
||||
|
@ -445,11 +428,11 @@
|
|||
"bytes": 2321,
|
||||
"imports": []
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytes": 18962,
|
||||
"src/human.ts": {
|
||||
"bytes": 19233,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -457,7 +440,7 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/tfjs/backend.js",
|
||||
"path": "src/tfjs/backend.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -465,23 +448,23 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/faceboxes/faceboxes.js",
|
||||
"path": "src/faceboxes/faceboxes.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/age/age.js",
|
||||
"path": "src/age/age.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/gender/gender.js",
|
||||
"path": "src/gender/gender.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/emotion/emotion.js",
|
||||
"path": "src/emotion/emotion.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/embedding/embedding.js",
|
||||
"path": "src/embedding/embedding.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -493,15 +476,15 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/gesture/gesture.js",
|
||||
"path": "src/gesture/gesture.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/image.js",
|
||||
"path": "src/image.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js",
|
||||
"path": "src/profile.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -509,7 +492,7 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/sample.js",
|
||||
"path": "src/sample.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -524,14 +507,14 @@
|
|||
"imports": [],
|
||||
"exports": [],
|
||||
"inputs": {},
|
||||
"bytes": 714830
|
||||
"bytes": 712944
|
||||
},
|
||||
"dist/human.node-gpu.js": {
|
||||
"imports": [],
|
||||
"exports": [],
|
||||
"inputs": {
|
||||
"dist/tfjs.esm.js": {
|
||||
"bytesInOutput": 545
|
||||
"bytesInOutput": 550
|
||||
},
|
||||
"src/blazeface/blazeface.js": {
|
||||
"bytesInOutput": 3077
|
||||
|
@ -549,25 +532,7 @@
|
|||
"bytesInOutput": 5593
|
||||
},
|
||||
"src/blazeface/facemesh.js": {
|
||||
"bytesInOutput": 1556
|
||||
},
|
||||
"src/profile.js": {
|
||||
"bytesInOutput": 631
|
||||
},
|
||||
"src/faceboxes/faceboxes.js": {
|
||||
"bytesInOutput": 1425
|
||||
},
|
||||
"src/age/age.js": {
|
||||
"bytesInOutput": 852
|
||||
},
|
||||
"src/gender/gender.js": {
|
||||
"bytesInOutput": 1348
|
||||
},
|
||||
"src/emotion/emotion.js": {
|
||||
"bytesInOutput": 1306
|
||||
},
|
||||
"src/embedding/embedding.js": {
|
||||
"bytesInOutput": 908
|
||||
"bytesInOutput": 1574
|
||||
},
|
||||
"src/posenet/modelBase.js": {
|
||||
"bytesInOutput": 688
|
||||
|
@ -596,11 +561,8 @@
|
|||
"src/posenet/util.js": {
|
||||
"bytesInOutput": 1051
|
||||
},
|
||||
"src/posenet/modelPoseNet.js": {
|
||||
"bytesInOutput": 1180
|
||||
},
|
||||
"src/posenet/posenet.js": {
|
||||
"bytesInOutput": 385
|
||||
"bytesInOutput": 1223
|
||||
},
|
||||
"src/handpose/handdetector.js": {
|
||||
"bytesInOutput": 1844
|
||||
|
@ -612,43 +574,61 @@
|
|||
"bytesInOutput": 127005
|
||||
},
|
||||
"src/handpose/handpose.js": {
|
||||
"bytesInOutput": 1363
|
||||
"bytesInOutput": 1397
|
||||
},
|
||||
"src/gesture/gesture.js": {
|
||||
"bytesInOutput": 2423
|
||||
"src/human.ts": {
|
||||
"bytesInOutput": 10355
|
||||
},
|
||||
"src/imagefx.js": {
|
||||
"bytesInOutput": 10999
|
||||
},
|
||||
"src/image.js": {
|
||||
"bytesInOutput": 2478
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 10681
|
||||
},
|
||||
"src/log.js": {
|
||||
"src/log.ts": {
|
||||
"bytesInOutput": 251
|
||||
},
|
||||
"src/tfjs/backend.js": {
|
||||
"src/tfjs/backend.ts": {
|
||||
"bytesInOutput": 1304
|
||||
},
|
||||
"src/faceboxes/faceboxes.ts": {
|
||||
"bytesInOutput": 1592
|
||||
},
|
||||
"src/profile.ts": {
|
||||
"bytesInOutput": 604
|
||||
},
|
||||
"src/age/age.ts": {
|
||||
"bytesInOutput": 828
|
||||
},
|
||||
"src/gender/gender.ts": {
|
||||
"bytesInOutput": 1337
|
||||
},
|
||||
"src/emotion/emotion.ts": {
|
||||
"bytesInOutput": 1265
|
||||
},
|
||||
"src/embedding/embedding.ts": {
|
||||
"bytesInOutput": 851
|
||||
},
|
||||
"src/handpose/box.js": {
|
||||
"bytesInOutput": 958
|
||||
},
|
||||
"src/handpose/util.js": {
|
||||
"bytesInOutput": 812
|
||||
},
|
||||
"src/gesture/gesture.ts": {
|
||||
"bytesInOutput": 2391
|
||||
},
|
||||
"src/image.ts": {
|
||||
"bytesInOutput": 2434
|
||||
},
|
||||
"src/imagefx.js": {
|
||||
"bytesInOutput": 11045
|
||||
},
|
||||
"config.js": {
|
||||
"bytesInOutput": 1426
|
||||
},
|
||||
"src/sample.js": {
|
||||
"src/sample.ts": {
|
||||
"bytesInOutput": 55295
|
||||
},
|
||||
"package.json": {
|
||||
"bytesInOutput": 16
|
||||
}
|
||||
},
|
||||
"bytes": 280251
|
||||
"bytes": 279609
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,18 +1,18 @@
|
|||
{
|
||||
"inputs": {
|
||||
"src/log.js": {
|
||||
"src/log.ts": {
|
||||
"bytes": 401,
|
||||
"imports": []
|
||||
},
|
||||
"dist/tfjs.esm.js": {
|
||||
"bytes": 1071833,
|
||||
"bytes": 1071825,
|
||||
"imports": []
|
||||
},
|
||||
"src/tfjs/backend.js": {
|
||||
"bytes": 2171,
|
||||
"src/tfjs/backend.ts": {
|
||||
"bytes": 2168,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -21,11 +21,11 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"src/blazeface/blazeface.js": {
|
||||
"bytes": 7024,
|
||||
"src/blazeface/blazeface.ts": {
|
||||
"bytes": 6024,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -34,8 +34,8 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"src/blazeface/box.js": {
|
||||
"bytes": 1935,
|
||||
"src/blazeface/box.ts": {
|
||||
"bytes": 1727,
|
||||
"imports": [
|
||||
{
|
||||
"path": "dist/tfjs.esm.js",
|
||||
|
@ -43,44 +43,40 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"src/blazeface/util.js": {
|
||||
"bytes": 3087,
|
||||
"src/blazeface/util.ts": {
|
||||
"bytes": 2777,
|
||||
"imports": []
|
||||
},
|
||||
"src/blazeface/coords.js": {
|
||||
"bytes": 37915,
|
||||
"src/blazeface/coords.ts": {
|
||||
"bytes": 37783,
|
||||
"imports": []
|
||||
},
|
||||
"src/blazeface/facepipeline.js": {
|
||||
"bytes": 14275,
|
||||
"src/blazeface/facepipeline.ts": {
|
||||
"bytes": 14254,
|
||||
"imports": [
|
||||
{
|
||||
"path": "dist/tfjs.esm.js",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/blazeface/box.js",
|
||||
"path": "src/blazeface/box.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/blazeface/util.js",
|
||||
"path": "src/blazeface/util.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/blazeface/coords.js",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/blazeface/coords.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/blazeface/facemesh.js": {
|
||||
"bytes": 2973,
|
||||
"src/blazeface/facemesh.ts": {
|
||||
"bytes": 2935,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -88,33 +84,33 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/blazeface/blazeface.js",
|
||||
"path": "src/blazeface/blazeface.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/blazeface/facepipeline.js",
|
||||
"path": "src/blazeface/facepipeline.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/blazeface/coords.js",
|
||||
"path": "src/blazeface/coords.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/profile.js": {
|
||||
"bytes": 1045,
|
||||
"src/profile.ts": {
|
||||
"bytes": 1004,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/faceboxes/faceboxes.js": {
|
||||
"bytes": 2612,
|
||||
"src/faceboxes/faceboxes.ts": {
|
||||
"bytes": 2852,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -122,16 +118,16 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js",
|
||||
"path": "src/profile.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/age/age.js": {
|
||||
"bytes": 2037,
|
||||
"src/age/age.ts": {
|
||||
"bytes": 2064,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -139,16 +135,16 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js",
|
||||
"path": "src/profile.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/gender/gender.js": {
|
||||
"bytes": 2906,
|
||||
"src/gender/gender.ts": {
|
||||
"bytes": 2904,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -156,16 +152,16 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js",
|
||||
"path": "src/profile.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/emotion/emotion.js": {
|
||||
"bytes": 3056,
|
||||
"src/emotion/emotion.ts": {
|
||||
"bytes": 3033,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -173,16 +169,16 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js",
|
||||
"path": "src/profile.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/embedding/embedding.js": {
|
||||
"bytes": 2063,
|
||||
"src/embedding/embedding.ts": {
|
||||
"bytes": 1992,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -190,13 +186,13 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js",
|
||||
"path": "src/profile.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/modelBase.js": {
|
||||
"bytes": 1343,
|
||||
"src/posenet/modelBase.ts": {
|
||||
"bytes": 1333,
|
||||
"imports": [
|
||||
{
|
||||
"path": "dist/tfjs.esm.js",
|
||||
|
@ -204,93 +200,93 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/heapSort.js": {
|
||||
"bytes": 1590,
|
||||
"src/posenet/heapSort.ts": {
|
||||
"bytes": 1645,
|
||||
"imports": []
|
||||
},
|
||||
"src/posenet/buildParts.js": {
|
||||
"bytes": 1775,
|
||||
"src/posenet/buildParts.ts": {
|
||||
"bytes": 1723,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/posenet/heapSort.js",
|
||||
"path": "src/posenet/heapSort.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/keypoints.js": {
|
||||
"bytes": 2011,
|
||||
"src/posenet/keypoints.ts": {
|
||||
"bytes": 2025,
|
||||
"imports": []
|
||||
},
|
||||
"src/posenet/vectors.js": {
|
||||
"bytes": 1273,
|
||||
"src/posenet/vectors.ts": {
|
||||
"bytes": 1075,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/posenet/keypoints.js",
|
||||
"path": "src/posenet/keypoints.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/decoders.js": {
|
||||
"bytes": 2083,
|
||||
"src/posenet/decoders.ts": {
|
||||
"bytes": 1943,
|
||||
"imports": [
|
||||
{
|
||||
"path": "dist/tfjs.esm.js",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/keypoints.js",
|
||||
"path": "src/posenet/keypoints.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/decodePose.js": {
|
||||
"bytes": 5368,
|
||||
"src/posenet/decodePose.ts": {
|
||||
"bytes": 5152,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/posenet/keypoints.js",
|
||||
"path": "src/posenet/keypoints.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/vectors.js",
|
||||
"path": "src/posenet/vectors.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/decoders.js",
|
||||
"path": "src/posenet/decoders.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/decodeMultiple.js": {
|
||||
"bytes": 2373,
|
||||
"src/posenet/decodeMultiple.ts": {
|
||||
"bytes": 2259,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/posenet/buildParts.js",
|
||||
"path": "src/posenet/buildParts.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/decodePose.js",
|
||||
"path": "src/posenet/decodePose.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/vectors.js",
|
||||
"path": "src/posenet/vectors.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/util.js": {
|
||||
"bytes": 2262,
|
||||
"src/posenet/util.ts": {
|
||||
"bytes": 2017,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/posenet/keypoints.js",
|
||||
"path": "src/posenet/keypoints.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/modelPoseNet.js": {
|
||||
"bytes": 2519,
|
||||
"src/posenet/posenet.ts": {
|
||||
"bytes": 2376,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -298,42 +294,25 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/modelBase.js",
|
||||
"path": "src/posenet/modelBase.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/decodeMultiple.js",
|
||||
"path": "src/posenet/decodeMultiple.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/decodePose.js",
|
||||
"path": "src/posenet/decodePose.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/util.js",
|
||||
"path": "src/posenet/util.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/posenet/posenet.js": {
|
||||
"bytes": 712,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/posenet/modelPoseNet.js",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/keypoints.js",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/util.js",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/handpose/box.js": {
|
||||
"bytes": 2522,
|
||||
"src/handpose/box.ts": {
|
||||
"bytes": 2443,
|
||||
"imports": [
|
||||
{
|
||||
"path": "dist/tfjs.esm.js",
|
||||
|
@ -341,53 +320,49 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"src/handpose/handdetector.js": {
|
||||
"bytes": 3548,
|
||||
"src/handpose/handdetector.ts": {
|
||||
"bytes": 3627,
|
||||
"imports": [
|
||||
{
|
||||
"path": "dist/tfjs.esm.js",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/handpose/box.js",
|
||||
"path": "src/handpose/box.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/handpose/util.js": {
|
||||
"bytes": 2346,
|
||||
"src/handpose/util.ts": {
|
||||
"bytes": 2254,
|
||||
"imports": []
|
||||
},
|
||||
"src/handpose/handpipeline.js": {
|
||||
"bytes": 7246,
|
||||
"src/handpose/handpipeline.ts": {
|
||||
"bytes": 7344,
|
||||
"imports": [
|
||||
{
|
||||
"path": "dist/tfjs.esm.js",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/handpose/box.js",
|
||||
"path": "src/handpose/box.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/handpose/util.js",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/handpose/util.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/handpose/anchors.js": {
|
||||
"bytes": 224151,
|
||||
"src/handpose/anchors.ts": {
|
||||
"bytes": 224156,
|
||||
"imports": []
|
||||
},
|
||||
"src/handpose/handpose.js": {
|
||||
"bytes": 2578,
|
||||
"src/handpose/handpose.ts": {
|
||||
"bytes": 2529,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -395,32 +370,32 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/handpose/handdetector.js",
|
||||
"path": "src/handpose/handdetector.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/handpose/handpipeline.js",
|
||||
"path": "src/handpose/handpipeline.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/handpose/anchors.js",
|
||||
"path": "src/handpose/anchors.ts",
|
||||
"kind": "import-statement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"src/gesture/gesture.js": {
|
||||
"bytes": 4245,
|
||||
"src/gesture/gesture.ts": {
|
||||
"bytes": 4265,
|
||||
"imports": []
|
||||
},
|
||||
"src/imagefx.js": {
|
||||
"bytes": 19445,
|
||||
"bytes": 19447,
|
||||
"imports": []
|
||||
},
|
||||
"src/image.js": {
|
||||
"bytes": 5871,
|
||||
"src/image.ts": {
|
||||
"bytes": 5851,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -437,19 +412,19 @@
|
|||
"bytes": 9786,
|
||||
"imports": []
|
||||
},
|
||||
"src/sample.js": {
|
||||
"src/sample.ts": {
|
||||
"bytes": 55382,
|
||||
"imports": []
|
||||
},
|
||||
"package.json": {
|
||||
"bytes": 2321,
|
||||
"bytes": 2344,
|
||||
"imports": []
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytes": 18962,
|
||||
"src/human.ts": {
|
||||
"bytes": 19393,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/log.js",
|
||||
"path": "src/log.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -457,51 +432,51 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/tfjs/backend.js",
|
||||
"path": "src/tfjs/backend.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/blazeface/facemesh.js",
|
||||
"path": "src/blazeface/facemesh.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/faceboxes/faceboxes.js",
|
||||
"path": "src/faceboxes/faceboxes.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/age/age.js",
|
||||
"path": "src/age/age.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/gender/gender.js",
|
||||
"path": "src/gender/gender.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/emotion/emotion.js",
|
||||
"path": "src/emotion/emotion.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/embedding/embedding.js",
|
||||
"path": "src/embedding/embedding.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/posenet/posenet.js",
|
||||
"path": "src/posenet/posenet.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/handpose/handpose.js",
|
||||
"path": "src/handpose/handpose.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/gesture/gesture.js",
|
||||
"path": "src/gesture/gesture.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/image.js",
|
||||
"path": "src/image.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/profile.js",
|
||||
"path": "src/profile.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -509,7 +484,7 @@
|
|||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
"path": "src/sample.js",
|
||||
"path": "src/sample.ts",
|
||||
"kind": "import-statement"
|
||||
},
|
||||
{
|
||||
|
@ -520,135 +495,132 @@
|
|||
}
|
||||
},
|
||||
"outputs": {
|
||||
"dist/human.js.map": {
|
||||
"dist/human.ts.map": {
|
||||
"imports": [],
|
||||
"exports": [],
|
||||
"inputs": {},
|
||||
"bytes": 1932088
|
||||
"bytes": 1923057
|
||||
},
|
||||
"dist/human.js": {
|
||||
"dist/human.ts": {
|
||||
"imports": [],
|
||||
"exports": [],
|
||||
"inputs": {
|
||||
"src/blazeface/blazeface.js": {
|
||||
"bytesInOutput": 2915
|
||||
"src/blazeface/facemesh.ts": {
|
||||
"bytesInOutput": 1445
|
||||
},
|
||||
"src/blazeface/box.js": {
|
||||
"bytesInOutput": 987
|
||||
},
|
||||
"src/blazeface/util.js": {
|
||||
"bytesInOutput": 1197
|
||||
},
|
||||
"src/blazeface/coords.js": {
|
||||
"bytesInOutput": 30534
|
||||
},
|
||||
"src/blazeface/facepipeline.js": {
|
||||
"bytesInOutput": 5578
|
||||
},
|
||||
"src/blazeface/facemesh.js": {
|
||||
"bytesInOutput": 1518
|
||||
},
|
||||
"src/profile.js": {
|
||||
"bytesInOutput": 637
|
||||
},
|
||||
"src/faceboxes/faceboxes.js": {
|
||||
"bytesInOutput": 1387
|
||||
},
|
||||
"src/age/age.js": {
|
||||
"bytesInOutput": 813
|
||||
},
|
||||
"src/gender/gender.js": {
|
||||
"bytesInOutput": 1283
|
||||
},
|
||||
"src/emotion/emotion.js": {
|
||||
"bytesInOutput": 1247
|
||||
},
|
||||
"src/embedding/embedding.js": {
|
||||
"bytesInOutput": 870
|
||||
},
|
||||
"src/posenet/modelBase.js": {
|
||||
"bytesInOutput": 679
|
||||
},
|
||||
"src/posenet/heapSort.js": {
|
||||
"bytesInOutput": 1048
|
||||
},
|
||||
"src/posenet/buildParts.js": {
|
||||
"bytesInOutput": 529
|
||||
},
|
||||
"src/posenet/keypoints.js": {
|
||||
"bytesInOutput": 1638
|
||||
},
|
||||
"src/posenet/vectors.js": {
|
||||
"bytesInOutput": 627
|
||||
},
|
||||
"src/posenet/decoders.js": {
|
||||
"bytesInOutput": 875
|
||||
},
|
||||
"src/posenet/decodePose.js": {
|
||||
"bytesInOutput": 1482
|
||||
},
|
||||
"src/posenet/decodeMultiple.js": {
|
||||
"bytesInOutput": 704
|
||||
},
|
||||
"src/posenet/util.js": {
|
||||
"bytesInOutput": 1065
|
||||
},
|
||||
"src/posenet/modelPoseNet.js": {
|
||||
"bytesInOutput": 1167
|
||||
},
|
||||
"src/posenet/posenet.js": {
|
||||
"bytesInOutput": 401
|
||||
},
|
||||
"src/handpose/handdetector.js": {
|
||||
"bytesInOutput": 1704
|
||||
},
|
||||
"src/handpose/handpipeline.js": {
|
||||
"bytesInOutput": 2485
|
||||
},
|
||||
"src/handpose/anchors.js": {
|
||||
"bytesInOutput": 127006
|
||||
},
|
||||
"src/handpose/handpose.js": {
|
||||
"bytesInOutput": 1331
|
||||
},
|
||||
"src/gesture/gesture.js": {
|
||||
"bytesInOutput": 2424
|
||||
"src/posenet/keypoints.ts": {
|
||||
"bytesInOutput": 1690
|
||||
},
|
||||
"src/imagefx.js": {
|
||||
"bytesInOutput": 11004
|
||||
"bytesInOutput": 11016
|
||||
},
|
||||
"src/image.js": {
|
||||
"bytesInOutput": 2480
|
||||
"src/human.ts": {
|
||||
"bytesInOutput": 10259
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 10573
|
||||
},
|
||||
"src/log.js": {
|
||||
"src/log.ts": {
|
||||
"bytesInOutput": 252
|
||||
},
|
||||
"dist/tfjs.esm.js": {
|
||||
"bytesInOutput": 1062888
|
||||
"bytesInOutput": 1062782
|
||||
},
|
||||
"src/tfjs/backend.js": {
|
||||
"src/tfjs/backend.ts": {
|
||||
"bytesInOutput": 1205
|
||||
},
|
||||
"src/handpose/box.js": {
|
||||
"src/blazeface/blazeface.ts": {
|
||||
"bytesInOutput": 2185
|
||||
},
|
||||
"src/blazeface/box.ts": {
|
||||
"bytesInOutput": 834
|
||||
},
|
||||
"src/blazeface/util.ts": {
|
||||
"bytesInOutput": 858
|
||||
},
|
||||
"src/blazeface/coords.ts": {
|
||||
"bytesInOutput": 28983
|
||||
},
|
||||
"src/blazeface/facepipeline.ts": {
|
||||
"bytesInOutput": 5046
|
||||
},
|
||||
"src/faceboxes/faceboxes.ts": {
|
||||
"bytesInOutput": 1549
|
||||
},
|
||||
"src/profile.ts": {
|
||||
"bytesInOutput": 606
|
||||
},
|
||||
"src/age/age.ts": {
|
||||
"bytesInOutput": 826
|
||||
},
|
||||
"src/gender/gender.ts": {
|
||||
"bytesInOutput": 1309
|
||||
},
|
||||
"src/emotion/emotion.ts": {
|
||||
"bytesInOutput": 1243
|
||||
},
|
||||
"src/embedding/embedding.ts": {
|
||||
"bytesInOutput": 802
|
||||
},
|
||||
"src/posenet/posenet.ts": {
|
||||
"bytesInOutput": 1007
|
||||
},
|
||||
"src/posenet/modelBase.ts": {
|
||||
"bytesInOutput": 646
|
||||
},
|
||||
"src/posenet/heapSort.ts": {
|
||||
"bytesInOutput": 1017
|
||||
},
|
||||
"src/posenet/buildParts.ts": {
|
||||
"bytesInOutput": 456
|
||||
},
|
||||
"src/posenet/decodePose.ts": {
|
||||
"bytesInOutput": 1292
|
||||
},
|
||||
"src/posenet/vectors.ts": {
|
||||
"bytesInOutput": 346
|
||||
},
|
||||
"src/posenet/decoders.ts": {
|
||||
"bytesInOutput": 768
|
||||
},
|
||||
"src/posenet/decodeMultiple.ts": {
|
||||
"bytesInOutput": 557
|
||||
},
|
||||
"src/posenet/util.ts": {
|
||||
"bytesInOutput": 354
|
||||
},
|
||||
"src/handpose/handpose.ts": {
|
||||
"bytesInOutput": 1263
|
||||
},
|
||||
"src/handpose/box.ts": {
|
||||
"bytesInOutput": 938
|
||||
},
|
||||
"src/handpose/util.js": {
|
||||
"src/handpose/handdetector.ts": {
|
||||
"bytesInOutput": 1668
|
||||
},
|
||||
"src/handpose/util.ts": {
|
||||
"bytesInOutput": 816
|
||||
},
|
||||
"src/handpose/handpipeline.ts": {
|
||||
"bytesInOutput": 2449
|
||||
},
|
||||
"src/handpose/anchors.ts": {
|
||||
"bytesInOutput": 126985
|
||||
},
|
||||
"src/gesture/gesture.ts": {
|
||||
"bytesInOutput": 2391
|
||||
},
|
||||
"src/image.ts": {
|
||||
"bytesInOutput": 2454
|
||||
},
|
||||
"config.js": {
|
||||
"bytesInOutput": 1426
|
||||
},
|
||||
"src/sample.js": {
|
||||
"src/sample.ts": {
|
||||
"bytesInOutput": 55295
|
||||
},
|
||||
"package.json": {
|
||||
"bytesInOutput": 16
|
||||
}
|
||||
},
|
||||
"bytes": 1349045
|
||||
"bytes": 1343047
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -25407,7 +25407,7 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"src/tfjs/tf-browser.js": {
|
||||
"src/tfjs/tf-browser.ts": {
|
||||
"bytes": 1784,
|
||||
"imports": [
|
||||
{
|
||||
|
@ -28613,7 +28613,7 @@
|
|||
"node_modules/@tensorflow/tfjs-backend-wasm/dist/index.js": {
|
||||
"bytesInOutput": 0
|
||||
},
|
||||
"src/tfjs/tf-browser.js": {
|
||||
"src/tfjs/tf-browser.ts": {
|
||||
"bytesInOutput": 154
|
||||
},
|
||||
"node_modules/@tensorflow/tfjs-core/dist/public/chained_ops/abs.js": {
|
||||
|
@ -29739,7 +29739,7 @@
|
|||
"bytesInOutput": 15
|
||||
}
|
||||
},
|
||||
"bytes": 1071833
|
||||
"bytes": 1071825
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -821,9 +821,9 @@
|
|||
}
|
||||
},
|
||||
"esbuild": {
|
||||
"version": "0.8.42",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.8.42.tgz",
|
||||
"integrity": "sha512-zUtj5RMqROCCCH0vV/a7cd8YQg8I0GWBhV3A3PklWRT+oM/YwVbnrtFnITzE1otGdnXplWHWdZ4OcYiV0PN+JQ==",
|
||||
"version": "0.8.43",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.8.43.tgz",
|
||||
"integrity": "sha512-ZVE2CpootS4jtnfV0bbtJdgRsHEXcMP0P7ZXGfTmNzzhBr2e5ag7Vp3ry0jmw8zduJz4iHzxg4m5jtPxWERz1w==",
|
||||
"dev": true
|
||||
},
|
||||
"escalade": {
|
||||
|
@ -2285,9 +2285,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"simple-git": {
|
||||
"version": "2.32.0",
|
||||
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-2.32.0.tgz",
|
||||
"integrity": "sha512-swz7avV2JADYgTmvs+j/eDBt+gPx3SAyh2MxlDVvxqHzHLkKr6kLr4N62qZCv5LBxc9Wx8TIXVeJKmTTY8UdSQ==",
|
||||
"version": "2.34.2",
|
||||
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-2.34.2.tgz",
|
||||
"integrity": "sha512-/EX4FtcpAj5L/Bs5zgaBGYDrnkrKflFVNppNLH9VXpIjZBLHx5cZ6/mOYJCoKXKlLRuk3iTvzrIsHo7v42zWHg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@kwsites/file-exists": "^1.1.1",
|
||||
|
@ -2505,6 +2505,12 @@
|
|||
"strip-bom": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
|
||||
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==",
|
||||
"dev": true
|
||||
},
|
||||
"type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
|
@ -2520,6 +2526,12 @@
|
|||
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
|
||||
"dev": true
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz",
|
||||
"integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==",
|
||||
"dev": true
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
"@vladmandic/pilogger": "^0.2.14",
|
||||
"chokidar": "^3.5.1",
|
||||
"dayjs": "^1.10.4",
|
||||
"esbuild": "^0.8.42",
|
||||
"esbuild": "^0.8.43",
|
||||
"eslint": "^7.19.0",
|
||||
"eslint-config-airbnb-base": "^14.2.1",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
|
@ -44,7 +44,9 @@
|
|||
"eslint-plugin-promise": "^4.2.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"seedrandom": "^3.0.5",
|
||||
"simple-git": "^2.32.0"
|
||||
"simple-git": "^2.34.2",
|
||||
"tslib": "^2.1.0",
|
||||
"typescript": "^4.1.3"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node --trace-warnings --unhandled-rejections=strict --trace-uncaught --no-deprecation src/node.js",
|
||||
|
|
|
@ -6,6 +6,7 @@ const log = require('@vladmandic/pilogger');
|
|||
|
||||
// keeps esbuild service instance cached
|
||||
let es;
|
||||
let busy = false;
|
||||
const banner = `
|
||||
/*
|
||||
Human library
|
||||
|
@ -33,7 +34,7 @@ const targets = {
|
|||
platform: 'node',
|
||||
format: 'cjs',
|
||||
metafile: 'dist/tfjs.esm.json',
|
||||
entryPoints: ['src/tfjs/tf-node.js'],
|
||||
entryPoints: ['src/tfjs/tf-node.ts'],
|
||||
outfile: 'dist/tfjs.esm.js',
|
||||
external: ['@tensorflow'],
|
||||
},
|
||||
|
@ -41,7 +42,7 @@ const targets = {
|
|||
platform: 'node',
|
||||
format: 'cjs',
|
||||
metafile: 'dist/human.node.json',
|
||||
entryPoints: ['src/human.js'],
|
||||
entryPoints: ['src/human.ts'],
|
||||
outfile: 'dist/human.node.js',
|
||||
external: ['@tensorflow'],
|
||||
},
|
||||
|
@ -51,7 +52,7 @@ const targets = {
|
|||
platform: 'node',
|
||||
format: 'cjs',
|
||||
metafile: 'dist/tfjs.esm.json',
|
||||
entryPoints: ['src/tfjs/tf-node-gpu.js'],
|
||||
entryPoints: ['src/tfjs/tf-node-gpu.ts'],
|
||||
outfile: 'dist/tfjs.esm.js',
|
||||
external: ['@tensorflow'],
|
||||
},
|
||||
|
@ -59,7 +60,7 @@ const targets = {
|
|||
platform: 'node',
|
||||
format: 'cjs',
|
||||
metafile: 'dist/human.node.json',
|
||||
entryPoints: ['src/human.js'],
|
||||
entryPoints: ['src/human.ts'],
|
||||
outfile: 'dist/human.node-gpu.js',
|
||||
external: ['@tensorflow'],
|
||||
},
|
||||
|
@ -69,7 +70,7 @@ const targets = {
|
|||
platform: 'browser',
|
||||
format: 'esm',
|
||||
metafile: 'dist/tfjs.esm.json',
|
||||
entryPoints: ['src/tfjs/tf-browser.js'],
|
||||
entryPoints: ['src/tfjs/tf-browser.ts'],
|
||||
outfile: 'dist/tfjs.esm.js',
|
||||
external: ['fs', 'buffer', 'util', '@tensorflow'],
|
||||
},
|
||||
|
@ -77,7 +78,7 @@ const targets = {
|
|||
platform: 'browser',
|
||||
format: 'esm',
|
||||
metafile: 'dist/human.esm.json',
|
||||
entryPoints: ['src/human.js'],
|
||||
entryPoints: ['src/human.ts'],
|
||||
outfile: 'dist/human.esm-nobundle.js',
|
||||
external: ['fs', 'buffer', 'util', '@tensorflow'],
|
||||
},
|
||||
|
@ -87,7 +88,7 @@ const targets = {
|
|||
platform: 'browser',
|
||||
format: 'esm',
|
||||
metafile: 'dist/tfjs.esm.json',
|
||||
entryPoints: ['src/tfjs/tf-browser.js'],
|
||||
entryPoints: ['src/tfjs/tf-browser.ts'],
|
||||
outfile: 'dist/tfjs.esm.js',
|
||||
external: ['fs', 'buffer', 'util'],
|
||||
},
|
||||
|
@ -95,16 +96,16 @@ const targets = {
|
|||
platform: 'browser',
|
||||
format: 'iife',
|
||||
globalName: 'Human',
|
||||
metafile: 'dist/human.json',
|
||||
entryPoints: ['src/human.js'],
|
||||
outfile: 'dist/human.js',
|
||||
metafile: 'dist/human.tson',
|
||||
entryPoints: ['src/human.ts'],
|
||||
outfile: 'dist/human.ts',
|
||||
external: ['fs', 'buffer', 'util'],
|
||||
},
|
||||
esm: {
|
||||
platform: 'browser',
|
||||
format: 'esm',
|
||||
metafile: 'dist/human.esm.json',
|
||||
entryPoints: ['src/human.js'],
|
||||
entryPoints: ['src/human.ts'],
|
||||
outfile: 'dist/human.esm.js',
|
||||
external: ['fs', 'buffer', 'util'],
|
||||
},
|
||||
|
@ -148,6 +149,12 @@ async function getStats(metafile) {
|
|||
|
||||
// rebuild on file change
|
||||
async function build(f, msg) {
|
||||
if (busy) {
|
||||
log.state('Build: busy...');
|
||||
setTimeout(() => build(f, msg), 500);
|
||||
return;
|
||||
}
|
||||
busy = true;
|
||||
log.info('Build: file', msg, f, 'target:', common.target);
|
||||
if (!es) es = await esbuild.startService();
|
||||
// common build options
|
||||
|
@ -168,6 +175,7 @@ async function build(f, msg) {
|
|||
log.error('Build error', JSON.stringify(err.errors || err, null, 2));
|
||||
if (require.main === module) process.exit(1);
|
||||
}
|
||||
busy = false;
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
|
|
|
@ -21,9 +21,9 @@ Repository: **<${app.repository.url}>**
|
|||
`;
|
||||
|
||||
async function update(f) {
|
||||
const all = await git.log();
|
||||
const gitLog = await git.log();
|
||||
// @ts-ignore
|
||||
const log = all.all.sort((a, b) => (new Date(b.date).getTime() - new Date(a.date).getTime()));
|
||||
const log = gitLog.all.sort((a, b) => (new Date(b.date).getTime() - new Date(a.date).getTime()));
|
||||
|
||||
let previous = '';
|
||||
for (const l of log) {
|
||||
|
|
|
@ -52,6 +52,14 @@ const mime = {
|
|||
'.wasm': 'application/wasm',
|
||||
};
|
||||
|
||||
let last = Date.now();
|
||||
async function buildAll(evt, msg) {
|
||||
const now = Date.now();
|
||||
if ((now - last) > 2) build.build(evt, msg);
|
||||
else log.state('Build: merge event file', msg, evt);
|
||||
last = now;
|
||||
}
|
||||
|
||||
// watch filesystem for any changes and notify build when needed
|
||||
async function watch() {
|
||||
const watcher = chokidar.watch(options.monitor, {
|
||||
|
@ -66,9 +74,9 @@ async function watch() {
|
|||
});
|
||||
// single event handler for file add/change/delete
|
||||
watcher
|
||||
.on('add', (evt) => build.build(evt, 'add'))
|
||||
.on('change', (evt) => build.build(evt, 'modify'))
|
||||
.on('unlink', (evt) => build.build(evt, 'remove'))
|
||||
.on('add', (evt) => buildAll(evt, 'add'))
|
||||
.on('change', (evt) => buildAll(evt, 'modify'))
|
||||
.on('unlink', (evt) => buildAll(evt, 'remove'))
|
||||
.on('error', (err) => log.error(`Client watcher error: ${err}`))
|
||||
.on('ready', () => log.state('Monitoring:', options.monitor));
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { log } from '../log.js';
|
||||
import { log } from '../log';
|
||||
import * as tf from '../../dist/tfjs.esm.js';
|
||||
import * as profile from '../profile.js';
|
||||
|
||||
const models = {};
|
||||
const models = { age: null };
|
||||
let last = { age: 0 };
|
||||
let skipped = Number.MAX_SAFE_INTEGER;
|
||||
|
||||
async function load(config) {
|
||||
export async function load(config) {
|
||||
if (!models.age) {
|
||||
models.age = await tf.loadGraphModel(config.face.age.modelPath);
|
||||
log(`load model: ${config.face.age.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
|
@ -14,7 +14,7 @@ async function load(config) {
|
|||
return models.age;
|
||||
}
|
||||
|
||||
async function predict(image, config) {
|
||||
export async function predict(image, config) {
|
||||
if (!models.age) return null;
|
||||
if ((skipped < config.face.age.skipFrames) && config.videoOptimized && last.age && (last.age > 0)) {
|
||||
skipped++;
|
||||
|
@ -38,29 +38,27 @@ async function predict(image, config) {
|
|||
tf.dispose(resize);
|
||||
|
||||
let ageT;
|
||||
const obj = {};
|
||||
const obj = { age: undefined };
|
||||
|
||||
if (!config.profile) {
|
||||
if (config.face.age.enabled) ageT = await models.age.predict(enhance);
|
||||
} else {
|
||||
const profileAge = config.face.age.enabled ? await tf.profile(() => models.age.predict(enhance)) : {};
|
||||
ageT = profileAge.result.clone();
|
||||
profileAge.result.dispose();
|
||||
// @ts-ignore
|
||||
profile.run('age', profileAge);
|
||||
if (models.age) {
|
||||
if (!config.profile) {
|
||||
if (config.face.age.enabled) ageT = await models.age.predict(enhance);
|
||||
} else {
|
||||
const profileAge = config.face.age.enabled ? await tf.profile(() => models.age.predict(enhance)) : {};
|
||||
ageT = profileAge.result.clone();
|
||||
profileAge.result.dispose();
|
||||
profile.run('age', profileAge);
|
||||
}
|
||||
enhance.dispose();
|
||||
|
||||
if (ageT) {
|
||||
const data = ageT.dataSync();
|
||||
obj.age = Math.trunc(10 * data[0]) / 10;
|
||||
}
|
||||
ageT.dispose();
|
||||
|
||||
last = obj;
|
||||
}
|
||||
enhance.dispose();
|
||||
|
||||
if (ageT) {
|
||||
const data = ageT.dataSync();
|
||||
obj.age = Math.trunc(10 * data[0]) / 10;
|
||||
}
|
||||
ageT.dispose();
|
||||
|
||||
last = obj;
|
||||
resolve(obj);
|
||||
});
|
||||
}
|
||||
|
||||
exports.predict = predict;
|
||||
exports.load = load;
|
|
@ -1,4 +1,4 @@
|
|||
import { log } from '../log.js';
|
||||
import { log } from '../log';
|
||||
import * as tf from '../../dist/tfjs.esm.js';
|
||||
|
||||
const NUM_LANDMARKS = 6;
|
||||
|
@ -24,7 +24,7 @@ function generateAnchors(inputSize) {
|
|||
return anchors;
|
||||
}
|
||||
|
||||
const disposeBox = (box) => {
|
||||
export const disposeBox = (box) => {
|
||||
box.startEndTensor.dispose();
|
||||
box.startPoint.dispose();
|
||||
box.endPoint.dispose();
|
||||
|
@ -65,7 +65,16 @@ function scaleBoxFromPrediction(face, scaleFactor) {
|
|||
});
|
||||
}
|
||||
|
||||
class BlazeFaceModel {
|
||||
export class BlazeFaceModel {
|
||||
blazeFaceModel: any;
|
||||
width: number;
|
||||
height: number;
|
||||
anchorsData: any;
|
||||
anchors: any;
|
||||
inputSize: number;
|
||||
config: any;
|
||||
scaleFaces: number;
|
||||
|
||||
constructor(model, config) {
|
||||
this.blazeFaceModel = model;
|
||||
this.width = config.face.detector.inputSize;
|
||||
|
@ -132,47 +141,11 @@ class BlazeFaceModel {
|
|||
scaleFactor: [inputImage.shape[2] / this.width, inputImage.shape[1] / this.height],
|
||||
};
|
||||
}
|
||||
|
||||
async estimateFaces(input) {
|
||||
// @ts-ignore
|
||||
const { boxes, scaleFactor } = await this.getBoundingBoxes(input);
|
||||
const faces = [];
|
||||
for (const face of boxes) {
|
||||
const landmarkData = face.landmarks.arraySync();
|
||||
const scaledBox = scaleBoxFromPrediction(face, scaleFactor);
|
||||
// @ts-ignore
|
||||
const boxData = scaleBox.arraySync();
|
||||
const probabilityData = face.probability.arraySync();
|
||||
const anchor = face.anchor;
|
||||
const [scaleFactorX, scaleFactorY] = scaleFactor;
|
||||
const scaledLandmarks = landmarkData
|
||||
.map((landmark) => ([
|
||||
(landmark[0] + anchor[0]) * scaleFactorX,
|
||||
(landmark[1] + anchor[1]) * scaleFactorY,
|
||||
]));
|
||||
const normalizedFace = {
|
||||
topLeft: boxData.slice(0, 2),
|
||||
bottomRight: boxData.slice(2),
|
||||
landmarks: scaledLandmarks,
|
||||
probability: probabilityData,
|
||||
};
|
||||
disposeBox(face.box);
|
||||
face.landmarks.dispose();
|
||||
face.probability.dispose();
|
||||
scaledBox.dispose();
|
||||
faces.push(normalizedFace);
|
||||
}
|
||||
return faces;
|
||||
}
|
||||
}
|
||||
|
||||
async function load(config) {
|
||||
export async function load(config) {
|
||||
const blazeface = await tf.loadGraphModel(config.face.detector.modelPath, { fromTFHub: config.face.detector.modelPath.includes('tfhub.dev') });
|
||||
const model = new BlazeFaceModel(blazeface, config);
|
||||
log(`load model: ${config.face.detector.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
return model;
|
||||
}
|
||||
|
||||
exports.load = load;
|
||||
exports.BlazeFaceModel = BlazeFaceModel;
|
||||
exports.disposeBox = disposeBox;
|
|
@ -1,29 +1,26 @@
|
|||
import * as tf from '../../dist/tfjs.esm.js';
|
||||
|
||||
function scaleBoxCoordinates(box, factor) {
|
||||
export function scaleBoxCoordinates(box, factor) {
|
||||
const startPoint = [box.startPoint[0] * factor[0], box.startPoint[1] * factor[1]];
|
||||
const endPoint = [box.endPoint[0] * factor[0], box.endPoint[1] * factor[1]];
|
||||
return { startPoint, endPoint };
|
||||
}
|
||||
exports.scaleBoxCoordinates = scaleBoxCoordinates;
|
||||
|
||||
function getBoxSize(box) {
|
||||
export function getBoxSize(box) {
|
||||
return [
|
||||
Math.abs(box.endPoint[0] - box.startPoint[0]),
|
||||
Math.abs(box.endPoint[1] - box.startPoint[1]),
|
||||
];
|
||||
}
|
||||
exports.getBoxSize = getBoxSize;
|
||||
|
||||
function getBoxCenter(box) {
|
||||
export function getBoxCenter(box) {
|
||||
return [
|
||||
box.startPoint[0] + (box.endPoint[0] - box.startPoint[0]) / 2,
|
||||
box.startPoint[1] + (box.endPoint[1] - box.startPoint[1]) / 2,
|
||||
];
|
||||
}
|
||||
exports.getBoxCenter = getBoxCenter;
|
||||
|
||||
function cutBoxFromImageAndResize(box, image, cropSize) {
|
||||
export function cutBoxFromImageAndResize(box, image, cropSize) {
|
||||
const h = image.shape[1];
|
||||
const w = image.shape[2];
|
||||
const boxes = [[
|
||||
|
@ -32,9 +29,8 @@ function cutBoxFromImageAndResize(box, image, cropSize) {
|
|||
]];
|
||||
return tf.image.cropAndResize(image, boxes, [0], cropSize);
|
||||
}
|
||||
exports.cutBoxFromImageAndResize = cutBoxFromImageAndResize;
|
||||
|
||||
function enlargeBox(box, factor = 1.5) {
|
||||
export function enlargeBox(box, factor = 1.5) {
|
||||
const center = getBoxCenter(box);
|
||||
const size = getBoxSize(box);
|
||||
const newHalfSize = [factor * size[0] / 2, factor * size[1] / 2];
|
||||
|
@ -42,9 +38,8 @@ function enlargeBox(box, factor = 1.5) {
|
|||
const endPoint = [center[0] + newHalfSize[0], center[1] + newHalfSize[1]];
|
||||
return { startPoint, endPoint, landmarks: box.landmarks };
|
||||
}
|
||||
exports.enlargeBox = enlargeBox;
|
||||
|
||||
function squarifyBox(box) {
|
||||
export function squarifyBox(box) {
|
||||
const centers = getBoxCenter(box);
|
||||
const size = getBoxSize(box);
|
||||
const maxEdge = Math.max(...size);
|
||||
|
@ -53,4 +48,3 @@ function squarifyBox(box) {
|
|||
const endPoint = [centers[0] + halfSize, centers[1] + halfSize];
|
||||
return { startPoint, endPoint, landmarks: box.landmarks };
|
||||
}
|
||||
exports.squarifyBox = squarifyBox;
|
|
@ -1,4 +1,4 @@
|
|||
const MESH_ANNOTATIONS = {
|
||||
export const MESH_ANNOTATIONS = {
|
||||
silhouette: [
|
||||
10, 338, 297, 332, 284, 251, 389, 356, 454, 323, 361, 288,
|
||||
397, 365, 379, 378, 400, 377, 152, 148, 176, 149, 150, 136,
|
||||
|
@ -37,7 +37,7 @@ const MESH_ANNOTATIONS = {
|
|||
leftCheek: [425],
|
||||
};
|
||||
|
||||
const MESH_TO_IRIS_INDICES_MAP = [ // A mapping from facemesh model keypoints to iris model keypoints.
|
||||
export const MESH_TO_IRIS_INDICES_MAP = [ // A mapping from facemesh model keypoints to iris model keypoints.
|
||||
{ key: 'EyeUpper0', indices: [9, 10, 11, 12, 13, 14, 15] },
|
||||
{ key: 'EyeUpper1', indices: [25, 26, 27, 28, 29, 30, 31] },
|
||||
{ key: 'EyeUpper2', indices: [41, 42, 43, 44, 45, 46, 47] },
|
||||
|
@ -49,7 +49,7 @@ const MESH_TO_IRIS_INDICES_MAP = [ // A mapping from facemesh model keypoints to
|
|||
// { key: 'EyebrowLower', indices: [48, 49, 50, 51, 52, 53] },
|
||||
];
|
||||
|
||||
const UV468 = [
|
||||
export const UV468 = [
|
||||
[0.499976992607117, 0.652534008026123],
|
||||
[0.500025987625122, 0.547487020492554],
|
||||
[0.499974012374878, 0.602371990680695],
|
||||
|
@ -520,7 +520,7 @@ const UV468 = [
|
|||
[0.723330020904541, 0.363372981548309],
|
||||
];
|
||||
|
||||
const TRI468 = [
|
||||
export const TRI468 = [
|
||||
127, 34, 139, 11, 0, 37, 232, 231, 120, 72, 37, 39, 128, 121, 47, 232, 121, 128, 104, 69, 67, 175, 171, 148, 157, 154, 155, 118, 50, 101, 73, 39, 40, 9,
|
||||
151, 108, 48, 115, 131, 194, 204, 211, 74, 40, 185, 80, 42, 183, 40, 92, 186, 230, 229, 118, 202, 212, 214, 83, 18, 17, 76, 61, 146, 160, 29, 30, 56,
|
||||
157, 173, 106, 204, 194, 135, 214, 192, 203, 165, 98, 21, 71, 68, 51, 45, 4, 144, 24, 23, 77, 146, 91, 205, 50, 187, 201, 200, 18, 91, 106, 182, 90, 91,
|
||||
|
@ -606,7 +606,7 @@ const TRI468 = [
|
|||
259, 443, 259, 260, 444, 260, 467, 445, 309, 459, 250, 305, 289, 290, 305, 290, 460, 401, 376, 435, 309, 250, 392, 376, 411, 433, 453, 341, 464, 357,
|
||||
453, 465, 343, 357, 412, 437, 343, 399, 344, 360, 440, 420, 437, 456, 360, 420, 363, 361, 401, 288, 265, 372, 353, 390, 339, 249, 339, 448, 255];
|
||||
|
||||
const TRI68 = [0, 1, 36, 0, 36, 17, 1, 2, 41, 1, 41, 36, 2, 3, 31, 2, 31, 41, 3, 4, 48, 3, 48, 31, 4, 5, 48, 5, 6, 48, 6, 7, 59, 6, 59, 48, 7, 8, 58, 7, 58, 59,
|
||||
export const TRI68 = [0, 1, 36, 0, 36, 17, 1, 2, 41, 1, 41, 36, 2, 3, 31, 2, 31, 41, 3, 4, 48, 3, 48, 31, 4, 5, 48, 5, 6, 48, 6, 7, 59, 6, 59, 48, 7, 8, 58, 7, 58, 59,
|
||||
8, 9, 56, 8, 56, 57, 8, 57, 58, 9, 10, 55, 9, 55, 56, 10, 11, 54, 10, 54, 55, 11, 12, 54, 12, 13, 54, 13, 14, 35, 13, 35, 54, 14, 15, 46, 14, 46, 35, 15, 16,
|
||||
45, 15, 45, 46, 16, 26, 45, 17, 36, 18, 18, 37, 19, 18, 36, 37, 19, 38, 20, 19, 37, 38, 20, 39, 21, 20, 38, 39, 21, 39, 27, 22, 42, 23, 22, 27, 42, 23, 43, 24,
|
||||
23, 42, 43, 24, 44, 25, 24, 43, 44, 25, 45, 26, 25, 44, 45, 27, 39, 28, 27, 28, 42, 28, 39, 29, 28, 29, 42, 29, 31, 30, 29, 30, 35, 29, 40, 31, 29, 35, 47, 29,
|
||||
|
@ -614,7 +614,8 @@ const TRI68 = [0, 1, 36, 0, 36, 17, 1, 2, 41, 1, 41, 36, 2, 3, 31, 2, 31, 41, 3,
|
|||
35, 34, 51, 52, 35, 46, 47, 35, 52, 53, 35, 53, 54, 36, 41, 37, 37, 40, 38, 37, 41, 40, 38, 40, 39, 42, 47, 43, 43, 47, 44, 44, 46, 45, 44, 47, 46, 48, 60, 49,
|
||||
48, 59, 60, 49, 61, 50, 49, 60, 61, 50, 62, 51, 50, 61, 62, 51, 62, 52, 52, 63, 53, 52, 62, 63, 53, 64, 54, 53, 63, 64, 54, 64, 55, 55, 65, 56, 55, 64, 65, 56,
|
||||
66, 57, 56, 65, 66, 57, 66, 58, 58, 67, 59, 58, 66, 67, 59, 67, 60, 60, 67, 61, 61, 66, 62, 61, 67, 66, 62, 66, 63, 63, 65, 64, 63, 66, 65, 21, 27, 22];
|
||||
const TRI33 = [
|
||||
|
||||
export const TRI33 = [
|
||||
/* eyes */ 0, 8, 7, 7, 8, 1, 2, 10, 9, 9, 10, 3,
|
||||
/* brows */ 17, 0, 18, 18, 0, 7, 18, 7, 19, 19, 7, 1, 19, 1, 11, 19, 11, 20, 21, 3, 22, 21, 9, 3, 20, 9, 21, 20, 2, 9, 20, 11, 2,
|
||||
/* 4head */ 23, 17, 18, 25, 21, 22, 24, 19, 20, 24, 18, 19, 24, 20, 21, 24, 23, 18, 24, 21, 25,
|
||||
|
@ -624,9 +625,10 @@ const TRI33 = [
|
|||
/* chin */ 5, 32, 16, 16, 32, 6, 5, 30, 32, 6, 32, 31,
|
||||
/* cont */ 26, 30, 5, 27, 6, 31, 0, 28, 26, 3, 27, 29, 17, 28, 0, 3, 29, 22, 23, 28, 17, 22, 29, 25, 28, 30, 26, 27, 31, 29,
|
||||
];
|
||||
const TRI7 = [0, 4, 1, 2, 4, 3, 4, 5, 6];
|
||||
|
||||
const VTX68 = [
|
||||
export const TRI7 = [0, 4, 1, 2, 4, 3, 4, 5, 6];
|
||||
|
||||
export const VTX68 = [
|
||||
/* cont */ 127, 234, 132, 58, 172, 150, 149, 148, 152, 377, 378, 379, 397, 288, 361, 454, 356,
|
||||
/* brows */ 70, 63, 105, 66, 107, 336, 296, 334, 293, 300,
|
||||
/* nose */ 168, 6, 195, 4, 98, 97, 2, 326, 327,
|
||||
|
@ -634,18 +636,13 @@ const VTX68 = [
|
|||
/* lip */ 57, 40, 37, 0, 267, 270, 287, 321, 314, 17, 84, 91,
|
||||
/* mouth */ 78, 81, 13, 311, 308, 402, 14, 178,
|
||||
];
|
||||
const VTX33 = [33, 133, 362, 263, 1, 62, 308, 159, 145, 386, 374, 6, 102, 331, 2, 13, 14, 70, 105, 107, 336, 334, 300, 54, 10, 284, 50, 280, 234, 454, 58, 288, 152];
|
||||
const VTX7 = [33, 133, 362, 263, 1, 78, 308];
|
||||
|
||||
exports.MESH_ANNOTATIONS = MESH_ANNOTATIONS;
|
||||
exports.MESH_TO_IRIS_INDICES_MAP = MESH_TO_IRIS_INDICES_MAP;
|
||||
export const VTX33 = [33, 133, 362, 263, 1, 62, 308, 159, 145, 386, 374, 6, 102, 331, 2, 13, 14, 70, 105, 107, 336, 334, 300, 54, 10, 284, 50, 280, 234, 454, 58, 288, 152];
|
||||
|
||||
exports.TRI468 = TRI468;
|
||||
exports.TRI68 = TRI68;
|
||||
exports.TRI33 = TRI33;
|
||||
exports.TRI7 = TRI7;
|
||||
export const VTX7 = [33, 133, 362, 263, 1, 78, 308];
|
||||
|
||||
exports.UV468 = UV468;
|
||||
exports.UV68 = VTX68.map((x) => UV468[x]);
|
||||
exports.UV33 = VTX33.map((x) => UV468[x]);
|
||||
exports.UV7 = VTX7.map((x) => UV468[x]);
|
||||
export const UV68 = VTX68.map((x) => UV468[x]);
|
||||
|
||||
export const UV33 = VTX33.map((x) => UV468[x]);
|
||||
|
||||
export const UV7 = VTX7.map((x) => UV468[x]);
|
|
@ -1,12 +1,14 @@
|
|||
import { log } from '../log.js';
|
||||
import { log } from '../log';
|
||||
import * as tf from '../../dist/tfjs.esm.js';
|
||||
import * as blazeface from './blazeface.js';
|
||||
import * as facepipeline from './facepipeline.js';
|
||||
import * as coords from './coords.js';
|
||||
|
||||
class MediaPipeFaceMesh {
|
||||
export class MediaPipeFaceMesh {
|
||||
facePipeline: any;
|
||||
config: any;
|
||||
|
||||
constructor(blazeFace, blazeMeshModel, irisModel, config) {
|
||||
// @ts-ignore
|
||||
this.facePipeline = new facepipeline.Pipeline(blazeFace, blazeMeshModel, irisModel, config);
|
||||
this.config = config;
|
||||
}
|
||||
|
@ -48,7 +50,7 @@ class MediaPipeFaceMesh {
|
|||
}
|
||||
|
||||
let faceModels = [null, null, null];
|
||||
async function load(config) {
|
||||
export async function load(config) {
|
||||
faceModels = await Promise.all([
|
||||
(!faceModels[0] && config.face.enabled) ? blazeface.load(config) : null,
|
||||
(!faceModels[1] && config.face.mesh.enabled) ? tf.loadGraphModel(config.face.mesh.modelPath, { fromTFHub: config.face.mesh.modelPath.includes('tfhub.dev') }) : null,
|
||||
|
@ -60,6 +62,4 @@ async function load(config) {
|
|||
return faceMesh;
|
||||
}
|
||||
|
||||
exports.load = load;
|
||||
exports.MediaPipeFaceMesh = MediaPipeFaceMesh;
|
||||
exports.triangulation = coords.TRI468;
|
|
@ -4,7 +4,7 @@ import * as bounding from './box';
|
|||
import * as util from './util';
|
||||
import * as coords from './coords.js';
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import { log } from '../log.js';
|
||||
import { log } from '../log';
|
||||
|
||||
const LANDMARKS_COUNT = 468;
|
||||
const MESH_MOUTH_INDEX = 13;
|
||||
|
@ -22,11 +22,11 @@ const IRIS_IRIS_INDEX = 71;
|
|||
const IRIS_NUM_COORDINATES = 76;
|
||||
|
||||
// Replace the raw coordinates returned by facemesh with refined iris model coordinates. Update the z coordinate to be an average of the original and the new. This produces the best visual effect.
|
||||
function replaceRawCoordinates(rawCoords, newCoords, prefix, keys) {
|
||||
function replaceRawCoordinates(rawCoords, newCoords, prefix, keys = null) {
|
||||
for (let i = 0; i < coords.MESH_TO_IRIS_INDICES_MAP.length; i++) {
|
||||
const { key, indices } = coords.MESH_TO_IRIS_INDICES_MAP[i];
|
||||
const originalIndices = coords.MESH_ANNOTATIONS[`${prefix}${key}`];
|
||||
const shouldReplaceAllKeys = keys == null;
|
||||
const shouldReplaceAllKeys = keys === null;
|
||||
if (shouldReplaceAllKeys || keys.includes(key)) {
|
||||
for (let j = 0; j < indices.length; j++) {
|
||||
const index = indices[j];
|
||||
|
@ -39,7 +39,19 @@ function replaceRawCoordinates(rawCoords, newCoords, prefix, keys) {
|
|||
}
|
||||
}
|
||||
// The Pipeline coordinates between the bounding box and skeleton models.
|
||||
class Pipeline {
|
||||
export class Pipeline {
|
||||
storedBoxes: any;
|
||||
runsWithoutFaceDetector: number;
|
||||
boundingBoxDetector: any;
|
||||
meshDetector: any;
|
||||
irisModel: any;
|
||||
meshWidth: number;
|
||||
meshHeight: number;
|
||||
irisSize: number;
|
||||
irisEnlarge: number;
|
||||
skipped: number;
|
||||
detectedFaces: number;
|
||||
|
||||
constructor(boundingBoxDetector, meshDetector, irisModel, config) {
|
||||
// An array of facial bounding boxes.
|
||||
this.storedBoxes = [];
|
||||
|
@ -56,7 +68,6 @@ class Pipeline {
|
|||
}
|
||||
|
||||
transformRawCoords(rawCoords, box, angle, rotationMatrix) {
|
||||
// @ts-ignore
|
||||
const boxSize = bounding.getBoxSize({ startPoint: box.startPoint, endPoint: box.endPoint });
|
||||
const scaleFactor = [boxSize[0] / this.meshWidth, boxSize[1] / this.meshHeight];
|
||||
const coordsScaled = rawCoords.map((coord) => ([
|
||||
|
@ -66,7 +77,6 @@ class Pipeline {
|
|||
const coordsRotationMatrix = (angle !== 0) ? util.buildRotationMatrix(angle, [0, 0]) : util.IDENTITY_MATRIX;
|
||||
const coordsRotated = (angle !== 0) ? coordsScaled.map((coord) => ([...util.rotatePoint(coord, coordsRotationMatrix), coord[2]])) : coordsScaled;
|
||||
const inverseRotationMatrix = (angle !== 0) ? util.invertTransformMatrix(rotationMatrix) : util.IDENTITY_MATRIX;
|
||||
// @ts-ignore
|
||||
const boxCenter = [...bounding.getBoxCenter({ startPoint: box.startPoint, endPoint: box.endPoint }), 1];
|
||||
return coordsRotated.map((coord) => ([
|
||||
coord[0] + util.dot(boxCenter, inverseRotationMatrix[0]),
|
||||
|
@ -83,9 +93,7 @@ class Pipeline {
|
|||
|
||||
// Returns a box describing a cropped region around the eye fit for passing to the iris model.
|
||||
getEyeBox(rawCoords, face, eyeInnerCornerIndex, eyeOuterCornerIndex, flip = false) {
|
||||
// @ts-ignore
|
||||
const box = bounding.squarifyBox(bounding.enlargeBox(this.calculateLandmarksBoundingBox([rawCoords[eyeInnerCornerIndex], rawCoords[eyeOuterCornerIndex]]), this.irisEnlarge));
|
||||
// @ts-ignore
|
||||
const boxSize = bounding.getBoxSize(box);
|
||||
let crop = tf.image.cropAndResize(face, [[
|
||||
box.startPoint[1] / this.meshHeight,
|
||||
|
@ -159,11 +167,8 @@ class Pipeline {
|
|||
return null;
|
||||
}
|
||||
for (let i = 0; i < this.storedBoxes.length; i++) {
|
||||
// @ts-ignore
|
||||
const scaledBox = bounding.scaleBoxCoordinates({ startPoint: this.storedBoxes[i].startPoint, endPoint: this.storedBoxes[i].endPoint }, detector.scaleFactor);
|
||||
// @ts-ignore
|
||||
const enlargedBox = bounding.enlargeBox(scaledBox);
|
||||
// @ts-ignore
|
||||
const squarifiedBox = bounding.squarifyBox(enlargedBox);
|
||||
const landmarks = this.storedBoxes[i].landmarks.arraySync();
|
||||
const confidence = this.storedBoxes[i].confidence;
|
||||
|
@ -188,17 +193,14 @@ class Pipeline {
|
|||
if (config.face.detector.rotation) {
|
||||
const [indexOfMouth, indexOfForehead] = (box.landmarks.length >= LANDMARKS_COUNT) ? MESH_KEYPOINTS_LINE_OF_SYMMETRY_INDICES : BLAZEFACE_KEYPOINTS_LINE_OF_SYMMETRY_INDICES;
|
||||
angle = util.computeRotation(box.landmarks[indexOfMouth], box.landmarks[indexOfForehead]);
|
||||
// @ts-ignore
|
||||
const faceCenter = bounding.getBoxCenter({ startPoint: box.startPoint, endPoint: box.endPoint });
|
||||
const faceCenterNormalized = [faceCenter[0] / input.shape[2], faceCenter[1] / input.shape[1]];
|
||||
const rotatedImage = tf.image.rotateWithOffset(input, angle, 0, faceCenterNormalized);
|
||||
rotationMatrix = util.buildRotationMatrix(-angle, faceCenter);
|
||||
// @ts-ignore
|
||||
face = bounding.cutBoxFromImageAndResize({ startPoint: box.startPoint, endPoint: box.endPoint }, rotatedImage, [this.meshHeight, this.meshWidth]).div(255);
|
||||
} else {
|
||||
rotationMatrix = util.IDENTITY_MATRIX;
|
||||
const cloned = input.clone();
|
||||
// @ts-ignore
|
||||
face = bounding.cutBoxFromImageAndResize({ startPoint: box.startPoint, endPoint: box.endPoint }, cloned, [this.meshHeight, this.meshWidth]).div(255);
|
||||
}
|
||||
|
||||
|
@ -215,8 +217,8 @@ class Pipeline {
|
|||
}
|
||||
|
||||
const [, confidence, contourCoords] = this.meshDetector.predict(face); // The first returned tensor represents facial contours, which are included in the coordinates.
|
||||
const confidenceVal = confidence.dataSync()[0];
|
||||
if (confidenceVal < config.face.detector.minConfidence) return null; // if below confidence just exit
|
||||
const faceConfidence = confidence.dataSync()[0];
|
||||
if (faceConfidence < config.face.detector.minConfidence) return null; // if below confidence just exit
|
||||
const coordsReshaped = tf.reshape(contourCoords, [-1, 3]);
|
||||
let rawCoords = coordsReshaped.arraySync();
|
||||
|
||||
|
@ -245,20 +247,19 @@ class Pipeline {
|
|||
}
|
||||
|
||||
const transformedCoordsData = this.transformRawCoords(rawCoords, box, angle, rotationMatrix);
|
||||
// @ts-ignore
|
||||
const landmarksBox = bounding.enlargeBox(this.calculateLandmarksBoundingBox(transformedCoordsData));
|
||||
// @ts-ignore
|
||||
const squarifiedLandmarksBox = bounding.squarifyBox(landmarksBox);
|
||||
const transformedCoords = tf.tensor2d(transformedCoordsData);
|
||||
const prediction = {
|
||||
coords: transformedCoords,
|
||||
box: landmarksBox,
|
||||
faceConfidence: confidenceVal,
|
||||
faceConfidence,
|
||||
confidence: box.confidence,
|
||||
image: face,
|
||||
rawCoords,
|
||||
};
|
||||
if (config.face.mesh.returnRawData) prediction.rawCoords = rawCoords;
|
||||
this.storedBoxes[i] = { ...squarifiedLandmarksBox, landmarks: transformedCoords.arraySync(), confidence: box.confidence, faceConfidence: confidenceVal };
|
||||
if (!config.face.mesh.returnRawData) delete prediction.rawCoords;
|
||||
this.storedBoxes[i] = { ...squarifiedLandmarksBox, landmarks: transformedCoords.arraySync(), confidence: box.confidence, faceConfidence };
|
||||
|
||||
return prediction;
|
||||
}));
|
||||
|
@ -275,4 +276,3 @@ class Pipeline {
|
|||
return { startPoint, endPoint, landmarks };
|
||||
}
|
||||
}
|
||||
exports.Pipeline = Pipeline;
|
|
@ -1,52 +1,47 @@
|
|||
exports.IDENTITY_MATRIX = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
|
||||
export const IDENTITY_MATRIX = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
|
||||
/**
|
||||
* Normalizes the provided angle to the range -pi to pi.
|
||||
* @param angle The angle in radians to be normalized.
|
||||
*/
|
||||
function normalizeRadians(angle) {
|
||||
export function normalizeRadians(angle) {
|
||||
return angle - 2 * Math.PI * Math.floor((angle + Math.PI) / (2 * Math.PI));
|
||||
}
|
||||
exports.normalizeRadians = normalizeRadians;
|
||||
|
||||
/**
|
||||
* Computes the angle of rotation between two anchor points.
|
||||
* @param point1 First anchor point
|
||||
* @param point2 Second anchor point
|
||||
*/
|
||||
function computeRotation(point1, point2) {
|
||||
export function computeRotation(point1, point2) {
|
||||
const radians = Math.PI / 2 - Math.atan2(-(point2[1] - point1[1]), point2[0] - point1[0]);
|
||||
return normalizeRadians(radians);
|
||||
}
|
||||
exports.computeRotation = computeRotation;
|
||||
|
||||
function radToDegrees(rad) {
|
||||
export function radToDegrees(rad) {
|
||||
return rad * 180 / Math.PI;
|
||||
}
|
||||
exports.radToDegrees = radToDegrees;
|
||||
|
||||
function buildTranslationMatrix(x, y) {
|
||||
export function buildTranslationMatrix(x, y) {
|
||||
return [[1, 0, x], [0, 1, y], [0, 0, 1]];
|
||||
}
|
||||
|
||||
function dot(v1, v2) {
|
||||
export function dot(v1, v2) {
|
||||
let product = 0;
|
||||
for (let i = 0; i < v1.length; i++) {
|
||||
product += v1[i] * v2[i];
|
||||
}
|
||||
return product;
|
||||
}
|
||||
exports.dot = dot;
|
||||
|
||||
function getColumnFrom2DArr(arr, columnIndex) {
|
||||
export function getColumnFrom2DArr(arr, columnIndex) {
|
||||
const column = [];
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
column.push(arr[i][columnIndex]);
|
||||
}
|
||||
return column;
|
||||
}
|
||||
exports.getColumnFrom2DArr = getColumnFrom2DArr;
|
||||
|
||||
function multiplyTransformMatrices(mat1, mat2) {
|
||||
export function multiplyTransformMatrices(mat1, mat2) {
|
||||
const product = [];
|
||||
const size = mat1.length;
|
||||
for (let row = 0; row < size; row++) {
|
||||
|
@ -57,7 +52,8 @@ function multiplyTransformMatrices(mat1, mat2) {
|
|||
}
|
||||
return product;
|
||||
}
|
||||
function buildRotationMatrix(rotation, center) {
|
||||
|
||||
export function buildRotationMatrix(rotation, center) {
|
||||
const cosA = Math.cos(rotation);
|
||||
const sinA = Math.sin(rotation);
|
||||
const rotationMatrix = [[cosA, -sinA, 0], [sinA, cosA, 0], [0, 0, 1]];
|
||||
|
@ -66,9 +62,8 @@ function buildRotationMatrix(rotation, center) {
|
|||
const negativeTranslationMatrix = buildTranslationMatrix(-center[0], -center[1]);
|
||||
return multiplyTransformMatrices(translationTimesRotation, negativeTranslationMatrix);
|
||||
}
|
||||
exports.buildRotationMatrix = buildRotationMatrix;
|
||||
|
||||
function invertTransformMatrix(matrix) {
|
||||
export function invertTransformMatrix(matrix) {
|
||||
const rotationComponent = [[matrix[0][0], matrix[1][0]], [matrix[0][1], matrix[1][1]]];
|
||||
const translationComponent = [matrix[0][2], matrix[1][2]];
|
||||
const invertedTranslation = [
|
||||
|
@ -81,17 +76,14 @@ function invertTransformMatrix(matrix) {
|
|||
[0, 0, 1],
|
||||
];
|
||||
}
|
||||
exports.invertTransformMatrix = invertTransformMatrix;
|
||||
|
||||
function rotatePoint(homogeneousCoordinate, rotationMatrix) {
|
||||
export function rotatePoint(homogeneousCoordinate, rotationMatrix) {
|
||||
return [
|
||||
dot(homogeneousCoordinate, rotationMatrix[0]),
|
||||
dot(homogeneousCoordinate, rotationMatrix[1]),
|
||||
];
|
||||
}
|
||||
exports.rotatePoint = rotatePoint;
|
||||
|
||||
function xyDistanceBetweenPoints(a, b) {
|
||||
export function xyDistanceBetweenPoints(a, b) {
|
||||
return Math.sqrt(((a[0] - b[0]) ** 2) + ((a[1] - b[1]) ** 2));
|
||||
}
|
||||
exports.xyDistanceBetweenPoints = xyDistanceBetweenPoints;
|
|
@ -1,13 +1,13 @@
|
|||
import { log } from '../log.js';
|
||||
import { log } from '../log';
|
||||
import * as tf from '../../dist/tfjs.esm.js';
|
||||
import * as profile from '../profile.js';
|
||||
|
||||
// based on https://github.com/sirius-ai/MobileFaceNet_TF
|
||||
// model converted from https://github.com/sirius-ai/MobileFaceNet_TF/files/3551493/FaceMobileNet192_train_false.zip
|
||||
|
||||
const models = {};
|
||||
const models = { embedding: null };
|
||||
|
||||
async function load(config) {
|
||||
export async function load(config) {
|
||||
if (!models.embedding) {
|
||||
models.embedding = await tf.loadGraphModel(config.face.embedding.modelPath);
|
||||
log(`load model: ${config.face.embedding.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
|
@ -15,7 +15,7 @@ async function load(config) {
|
|||
return models.embedding;
|
||||
}
|
||||
|
||||
function simmilarity(embedding1, embedding2) {
|
||||
export function simmilarity(embedding1, embedding2) {
|
||||
if (embedding1?.length !== embedding2?.length) return 0;
|
||||
// general minkowski distance
|
||||
// euclidean distance is limited case where order is 2
|
||||
|
@ -24,7 +24,7 @@ function simmilarity(embedding1, embedding2) {
|
|||
return (Math.trunc(1000 * (1 - distance)) / 1000);
|
||||
}
|
||||
|
||||
async function predict(image, config) {
|
||||
export async function predict(image, config) {
|
||||
if (!models.embedding) return null;
|
||||
return new Promise(async (resolve) => {
|
||||
const resize = tf.image.resizeBilinear(image, [config.face.embedding.inputSize, config.face.embedding.inputSize], false);
|
||||
|
@ -39,7 +39,6 @@ async function predict(image, config) {
|
|||
const profileData = await tf.profile(() => models.embedding.predict({ img_inputs: resize }));
|
||||
data = [...profileData.result.dataSync()];
|
||||
profileData.result.dispose();
|
||||
// @ts-ignore
|
||||
profile.run('emotion', profileData);
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +47,3 @@ async function predict(image, config) {
|
|||
resolve(data);
|
||||
});
|
||||
}
|
||||
|
||||
exports.predict = predict;
|
||||
exports.simmilarity = simmilarity;
|
||||
exports.load = load;
|
|
@ -1,9 +1,9 @@
|
|||
import { log } from '../log.js';
|
||||
import { log } from '../log';
|
||||
import * as tf from '../../dist/tfjs.esm.js';
|
||||
import * as profile from '../profile.js';
|
||||
|
||||
const annotations = ['angry', 'disgust', 'fear', 'happy', 'sad', 'surprise', 'neutral'];
|
||||
const models = {};
|
||||
const models = { emotion: null };
|
||||
let last = [];
|
||||
let skipped = Number.MAX_SAFE_INTEGER;
|
||||
|
||||
|
@ -11,7 +11,7 @@ let skipped = Number.MAX_SAFE_INTEGER;
|
|||
const rgb = [0.2989, 0.5870, 0.1140]; // factors for red/green/blue colors when converting to grayscale
|
||||
const scale = 1; // score multiplication factor
|
||||
|
||||
async function load(config) {
|
||||
export async function load(config) {
|
||||
if (!models.emotion) {
|
||||
models.emotion = await tf.loadGraphModel(config.face.emotion.modelPath);
|
||||
log(`load model: ${config.face.emotion.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
|
@ -19,7 +19,7 @@ async function load(config) {
|
|||
return models.emotion;
|
||||
}
|
||||
|
||||
async function predict(image, config) {
|
||||
export async function predict(image, config) {
|
||||
if (!models.emotion) return null;
|
||||
if ((skipped < config.face.emotion.skipFrames) && config.videoOptimized && (last.length > 0)) {
|
||||
skipped++;
|
||||
|
@ -77,6 +77,3 @@ async function predict(image, config) {
|
|||
resolve(obj);
|
||||
});
|
||||
}
|
||||
|
||||
exports.predict = predict;
|
||||
exports.load = load;
|
|
@ -1,9 +1,14 @@
|
|||
import { log } from '../log.js';
|
||||
import { log } from '../log';
|
||||
import * as tf from '../../dist/tfjs.esm.js';
|
||||
import * as profile from '../profile.js';
|
||||
|
||||
class FaceBoxes {
|
||||
export class FaceBoxes {
|
||||
enlarge: number;
|
||||
model: any;
|
||||
config: any;
|
||||
|
||||
constructor(model, config) {
|
||||
this.enlarge = 1.1;
|
||||
this.model = model;
|
||||
this.config = config;
|
||||
}
|
||||
|
@ -36,15 +41,20 @@ class FaceBoxes {
|
|||
resizeT.dispose();
|
||||
for (const i in boxes) {
|
||||
if (scores[i] && scores[i] > this.config.face.detector.minConfidence) {
|
||||
const enlarge = 1.05;
|
||||
const crop = [boxes[i][0] / enlarge, boxes[i][1] / enlarge, boxes[i][2] * enlarge, boxes[i][3] * enlarge];
|
||||
const crop = [boxes[i][0] / this.enlarge, boxes[i][1] / this.enlarge, boxes[i][2] * this.enlarge, boxes[i][3] * this.enlarge];
|
||||
const boxRaw = [crop[1], crop[0], (crop[3]) - (crop[1]), (crop[2]) - (crop[0])];
|
||||
const box = [parseInt(boxRaw[0] * input.shape[2]), parseInt(boxRaw[1] * input.shape[1]), parseInt(boxRaw[2] * input.shape[2]), parseInt(boxRaw[3] * input.shape[1])];
|
||||
const image = tf.image.cropAndResize(input, [crop], [0], [this.config.face.detector.inputSize, this.config.face.detector.inputSize]);
|
||||
const box = [
|
||||
parseInt((boxRaw[0] * input.shape[2]).toString()),
|
||||
parseInt((boxRaw[1] * input.shape[1]).toString()),
|
||||
parseInt((boxRaw[2] * input.shape[2]).toString()),
|
||||
parseInt((boxRaw[3] * input.shape[1]).toString())];
|
||||
const resized = tf.image.cropAndResize(input, [crop], [0], [this.config.face.detector.inputSize, this.config.face.detector.inputSize]);
|
||||
const image = resized.div([255]);
|
||||
resized.dispose();
|
||||
results.push({
|
||||
confidence: scores[i],
|
||||
box,
|
||||
boxRaw,
|
||||
boxRaw: this.config.face.mesh.returnRawData ? boxRaw : null,
|
||||
image,
|
||||
// mesh,
|
||||
// meshRaw,
|
||||
|
@ -56,7 +66,7 @@ class FaceBoxes {
|
|||
}
|
||||
}
|
||||
|
||||
async function load(config) {
|
||||
export async function load(config) {
|
||||
const model = await tf.loadGraphModel(config.face.detector.modelPath);
|
||||
log(`load model: ${config.face.detector.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
const faceboxes = new FaceBoxes(model, config);
|
||||
|
@ -64,6 +74,3 @@ async function load(config) {
|
|||
if (config.face.iris.enabled) log(`load model: ${config.face.iris.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
return faceboxes;
|
||||
}
|
||||
|
||||
exports.load = load;
|
||||
exports.FaceBoxes = FaceBoxes;
|
|
@ -1,8 +1,8 @@
|
|||
import { log } from '../log.js';
|
||||
import { log } from '../log';
|
||||
import * as tf from '../../dist/tfjs.esm.js';
|
||||
import * as profile from '../profile.js';
|
||||
|
||||
const models = {};
|
||||
const models = { gender: null };
|
||||
let last = { gender: '' };
|
||||
let skipped = Number.MAX_SAFE_INTEGER;
|
||||
let alternative = false;
|
||||
|
@ -10,7 +10,7 @@ let alternative = false;
|
|||
// tuning values
|
||||
const rgb = [0.2989, 0.5870, 0.1140]; // factors for red/green/blue colors when converting to grayscale
|
||||
|
||||
async function load(config) {
|
||||
export async function load(config) {
|
||||
if (!models.gender) {
|
||||
models.gender = await tf.loadGraphModel(config.face.gender.modelPath);
|
||||
alternative = models.gender.inputs[0].shape[3] === 1;
|
||||
|
@ -19,7 +19,7 @@ async function load(config) {
|
|||
return models.gender;
|
||||
}
|
||||
|
||||
async function predict(image, config) {
|
||||
export async function predict(image, config) {
|
||||
if (!models.gender) return null;
|
||||
if ((skipped < config.face.gender.skipFrames) && config.videoOptimized && last.gender !== '') {
|
||||
skipped++;
|
||||
|
@ -45,7 +45,7 @@ async function predict(image, config) {
|
|||
tf.dispose(resize);
|
||||
|
||||
let genderT;
|
||||
const obj = {};
|
||||
const obj = { gender: undefined, confidence: undefined };
|
||||
|
||||
if (!config.profile) {
|
||||
if (config.face.gender.enabled) genderT = await models.gender.predict(enhance);
|
||||
|
@ -53,7 +53,6 @@ async function predict(image, config) {
|
|||
const profileGender = config.face.gender.enabled ? await tf.profile(() => models.gender.predict(enhance)) : {};
|
||||
genderT = profileGender.result.clone();
|
||||
profileGender.result.dispose();
|
||||
// @ts-ignore
|
||||
profile.run('gender', profileGender);
|
||||
}
|
||||
enhance.dispose();
|
||||
|
@ -82,6 +81,3 @@ async function predict(image, config) {
|
|||
resolve(obj);
|
||||
});
|
||||
}
|
||||
|
||||
exports.predict = predict;
|
||||
exports.load = load;
|
|
@ -1,4 +1,4 @@
|
|||
exports.body = (res) => {
|
||||
export const body = (res) => {
|
||||
if (!res) return [];
|
||||
const gestures = [];
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
|
@ -18,7 +18,7 @@ exports.body = (res) => {
|
|||
return gestures;
|
||||
};
|
||||
|
||||
exports.face = (res) => {
|
||||
export const face = (res) => {
|
||||
if (!res) return [];
|
||||
const gestures = [];
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
|
@ -39,7 +39,7 @@ exports.face = (res) => {
|
|||
return gestures;
|
||||
};
|
||||
|
||||
exports.iris = (res) => {
|
||||
export const iris = (res) => {
|
||||
if (!res) return [];
|
||||
const gestures = [];
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
|
@ -58,7 +58,7 @@ exports.iris = (res) => {
|
|||
return gestures;
|
||||
};
|
||||
|
||||
exports.hand = (res) => {
|
||||
export const hand = (res) => {
|
||||
if (!res) return [];
|
||||
const gestures = [];
|
||||
for (let i = 0; i < res.length; i++) {
|
|
@ -1,4 +1,4 @@
|
|||
exports.anchors = [
|
||||
export const anchors = [
|
||||
{
|
||||
w: 1,
|
||||
h: 1,
|
|
@ -1,18 +1,20 @@
|
|||
import * as tf from '../../dist/tfjs.esm.js';
|
||||
|
||||
function getBoxSize(box) {
|
||||
export function getBoxSize(box) {
|
||||
return [
|
||||
Math.abs(box.endPoint[0] - box.startPoint[0]),
|
||||
Math.abs(box.endPoint[1] - box.startPoint[1]),
|
||||
];
|
||||
}
|
||||
function getBoxCenter(box) {
|
||||
|
||||
export function getBoxCenter(box) {
|
||||
return [
|
||||
box.startPoint[0] + (box.endPoint[0] - box.startPoint[0]) / 2,
|
||||
box.startPoint[1] + (box.endPoint[1] - box.startPoint[1]) / 2,
|
||||
];
|
||||
}
|
||||
function cutBoxFromImageAndResize(box, image, cropSize) {
|
||||
|
||||
export function cutBoxFromImageAndResize(box, image, cropSize) {
|
||||
const h = image.shape[1];
|
||||
const w = image.shape[2];
|
||||
const boxes = [[
|
||||
|
@ -23,7 +25,8 @@ function cutBoxFromImageAndResize(box, image, cropSize) {
|
|||
]];
|
||||
return tf.image.cropAndResize(image, boxes, [0], cropSize);
|
||||
}
|
||||
function scaleBoxCoordinates(box, factor) {
|
||||
|
||||
export function scaleBoxCoordinates(box, factor) {
|
||||
const startPoint = [box.startPoint[0] * factor[0], box.startPoint[1] * factor[1]];
|
||||
const endPoint = [box.endPoint[0] * factor[0], box.endPoint[1] * factor[1]];
|
||||
const palmLandmarks = box.palmLandmarks.map((coord) => {
|
||||
|
@ -32,7 +35,8 @@ function scaleBoxCoordinates(box, factor) {
|
|||
});
|
||||
return { startPoint, endPoint, palmLandmarks, confidence: box.confidence };
|
||||
}
|
||||
function enlargeBox(box, factor = 1.5) {
|
||||
|
||||
export function enlargeBox(box, factor = 1.5) {
|
||||
const center = getBoxCenter(box);
|
||||
const size = getBoxSize(box);
|
||||
const newHalfSize = [factor * size[0] / 2, factor * size[1] / 2];
|
||||
|
@ -40,7 +44,8 @@ function enlargeBox(box, factor = 1.5) {
|
|||
const endPoint = [center[0] + newHalfSize[0], center[1] + newHalfSize[1]];
|
||||
return { startPoint, endPoint, palmLandmarks: box.palmLandmarks };
|
||||
}
|
||||
function squarifyBox(box) {
|
||||
|
||||
export function squarifyBox(box) {
|
||||
const centers = getBoxCenter(box);
|
||||
const size = getBoxSize(box);
|
||||
const maxEdge = Math.max(...size);
|
||||
|
@ -49,7 +54,8 @@ function squarifyBox(box) {
|
|||
const endPoint = [centers[0] + halfSize, centers[1] + halfSize];
|
||||
return { startPoint, endPoint, palmLandmarks: box.palmLandmarks };
|
||||
}
|
||||
function shiftBox(box, shiftFactor) {
|
||||
|
||||
export function shiftBox(box, shiftFactor) {
|
||||
const boxSize = [
|
||||
box.endPoint[0] - box.startPoint[0],
|
||||
box.endPoint[1] - box.startPoint[1],
|
||||
|
@ -59,12 +65,3 @@ function shiftBox(box, shiftFactor) {
|
|||
const endPoint = [box.endPoint[0] + shiftVector[0], box.endPoint[1] + shiftVector[1]];
|
||||
return { startPoint, endPoint, palmLandmarks: box.palmLandmarks };
|
||||
}
|
||||
export {
|
||||
cutBoxFromImageAndResize,
|
||||
enlargeBox,
|
||||
getBoxCenter,
|
||||
getBoxSize,
|
||||
scaleBoxCoordinates,
|
||||
shiftBox,
|
||||
squarifyBox,
|
||||
};
|
|
@ -1,7 +1,13 @@
|
|||
import * as tf from '../../dist/tfjs.esm.js';
|
||||
import * as box from './box';
|
||||
|
||||
class HandDetector {
|
||||
export class HandDetector {
|
||||
model: any;
|
||||
anchors: any;
|
||||
anchorsTensor: any;
|
||||
inputSizeTensor: any;
|
||||
doubleInputSizeTensor: any;
|
||||
|
||||
constructor(model, inputSize, anchorsAnnotated) {
|
||||
this.model = model;
|
||||
this.anchors = anchorsAnnotated.map((anchor) => [anchor.x_center, anchor.y_center]);
|
||||
|
@ -78,4 +84,3 @@ class HandDetector {
|
|||
return hands;
|
||||
}
|
||||
}
|
||||
exports.HandDetector = HandDetector;
|
|
@ -2,7 +2,7 @@ import * as tf from '../../dist/tfjs.esm.js';
|
|||
import * as box from './box';
|
||||
import * as util from './util';
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import { log } from '../log.js';
|
||||
import { log } from '../log';
|
||||
|
||||
// const PALM_BOX_SHIFT_VECTOR = [0, -0.4];
|
||||
const PALM_BOX_ENLARGE_FACTOR = 5; // default 3
|
||||
|
@ -12,7 +12,14 @@ const PALM_LANDMARK_IDS = [0, 5, 9, 13, 17, 1, 2];
|
|||
const PALM_LANDMARKS_INDEX_OF_PALM_BASE = 0;
|
||||
const PALM_LANDMARKS_INDEX_OF_MIDDLE_FINGER_BASE = 2;
|
||||
|
||||
class HandPipeline {
|
||||
export class HandPipeline {
|
||||
handDetector: any;
|
||||
landmarkDetector: any;
|
||||
inputSize: number;
|
||||
storedBoxes: any;
|
||||
skipped: number;
|
||||
detectedHands: number;
|
||||
|
||||
constructor(handDetector, landmarkDetector, inputSize) {
|
||||
this.handDetector = handDetector;
|
||||
this.landmarkDetector = landmarkDetector;
|
||||
|
@ -154,5 +161,3 @@ class HandPipeline {
|
|||
return { startPoint, endPoint };
|
||||
}
|
||||
}
|
||||
|
||||
exports.HandPipeline = HandPipeline;
|
|
@ -1,6 +1,6 @@
|
|||
// https://storage.googleapis.com/tfjs-models/demos/handpose/index.html
|
||||
|
||||
import { log } from '../log.js';
|
||||
import { log } from '../log';
|
||||
import * as tf from '../../dist/tfjs.esm.js';
|
||||
import * as handdetector from './handdetector';
|
||||
import * as handpipeline from './handpipeline';
|
||||
|
@ -15,7 +15,9 @@ const MESH_ANNOTATIONS = {
|
|||
palmBase: [0],
|
||||
};
|
||||
|
||||
class HandPose {
|
||||
export class HandPose {
|
||||
handPipeline: any;
|
||||
|
||||
constructor(handPipeline) {
|
||||
this.handPipeline = handPipeline;
|
||||
}
|
||||
|
@ -51,20 +53,16 @@ class HandPose {
|
|||
return hands;
|
||||
}
|
||||
}
|
||||
exports.HandPose = HandPose;
|
||||
|
||||
async function load(config) {
|
||||
export async function load(config) {
|
||||
const [handDetectorModel, handPoseModel] = await Promise.all([
|
||||
config.hand.enabled ? tf.loadGraphModel(config.hand.detector.modelPath, { fromTFHub: config.hand.detector.modelPath.includes('tfhub.dev') }) : null,
|
||||
config.hand.landmarks ? tf.loadGraphModel(config.hand.skeleton.modelPath, { fromTFHub: config.hand.skeleton.modelPath.includes('tfhub.dev') }) : null,
|
||||
]);
|
||||
// @ts-ignore
|
||||
const handDetector = new handdetector.HandDetector(handDetectorModel, config.hand.inputSize, anchors.anchors);
|
||||
// @ts-ignore
|
||||
const handPipeline = new handpipeline.HandPipeline(handDetector, handPoseModel, config.hand.inputSize);
|
||||
const handPose = new HandPose(handPipeline);
|
||||
if (config.hand.enabled) log(`load model: ${config.hand.detector.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
if (config.hand.landmarks) log(`load model: ${config.hand.skeleton.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
return handPose;
|
||||
}
|
||||
exports.load = load;
|
|
@ -1,38 +1,43 @@
|
|||
function normalizeRadians(angle) {
|
||||
export function normalizeRadians(angle) {
|
||||
return angle - 2 * Math.PI * Math.floor((angle + Math.PI) / (2 * Math.PI));
|
||||
}
|
||||
function computeRotation(point1, point2) {
|
||||
|
||||
export function computeRotation(point1, point2) {
|
||||
const radians = Math.PI / 2 - Math.atan2(-(point2[1] - point1[1]), point2[0] - point1[0]);
|
||||
return normalizeRadians(radians);
|
||||
}
|
||||
const buildTranslationMatrix = (x, y) => [[1, 0, x], [0, 1, y], [0, 0, 1]];
|
||||
function dot(v1, v2) {
|
||||
|
||||
export const buildTranslationMatrix = (x, y) => [[1, 0, x], [0, 1, y], [0, 0, 1]];
|
||||
|
||||
export function dot(v1, v2) {
|
||||
let product = 0;
|
||||
for (let i = 0; i < v1.length; i++) {
|
||||
product += v1[i] * v2[i];
|
||||
}
|
||||
return product;
|
||||
}
|
||||
function getColumnFrom2DArr(arr, columnIndex) {
|
||||
|
||||
export function getColumnFrom2DArr(arr, columnIndex) {
|
||||
const column = [];
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
column.push(arr[i][columnIndex]);
|
||||
}
|
||||
return column;
|
||||
}
|
||||
function multiplyTransformMatrices(mat1, mat2) {
|
||||
|
||||
export function multiplyTransformMatrices(mat1, mat2) {
|
||||
const product = [];
|
||||
const size = mat1.length;
|
||||
for (let row = 0; row < size; row++) {
|
||||
product.push([]);
|
||||
for (let col = 0; col < size; col++) {
|
||||
// @ts-ignore
|
||||
product[row].push(dot(mat1[row], getColumnFrom2DArr(mat2, col)));
|
||||
}
|
||||
}
|
||||
return product;
|
||||
}
|
||||
function buildRotationMatrix(rotation, center) {
|
||||
|
||||
export function buildRotationMatrix(rotation, center) {
|
||||
const cosA = Math.cos(rotation);
|
||||
const sinA = Math.sin(rotation);
|
||||
const rotationMatrix = [[cosA, -sinA, 0], [sinA, cosA, 0], [0, 0, 1]];
|
||||
|
@ -41,7 +46,8 @@ function buildRotationMatrix(rotation, center) {
|
|||
const negativeTranslationMatrix = buildTranslationMatrix(-center[0], -center[1]);
|
||||
return multiplyTransformMatrices(translationTimesRotation, negativeTranslationMatrix);
|
||||
}
|
||||
function invertTransformMatrix(matrix) {
|
||||
|
||||
export function invertTransformMatrix(matrix) {
|
||||
const rotationComponent = [[matrix[0][0], matrix[1][0]], [matrix[0][1], matrix[1][1]]];
|
||||
const translationComponent = [matrix[0][2], matrix[1][2]];
|
||||
const invertedTranslation = [
|
||||
|
@ -54,18 +60,10 @@ function invertTransformMatrix(matrix) {
|
|||
[0, 0, 1],
|
||||
];
|
||||
}
|
||||
function rotatePoint(homogeneousCoordinate, rotationMatrix) {
|
||||
|
||||
export function rotatePoint(homogeneousCoordinate, rotationMatrix) {
|
||||
return [
|
||||
dot(homogeneousCoordinate, rotationMatrix[0]),
|
||||
dot(homogeneousCoordinate, rotationMatrix[1]),
|
||||
];
|
||||
}
|
||||
export {
|
||||
buildRotationMatrix,
|
||||
computeRotation,
|
||||
dot,
|
||||
getColumnFrom2DArr,
|
||||
invertTransformMatrix,
|
||||
normalizeRadians,
|
||||
rotatePoint,
|
||||
};
|
|
@ -1,25 +1,26 @@
|
|||
import { log } from './log.js';
|
||||
import { log } from './log';
|
||||
import * as tf from '../dist/tfjs.esm.js';
|
||||
import * as backend from './tfjs/backend.js';
|
||||
import * as facemesh from './blazeface/facemesh.js';
|
||||
import * as faceboxes from './faceboxes/faceboxes.js';
|
||||
import * as age from './age/age.js';
|
||||
import * as gender from './gender/gender.js';
|
||||
import * as emotion from './emotion/emotion.js';
|
||||
import * as embedding from './embedding/embedding.js';
|
||||
import * as posenet from './posenet/posenet.js';
|
||||
import * as handpose from './handpose/handpose.js';
|
||||
import * as gesture from './gesture/gesture.js';
|
||||
import * as image from './image.js';
|
||||
import * as profile from './profile.js';
|
||||
import * as config from '../config.js';
|
||||
import * as sample from './sample.js';
|
||||
import * as backend from './tfjs/backend';
|
||||
import * as facemesh from './blazeface/facemesh';
|
||||
import * as faceboxes from './faceboxes/faceboxes';
|
||||
import * as age from './age/age';
|
||||
import * as gender from './gender/gender';
|
||||
import * as emotion from './emotion/emotion';
|
||||
import * as embedding from './embedding/embedding';
|
||||
import * as posenet from './posenet/posenet';
|
||||
import * as handpose from './handpose/handpose';
|
||||
import * as gesture from './gesture/gesture';
|
||||
import * as image from './image';
|
||||
import * as profile from './profile';
|
||||
import * as config from '../config';
|
||||
import * as sample from './sample';
|
||||
import * as app from '../package.json';
|
||||
import { NodeFileSystem } from '@tensorflow/tfjs-node/dist/io/file_system';
|
||||
|
||||
// helper function: gets elapsed time on both browser and nodejs
|
||||
const now = () => {
|
||||
if (typeof performance !== 'undefined') return performance.now();
|
||||
return parseInt(Number(process.hrtime.bigint()) / 1000 / 1000);
|
||||
return parseInt((Number(process.hrtime.bigint()) / 1000 / 1000).toString());
|
||||
};
|
||||
|
||||
// helper function: perform deep merge of multiple objects so it allows full inheriance with overrides
|
||||
|
@ -42,6 +43,25 @@ function mergeDeep(...objects) {
|
|||
}
|
||||
|
||||
class Human {
|
||||
tf: any;
|
||||
version: string;
|
||||
config: any;
|
||||
fx: any;
|
||||
state: string;
|
||||
numTensors: number;
|
||||
analyzeMemoryLeaks: boolean;
|
||||
checkSanity: boolean;
|
||||
firstRun: boolean;
|
||||
perf: any;
|
||||
models: any;
|
||||
// models
|
||||
facemesh: any;
|
||||
age: any;
|
||||
gender: any;
|
||||
emotion: any;
|
||||
body: any;
|
||||
hand: any;
|
||||
|
||||
constructor(userConfig = {}) {
|
||||
this.tf = tf;
|
||||
this.version = app.version;
|
||||
|
@ -108,7 +128,7 @@ class Human {
|
|||
}
|
||||
|
||||
// preload models, not explicitly required as it's done automatically on first use
|
||||
async load(userConfig) {
|
||||
async load(userConfig = null) {
|
||||
this.state = 'load';
|
||||
const timeStamp = now();
|
||||
if (userConfig) this.config = mergeDeep(this.config, userConfig);
|
||||
|
@ -160,7 +180,7 @@ class Human {
|
|||
}
|
||||
|
||||
// check if backend needs initialization if it changed
|
||||
async checkBackend(force) {
|
||||
async checkBackend(force = false) {
|
||||
if (this.config.backend && (this.config.backend !== '') && force || (tf.getBackend() !== this.config.backend)) {
|
||||
const timeStamp = now();
|
||||
this.state = 'backend';
|
||||
|
@ -308,7 +328,7 @@ class Human {
|
|||
emotion: emotionRes,
|
||||
embedding: embeddingRes,
|
||||
iris: (irisSize !== 0) ? Math.trunc(irisSize) / 100 : 0,
|
||||
image: face.image.toInt().squeeze(),
|
||||
// image: face.image.toInt().squeeze(),
|
||||
});
|
||||
|
||||
// dont need face anymore
|
||||
|
@ -487,7 +507,8 @@ class Human {
|
|||
async warmupNode() {
|
||||
const atob = (str) => Buffer.from(str, 'base64');
|
||||
const img = this.config.warmup === 'face' ? atob(sample.face) : atob(sample.body);
|
||||
const data = tf.node.decodeJpeg(img);
|
||||
// @ts-ignore
|
||||
const data = tf.node.decodeJpeg(img); // tf.node is only defined when compiling for nodejs
|
||||
const expanded = data.expandDims(0);
|
||||
tf.dispose(data);
|
||||
// log('Input:', expanded);
|
|
@ -1,6 +1,6 @@
|
|||
import { log } from './log.js';
|
||||
import { log } from './log';
|
||||
import * as tf from '../dist/tfjs.esm.js';
|
||||
import * as fxImage from './imagefx.js';
|
||||
import * as fxImage from './imagefx';
|
||||
|
||||
// internal temp canvases
|
||||
let inCanvas = null;
|
||||
|
@ -9,7 +9,7 @@ let outCanvas = null;
|
|||
// process input image and return tensor
|
||||
// input can be tensor, imagedata, htmlimageelement, htmlvideoelement
|
||||
// input is resized and run through imagefx filter
|
||||
function process(input, config) {
|
||||
export function process(input, config) {
|
||||
let tensor;
|
||||
if (input instanceof tf.Tensor) {
|
||||
tensor = tf.clone(input);
|
||||
|
@ -39,7 +39,7 @@ function process(input, config) {
|
|||
outCanvas = (typeof OffscreenCanvas !== 'undefined') ? new OffscreenCanvas(inCanvas.width, inCanvas.height) : document.createElement('canvas');
|
||||
if (outCanvas.width !== inCanvas.width) outCanvas.width = inCanvas.width;
|
||||
if (outCanvas.height !== inCanvas.height) outCanvas.height = inCanvas.height;
|
||||
this.fx = tf.ENV.flags.IS_BROWSER ? new fxImage.Canvas({ canvas: outCanvas }) : null; // && (typeof document !== 'undefined')
|
||||
this.fx = tf.ENV.flags.IS_BROWSER ? new fxImage.GLImageFilter({ canvas: outCanvas }) : null; // && (typeof document !== 'undefined')
|
||||
}
|
||||
if (!this.fx) return inCanvas;
|
||||
this.fx.reset();
|
||||
|
@ -106,5 +106,3 @@ function process(input, config) {
|
|||
}
|
||||
return { tensor, canvas: config.filter.return ? outCanvas : null };
|
||||
}
|
||||
|
||||
exports.process = process;
|
|
@ -5,7 +5,7 @@ WebGLImageFilter - MIT Licensed
|
|||
<https://github.com/phoboslab/WebGLImageFilter>
|
||||
*/
|
||||
|
||||
const WebGLProgram = function (gl, vertexSource, fragmentSource) {
|
||||
const GLProgram = function (gl, vertexSource, fragmentSource) {
|
||||
const _collect = function (source, prefix, collection) {
|
||||
const r = new RegExp('\\b' + prefix + ' \\w+ (\\w+)', 'ig');
|
||||
source.replace(r, (match, name) => {
|
||||
|
@ -58,7 +58,7 @@ const WebGLProgram = function (gl, vertexSource, fragmentSource) {
|
|||
}
|
||||
};
|
||||
|
||||
const WebGLImageFilter = function (params) {
|
||||
const GLImageFilter = function (params) {
|
||||
if (!params) params = { };
|
||||
let _drawCount = 0;
|
||||
let _sourceTexture = null;
|
||||
|
@ -180,7 +180,7 @@ const WebGLImageFilter = function (params) {
|
|||
return { fbo, texture };
|
||||
};
|
||||
|
||||
const _draw = function (flags) {
|
||||
const _draw = function (flags = null) {
|
||||
let source = null;
|
||||
let target = null;
|
||||
let flipY = false;
|
||||
|
@ -225,7 +225,7 @@ const WebGLImageFilter = function (params) {
|
|||
}
|
||||
|
||||
// Compile shaders
|
||||
_currentProgram = new WebGLProgram(gl, SHADER.VERTEX_IDENTITY, fragmentSource);
|
||||
_currentProgram = new GLProgram(gl, SHADER.VERTEX_IDENTITY, fragmentSource);
|
||||
|
||||
const floatSize = Float32Array.BYTES_PER_ELEMENT;
|
||||
const vertSize = 4 * floatSize;
|
||||
|
@ -606,4 +606,4 @@ const WebGLImageFilter = function (params) {
|
|||
].join('\n');
|
||||
};
|
||||
|
||||
exports.Canvas = WebGLImageFilter;
|
||||
exports.GLImageFilter = GLImageFilter;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const console = require('console');
|
||||
const tf = require('@tensorflow/tfjs-node');
|
||||
const Human = require('..').default; // this resolves to project root which is '@vladmandic/human'
|
||||
const Human = require('../dist/human.node').default; // this resolves to project root which is '@vladmandic/human'
|
||||
|
||||
const logger = new console.Console({
|
||||
stdout: process.stdout,
|
||||
|
|
|
@ -19,7 +19,7 @@ function scoreIsMaximumInLocalWindow(keypointId, score, heatmapY, heatmapX, loca
|
|||
return localMaximum;
|
||||
}
|
||||
|
||||
function buildPartWithScoreQueue(scoreThreshold, localMaximumRadius, scores) {
|
||||
export function buildPartWithScoreQueue(scoreThreshold, localMaximumRadius, scores) {
|
||||
const [height, width, numKeypoints] = scores.shape;
|
||||
const queue = new heapSort.MaxHeap(height * width * numKeypoints, ({ score }) => score);
|
||||
for (let heatmapY = 0; heatmapY < height; ++heatmapY) {
|
||||
|
@ -37,4 +37,3 @@ function buildPartWithScoreQueue(scoreThreshold, localMaximumRadius, scores) {
|
|||
}
|
||||
return queue;
|
||||
}
|
||||
exports.buildPartWithScoreQueue = buildPartWithScoreQueue;
|
|
@ -7,7 +7,6 @@ const kLocalMaximumRadius = 1;
|
|||
function withinNmsRadiusOfCorrespondingPoint(poses, squaredNmsRadius, { x, y }, keypointId) {
|
||||
return poses.some(({ keypoints }) => {
|
||||
const correspondingKeypoint = keypoints[keypointId].position;
|
||||
// @ts-ignore
|
||||
return vectors.squaredDistance(y, x, correspondingKeypoint.y, correspondingKeypoint.x) <= squaredNmsRadius;
|
||||
});
|
||||
}
|
||||
|
@ -20,9 +19,8 @@ function getInstanceScore(existingPoses, squaredNmsRadius, instanceKeypoints) {
|
|||
return notOverlappedKeypointScores / instanceKeypoints.length;
|
||||
}
|
||||
|
||||
function decodeMultiplePoses(scoresBuffer, offsetsBuffer, displacementsFwdBuffer, displacementsBwdBuffer, config) {
|
||||
export function decodeMultiplePoses(scoresBuffer, offsetsBuffer, displacementsFwdBuffer, displacementsBwdBuffer, config) {
|
||||
const poses = [];
|
||||
// @ts-ignore
|
||||
const queue = buildParts.buildPartWithScoreQueue(config.body.scoreThreshold, kLocalMaximumRadius, scoresBuffer);
|
||||
const squaredNmsRadius = config.body.nmsRadius ^ 2;
|
||||
// Generate at most maxDetections object instances per image in decreasing root part score order.
|
||||
|
@ -30,15 +28,12 @@ function decodeMultiplePoses(scoresBuffer, offsetsBuffer, displacementsFwdBuffer
|
|||
// The top element in the queue is the next root candidate.
|
||||
const root = queue.dequeue();
|
||||
// Part-based non-maximum suppression: We reject a root candidate if it is within a disk of `nmsRadius` pixels from the corresponding part of a previously detected instance.
|
||||
// @ts-ignore
|
||||
const rootImageCoords = vectors.getImageCoords(root.part, config.body.outputStride, offsetsBuffer);
|
||||
if (withinNmsRadiusOfCorrespondingPoint(poses, squaredNmsRadius, rootImageCoords, root.part.id)) continue;
|
||||
// Else start a new detection instance at the position of the root.
|
||||
// @ts-ignore
|
||||
const keypoints = decodePose.decodePose(root, scoresBuffer, offsetsBuffer, config.body.outputStride, displacementsFwdBuffer, displacementsBwdBuffer);
|
||||
const score = getInstanceScore(poses, squaredNmsRadius, keypoints);
|
||||
if (score > config.body.scoreThreshold) poses.push({ keypoints, score });
|
||||
}
|
||||
return poses;
|
||||
}
|
||||
exports.decodeMultiplePoses = decodeMultiplePoses;
|
|
@ -14,9 +14,7 @@ function getDisplacement(edgeId, point, displacements) {
|
|||
}
|
||||
function getStridedIndexNearPoint(point, outputStride, height, width) {
|
||||
return {
|
||||
// @ts-ignore
|
||||
y: vectors.clamp(Math.round(point.y / outputStride), 0, height - 1),
|
||||
// @ts-ignore
|
||||
x: vectors.clamp(Math.round(point.x / outputStride), 0, width - 1),
|
||||
};
|
||||
}
|
||||
|
@ -26,14 +24,11 @@ function traverseToTargetKeypoint(edgeId, sourceKeypoint, targetKeypointId, scor
|
|||
// Nearest neighbor interpolation for the source->target displacements.
|
||||
const sourceKeypointIndices = getStridedIndexNearPoint(sourceKeypoint.position, outputStride, height, width);
|
||||
const displacement = getDisplacement(edgeId, sourceKeypointIndices, displacements);
|
||||
// @ts-ignore
|
||||
const displacedPoint = vectors.addVectors(sourceKeypoint.position, displacement);
|
||||
let targetKeypoint = displacedPoint;
|
||||
for (let i = 0; i < offsetRefineStep; i++) {
|
||||
const targetKeypointIndices = getStridedIndexNearPoint(targetKeypoint, outputStride, height, width);
|
||||
// @ts-ignore
|
||||
const offsetPoint = vectors.getOffsetPoint(targetKeypointIndices.y, targetKeypointIndices.x, targetKeypointId, offsets);
|
||||
// @ts-ignore
|
||||
targetKeypoint = vectors.addVectors({
|
||||
x: targetKeypointIndices.x * outputStride,
|
||||
y: targetKeypointIndices.y * outputStride,
|
||||
|
@ -44,13 +39,12 @@ function traverseToTargetKeypoint(edgeId, sourceKeypoint, targetKeypointId, scor
|
|||
return { position: targetKeypoint, part: keypoints.partNames[targetKeypointId], score };
|
||||
}
|
||||
|
||||
function decodePose(root, scores, offsets, outputStride, displacementsFwd, displacementsBwd) {
|
||||
export function decodePose(root, scores, offsets, outputStride, displacementsFwd, displacementsBwd) {
|
||||
const numParts = scores.shape[2];
|
||||
const numEdges = parentToChildEdges.length;
|
||||
const instanceKeypoints = new Array(numParts);
|
||||
// Start a new detection instance at the position of the root.
|
||||
const { part: rootPart, score: rootScore } = root;
|
||||
// @ts-ignore
|
||||
const rootPoint = vectors.getImageCoords(rootPart, outputStride, offsets);
|
||||
instanceKeypoints[rootPart.id] = {
|
||||
score: rootScore,
|
||||
|
@ -75,20 +69,16 @@ function decodePose(root, scores, offsets, outputStride, displacementsFwd, displ
|
|||
}
|
||||
return instanceKeypoints;
|
||||
}
|
||||
exports.decodePose = decodePose;
|
||||
|
||||
async function decodeSinglePose(heatmapScores, offsets, config) {
|
||||
export async function decodeSinglePose(heatmapScores, offsets, config) {
|
||||
let totalScore = 0.0;
|
||||
// @ts-ignore
|
||||
const heatmapValues = decoders.argmax2d(heatmapScores);
|
||||
const allTensorBuffers = await Promise.all([heatmapScores.buffer(), offsets.buffer(), heatmapValues.buffer()]);
|
||||
const scoresBuffer = allTensorBuffers[0];
|
||||
const offsetsBuffer = allTensorBuffers[1];
|
||||
const heatmapValuesBuffer = allTensorBuffers[2];
|
||||
// @ts-ignore
|
||||
const offsetPoints = decoders.getOffsetPoints(heatmapValuesBuffer, config.body.outputStride, offsetsBuffer);
|
||||
const offsetPointsBuffer = await offsetPoints.buffer();
|
||||
// @ts-ignore
|
||||
const keypointConfidence = Array.from(decoders.getPointsConfidence(scoresBuffer, heatmapValuesBuffer));
|
||||
const instanceKeypoints = keypointConfidence.map((score, i) => {
|
||||
totalScore += score;
|
||||
|
@ -106,4 +96,3 @@ async function decodeSinglePose(heatmapScores, offsets, config) {
|
|||
offsetPoints.dispose();
|
||||
return { keypoints: filteredKeypoints, score: totalScore / instanceKeypoints.length };
|
||||
}
|
||||
exports.decodeSinglePose = decodeSinglePose;
|
|
@ -1,7 +1,7 @@
|
|||
import * as tf from '../../dist/tfjs.esm.js';
|
||||
import * as kpt from './keypoints';
|
||||
|
||||
function getPointsConfidence(heatmapScores, heatMapCoords) {
|
||||
export function getPointsConfidence(heatmapScores, heatMapCoords) {
|
||||
const numKeypoints = heatMapCoords.shape[0];
|
||||
const result = new Float32Array(numKeypoints);
|
||||
for (let keypoint = 0; keypoint < numKeypoints; keypoint++) {
|
||||
|
@ -11,7 +11,6 @@ function getPointsConfidence(heatmapScores, heatMapCoords) {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
exports.getPointsConfidence = getPointsConfidence;
|
||||
|
||||
function getOffsetPoint(y, x, keypoint, offsetsBuffer) {
|
||||
return {
|
||||
|
@ -20,7 +19,7 @@ function getOffsetPoint(y, x, keypoint, offsetsBuffer) {
|
|||
};
|
||||
}
|
||||
|
||||
function getOffsetVectors(heatMapCoordsBuffer, offsetsBuffer) {
|
||||
export function getOffsetVectors(heatMapCoordsBuffer, offsetsBuffer) {
|
||||
const result = [];
|
||||
for (let keypoint = 0; keypoint < kpt.NUM_KEYPOINTS; keypoint++) {
|
||||
const heatmapY = heatMapCoordsBuffer.get(keypoint, 0).valueOf();
|
||||
|
@ -31,12 +30,10 @@ function getOffsetVectors(heatMapCoordsBuffer, offsetsBuffer) {
|
|||
}
|
||||
return tf.tensor2d(result, [kpt.NUM_KEYPOINTS, 2]);
|
||||
}
|
||||
exports.getOffsetVectors = getOffsetVectors;
|
||||
|
||||
function getOffsetPoints(heatMapCoordsBuffer, outputStride, offsetsBuffer) {
|
||||
export function getOffsetPoints(heatMapCoordsBuffer, outputStride, offsetsBuffer) {
|
||||
return tf.tidy(() => heatMapCoordsBuffer.toTensor().mul(tf.scalar(outputStride, 'int32')).toFloat().add(getOffsetVectors(heatMapCoordsBuffer, offsetsBuffer)));
|
||||
}
|
||||
exports.getOffsetPoints = getOffsetPoints;
|
||||
|
||||
function mod(a, b) {
|
||||
return tf.tidy(() => {
|
||||
|
@ -45,7 +42,7 @@ function mod(a, b) {
|
|||
});
|
||||
}
|
||||
|
||||
function argmax2d(inputs) {
|
||||
export function argmax2d(inputs) {
|
||||
const [height, width, depth] = inputs.shape;
|
||||
return tf.tidy(() => {
|
||||
const reshaped = inputs.reshape([height * width, depth]);
|
||||
|
@ -55,4 +52,3 @@ function argmax2d(inputs) {
|
|||
return tf.concat([yCoords, xCoords], 1);
|
||||
});
|
||||
}
|
||||
exports.argmax2d = argmax2d;
|
|
@ -2,7 +2,11 @@
|
|||
function half(k) {
|
||||
return Math.floor(k / 2);
|
||||
}
|
||||
class MaxHeap {
|
||||
export class MaxHeap {
|
||||
priorityQueue: any;
|
||||
numberOfElements: number;
|
||||
getElementValue: any;
|
||||
|
||||
constructor(maxSize, getElementValue) {
|
||||
this.priorityQueue = new Array(maxSize);
|
||||
this.numberOfElements = -1;
|
||||
|
@ -69,4 +73,3 @@ class MaxHeap {
|
|||
this.priorityQueue[j] = t;
|
||||
}
|
||||
}
|
||||
exports.MaxHeap = MaxHeap;
|
|
@ -1,12 +1,12 @@
|
|||
exports.partNames = [
|
||||
export const partNames = [
|
||||
'nose', 'leftEye', 'rightEye', 'leftEar', 'rightEar', 'leftShoulder',
|
||||
'rightShoulder', 'leftElbow', 'rightElbow', 'leftWrist', 'rightWrist',
|
||||
'leftHip', 'rightHip', 'leftKnee', 'rightKnee', 'leftAnkle', 'rightAnkle',
|
||||
];
|
||||
|
||||
exports.NUM_KEYPOINTS = exports.partNames.length;
|
||||
export const NUM_KEYPOINTS = exports.partNames.length;
|
||||
|
||||
exports.partIds = exports.partNames.reduce((result, jointName, i) => {
|
||||
export const partIds = exports.partNames.reduce((result, jointName, i) => {
|
||||
result[jointName] = i;
|
||||
return result;
|
||||
}, {});
|
||||
|
@ -19,9 +19,9 @@ const connectedPartNames = [
|
|||
['rightHip', 'rightKnee'], ['rightKnee', 'rightAnkle'],
|
||||
['leftShoulder', 'rightShoulder'], ['leftHip', 'rightHip'],
|
||||
];
|
||||
exports.connectedPartIndices = connectedPartNames.map(([jointNameA, jointNameB]) => ([exports.partIds[jointNameA], exports.partIds[jointNameB]]));
|
||||
export const connectedPartIndices = connectedPartNames.map(([jointNameA, jointNameB]) => ([partIds[jointNameA], partIds[jointNameB]]));
|
||||
|
||||
exports.poseChain = [
|
||||
export const poseChain = [
|
||||
['nose', 'leftEye'], ['leftEye', 'leftEar'], ['nose', 'rightEye'],
|
||||
['rightEye', 'rightEar'], ['nose', 'leftShoulder'],
|
||||
['leftShoulder', 'leftElbow'], ['leftElbow', 'leftWrist'],
|
||||
|
@ -32,7 +32,7 @@ exports.poseChain = [
|
|||
['rightKnee', 'rightAnkle'],
|
||||
];
|
||||
|
||||
exports.partChannels = [
|
||||
export const partChannels = [
|
||||
'left_face',
|
||||
'right_face',
|
||||
'right_upper_leg_front',
|
|
@ -12,7 +12,8 @@ function nameOutputResultsResNet(results) {
|
|||
return { offsets, heatmap, displacementFwd, displacementBwd };
|
||||
}
|
||||
|
||||
class BaseModel {
|
||||
export class BaseModel {
|
||||
model: any;
|
||||
constructor(model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
@ -37,4 +38,3 @@ class BaseModel {
|
|||
this.model.dispose();
|
||||
}
|
||||
}
|
||||
exports.BaseModel = BaseModel;
|
|
@ -1,4 +1,5 @@
|
|||
class ModelWeights {
|
||||
export class ModelWeights {
|
||||
variables: any;
|
||||
constructor(variables) {
|
||||
this.variables = variables;
|
||||
}
|
||||
|
@ -23,4 +24,3 @@ class ModelWeights {
|
|||
for (let i = 0; i < this.variables.length; i++) this.variables[i].dispose();
|
||||
}
|
||||
}
|
||||
exports.ModelWeights = ModelWeights;
|
|
@ -1,23 +0,0 @@
|
|||
import * as modelPoseNet from './modelPoseNet';
|
||||
import * as keypoints from './keypoints';
|
||||
import * as util from './util';
|
||||
|
||||
// @ts-ignore
|
||||
exports.load = modelPoseNet.load;
|
||||
// @ts-ignore
|
||||
exports.PoseNet = modelPoseNet.PoseNet;
|
||||
|
||||
exports.partChannels = keypoints.partChannels;
|
||||
exports.partIds = keypoints.partIds;
|
||||
exports.partNames = keypoints.partNames;
|
||||
exports.poseChain = keypoints.poseChain;
|
||||
// @ts-ignore
|
||||
exports.getAdjacentKeyPoints = util.getAdjacentKeyPoints;
|
||||
// @ts-ignore
|
||||
exports.getBoundingBox = util.getBoundingBox;
|
||||
// @ts-ignore
|
||||
exports.getBoundingBoxPoints = util.getBoundingBoxPoints;
|
||||
// @ts-ignore
|
||||
exports.scaleAndFlipPoses = util.scaleAndFlipPoses;
|
||||
// @ts-ignore
|
||||
exports.scalePose = util.scalePose;
|
|
@ -1,4 +1,4 @@
|
|||
import { log } from '../log.js';
|
||||
import { log } from '../log';
|
||||
import * as tf from '../../dist/tfjs.esm.js';
|
||||
import * as modelBase from './modelBase';
|
||||
import * as decodeMultiple from './decodeMultiple';
|
||||
|
@ -9,15 +9,12 @@ async function estimateMultiple(input, res, config) {
|
|||
return new Promise(async (resolve) => {
|
||||
const height = input.shape[1];
|
||||
const width = input.shape[2];
|
||||
// @ts-ignore
|
||||
const allTensorBuffers = await util.toTensorBuffers3D([res.heatmapScores, res.offsets, res.displacementFwd, res.displacementBwd]);
|
||||
const scoresBuffer = allTensorBuffers[0];
|
||||
const offsetsBuffer = allTensorBuffers[1];
|
||||
const displacementsFwdBuffer = allTensorBuffers[2];
|
||||
const displacementsBwdBuffer = allTensorBuffers[3];
|
||||
// @ts-ignore
|
||||
const poses = await decodeMultiple.decodeMultiplePoses(scoresBuffer, offsetsBuffer, displacementsFwdBuffer, displacementsBwdBuffer, config);
|
||||
// @ts-ignore
|
||||
const scaled = util.scaleAndFlipPoses(poses, [height, width], [config.body.inputSize, config.body.inputSize]);
|
||||
resolve(scaled);
|
||||
});
|
||||
|
@ -27,22 +24,20 @@ async function estimateSingle(input, res, config) {
|
|||
return new Promise(async (resolve) => {
|
||||
const height = input.shape[1];
|
||||
const width = input.shape[2];
|
||||
// @ts-ignore
|
||||
const pose = await decodePose.decodeSinglePose(res.heatmapScores, res.offsets, config);
|
||||
const poses = [pose];
|
||||
// @ts-ignore
|
||||
const scaled = util.scaleAndFlipPoses(poses, [height, width], [config.body.inputSize, config.body.inputSize]);
|
||||
resolve(scaled);
|
||||
});
|
||||
}
|
||||
|
||||
class PoseNet {
|
||||
export class PoseNet {
|
||||
baseModel: any;
|
||||
constructor(model) {
|
||||
this.baseModel = model;
|
||||
}
|
||||
|
||||
async estimatePoses(input, config) {
|
||||
// @ts-ignore
|
||||
const resized = util.resizeTo(input, [config.body.inputSize, config.body.inputSize]);
|
||||
const res = this.baseModel.predict(resized, config);
|
||||
|
||||
|
@ -61,13 +56,10 @@ class PoseNet {
|
|||
this.baseModel.dispose();
|
||||
}
|
||||
}
|
||||
exports.PoseNet = PoseNet;
|
||||
|
||||
async function load(config) {
|
||||
export async function load(config) {
|
||||
const model = await tf.loadGraphModel(config.body.modelPath);
|
||||
// @ts-ignore
|
||||
const mobilenet = new modelBase.BaseModel(model);
|
||||
log(`load model: ${config.body.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
return new PoseNet(mobilenet);
|
||||
}
|
||||
exports.load = load;
|
|
@ -1,10 +1,10 @@
|
|||
import * as kpt from './keypoints';
|
||||
|
||||
function eitherPointDoesntMeetConfidence(a, b, minConfidence) {
|
||||
export function eitherPointDoesntMeetConfidence(a, b, minConfidence) {
|
||||
return (a < minConfidence || b < minConfidence);
|
||||
}
|
||||
|
||||
function getAdjacentKeyPoints(keypoints, minConfidence) {
|
||||
export function getAdjacentKeyPoints(keypoints, minConfidence) {
|
||||
return kpt.connectedPartIndices.reduce((result, [leftJoint, rightJoint]) => {
|
||||
if (eitherPointDoesntMeetConfidence(keypoints[leftJoint].score, keypoints[rightJoint].score, minConfidence)) {
|
||||
return result;
|
||||
|
@ -13,10 +13,9 @@ function getAdjacentKeyPoints(keypoints, minConfidence) {
|
|||
return result;
|
||||
}, []);
|
||||
}
|
||||
exports.getAdjacentKeyPoints = getAdjacentKeyPoints;
|
||||
|
||||
const { NEGATIVE_INFINITY, POSITIVE_INFINITY } = Number;
|
||||
function getBoundingBox(keypoints) {
|
||||
export function getBoundingBox(keypoints) {
|
||||
return keypoints.reduce(({ maxX, maxY, minX, minY }, { position: { x, y } }) => ({
|
||||
maxX: Math.max(maxX, x),
|
||||
maxY: Math.max(maxY, y),
|
||||
|
@ -29,20 +28,17 @@ function getBoundingBox(keypoints) {
|
|||
minY: POSITIVE_INFINITY,
|
||||
});
|
||||
}
|
||||
exports.getBoundingBox = getBoundingBox;
|
||||
|
||||
function getBoundingBoxPoints(keypoints) {
|
||||
export function getBoundingBoxPoints(keypoints) {
|
||||
const { minX, minY, maxX, maxY } = getBoundingBox(keypoints);
|
||||
return [{ x: minX, y: minY }, { x: maxX, y: minY }, { x: maxX, y: maxY }, { x: minX, y: maxY }];
|
||||
}
|
||||
exports.getBoundingBoxPoints = getBoundingBoxPoints;
|
||||
|
||||
async function toTensorBuffers3D(tensors) {
|
||||
export async function toTensorBuffers3D(tensors) {
|
||||
return Promise.all(tensors.map((tensor) => tensor.buffer()));
|
||||
}
|
||||
exports.toTensorBuffers3D = toTensorBuffers3D;
|
||||
|
||||
function scalePose(pose, scaleY, scaleX) {
|
||||
export function scalePose(pose, scaleY, scaleX) {
|
||||
return {
|
||||
score: pose.score,
|
||||
keypoints: pose.keypoints.map(({ score, part, position }) => ({
|
||||
|
@ -52,18 +48,15 @@ function scalePose(pose, scaleY, scaleX) {
|
|||
})),
|
||||
};
|
||||
}
|
||||
exports.scalePose = scalePose;
|
||||
|
||||
function resizeTo(image, [targetH, targetW]) {
|
||||
export function resizeTo(image, [targetH, targetW]) {
|
||||
const input = image.squeeze(0);
|
||||
const resized = input.resizeBilinear([targetH, targetW]);
|
||||
input.dispose();
|
||||
return resized;
|
||||
}
|
||||
exports.resizeTo = resizeTo;
|
||||
|
||||
function scaleAndFlipPoses(poses, [height, width], [inputResolutionHeight, inputResolutionWidth]) {
|
||||
export function scaleAndFlipPoses(poses, [height, width], [inputResolutionHeight, inputResolutionWidth]) {
|
||||
const scaledPoses = poses.map((pose) => scalePose(pose, height / inputResolutionHeight, width / inputResolutionWidth));
|
||||
return scaledPoses;
|
||||
}
|
||||
exports.scaleAndFlipPoses = scaleAndFlipPoses;
|
|
@ -1,14 +1,13 @@
|
|||
import * as kpt from './keypoints';
|
||||
|
||||
function getOffsetPoint(y, x, keypoint, offsets) {
|
||||
export function getOffsetPoint(y, x, keypoint, offsets) {
|
||||
return {
|
||||
y: offsets.get(y, x, keypoint),
|
||||
x: offsets.get(y, x, keypoint + kpt.NUM_KEYPOINTS),
|
||||
};
|
||||
}
|
||||
exports.getOffsetPoint = getOffsetPoint;
|
||||
|
||||
function getImageCoords(part, outputStride, offsets) {
|
||||
export function getImageCoords(part, outputStride, offsets) {
|
||||
const { heatmapY, heatmapX, id: keypoint } = part;
|
||||
const { y, x } = getOffsetPoint(heatmapY, heatmapX, keypoint, offsets);
|
||||
return {
|
||||
|
@ -16,37 +15,31 @@ function getImageCoords(part, outputStride, offsets) {
|
|||
y: part.heatmapY * outputStride + y,
|
||||
};
|
||||
}
|
||||
exports.getImageCoords = getImageCoords;
|
||||
|
||||
function fillArray(element, size) {
|
||||
export function fillArray(element, size) {
|
||||
const result = new Array(size);
|
||||
for (let i = 0; i < size; i++) {
|
||||
result[i] = element;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
exports.fillArray = fillArray;
|
||||
|
||||
function clamp(a, min, max) {
|
||||
export function clamp(a, min, max) {
|
||||
if (a < min) return min;
|
||||
if (a > max) return max;
|
||||
return a;
|
||||
}
|
||||
exports.clamp = clamp;
|
||||
|
||||
function squaredDistance(y1, x1, y2, x2) {
|
||||
export function squaredDistance(y1, x1, y2, x2) {
|
||||
const dy = y2 - y1;
|
||||
const dx = x2 - x1;
|
||||
return dy * dy + dx * dx;
|
||||
}
|
||||
exports.squaredDistance = squaredDistance;
|
||||
|
||||
function addVectors(a, b) {
|
||||
export function addVectors(a, b) {
|
||||
return { x: a.x + b.x, y: a.y + b.y };
|
||||
}
|
||||
exports.addVectors = addVectors;
|
||||
|
||||
function clampVector(a, min, max) {
|
||||
export function clampVector(a, min, max) {
|
||||
return { y: clamp(a.y, min, max), x: clamp(a.x, min, max) };
|
||||
}
|
||||
exports.clampVector = clampVector;
|
|
@ -1,26 +1,24 @@
|
|||
import { log } from './log.js';
|
||||
import { log } from './log';
|
||||
|
||||
const profileData = {};
|
||||
export const data = {};
|
||||
|
||||
function profile(name, data) {
|
||||
if (!data || !data.kernels) return;
|
||||
export function run(name, raw) {
|
||||
if (!raw || !raw.kernels) return;
|
||||
const maxResults = 5;
|
||||
const time = data.kernels
|
||||
const time = raw.kernels
|
||||
.filter((a) => a.kernelTimeMs > 0)
|
||||
.reduce((a, b) => a += b.kernelTimeMs, 0);
|
||||
const slowest = data.kernels
|
||||
const slowest = raw.kernels
|
||||
.map((a, i) => { a.id = i; return a; })
|
||||
.filter((a) => a.kernelTimeMs > 0)
|
||||
.sort((a, b) => b.kernelTimeMs - a.kernelTimeMs);
|
||||
const largest = data.kernels
|
||||
const largest = raw.kernels
|
||||
.map((a, i) => { a.id = i; return a; })
|
||||
.filter((a) => a.totalBytesSnapshot > 0)
|
||||
.sort((a, b) => b.totalBytesSnapshot - a.totalBytesSnapshot);
|
||||
if (slowest.length > maxResults) slowest.length = maxResults;
|
||||
if (largest.length > maxResults) largest.length = maxResults;
|
||||
const res = { newBytes: data.newBytes, newTensors: data.newTensors, peakBytes: data.peakBytes, numKernelOps: data.kernels.length, timeKernelOps: time, slowestKernelOps: slowest, largestKernelOps: largest };
|
||||
profileData[name] = res;
|
||||
const res = { newBytes: raw.newBytes, newTensors: raw.newTensors, peakBytes: raw.peakBytes, numKernelOps: raw.kernels.length, timeKernelOps: time, slowestKernelOps: slowest, largestKernelOps: largest };
|
||||
data[name] = res;
|
||||
log('Human profiler', name, res);
|
||||
}
|
||||
|
||||
exports.run = profile;
|
|
@ -1,4 +1,4 @@
|
|||
import { log } from '../log.js';
|
||||
import { log } from '../log';
|
||||
import * as tf from '../../dist/tfjs.esm.js';
|
||||
|
||||
export const config = {
|
Loading…
Reference in New Issue