accept uri as input to demo node and node-canvas
parent
1410be346a
commit
b8830e8cd3
|
@ -22,6 +22,9 @@ async function image(input) {
|
|||
const c = canvas.createCanvas(img.width, img.height);
|
||||
const ctx = c.getContext('2d');
|
||||
ctx.drawImage(img, 0, 0, img.width, img.height);
|
||||
// const out = fs.createWriteStream('test.jpg');
|
||||
// const stream = c.createJPEGStream({ quality: 0.6, progressive: true, chromaSubsampling: true });
|
||||
// stream.pipe(out);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
@ -80,7 +83,7 @@ async function main() {
|
|||
log.info('Processed', numImages, 'images in', Math.trunc(parseInt(t1 - t0) / 1000 / 1000), 'ms');
|
||||
} else {
|
||||
const param = process.argv[2];
|
||||
if (fs.existsSync(param)) {
|
||||
if (fs.existsSync(param) || param.startsWith('http:') || param.startsWith('https:')) {
|
||||
const c = await image(param);
|
||||
const result = await detect(c);
|
||||
log.data('Image:', param, 'Detected faces:', result.length);
|
||||
|
|
41
demo/node.js
41
demo/node.js
|
@ -6,6 +6,8 @@ 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 fetch = require('node-fetch').default;
|
||||
// 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'
|
||||
|
||||
|
@ -15,14 +17,35 @@ const minConfidence = 0.15;
|
|||
const maxResults = 5;
|
||||
let optionsSSDMobileNet;
|
||||
|
||||
async function image(img) {
|
||||
const buffer = fs.readFileSync(img);
|
||||
const decoded = tf.node.decodeImage(buffer);
|
||||
const casted = decoded.toFloat();
|
||||
const result = casted.expandDims(0);
|
||||
decoded.dispose();
|
||||
casted.dispose();
|
||||
return result;
|
||||
async function image(input) {
|
||||
// read input image file and create tensor to be used for processing
|
||||
let buffer;
|
||||
log.info('Loading image:', input);
|
||||
if (input.startsWith('http:') || input.startsWith('https:')) {
|
||||
const res = await fetch(input);
|
||||
if (res && res.ok) buffer = await res.buffer();
|
||||
else log.error('Invalid image URL:', input, res.status, res.statusText, res.headers.get('content-type'));
|
||||
} else {
|
||||
buffer = fs.readFileSync(input);
|
||||
}
|
||||
|
||||
// decode image using tfjs-node so we don't need external depenencies
|
||||
// can also be done using canvas.js or some other 3rd party image library
|
||||
if (!buffer) return {};
|
||||
const tensor = tf.tidy(() => {
|
||||
const decode = faceapi.tf.node.decodeImage(buffer, 3);
|
||||
let expand;
|
||||
if (decode.shape[2] === 4) { // input is in rgba format, need to convert to rgb
|
||||
const channels = faceapi.tf.split(decode, 4, 2); // tf.split(tensor, 4, 2); // split rgba to channels
|
||||
const rgb = faceapi.tf.stack([channels[0], channels[1], channels[2]], 2); // stack channels back to rgb and ignore alpha
|
||||
expand = faceapi.tf.reshape(rgb, [1, decode.shape[0], decode.shape[1], 3]); // move extra dim from the end of tensor and use it as batch number instead
|
||||
} else {
|
||||
expand = faceapi.tf.expandDims(decode, 0);
|
||||
}
|
||||
const cast = faceapi.tf.cast(expand, 'float32');
|
||||
return cast;
|
||||
});
|
||||
return tensor;
|
||||
}
|
||||
|
||||
async function detect(tensor) {
|
||||
|
@ -97,7 +120,7 @@ async function main() {
|
|||
log.info('Processed', dir.length, 'images in', Math.trunc(parseInt(t1 - t0) / 1000 / 1000), 'ms');
|
||||
} else {
|
||||
const param = process.argv[2];
|
||||
if (fs.existsSync(param)) {
|
||||
if (fs.existsSync(param) || param.startsWith('http:') || param.startsWith('https:')) {
|
||||
const tensor = await image(param);
|
||||
const result = await detect(tensor);
|
||||
// const result = await detectPromise(null);
|
||||
|
|
|
@ -53,18 +53,19 @@
|
|||
"canvas": "^2.7.0",
|
||||
"chokidar": "^3.5.1",
|
||||
"dayjs": "^1.10.4",
|
||||
"esbuild": "^0.11.12",
|
||||
"eslint": "^7.24.0",
|
||||
"esbuild": "^0.11.14",
|
||||
"eslint": "^7.25.0",
|
||||
"eslint-config-airbnb-base": "^14.2.1",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-json": "^2.1.2",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^5.1.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"seedrandom": "^3.0.5",
|
||||
"simple-git": "^2.38.0",
|
||||
"tslib": "^2.2.0",
|
||||
"typedoc": "^0.20.35",
|
||||
"typedoc": "^0.20.36",
|
||||
"typescript": "^4.2.4"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue