2021-09-20 15:42:34 +02:00
const fs = require ( 'fs' ) ;
2021-04-14 18:53:00 +02:00
const process = require ( 'process' ) ;
const canvasJS = require ( 'canvas' ) ;
2021-08-31 19:29:29 +02:00
let fetch ; // fetch is dynamically imported later
2021-04-14 18:53:00 +02:00
let config ;
2021-04-15 15:43:55 +02:00
const log = ( status , ... data ) => {
2021-04-15 23:13:27 +02:00
if ( typeof process . send !== 'undefined' ) process . send ( [ status , data ] ) ; // send to parent process over ipc
// eslint-disable-next-line no-console
else console . log ( status , ... data ) ; // write to console if no parent process
2021-04-15 15:43:55 +02:00
} ;
2021-04-14 18:53:00 +02:00
async function testHTTP ( ) {
if ( config . modelBasePath . startsWith ( 'file:' ) ) return true ;
return new Promise ( ( resolve ) => {
fetch ( config . modelBasePath )
. then ( ( res ) => {
2021-04-15 15:43:55 +02:00
if ( res && res . ok ) log ( 'state' , 'passed: model server:' , config . modelBasePath ) ;
else log ( 'error' , 'failed: model server:' , config . modelBasePath ) ;
2021-04-14 18:53:00 +02:00
resolve ( res && res . ok ) ;
} )
. catch ( ( err ) => {
2021-04-15 15:43:55 +02:00
log ( 'error' , 'failed: model server:' , err . message ) ;
2021-04-14 18:53:00 +02:00
resolve ( false ) ;
} ) ;
} ) ;
}
async function getImage ( human , input ) {
let img ;
try {
img = await canvasJS . loadImage ( input ) ;
} catch ( err ) {
2021-04-15 15:43:55 +02:00
log ( 'error' , 'failed: load image' , input , err . message ) ;
2021-04-14 18:53:00 +02:00
return img ;
}
const canvas = canvasJS . createCanvas ( img . width , img . height ) ;
const ctx = canvas . getContext ( '2d' ) ;
ctx . drawImage ( img , 0 , 0 , img . width , img . height ) ;
const imageData = ctx . getImageData ( 0 , 0 , canvas . width , canvas . height ) ;
const res = human . tf . tidy ( ( ) => {
2021-09-19 20:07:53 +02:00
const tensor = human . tf . tensor ( Array . from ( imageData . data ) , [ canvas . height , canvas . width , 4 ] , 'float32' ) ; // create rgba image tensor from flat array
2021-04-14 18:53:00 +02:00
const channels = human . tf . split ( tensor , 4 , 2 ) ; // split rgba to channels
const rgb = human . tf . stack ( [ channels [ 0 ] , channels [ 1 ] , channels [ 2 ] ] , 2 ) ; // stack channels back to rgb
2021-04-15 21:26:31 +02:00
const reshape = human . tf . reshape ( rgb , [ 1 , canvas . height , canvas . width , 3 ] ) ; // move extra dim from the end of tensor and use it as batch number instead
2021-04-14 18:53:00 +02:00
return reshape ;
} ) ;
2021-09-19 20:07:53 +02:00
const sum = human . tf . sum ( res ) ;
if ( res && res . shape [ 0 ] === 1 && res . shape [ 3 ] === 3 ) log ( 'state' , 'passed: load image:' , input , res . shape , { checksum : sum . dataSync ( ) [ 0 ] } ) ;
2021-04-15 15:43:55 +02:00
else log ( 'error' , 'failed: load image:' , input , res ) ;
2021-09-19 20:07:53 +02:00
human . tf . dispose ( sum ) ;
2021-04-14 18:53:00 +02:00
return res ;
}
function printResults ( detect ) {
2021-09-13 19:30:46 +02:00
const person = ( detect . face && detect . face [ 0 ] ) ? { score : detect . face [ 0 ] . score , age : detect . face [ 0 ] . age , gender : detect . face [ 0 ] . gender } : { } ;
2021-04-14 18:53:00 +02:00
const object = ( detect . object && detect . object [ 0 ] ) ? { score : detect . object [ 0 ] . score , class : detect . object [ 0 ] . label } : { } ;
const body = ( detect . body && detect . body [ 0 ] ) ? { score : detect . body [ 0 ] . score , keypoints : detect . body [ 0 ] . keypoints . length } : { } ;
2021-05-24 17:10:13 +02:00
const persons = detect . persons ;
if ( detect . face ) log ( 'data' , ' result: face:' , detect . face ? . length , 'body:' , detect . body ? . length , 'hand:' , detect . hand ? . length , 'gesture:' , detect . gesture ? . length , 'object:' , detect . object ? . length , 'person:' , persons . length , person , object , body ) ;
2021-04-15 15:43:55 +02:00
if ( detect . performance ) log ( 'data' , ' result: performance:' , 'load:' , detect ? . performance . load , 'total:' , detect . performance ? . total ) ;
2021-04-14 18:53:00 +02:00
}
async function testInstance ( human ) {
2021-04-15 15:43:55 +02:00
if ( human ) log ( 'state' , 'passed: create human' ) ;
else log ( 'error' , 'failed: create human' ) ;
2021-04-14 18:53:00 +02:00
// if (!human.tf) human.tf = tf;
2021-04-15 15:43:55 +02:00
log ( 'info' , 'human version:' , human . version ) ;
2021-09-13 00:37:06 +02:00
log ( 'info' , 'platform:' , human . env . platform , 'agent:' , human . env . agent ) ;
2021-04-15 15:43:55 +02:00
log ( 'info' , 'tfjs version:' , human . tf . version . tfjs ) ;
2021-04-14 18:53:00 +02:00
await human . load ( ) ;
2021-04-15 15:43:55 +02:00
if ( config . backend === human . tf . getBackend ( ) ) log ( 'state' , 'passed: set backend:' , config . backend ) ;
else log ( 'error' , 'failed: set backend:' , config . backend ) ;
2021-09-23 20:09:41 +02:00
log ( 'state' , 'tensors' , human . tf . memory ( ) . numTensors ) ;
2021-04-14 18:53:00 +02:00
if ( human . models ) {
2021-04-15 15:43:55 +02:00
log ( 'state' , 'passed: load models' ) ;
2021-04-14 18:53:00 +02:00
const keys = Object . keys ( human . models ) ;
const loaded = keys . filter ( ( model ) => human . models [ model ] ) ;
2021-04-15 15:43:55 +02:00
log ( 'state' , ' result: defined models:' , keys . length , 'loaded models:' , loaded . length ) ;
2021-04-14 18:53:00 +02:00
return true ;
}
2021-04-15 15:43:55 +02:00
log ( 'error' , 'failed: load models' ) ;
2021-04-14 18:53:00 +02:00
return false ;
}
async function testWarmup ( human , title ) {
let warmup ;
try {
warmup = await human . warmup ( config ) ;
} catch ( err ) {
2021-04-15 15:43:55 +02:00
log ( 'error' , 'error warmup' ) ;
2021-04-14 18:53:00 +02:00
}
if ( warmup ) {
2021-04-15 15:43:55 +02:00
log ( 'state' , 'passed: warmup:' , config . warmup , title ) ;
2021-09-13 19:30:46 +02:00
// const count = human.tf.engine().state.numTensors;
// if (count - tensors > 0) log('warn', 'failed: memory', config.warmup, title, 'tensors:', count - tensors);
2021-04-14 18:53:00 +02:00
printResults ( warmup ) ;
2021-09-19 20:07:53 +02:00
} else {
log ( 'error' , 'failed: warmup:' , config . warmup , title ) ;
2021-04-14 18:53:00 +02:00
}
2021-09-19 20:07:53 +02:00
return warmup ;
2021-04-14 18:53:00 +02:00
}
2021-09-23 20:09:41 +02:00
async function testDetect ( human , input , title , checkLeak = true ) {
2021-09-13 19:30:46 +02:00
await human . load ( config ) ;
2021-09-23 20:09:41 +02:00
const tensors = human . tf . engine ( ) . state . numTensors ;
2021-04-14 18:53:00 +02:00
const image = input ? await getImage ( human , input ) : human . tf . randomNormal ( [ 1 , 1024 , 1024 , 3 ] ) ;
if ( ! image ) {
2021-04-15 15:43:55 +02:00
log ( 'error' , 'failed: detect: input is null' ) ;
2021-04-14 18:53:00 +02:00
return false ;
}
let detect ;
try {
detect = await human . detect ( image , config ) ;
} catch ( err ) {
2021-04-15 15:43:55 +02:00
log ( 'error' , 'error: detect' , err ) ;
2021-04-14 18:53:00 +02:00
}
if ( image instanceof human . tf . Tensor ) human . tf . dispose ( image ) ;
if ( detect ) {
2021-04-15 15:43:55 +02:00
log ( 'state' , 'passed: detect:' , input || 'random' , title ) ;
2021-09-13 19:30:46 +02:00
// const count = human.tf.engine().state.numTensors;
// if (count - tensors > 0) log('warn', 'failed: memory', config.warmup, title, 'tensors:', count - tensors);
2021-04-14 18:53:00 +02:00
printResults ( detect ) ;
2021-09-19 20:07:53 +02:00
} else {
log ( 'error' , 'failed: detect' , input || 'random' , title ) ;
2021-04-14 18:53:00 +02:00
}
2021-09-23 20:09:41 +02:00
// check tensor leaks
if ( checkLeak ) {
const leak = human . tf . engine ( ) . state . numTensors - tensors ;
if ( leak !== 0 ) log ( 'error' , 'failed: memory leak' , leak ) ;
}
2021-09-19 20:07:53 +02:00
return detect ;
2021-04-14 18:53:00 +02:00
}
2021-09-13 19:30:46 +02:00
const evt = { image : 0 , detect : 0 , warmup : 0 } ;
async function events ( event ) {
log ( 'state' , 'event:' , event ) ;
evt [ event ] ++ ;
}
2021-04-14 18:53:00 +02:00
async function test ( Human , inputConfig ) {
config = inputConfig ;
2021-08-31 19:29:29 +02:00
fetch = ( await import ( 'node-fetch' ) ) . default ;
2021-04-14 18:53:00 +02:00
const ok = await testHTTP ( ) ;
if ( ! ok ) {
2021-04-15 15:43:55 +02:00
log ( 'error' , 'aborting test' ) ;
2021-04-14 18:53:00 +02:00
return ;
}
const t0 = process . hrtime . bigint ( ) ;
2021-09-19 20:07:53 +02:00
let res ;
2021-09-19 01:09:02 +02:00
// test event emitter
2021-09-19 20:07:53 +02:00
const human = new Human ( config ) ;
2021-09-13 19:30:46 +02:00
human . events . addEventListener ( 'warmup' , ( ) => events ( 'warmup' ) ) ;
human . events . addEventListener ( 'image' , ( ) => events ( 'image' ) ) ;
human . events . addEventListener ( 'detect' , ( ) => events ( 'detect' ) ) ;
2021-09-19 20:07:53 +02:00
// test configuration validation
let invalid = human . validate ( ) ;
if ( invalid . length === 0 ) log ( 'state' , 'passed: configuration default validation' , invalid ) ;
else log ( 'error' , 'failed: configuration default validation' , invalid ) ;
config . invalid = true ;
invalid = human . validate ( config ) ;
if ( invalid . length === 1 ) log ( 'state' , 'passed: configuration invalid validation' , invalid ) ;
else log ( 'error' , 'failed: configuration default validation' , invalid ) ;
delete config . invalid ;
2021-09-20 15:42:34 +02:00
// test model loading
await human . load ( ) ;
const models = Object . keys ( human . models ) . map ( ( model ) => ( { name : model , loaded : ( human . models [ model ] !== null ) } ) ) ;
const loaded = models . filter ( ( model ) => model . loaded ) ;
2021-09-23 20:09:41 +02:00
if ( models . length === 19 && loaded . length === 10 ) log ( 'state' , 'passed: models loaded' , models ) ;
else log ( 'error' , 'failed: models loaded' , models ) ;
2021-09-20 15:42:34 +02:00
2021-09-19 01:09:02 +02:00
// test warmup sequences
2021-04-14 18:53:00 +02:00
await testInstance ( human ) ;
config . warmup = 'none' ;
2021-09-19 20:07:53 +02:00
res = await testWarmup ( human , 'default' ) ;
if ( res . error !== 'null' ) log ( 'error' , 'failed: warmup none result mismatch' ) ;
else log ( 'state' , 'passed: warmup none result match' ) ;
2021-04-14 18:53:00 +02:00
config . warmup = 'face' ;
2021-09-19 20:07:53 +02:00
res = await testWarmup ( human , 'default' ) ;
if ( ! res || res ? . face ? . length !== 1 || res ? . body ? . length !== 1 || res ? . hand ? . length !== 0 || res ? . gesture ? . length !== 3 ) log ( 'error' , 'failed: warmup face result mismatch' , res ? . face ? . length , res ? . body ? . length , res ? . hand ? . length , res ? . gesture ? . length ) ;
else log ( 'state' , 'passed: warmup face result match' ) ;
2021-04-14 18:53:00 +02:00
config . warmup = 'body' ;
2021-09-19 20:07:53 +02:00
res = await testWarmup ( human , 'default' ) ;
if ( ! res || res ? . face ? . length !== 1 || res ? . body ? . length !== 1 || res ? . hand ? . length !== 0 || res ? . gesture ? . length !== 3 ) log ( 'error' , 'failed: warmup body result mismatch' , res ? . face ? . length , res ? . body ? . length , res ? . hand ? . length , res ? . gesture ? . length ) ;
else log ( 'state' , 'passed: warmup body result match' ) ;
2021-04-14 18:53:00 +02:00
2021-09-20 15:42:34 +02:00
// test default config async
2021-09-13 19:30:46 +02:00
log ( 'info' , 'test default' ) ;
2021-09-19 20:07:53 +02:00
human . reset ( ) ;
2021-09-20 15:42:34 +02:00
config . async = true ;
2021-09-19 20:07:53 +02:00
config . cacheSensitivity = 0 ;
res = await testDetect ( human , 'samples/ai-body.jpg' , 'default' ) ;
if ( ! res || res ? . face ? . length !== 1 || res ? . face [ 0 ] . gender !== 'female' ) log ( 'error' , 'failed: default result face mismatch' , res ? . face ? . length , res ? . body ? . length , res ? . hand ? . length , res ? . gesture ? . length ) ;
else log ( 'state' , 'passed: default result face match' ) ;
2021-09-20 15:42:34 +02:00
// test default config sync
2021-09-19 20:20:22 +02:00
log ( 'info' , 'test sync' ) ;
human . reset ( ) ;
config . async = false ;
2021-09-20 15:42:34 +02:00
config . cacheSensitivity = 0 ;
2021-09-19 20:20:22 +02:00
res = await testDetect ( human , 'samples/ai-body.jpg' , 'default' ) ;
if ( ! res || res ? . face ? . length !== 1 || res ? . face [ 0 ] . gender !== 'female' ) log ( 'error' , 'failed: default sync' , res ? . face ? . length , res ? . body ? . length , res ? . hand ? . length , res ? . gesture ? . length ) ;
else log ( 'state' , 'passed: default sync' ) ;
2021-09-20 15:42:34 +02:00
// test image processing
const img1 = await human . image ( null ) ;
const img2 = await human . image ( await getImage ( human , 'samples/ai-face.jpg' ) ) ;
if ( ! img1 || ! img2 || img1 . tensor !== null || img2 . tensor ? . shape ? . length !== 4 ) log ( 'error' , 'failed: image input' , img1 ? . tensor ? . shape , img2 ? . tensor ? . shape ) ;
else log ( 'state' , 'passed: image input' , img1 ? . tensor ? . shape , img2 ? . tensor ? . shape ) ;
// test null input
res = await human . detect ( null ) ;
if ( ! res || ! res . error ) log ( 'error' , 'failed: invalid input' , res ) ;
else log ( 'state' , 'passed: invalid input' , res ) ;
// test face similarity
log ( 'info' , 'test face similarity' ) ;
human . reset ( ) ;
config . async = false ;
config . cacheSensitivity = 0 ;
let res1 = await testDetect ( human , 'samples/ai-face.jpg' , 'default' ) ;
let res2 = await testDetect ( human , 'samples/ai-body.jpg' , 'default' ) ;
let res3 = await testDetect ( human , 'samples/ai-upper.jpg' , 'default' ) ;
const desc1 = res1 && res1 . face && res1 . face [ 0 ] && res1 . face [ 0 ] . embedding ? [ ... res1 . face [ 0 ] . embedding ] : null ;
const desc2 = res2 && res2 . face && res2 . face [ 0 ] && res2 . face [ 0 ] . embedding ? [ ... res2 . face [ 0 ] . embedding ] : null ;
const desc3 = res3 && res3 . face && res3 . face [ 0 ] && res3 . face [ 0 ] . embedding ? [ ... res3 . face [ 0 ] . embedding ] : null ;
if ( ! desc1 || ! desc2 || ! desc3 || desc1 . length !== 1024 || desc2 . length !== 1024 || desc3 . length !== 1024 ) log ( 'error' , 'failed: face descriptor' , desc1 ? . length , desc2 ? . length , desc3 ? . length ) ;
else log ( 'state' , 'passed: face descriptor' ) ;
res1 = Math . round ( 100 * human . similarity ( desc1 , desc2 ) ) ;
res2 = Math . round ( 100 * human . similarity ( desc1 , desc3 ) ) ;
res3 = Math . round ( 100 * human . similarity ( desc2 , desc3 ) ) ;
2021-09-21 03:59:49 +02:00
if ( res1 !== 51 || res2 !== 49 || res3 !== 53 ) log ( 'error' , 'failed: face similarity ' , res1 , res2 , res3 ) ;
else log ( 'state' , 'passed: face similarity' ) ;
2021-09-20 15:42:34 +02:00
// test face matching
log ( 'info' , 'test face matching' ) ;
let db = [ ] ;
try {
db = JSON . parse ( fs . readFileSync ( 'demo/facematch/faces.json' ) . toString ( ) ) ;
} catch { /***/ }
if ( db . length < 100 ) log ( 'error' , 'failed: face database ' , db . length ) ;
else log ( 'state' , 'passed: face database' , db . length ) ;
res1 = human . match ( desc1 , db ) ;
res2 = human . match ( desc2 , db ) ;
res3 = human . match ( desc3 , db ) ;
2021-09-21 03:59:49 +02:00
if ( ! res1 || ! res1 [ 'name' ] || ! res2 || ! res2 [ 'name' ] || ! res3 || ! res3 [ 'name' ] ) log ( 'error' , 'failed: face match ' , res1 , res2 , res3 ) ;
2021-09-20 15:42:34 +02:00
else log ( 'state' , 'passed: face match' , { first : { name : res1 . name , similarity : res1 . similarity } } , { second : { name : res2 . name , similarity : res2 . similarity } } , { third : { name : res3 . name , similarity : res3 . similarity } } ) ;
2021-09-19 20:20:22 +02:00
// test object detection
2021-09-19 20:07:53 +02:00
log ( 'info' , 'test object' ) ;
human . reset ( ) ;
config . object = { enabled : true } ;
res = await testDetect ( human , 'samples/ai-body.jpg' , 'default' ) ;
if ( ! res || res ? . object ? . length !== 1 || res ? . object [ 0 ] ? . label !== 'person' ) log ( 'error' , 'failed: object result mismatch' , res ? . object ? . length ) ;
else log ( 'state' , 'passed: object result match' ) ;
// test sensitive config
log ( 'info' , 'test sensitive' ) ;
human . reset ( ) ;
config . cacheSensitivity = 0 ;
config . face = { detector : { minConfidence : 0.0001 , maxDetected : 1 } } ;
config . body = { minConfidence : 0.0001 , maxDetected : 1 } ;
config . hand = { minConfidence : 0.0001 , maxDetected : 3 } ;
res = await testDetect ( human , 'samples/ai-body.jpg' , 'default' ) ;
if ( ! res || res ? . face ? . length !== 1 || res ? . body ? . length !== 1 || res ? . hand ? . length !== 3 || res ? . gesture ? . length !== 9 ) log ( 'error' , 'failed: sensitive result mismatch' , res ? . face ? . length , res ? . body ? . length , res ? . hand ? . length , res ? . gesture ? . length ) ;
else log ( 'state' , 'passed: sensitive result match' ) ;
// test sensitive details face
const face = res && res . face ? res . face [ 0 ] : null ;
if ( ! face || face ? . box ? . length !== 4 || face ? . mesh ? . length !== 478 || face ? . emotion ? . length !== 4 || face ? . embedding ? . length !== 1024 || face ? . rotation ? . matrix ? . length !== 9 ) {
log ( 'error' , 'failed: sensitive face result mismatch' , res ? . face ? . length , face ? . box ? . length , face ? . mesh ? . length , face ? . emotion ? . length , face ? . embedding ? . length , face ? . rotation ? . matrix ? . length ) ;
} else log ( 'state' , 'passed: sensitive face result match' ) ;
// test sensitive details body
const body = res && res . body ? res . body [ 0 ] : null ;
if ( ! body || body ? . box ? . length !== 4 || body ? . keypoints ? . length !== 17 ) log ( 'error' , 'failed: sensitive body result mismatch' , body ) ;
else log ( 'state' , 'passed: sensitive body result match' ) ;
// test sensitive details hand
const hand = res && res . hand ? res . hand [ 0 ] : null ;
if ( ! hand || hand ? . box ? . length !== 4 || hand ? . keypoints ? . length !== 21 ) log ( 'error' , 'failed: sensitive hand result mismatch' , hand ? . keypoints ? . length ) ;
else log ( 'state' , 'passed: sensitive hand result match' ) ;
2021-09-19 01:09:02 +02:00
// test detectors only
log ( 'info' , 'test detectors' ) ;
2021-09-19 20:07:53 +02:00
human . reset ( ) ;
config . face = { mesh : { enabled : false } , iris : { enabled : false } , description : { enabled : false } , emotion : { enabled : false } } ;
config . hand = { landmarks : false } ;
res = await testDetect ( human , 'samples/ai-body.jpg' , 'default' ) ;
if ( ! res || res ? . face ? . length !== 1 || res ? . face [ 0 ] ? . gender || res ? . face [ 0 ] ? . age || res ? . face [ 0 ] ? . embedding ) log ( 'error' , 'failed: detectors result face mismatch' , res ? . face ) ;
else log ( 'state' , 'passed: detector result face match' ) ;
if ( ! res || res ? . hand ? . length !== 1 || res ? . hand [ 0 ] ? . landmarks ) log ( 'error' , 'failed: detectors result hand mismatch' , res ? . hand ? . length ) ;
else log ( 'state' , 'passed: detector result hand match' ) ;
2021-09-13 19:30:46 +02:00
2021-09-19 01:09:02 +02:00
// test posenet and movenet
2021-04-15 15:43:55 +02:00
log ( 'info' , 'test body variants' ) ;
2021-09-13 19:30:46 +02:00
config . body = { modelPath : 'posenet.json' } ;
2021-09-24 15:55:27 +02:00
res = await testDetect ( human , 'samples/ai-body.jpg' , 'posenet' ) ;
if ( ! res || res ? . body ? . length !== 1 ) log ( 'error' , 'failed: body posenet' ) ;
else log ( 'state' , 'passed: body posenet' ) ;
2021-09-13 19:30:46 +02:00
config . body = { modelPath : 'movenet-lightning.json' } ;
2021-09-24 15:55:27 +02:00
res = await testDetect ( human , 'samples/ai-body.jpg' , 'movenet' ) ;
if ( ! res || res ? . body ? . length !== 1 ) log ( 'error' , 'failed: body movenet' ) ;
else log ( 'state' , 'passed: body movenet' ) ;
// test handdetect and handtrack
log ( 'info' , 'test hand variants' ) ;
config . hand = { enabled : true , maxDetected : 2 , minConfidence : 0.1 , detector : { modelPath : 'handdetect.json' } } ;
res = await testDetect ( human , 'samples/ai-body.jpg' , 'handdetect' ) ;
if ( ! res || res ? . hand ? . length !== 2 ) log ( 'error' , 'failed: hand handdetect' ) ;
else log ( 'state' , 'passed: hand handdetect' ) ;
config . hand = { enabled : true , maxDetected : 2 , minConfidence : 0.1 , detector : { modelPath : 'handtrack.json' } } ;
res = await testDetect ( human , 'samples/ai-body.jpg' , 'handtrack' ) ;
if ( ! res || res ? . hand ? . length !== 2 ) log ( 'error' , 'failed: hand handdetect' ) ;
else log ( 'state' , 'passed: hand handdetect' ) ;
2021-09-19 01:09:02 +02:00
// test multiple instances
const first = new Human ( config ) ;
const second = new Human ( config ) ;
2021-04-14 18:53:00 +02:00
await testDetect ( human , null , 'default' ) ;
2021-04-15 15:43:55 +02:00
log ( 'info' , 'test: first instance' ) ;
2021-09-19 01:09:02 +02:00
await testDetect ( first , 'samples/ai-upper.jpg' , 'default' ) ;
2021-04-15 15:43:55 +02:00
log ( 'info' , 'test: second instance' ) ;
2021-06-02 19:35:33 +02:00
await testDetect ( second , 'samples/ai-upper.jpg' , 'default' ) ;
2021-09-19 01:09:02 +02:00
// test async multiple instances
2021-04-15 15:43:55 +02:00
log ( 'info' , 'test: concurrent' ) ;
2021-04-14 18:53:00 +02:00
await Promise . all ( [
2021-09-23 20:09:41 +02:00
testDetect ( human , 'samples/ai-face.jpg' , 'default' , false ) ,
testDetect ( first , 'samples/ai-face.jpg' , 'default' , false ) ,
testDetect ( second , 'samples/ai-face.jpg' , 'default' , false ) ,
testDetect ( human , 'samples/ai-body.jpg' , 'default' , false ) ,
testDetect ( first , 'samples/ai-body.jpg' , 'default' , false ) ,
testDetect ( second , 'samples/ai-body.jpg' , 'default' , false ) ,
testDetect ( human , 'samples/ai-upper.jpg' , 'default' , false ) ,
testDetect ( first , 'samples/ai-upper.jpg' , 'default' , false ) ,
testDetect ( second , 'samples/ai-upper.jpg' , 'default' , false ) ,
2021-04-14 18:53:00 +02:00
] ) ;
2021-09-19 01:09:02 +02:00
2021-09-20 15:42:34 +02:00
// test monkey-patch
2021-09-23 01:27:12 +02:00
globalThis . Canvas = canvasJS . Canvas ; // monkey-patch to use external canvas library
globalThis . ImageData = canvasJS . ImageData ; // monkey-patch to use external canvas library
2021-09-20 15:42:34 +02:00
const inputImage = await canvasJS . loadImage ( 'samples/ai-face.jpg' ) ; // load image using canvas library
const inputCanvas = new canvasJS . Canvas ( inputImage . width , inputImage . height ) ; // create canvas
const ctx = inputCanvas . getContext ( '2d' ) ;
ctx . drawImage ( inputImage , 0 , 0 ) ; // draw input image onto canvas
res = await human . detect ( inputCanvas ) ;
if ( ! res || res ? . face ? . length !== 1 ) log ( 'error' , 'failed: monkey patch' ) ;
else log ( 'state' , 'passed: monkey patch' ) ;
// test segmentation
res = await human . segmentation ( inputCanvas , inputCanvas ) ;
2021-09-23 01:27:12 +02:00
if ( ! res || ! res . data || ! res . canvas ) log ( 'error' , 'failed: segmentation' ) ;
2021-09-22 22:00:43 +02:00
else log ( 'state' , 'passed: segmentation' , [ res . data . length ] ) ;
2021-09-20 15:42:34 +02:00
human . env . Canvas = undefined ;
2021-09-19 01:09:02 +02:00
// tests end
2021-04-14 18:53:00 +02:00
const t1 = process . hrtime . bigint ( ) ;
2021-09-19 01:09:02 +02:00
// check if all instances reported same
const tensors1 = human . tf . engine ( ) . state . numTensors ;
const tensors2 = first . tf . engine ( ) . state . numTensors ;
const tensors3 = second . tf . engine ( ) . state . numTensors ;
if ( tensors1 === tensors2 && tensors1 === tensors3 && tensors2 === tensors3 ) log ( 'state' , 'passeed: equal usage' ) ;
else log ( 'error' , 'failed: equal usage' , tensors1 , tensors2 , tensors3 ) ;
// report end
2021-09-13 19:30:46 +02:00
log ( 'info' , 'events:' , evt ) ;
2021-09-23 20:09:41 +02:00
log ( 'info' , 'tensors' , human . tf . memory ( ) . numTensors ) ;
2021-05-25 14:58:20 +02:00
log ( 'info' , 'test complete:' , Math . trunc ( Number ( t1 - t0 ) / 1000 / 1000 ) , 'ms' ) ;
2021-04-14 18:53:00 +02:00
}
exports . test = test ;