diff --git a/CHANGELOG.md b/CHANGELOG.md
index 41b1b5d..4066eee 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,7 +9,7 @@
## Changelog
-### **HEAD -> master** 2022/08/16 mandic00@live.com
+### **HEAD -> master** 2022/08/22 mandic00@live.com
### **release: 1.7.1** 2022/07/25 mandic00@live.com
diff --git a/demo/index.js b/demo/index.js
index 4c03ae8..3732dd3 100644
--- a/demo/index.js
+++ b/demo/index.js
@@ -1,8 +1,14 @@
-import * as faceapi from '../dist/face-api.esm.js';
+/**
+ * FaceAPI Demo for Browsers
+ * Loaded via `index.html`
+ */
+
+import * as faceapi from '../dist/face-api.esm.js'; // use when in dev mode
+// import * as faceapi from '@vladmandic/face-api'; // use when downloading face-api as npm
// configuration options
const modelPath = '../model/'; // path to model folder that will be loaded using http
-// const modelPath = 'https://vladmandic.github.io/face-api/model/'; // path to model folder that will be loaded using http
+// const modelPath = 'https://cdn.jsdelivr.net/npm/@vladmandic/face-api/model/'; // path to model folder that will be loaded using http
const imgSize = 800; // maximum image size in pixels
const minScore = 0.3; // minimum score
const maxResults = 10; // maximum number of results to return
@@ -13,8 +19,7 @@ const str = (json) => (json ? JSON.stringify(json).replace(/{|}|"|\[|\]/g, '').r
// helper function to print strings to html document as a log
function log(...txt) {
- // eslint-disable-next-line no-console
- console.log(...txt);
+ console.log(...txt); // eslint-disable-line no-console
const div = document.getElementById('log');
if (div) div.innerHTML += `
${txt}`;
}
@@ -67,8 +72,7 @@ function faces(name, title, id, data) {
// helper function to draw processed image and its results
function print(title, img, data) {
- // eslint-disable-next-line no-console
- console.log('Results:', title, img, data);
+ console.log('Results:', title, img, data); // eslint-disable-line no-console
const el = new Image();
el.id = Math.floor(Math.random() * 100000).toString();
el.src = img;
@@ -174,8 +178,7 @@ async function main() {
print('SSDMobileNet:', img, dataSSDMobileNet);
} catch (err) {
log(`Image: ${img} Error during processing ${str(err)}`);
- // eslint-disable-next-line no-console
- console.error(err);
+ console.error(err); // eslint-disable-line no-console
}
}
}
diff --git a/demo/node-canvas.js b/demo/node-canvas.js
index a8604cd..6f49050 100644
--- a/demo/node-canvas.js
+++ b/demo/node-canvas.js
@@ -1,13 +1,20 @@
+/**
+ * FaceAPI Demo for NodeJS
+ * - Uses external library [canvas](https://www.npmjs.com/package/canvas) to decode image
+ * - Loads image from provided param
+ * - Outputs results to console
+ */
+
+// canvas library provides full canvas (load/draw/write) functionality for nodejs
+// must be installed manually as it just a demo dependency and not actual face-api dependency
+const canvas = require('canvas'); // eslint-disable-line node/no-missing-require
const fs = require('fs');
const path = require('path');
const process = require('process');
const log = require('@vladmandic/pilogger');
-const canvas = require('canvas');
-
-// eslint-disable-next-line import/no-extraneous-dependencies, no-unused-vars, @typescript-eslint/no-unused-vars
const tf = require('@tensorflow/tfjs-node'); // in nodejs environments tfjs-node is required to be loaded before face-api
-// const faceapi = require('@vladmandic/face-api'); // use this when face-api is installed as module (majority of use cases)
const faceapi = require('../dist/face-api.node.js'); // use this when using face-api in dev mode
+// const faceapi = require('@vladmandic/face-api'); // use this when face-api is installed as module (majority of use cases)
const modelPathRoot = '../model';
const imgPathRoot = './demo'; // modify to include your sample images
@@ -50,11 +57,9 @@ async function main() {
faceapi.env.monkeyPatch({ Canvas: canvas.Canvas, Image: canvas.Image, ImageData: canvas.ImageData });
await faceapi.tf.setBackend('tensorflow');
- await faceapi.tf.enableProdMode();
- await faceapi.tf.ENV.set('DEBUG', false);
await faceapi.tf.ready();
- log.state(`Version: TensorFlow/JS ${faceapi.tf?.version_core} FaceAPI ${faceapi.version} Backend: ${faceapi.tf?.getBackend()}`);
+ log.state(`Version: FaceAPI ${faceapi.version} TensorFlow/JS ${tf.version_core} Backend: ${faceapi.tf?.getBackend()}`);
log.info('Loading FaceAPI models');
const modelPath = path.join(__dirname, modelPathRoot);
diff --git a/demo/node-image.js b/demo/node-image.js
index 7114a0e..6817a24 100644
--- a/demo/node-image.js
+++ b/demo/node-image.js
@@ -1,12 +1,18 @@
-const fs = require('fs');
-// eslint-disable-next-line import/no-extraneous-dependencies, node/no-unpublished-require
-const image = require('@canvas/image'); // @canvas/image can decode jpeg, png, webp
-const log = require('@vladmandic/pilogger');
+/**
+ * FaceAPI Demo for NodeJS
+ * - Uses external library [@canvas/image](https://www.npmjs.com/package/@canvas/image) to decode image
+ * - Loads image from provided param
+ * - Outputs results to console
+ */
-// eslint-disable-next-line import/no-extraneous-dependencies, no-unused-vars, @typescript-eslint/no-unused-vars
+// @canvas/image can decode jpeg, png, webp
+// must be installed manually as it just a demo dependency and not actual face-api dependency
+const image = require('@canvas/image'); // eslint-disable-line node/no-missing-require
+const fs = require('fs');
+const log = require('@vladmandic/pilogger');
const tf = require('@tensorflow/tfjs-node'); // in nodejs environments tfjs-node is required to be loaded before face-api
-// const faceapi = require('@vladmandic/face-api'); // use this when face-api is installed as module (majority of use cases)
const faceapi = require('../dist/face-api.node.js'); // use this when using face-api in dev mode
+// const faceapi = require('@vladmandic/face-api'); // use this when face-api is installed as module (majority of use cases)
const modelPath = 'model/';
const imageFile = 'demo/sample1.jpg';
diff --git a/demo/node-match.js b/demo/node-match.js
index 6629df1..8f5df87 100644
--- a/demo/node-match.js
+++ b/demo/node-match.js
@@ -1,11 +1,16 @@
+/**
+ * FaceAPI Demo for NodeJS
+ * - Analyzes face descriptors from source (image file or folder containing multiple image files)
+ * - Analyzes face descriptor from target
+ * - Finds best match
+ */
+
const fs = require('fs');
const path = require('path');
const log = require('@vladmandic/pilogger');
-
-// eslint-disable-next-line import/no-extraneous-dependencies, no-unused-vars, @typescript-eslint/no-unused-vars
const tf = require('@tensorflow/tfjs-node'); // in nodejs environments tfjs-node is required to be loaded before face-api
-// const faceapi = require('@vladmandic/face-api'); // use this when face-api is installed as module (majority of use cases)
const faceapi = require('../dist/face-api.node.js'); // use this when using face-api in dev mode
+// const faceapi = require('@vladmandic/face-api'); // use this when face-api is installed as module (majority of use cases)
let optionsSSDMobileNet;
const minConfidence = 0.1;
@@ -33,6 +38,8 @@ async function getDescriptors(imageFile) {
}
async function registerImage(inputFile) {
+ if (!inputFile.toLowerCase().endsWith('jpg') && !inputFile.toLowerCase().endsWith('png') && !inputFile.toLowerCase().endsWith('gif')) return;
+ log.data('Registered:', inputFile);
const descriptors = await getDescriptors(inputFile);
for (const descriptor of descriptors) {
const labeledFaceDescriptor = new faceapi.LabeledFaceDescriptors(inputFile, [descriptor]);
@@ -60,14 +67,18 @@ async function main() {
await initFaceAPI();
log.info('Input:', process.argv[2]);
if (fs.statSync(process.argv[2]).isFile()) {
- await registerImage(process.argv[2]);
+ await registerImage(process.argv[2]); // register image
} else if (fs.statSync(process.argv[2]).isDirectory()) {
const dir = fs.readdirSync(process.argv[2]);
- for (const f of dir) await registerImage(path.join(process.argv[2], f));
+ for (const f of dir) await registerImage(path.join(process.argv[2], f)); // register all images in a folder
+ }
+ log.info('Comparing:', process.argv[3], 'Descriptors:', labeledFaceDescriptors.length);
+ if (labeledFaceDescriptors.length > 0) {
+ const bestMatch = await findBestMatch(process.argv[3]); // find best match to all registered images
+ log.data('Match:', bestMatch);
+ } else {
+ log.warn('No registered faces');
}
- log.info('Descriptors:', labeledFaceDescriptors.length);
- const bestMatch = await findBestMatch(process.argv[3]);
- log.data('Match:', bestMatch);
}
main();
diff --git a/demo/node-multiprocess-worker.js b/demo/node-multiprocess-worker.js
index 0837686..e72532d 100644
--- a/demo/node-multiprocess-worker.js
+++ b/demo/node-multiprocess-worker.js
@@ -1,14 +1,16 @@
-// @ts-nocheck
+/**
+ * FaceAPI Demo for NodeJS
+ * - Used by `node-multiprocess.js`
+ */
const fs = require('fs');
const path = require('path');
const log = require('@vladmandic/pilogger');
// workers actual import tfjs and faceapi modules
-// eslint-disable-next-line import/no-extraneous-dependencies, no-unused-vars, @typescript-eslint/no-unused-vars
const tf = require('@tensorflow/tfjs-node'); // in nodejs environments tfjs-node is required to be loaded before face-api
-// const faceapi = require('@vladmandic/face-api'); // use this when face-api is installed as module (majority of use cases)
const faceapi = require('../dist/face-api.node.js'); // use this when using face-api in dev mode
+// const faceapi = require('@vladmandic/face-api'); // use this when face-api is installed as module (majority of use cases)
// options used by faceapi
const modelPathRoot = '../model';
diff --git a/demo/node-multiprocess.js b/demo/node-multiprocess.js
index a8e2924..6e45cfe 100644
--- a/demo/node-multiprocess.js
+++ b/demo/node-multiprocess.js
@@ -1,3 +1,9 @@
+/**
+ * FaceAPI Demo for NodeJS
+ * - Starts multiple worker processes and uses them as worker pool to process all input images
+ * - Images are enumerated in main process and sent for processing to worker processes via ipc
+ */
+
const fs = require('fs');
const path = require('path');
const log = require('@vladmandic/pilogger'); // this is my simple logger with few extra features
diff --git a/demo/node-simple.js b/demo/node-simple.js
index b9591d2..3d66237 100644
--- a/demo/node-simple.js
+++ b/demo/node-simple.js
@@ -1,7 +1,13 @@
+/**
+ * FaceAPI Demo for NodeJS
+ * - Loads image
+ * - Outputs results to console
+ */
+
const fs = require('fs');
-// const faceapi = require('@vladmandic/face-api'); // use this when face-api is installed as module (majority of use cases)
const faceapi = require('../dist/face-api.node.js'); // use this when using face-api in dev mode
+// const faceapi = require('@vladmandic/face-api'); // use this when face-api is installed as module (majority of use cases)
async function main() {
await faceapi.nets.ssdMobilenetv1.loadFromDisk('model'); // load models from a specific patch
@@ -19,8 +25,7 @@ async function main() {
.withFaceDescriptors()
.withAgeAndGender();
faceapi.tf.dispose([decodeT, expandT]); // dispose tensors to avoid memory leaks
- // eslint-disable-next-line no-console
- console.log({ result }); // print results
+ console.log({ result }); // eslint-disable-line no-console
}
main();
diff --git a/demo/node.js b/demo/node.js
index 099f86b..ff85248 100644
--- a/demo/node.js
+++ b/demo/node.js
@@ -1,12 +1,18 @@
+/**
+ * FaceAPI Demo for NodeJS
+ * - Uses external library [node-fetch](https://www.npmjs.com/package/node-fetch) to load images via http
+ * - Loads image from provided param
+ * - Outputs results to console
+ */
+
const fs = require('fs');
const process = require('process');
const path = require('path');
const log = require('@vladmandic/pilogger');
-// eslint-disable-next-line import/no-extraneous-dependencies, no-unused-vars, @typescript-eslint/no-unused-vars
const tf = require('@tensorflow/tfjs-node'); // in nodejs environments tfjs-node is required to be loaded before face-api
-// const faceapi = require('@vladmandic/face-api'); // use this when face-api is installed as module (majority of use cases)
const faceapi = require('../dist/face-api.node.js'); // use this when using face-api in dev mode
+// const faceapi = require('@vladmandic/face-api'); // use this when face-api is installed as module (majority of use cases)
const modelPathRoot = '../model';
const imgPathRoot = './demo'; // modify to include your sample images
@@ -87,11 +93,9 @@ async function main() {
log.header();
log.info('FaceAPI single-process test');
- fetch = (await import('node-fetch')).default;
+ fetch = (await import('node-fetch')).default; // eslint-disable-line node/no-missing-import
await faceapi.tf.setBackend('tensorflow');
- await faceapi.tf.enableProdMode();
- await faceapi.tf.ENV.set('DEBUG', false);
await faceapi.tf.ready();
log.state(`Version: TensorFlow/JS ${faceapi.tf?.version_core} FaceAPI ${faceapi.version} Backend: ${faceapi.tf?.getBackend()}`);
diff --git a/demo/webcam.js b/demo/webcam.js
index 9c8aa27..f2dad27 100644
--- a/demo/webcam.js
+++ b/demo/webcam.js
@@ -1,8 +1,14 @@
-import * as faceapi from '../dist/face-api.esm.js';
+/**
+ * FaceAPI Demo for Browsers
+ * Loaded via `webcam.html`
+ */
+
+import * as faceapi from '../dist/face-api.esm.js'; // use when in dev mode
+// import * as faceapi from '@vladmandic/face-api'; // use when downloading face-api as npm
// configuration options
const modelPath = '../model/'; // path to model folder that will be loaded using http
-// const modelPath = 'https://vladmandic.github.io/face-api/model/'; // path to model folder that will be loaded using http
+// const modelPath = 'https://cdn.jsdelivr.net/npm/@vladmandic/face-api/model/'; // path to model folder that will be loaded using http
const minScore = 0.2; // minimum score
const maxResults = 5; // maximum number of results to return
let optionsSSDMobileNet;
@@ -17,8 +23,7 @@ function str(json) {
// helper function to print strings to html document as a log
function log(...txt) {
- // eslint-disable-next-line no-console
- console.log(...txt);
+ console.log(...txt); // eslint-disable-line no-console
const div = document.getElementById('log');
if (div) div.innerHTML += `
${txt}`;
}
diff --git a/package.json b/package.json
index 0b63a02..03ecd2d 100644
--- a/package.json
+++ b/package.json
@@ -41,11 +41,6 @@
"tensorflowjs",
"tfjs"
],
- "optionalDependencies": {
- "@canvas/image": "^1.0.1",
- "canvas": "^2.9.3",
- "node-fetch": "^3.2.10"
- },
"devDependencies": {
"@microsoft/api-extractor": "^7.29.3",
"@tensorflow/tfjs": "^3.19.0",
@@ -59,10 +54,10 @@
"@tensorflow/tfjs-layers": "^3.19.0",
"@tensorflow/tfjs-node": "^3.19.0",
"@tensorflow/tfjs-node-gpu": "^3.19.0",
- "@types/node": "^18.7.9",
+ "@types/node": "^18.7.11",
"@types/offscreencanvas": "^2019.7.0",
- "@typescript-eslint/eslint-plugin": "^5.33.1",
- "@typescript-eslint/parser": "^5.33.1",
+ "@typescript-eslint/eslint-plugin": "^5.34.0",
+ "@typescript-eslint/parser": "^5.34.0",
"@vladmandic/build": "^0.7.10",
"@vladmandic/pilogger": "^0.4.6",
"@vladmandic/tfjs": "github:vladmandic/tfjs",
diff --git a/src/tfjs/tf-node-cpu.ts b/src/tfjs/tf-node-cpu.ts
index 3e4088d..4675a7c 100644
--- a/src/tfjs/tf-node-cpu.ts
+++ b/src/tfjs/tf-node-cpu.ts
@@ -1,4 +1 @@
-/* eslint-disable import/no-extraneous-dependencies */
-/* eslint-disable node/no-unpublished-import */
-
export * from '@tensorflow/tfjs';
diff --git a/src/tfjs/tf-node-gpu.ts b/src/tfjs/tf-node-gpu.ts
index 407d486..68781c3 100644
--- a/src/tfjs/tf-node-gpu.ts
+++ b/src/tfjs/tf-node-gpu.ts
@@ -1,4 +1 @@
-/* eslint-disable import/no-extraneous-dependencies */
-/* eslint-disable node/no-unpublished-import */
-
export * from '@tensorflow/tfjs-node-gpu';
diff --git a/src/tfjs/tf-node-wasm.ts b/src/tfjs/tf-node-wasm.ts
index 5be902b..79e5f49 100644
--- a/src/tfjs/tf-node-wasm.ts
+++ b/src/tfjs/tf-node-wasm.ts
@@ -1,5 +1,2 @@
-/* eslint-disable import/no-extraneous-dependencies */
-/* eslint-disable node/no-unpublished-import */
-
export * from '@tensorflow/tfjs';
export * from '@tensorflow/tfjs-backend-wasm';
diff --git a/src/tfjs/tf-node.ts b/src/tfjs/tf-node.ts
index 1df0c5d..c752d1b 100644
--- a/src/tfjs/tf-node.ts
+++ b/src/tfjs/tf-node.ts
@@ -1,4 +1 @@
-/* eslint-disable import/no-extraneous-dependencies */
-/* eslint-disable node/no-unpublished-import */
-
export * from '@tensorflow/tfjs-node';
diff --git a/test/test-node.js b/test/test-node.js
index 62b3643..10bf569 100644
--- a/test/test-node.js
+++ b/test/test-node.js
@@ -1,8 +1,6 @@
const fs = require('fs');
const path = require('path');
-// eslint-disable-next-line import/no-extraneous-dependencies, node/no-unpublished-require
const log = require('@vladmandic/pilogger');
-// eslint-disable-next-line import/no-extraneous-dependencies, node/no-unpublished-require
const tf = require('@tensorflow/tfjs-node');
const faceapi = require('../dist/face-api.node.js'); // this is equivalent to '@vladmandic/faceapi'