added filter.flip feature

pull/134/head
Vladimir Mandic 2021-04-19 16:02:47 -04:00
parent 4730e3f542
commit bcaed8c06d
19 changed files with 376817 additions and 5006 deletions

View File

@ -7,31 +7,32 @@ import Menu from './helpers/menu.js';
import GLBench from './helpers/gl-bench.js'; import GLBench from './helpers/gl-bench.js';
import webRTC from './helpers/webrtc.js'; import webRTC from './helpers/webrtc.js';
const userConfig = { backend: 'webgl' }; // add any user configuration overrides // const userConfig = { backend: 'webgl' }; // add any user configuration overrides
let human; let human;
/*
const userConfig = { const userConfig = {
backend: 'humangl', backend: 'humangl',
async: false, async: false,
profile: false, profile: false,
warmup: 'full', warmup: 'full',
videoOptimized: false, videoOptimized: false,
filter: { enabled: false }, filter: {
face: { enabled: false, enabled: true,
flip: true,
},
face: { enabled: true,
mesh: { enabled: true }, mesh: { enabled: true },
iris: { enabled: true }, iris: { enabled: true },
description: { enabled: true }, description: { enabled: false },
emotion: { enabled: true }, emotion: { enabled: false },
}, },
hand: { enabled: false }, hand: { enabled: false },
gesture: { enabled: false }, gesture: { enabled: true },
body: { enabled: false }, body: { enabled: false },
// body: { enabled: true, modelPath: 'blazepose.json' }, // body: { enabled: true, modelPath: 'blazepose.json' },
// body: { enabled: true, modelPath: 'efficientpose.json' }, // body: { enabled: true, modelPath: 'efficientpose.json' },
object: { enabled: true }, // object: { enabled: true },
}; };
*/
// ui options // ui options
const ui = { const ui = {

View File

@ -17,6 +17,10 @@ const myConfig = {
debug: true, debug: true,
videoOptimized: false, videoOptimized: false,
async: false, async: false,
filter: {
enabled: true,
flip: true,
},
face: { face: {
enabled: true, enabled: true,
detector: { enabled: true, rotation: false }, detector: { enabled: true, rotation: false },
@ -52,7 +56,7 @@ async function detect(input) {
// read input image file and create tensor to be used for processing // read input image file and create tensor to be used for processing
let buffer; let buffer;
log.info('Loading image:', input); log.info('Loading image:', input);
if (input.startsWith('http')) { if (input.startsWith('http:') || input.startsWith('https:')) {
const res = await fetch(input); const res = await fetch(input);
if (res && res.ok) buffer = await res.buffer(); 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 log.error('Invalid image URL:', input, res.status, res.statusText, res.headers.get('content-type'));
@ -62,6 +66,7 @@ async function detect(input) {
// decode image using tfjs-node so we don't need external depenencies // 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 // can also be done using canvas.js or some other 3rd party image library
if (!buffer) return {};
const decoded = human.tf.node.decodeImage(buffer); const decoded = human.tf.node.decodeImage(buffer);
const casted = decoded.toFloat(); const casted = decoded.toFloat();
const tensor = casted.expandDims(0); const tensor = casted.expandDims(0);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

100591
dist/human.esm.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

100617
dist/human.js vendored

File diff suppressed because one or more lines are too long

4
dist/human.js.map vendored

File diff suppressed because one or more lines are too long

25723
dist/human.node-gpu.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

25724
dist/human.node-wasm.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

25723
dist/human.node.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

77677
dist/tfjs.esm.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -55,6 +55,8 @@ export interface Config {
height: number, height: number,
/** Return processed canvas imagedata in result */ /** Return processed canvas imagedata in result */
return: boolean, return: boolean,
/** Flip input as mirror image */
flip: boolean,
/** Range: -1 (darken) to 1 (lighten) */ /** Range: -1 (darken) to 1 (lighten) */
brightness: number, brightness: number,
/** Range: -1 (reduce contrast) to 1 (increase contrast) */ /** Range: -1 (reduce contrast) to 1 (increase contrast) */
@ -82,6 +84,8 @@ export interface Config {
/** Range: 0 (no pixelate) to N (number of pixels to pixelate) */ /** Range: 0 (no pixelate) to N (number of pixels to pixelate) */
pixelate: number, pixelate: number,
}, },
// type definition end
/** Controlls gesture detection */ /** Controlls gesture detection */
gesture: { gesture: {
enabled: boolean, enabled: boolean,
@ -250,6 +254,7 @@ const config: Config = {
// if both width and height are set to 0, there is no resizing // if both width and height are set to 0, there is no resizing
// if just one is set, second one is scaled automatically // if just one is set, second one is scaled automatically
// if both are set, values are used as-is // if both are set, values are used as-is
flip: false, // flip input as mirror image
return: true, // return processed canvas imagedata in result return: true, // return processed canvas imagedata in result
brightness: 0, // range: -1 (darken) to 1 (lighten) brightness: 0, // range: -1 (darken) to 1 (lighten)
contrast: 0, // range: -1 (reduce contrast) to 1 (increase contrast) contrast: 0, // range: -1 (reduce contrast) to 1 (increase contrast)

View File

@ -25,7 +25,7 @@ export const face = (res) => {
if (res[i].mesh && res[i].mesh.length > 0) { if (res[i].mesh && res[i].mesh.length > 0) {
const eyeFacing = res[i].mesh[33][2] - res[i].mesh[263][2]; const eyeFacing = res[i].mesh[33][2] - res[i].mesh[263][2];
if (Math.abs(eyeFacing) < 10) gestures.push({ face: i, gesture: 'facing center' }); if (Math.abs(eyeFacing) < 10) gestures.push({ face: i, gesture: 'facing center' });
else gestures.push({ face: i, gesture: `facing ${eyeFacing < 0 ? 'right' : 'left'}` }); else gestures.push({ face: i, gesture: `facing ${eyeFacing < 0 ? 'left' : 'right'}` });
const openLeft = Math.abs(res[i].mesh[374][1] - res[i].mesh[386][1]) / Math.abs(res[i].mesh[443][1] - res[i].mesh[450][1]); // center of eye inner lid y coord div center of wider eye border y coord const openLeft = Math.abs(res[i].mesh[374][1] - res[i].mesh[386][1]) / Math.abs(res[i].mesh[443][1] - res[i].mesh[450][1]); // center of eye inner lid y coord div center of wider eye border y coord
if (openLeft < 0.2) gestures.push({ face: i, gesture: 'blink left eye' }); if (openLeft < 0.2) gestures.push({ face: i, gesture: 'blink left eye' });
const openRight = Math.abs(res[i].mesh[145][1] - res[i].mesh[159][1]) / Math.abs(res[i].mesh[223][1] - res[i].mesh[230][1]); // center of eye inner lid y coord div center of wider eye border y coord const openRight = Math.abs(res[i].mesh[145][1] - res[i].mesh[159][1]) / Math.abs(res[i].mesh[223][1] - res[i].mesh[230][1]); // center of eye inner lid y coord div center of wider eye border y coord

View File

@ -53,9 +53,21 @@ export function process(input, config): { tensor: typeof tf.Tensor | null, canva
if (inCanvas?.width !== targetWidth) inCanvas.width = targetWidth; if (inCanvas?.width !== targetWidth) inCanvas.width = targetWidth;
if (inCanvas?.height !== targetHeight) inCanvas.height = targetHeight; if (inCanvas?.height !== targetHeight) inCanvas.height = targetHeight;
} }
const ctx = inCanvas.getContext('2d'); const ctx = inCanvas.getContext('2d');
if (input instanceof ImageData) ctx.putImageData(input, 0, 0); if (input instanceof ImageData) {
else ctx.drawImage(input, 0, 0, originalWidth, originalHeight, 0, 0, inCanvas?.width, inCanvas?.height); ctx.putImageData(input, 0, 0);
} else {
if (!config.filter.flip) {
ctx.drawImage(input, 0, 0, originalWidth, originalHeight, 0, 0, inCanvas?.width, inCanvas?.height);
} else {
ctx.translate(originalWidth, 0);
ctx.scale(-1, 1);
ctx.drawImage(input, 0, 0, originalWidth, originalHeight, 0, 0, inCanvas?.width, inCanvas?.height);
ctx.setTransform(1, 0, 0, 1, 0, 0);
}
}
if (config.filter.enabled) { if (config.filter.enabled) {
if (!fx || !outCanvas || (inCanvas.width !== outCanvas.width) || (inCanvas?.height !== outCanvas?.height)) { if (!fx || !outCanvas || (inCanvas.width !== outCanvas.width) || (inCanvas?.height !== outCanvas?.height)) {
outCanvas = (typeof OffscreenCanvas !== 'undefined') ? new OffscreenCanvas(inCanvas?.width, inCanvas?.height) : document.createElement('canvas'); outCanvas = (typeof OffscreenCanvas !== 'undefined') ? new OffscreenCanvas(inCanvas?.width, inCanvas?.height) : document.createElement('canvas');