diff --git a/.gitignore b/.gitignore index b6fcf6b..cbbad87 100644 --- a/.gitignore +++ b/.gitignore @@ -109,3 +109,4 @@ dist images/* bin +out diff --git a/.vscode/launch.json b/.vscode/launch.json index 08f095c..a42b64a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,21 +1,29 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "node", - "request": "launch", - "name": "Launch Program", - "program": "${workspaceFolder}/bin/index.js", - "preLaunchTask": "build", - "console": "internalConsole", - "internalConsoleOptions": "openOnSessionStart", - "sourceMaps": true, - "outFiles": [ - "${workspaceFolder}/**/*.js" - ] - } - ] -} \ No newline at end of file + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "program": "${workspaceFolder}/bin/index.js", + "preLaunchTask": "build", + "console": "internalConsole", + "internalConsoleOptions": "openOnSessionStart", + "sourceMaps": true, + "outFiles": ["${workspaceFolder}/**/*.js"] + }, + { + "name": "Current TS File", + "type": "node", + "request": "launch", + "args": ["${relativeFile}"], + "runtimeArgs": ["--nolazy", "-r", "ts-node/register"], + "sourceMaps": true, + "cwd": "${workspaceRoot}", + "protocol": "inspector" + } + ] +} diff --git a/package-lock.json b/package-lock.json index 7b4c1ed..9c67a44 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,108 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@tensorflow/tfjs": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs/-/tfjs-2.6.0.tgz", + "integrity": "sha512-f70NAt480+/NH6ueAdKhwgN3BzeBWrvuAZ591pH44nuVlmUHtih7pSMVv2wREPOgA4ciAufops4FtTaqNamxZw==", + "requires": { + "@tensorflow/tfjs-backend-cpu": "2.6.0", + "@tensorflow/tfjs-backend-webgl": "2.6.0", + "@tensorflow/tfjs-converter": "2.6.0", + "@tensorflow/tfjs-core": "2.6.0", + "@tensorflow/tfjs-data": "2.6.0", + "@tensorflow/tfjs-layers": "2.6.0", + "argparse": "^1.0.10", + "chalk": "^4.1.0", + "core-js": "3", + "regenerator-runtime": "^0.13.5", + "yargs": "^16.0.3" + } + }, + "@tensorflow/tfjs-backend-cpu": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-2.6.0.tgz", + "integrity": "sha512-essk82VoET77tuFX5Sa9zv9F8d/2DxjEQ2RavoU+ugs0l64DTbdTpv3WdQwUihv1gNN7/16fUjJ6cG80SnS8/g==", + "requires": { + "@types/seedrandom": "2.4.27", + "seedrandom": "2.4.3" + } + }, + "@tensorflow/tfjs-backend-webgl": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-2.6.0.tgz", + "integrity": "sha512-j1eNYKIpO06CTSRXiIWdpZ2iPDBkx7PPl7K/1BtCEW/9FP7Q0q3doHKNmTdOPvuw7Dt1nNHEMnba0YB2lc5S7Q==", + "requires": { + "@tensorflow/tfjs-backend-cpu": "2.6.0", + "@types/offscreencanvas": "~2019.3.0", + "@types/seedrandom": "2.4.27", + "@types/webgl-ext": "0.0.30", + "@types/webgl2": "0.0.4", + "seedrandom": "2.4.3" + } + }, + "@tensorflow/tfjs-converter": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-converter/-/tfjs-converter-2.6.0.tgz", + "integrity": "sha512-TzL4ULidZ26iVqfLmv5G6dfnJyJt5HttU1VZoBYCbxUcWQYk1Z4D9wqLVwfdcJz01XEKpmsECh8HBF0hwYlrkA==" + }, + "@tensorflow/tfjs-core": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-core/-/tfjs-core-2.6.0.tgz", + "integrity": "sha512-akUB1iz663UCUdOfEUu91XeHzGpdYtdtMPxjsGEdF0CwENzSAcvHzQrEVoPBRD+RKpxrVXvQBoOd7GYBxMIIKQ==", + "requires": { + "@types/offscreencanvas": "~2019.3.0", + "@types/seedrandom": "2.4.27", + "@types/webgl-ext": "0.0.30", + "@types/webgl2": "0.0.4", + "node-fetch": "~2.6.1", + "seedrandom": "2.4.3" + } + }, + "@tensorflow/tfjs-data": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-data/-/tfjs-data-2.6.0.tgz", + "integrity": "sha512-/x/j/A4Quiyc21xEYyBC82mqyssbFHRuHez7pYVJA/28TOesAfWPWo2I+wkeOTt91UerUeZMSq2FV3HOnPInhQ==", + "requires": { + "@types/node-fetch": "^2.1.2", + "node-fetch": "~2.6.1" + } + }, + "@tensorflow/tfjs-layers": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-layers/-/tfjs-layers-2.6.0.tgz", + "integrity": "sha512-nU9WNSGpEU6GzKo5bvJBMa/OZRe1bR5Z2W6T0XiEY8CBiPNS+oJFJNm0NY8kQj/WnDS0Hfue38P46q7gV/9XMA==" + }, + "@tensorflow/tfjs-node": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-node/-/tfjs-node-2.6.0.tgz", + "integrity": "sha512-Yp1PICAVD3jBhqEShlzZHC9uOtT8axpFeciw8TeI4KxnIydWQOnrisI09z6uR7shCwNY4TM6txhpkO5b/RDyvw==", + "requires": { + "@tensorflow/tfjs": "2.6.0", + "@tensorflow/tfjs-core": "2.6.0", + "adm-zip": "^0.4.11", + "google-protobuf": "^3.9.2", + "https-proxy-agent": "^2.2.1", + "node-pre-gyp": "0.14.0", + "progress": "^2.0.0", + "rimraf": "^2.6.2", + "tar": "^4.4.6" + } + }, + "@types/node": { + "version": "14.14.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.6.tgz", + "integrity": "sha512-6QlRuqsQ/Ox/aJEQWBEJG7A9+u7oSYl3mem/K8IzxXG/kAGbV1YPD9Bg9Zw3vyxC/YP+zONKwy8hGkSt1jxFMw==" + }, + "@types/node-fetch": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", + "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, "@types/offscreencanvas": { "version": "2019.3.0", "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.3.0.tgz", @@ -19,11 +121,34 @@ "resolved": "https://registry.npmjs.org/@types/webgl-ext/-/webgl-ext-0.0.30.tgz", "integrity": "sha512-LKVgNmBxN0BbljJrVUwkxwRYqzsAEPcZOe6S2T6ZaBDIrFp0qu4FNlpc5sM1tGbXUYFgdVQIoeLk1Y1UoblyEg==" }, + "@types/webgl2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/webgl2/-/webgl2-0.0.4.tgz", + "integrity": "sha512-PACt1xdErJbMUOUweSrbVM7gSIYm1vTncW2hF6Os/EeWi6TXYAYMPp+8v6rzHmypE5gHrxaxZNXgMkJVIdZpHw==" + }, + "@vladmandic/face-api": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@vladmandic/face-api/-/face-api-0.8.8.tgz", + "integrity": "sha512-4bzHbswnoiLnRIrEuMMPH+qDRgqEaf+D2i5Tv3a4wjfZH3PUqHH3ziqq7jO2W4ImfDw0dm1UWUTx9CTpBbg++g==" + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, + "adm-zip": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", + "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==" + }, + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "requires": { + "es6-promisify": "^5.0.0" + } + }, "ansi-regex": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", @@ -51,6 +176,24 @@ "readable-stream": "^2.0.6" } }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -65,6 +208,11 @@ "concat-map": "0.0.1" } }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -99,11 +247,30 @@ } } }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, "chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, + "cliui": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.3.tgz", + "integrity": "sha512-Gj3QHTkVMPKqwP3f7B4KPkBZRMR9r4rfi5bXFpg1a+Svvj8l7q5CnkBkVQzfxT5DFSsGk2+PascOgL0JYkL2kw==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -122,6 +289,14 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -205,6 +380,11 @@ } } }, + "core-js": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.7.0.tgz", + "integrity": "sha512-NwS7fI5M5B85EwpWuIwJN4i/fbisQUwLwiSNUWeXlkAZ0sbBjLEvLvFLf1uzAUV66PcEPt4xCGCmOZSxVf3xzA==" + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -236,6 +416,11 @@ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -246,11 +431,34 @@ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, "face-api.js": { "version": "0.22.2", "resolved": "https://registry.npmjs.org/face-api.js/-/face-api.js-0.22.2.tgz", @@ -294,6 +502,16 @@ "path-exists": "^4.0.0" } }, + "form-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", + "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "fs-minipass": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", @@ -373,11 +591,30 @@ "path-is-absolute": "^1.0.0" } }, + "google-protobuf": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.13.0.tgz", + "integrity": "sha512-ZIf3qfLFayVrPvAjeKKxO5FRF1/NwRxt6Dko+fWEMuHwHbZx8/fcaAao9b0wCM6kr8qeg2te8XTpyuvKuD9aKw==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -431,6 +668,24 @@ "p-locate": "^4.1.0" } }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "requires": { + "mime-db": "1.44.0" + } + }, "mimic-response": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", @@ -494,12 +749,26 @@ "sax": "^1.2.4" } }, - "node-rtsp-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/node-rtsp-stream/-/node-rtsp-stream-0.0.9.tgz", - "integrity": "sha512-ynSkdHL4fuhctl1GeK890De7n8Dw+37D6IAZGrzsFSrd4TYho6neFQpMS1t0ZRDGsAegKh2p6kl1l9Vo3pJk8w==", + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + }, + "node-pre-gyp": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz", + "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==", "requires": { - "ws": "^7.0.0" + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" } }, "noms": { @@ -650,6 +919,11 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -675,6 +949,11 @@ "util-deprecate": "~1.0.1" } }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -761,6 +1040,25 @@ "simple-concat": "^1.0.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, "string-width": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", @@ -792,6 +1090,14 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, "tar": { "version": "4.4.13", "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", @@ -815,11 +1121,28 @@ "xtend": "~4.0.1" } }, + "ts-node": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.0.0.tgz", + "integrity": "sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg==", + "requires": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + } + }, "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, + "typescript": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz", + "integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==" + }, "untildify": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", @@ -872,25 +1195,59 @@ } } }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, - "ws": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", - "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==" - }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" }, + "y18n": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", + "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==" + }, "yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "yargs": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.1.0.tgz", + "integrity": "sha512-upWFJOmDdHN0syLuESuvXDmrRcWd1QafJolHskzaw79uZa7/x53gxQKiR07W59GWY1tFhhU/Th9DrtSfpS782g==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.2", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.3.tgz", + "integrity": "sha512-emOFRT9WVHw03QSvN5qor9QQT9+sw5vwxfYweivSMHTcAXPefwVae2FjO7JJjj8hCE4CzPOPeFM83VwT29HCww==" + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" } } } diff --git a/package.json b/package.json index 92b5830..c93e17e 100644 --- a/package.json +++ b/package.json @@ -19,10 +19,13 @@ "author": "Brandon Watson", "license": "ISC", "dependencies": { + "@tensorflow/tfjs": "^2.6.0", + "@tensorflow/tfjs-node": "^2.6.0", + "@vladmandic/face-api": "^0.8.8", "canvas": "^2.6.1", "copyfiles": "^2.4.0", - "face-api.js": "^0.22.2", - "node-rtsp-stream": "0.0.9", - "rtsp-stream": "file:../rtsp-stream" + "rtsp-stream": "file:../rtsp-stream", + "ts-node": "^9.0.0", + "typescript": "^4.0.5" } } diff --git a/scripts/train.ts b/scripts/train.ts new file mode 100644 index 0000000..a52bcd7 --- /dev/null +++ b/scripts/train.ts @@ -0,0 +1,87 @@ +import * as faceapi from "@vladmandic/face-api"; +import canvas from "canvas"; +import fs from "fs"; +import * as path from "path"; +import { TNetInput } from "@vladmandic/face-api"; +require("@tensorflow/tfjs-node"); + +const { Canvas, Image, ImageData } = canvas; +//@ts-ignore +faceapi.env.monkeyPatch({ Canvas, Image, ImageData }); + +const REFERENCE_IMAGE = + "/Users/brandonwatson/Documents/Git/Gitea/homebridge-face-location/images/brandon/IMG_1958.jpg"; +const QUERY_IMAGE = + "/Users/brandonwatson/Documents/Git/Gitea/homebridge-face-location/images/brandon/IMG_0001.JPG"; + +const main = async () => { + const faceDetectionNet = faceapi.nets.ssdMobilenetv1; + await faceDetectionNet.loadFromDisk(path.join(__dirname, "../weights")); + await faceapi.nets.faceLandmark68Net.loadFromDisk( + path.join(__dirname, "../weights") + ); + await faceapi.nets.faceRecognitionNet.loadFromDisk( + path.join(__dirname, "../weights") + ); + + const referenceImage = (await canvas.loadImage(REFERENCE_IMAGE)) as unknown; + const queryImage = (await canvas.loadImage(QUERY_IMAGE)) as unknown; + const options = getFaceDetectorOptions(faceDetectionNet); + + const resultsRef = await faceapi + .detectAllFaces(referenceImage as TNetInput, options) + .withFaceLandmarks() + .withFaceDescriptors(); + + const resultsQuery = await faceapi + .detectAllFaces(queryImage as TNetInput, options) + .withFaceLandmarks() + .withFaceDescriptors(); + + const faceMatcher = new faceapi.FaceMatcher(resultsRef); + + const labels = faceMatcher.labeledDescriptors.map((ld) => ld.label); + const refDrawBoxes = resultsRef + .map((res) => res.detection.box) + .map((box, i) => new faceapi.draw.DrawBox(box, { label: labels[i] })); + const outRef = faceapi.createCanvasFromMedia(referenceImage as ImageData); + refDrawBoxes.forEach((drawBox) => drawBox.draw(outRef)); + + saveFile("referenceImage.jpg", (outRef as any).toBuffer("image/jpeg")); + + const queryDrawBoxes = resultsQuery.map((res) => { + const bestMatch = faceMatcher.findBestMatch(res.descriptor); + return new faceapi.draw.DrawBox(res.detection.box, { + label: bestMatch.toString(), + }); + }); + const outQuery = faceapi.createCanvasFromMedia(queryImage as ImageData); + queryDrawBoxes.forEach((drawBox) => drawBox.draw(outQuery)); + saveFile("queryImage.jpg", (outQuery as any).toBuffer("image/jpeg")); + console.log("done, saved results to out/queryImage.jpg"); +}; + +// SsdMobilenetv1Options +const minConfidence = 0.5; + +// TinyFaceDetectorOptions +const inputSize = 408; +const scoreThreshold = 0.5; + +function getFaceDetectorOptions(net: faceapi.NeuralNetwork) { + return net === faceapi.nets.ssdMobilenetv1 + ? new faceapi.SsdMobilenetv1Options({ minConfidence }) + : new faceapi.TinyFaceDetectorOptions({ inputSize, scoreThreshold }); +} + +const baseDir = path.resolve(__dirname, "../out"); + +function saveFile(fileName: string, buf: Buffer) { + if (!fs.existsSync(baseDir)) { + fs.mkdirSync(baseDir); + } + + fs.writeFileSync(path.resolve(baseDir, fileName), buf); +} + +main(); diff --git a/resources/age_gender_model-shard1 b/weights/age_gender_model-shard1 similarity index 100% rename from resources/age_gender_model-shard1 rename to weights/age_gender_model-shard1 diff --git a/resources/age_gender_model-weights_manifest.json b/weights/age_gender_model-weights_manifest.json similarity index 100% rename from resources/age_gender_model-weights_manifest.json rename to weights/age_gender_model-weights_manifest.json diff --git a/resources/face_expression_model-shard1 b/weights/face_expression_model-shard1 similarity index 100% rename from resources/face_expression_model-shard1 rename to weights/face_expression_model-shard1 diff --git a/resources/face_expression_model-weights_manifest.json b/weights/face_expression_model-weights_manifest.json similarity index 100% rename from resources/face_expression_model-weights_manifest.json rename to weights/face_expression_model-weights_manifest.json diff --git a/resources/face_landmark_68_model-shard1 b/weights/face_landmark_68_model-shard1 similarity index 100% rename from resources/face_landmark_68_model-shard1 rename to weights/face_landmark_68_model-shard1 diff --git a/resources/face_landmark_68_model-weights_manifest.json b/weights/face_landmark_68_model-weights_manifest.json similarity index 100% rename from resources/face_landmark_68_model-weights_manifest.json rename to weights/face_landmark_68_model-weights_manifest.json diff --git a/resources/face_landmark_68_tiny_model-shard1 b/weights/face_landmark_68_tiny_model-shard1 similarity index 100% rename from resources/face_landmark_68_tiny_model-shard1 rename to weights/face_landmark_68_tiny_model-shard1 diff --git a/resources/face_landmark_68_tiny_model-weights_manifest.json b/weights/face_landmark_68_tiny_model-weights_manifest.json similarity index 100% rename from resources/face_landmark_68_tiny_model-weights_manifest.json rename to weights/face_landmark_68_tiny_model-weights_manifest.json diff --git a/resources/face_recognition_model-shard1 b/weights/face_recognition_model-shard1 similarity index 100% rename from resources/face_recognition_model-shard1 rename to weights/face_recognition_model-shard1 diff --git a/resources/face_recognition_model-shard2 b/weights/face_recognition_model-shard2 similarity index 100% rename from resources/face_recognition_model-shard2 rename to weights/face_recognition_model-shard2 diff --git a/resources/face_recognition_model-weights_manifest.json b/weights/face_recognition_model-weights_manifest.json similarity index 100% rename from resources/face_recognition_model-weights_manifest.json rename to weights/face_recognition_model-weights_manifest.json diff --git a/resources/mtcnn_model-shard1 b/weights/mtcnn_model-shard1 similarity index 100% rename from resources/mtcnn_model-shard1 rename to weights/mtcnn_model-shard1 diff --git a/resources/mtcnn_model-weights_manifest.json b/weights/mtcnn_model-weights_manifest.json similarity index 100% rename from resources/mtcnn_model-weights_manifest.json rename to weights/mtcnn_model-weights_manifest.json diff --git a/resources/ssd_mobilenetv1_model-shard1 b/weights/ssd_mobilenetv1_model-shard1 similarity index 100% rename from resources/ssd_mobilenetv1_model-shard1 rename to weights/ssd_mobilenetv1_model-shard1 diff --git a/resources/ssd_mobilenetv1_model-shard2 b/weights/ssd_mobilenetv1_model-shard2 similarity index 100% rename from resources/ssd_mobilenetv1_model-shard2 rename to weights/ssd_mobilenetv1_model-shard2 diff --git a/resources/ssd_mobilenetv1_model-weights_manifest.json b/weights/ssd_mobilenetv1_model-weights_manifest.json similarity index 100% rename from resources/ssd_mobilenetv1_model-weights_manifest.json rename to weights/ssd_mobilenetv1_model-weights_manifest.json diff --git a/resources/tiny_face_detector_model-shard1 b/weights/tiny_face_detector_model-shard1 similarity index 100% rename from resources/tiny_face_detector_model-shard1 rename to weights/tiny_face_detector_model-shard1 diff --git a/resources/tiny_face_detector_model-weights_manifest.json b/weights/tiny_face_detector_model-weights_manifest.json similarity index 100% rename from resources/tiny_face_detector_model-weights_manifest.json rename to weights/tiny_face_detector_model-weights_manifest.json