Permalink
Show file tree
Hide file tree
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
v5.1.5 - 2020.03.17:
+ Added an ASM.js export. We do now support a manual ASM.js fallback. Since WebAssembly is available almost everywhere, there is no automatic checking/switching. + Added a nodejs example. There is an issue with loading more than 6 model chunks for 68l, which leads to wrong results, not sure why yet.
- Loading branch information
Marcel Klammer
committed
Mar 17, 2020
1 parent
10064e3
commit b8a69b8b9271bb9b5d41eeb55a281b3946513f00
Showing
16 changed files
with
613 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@@ -0,0 +1,190 @@ | ||
const { brfv5Module } = require('./js/brfv5/brfv5_js_tk170320_v5.1.5_trial_nodejs') | ||
|
||
const fs = require('fs') | ||
const pixels = require('image-pixels') | ||
|
||
const imageURL = './assets/tracking/brfv5_portrait_marcel.jpg' | ||
|
||
let imageBuffer = null; // file buffer | ||
let imageData = null; // pixel buffer | ||
|
||
// Set the BRFv5 library name here, also set your own appId for reference. | ||
|
||
const _libraryName = 'brfv5_js_tk170320_v5.1.5_trial.brfv5' | ||
const _appId = 'brfv5.nodejs.minimal' // (mandatory): 8 to 64 characters, a-z . 0-9 allowed | ||
const brfv5 = {} // The library namespace. | ||
|
||
// References to the video and canvas. | ||
// const _webcam = document.getElementById('_webcam') | ||
// const _imageData = document.getElementById('_imageData') | ||
|
||
// Those variables will be retrieved from the stream and the library. | ||
let _brfv5Manager = null | ||
let _brfv5Config = null | ||
let _width = 0 | ||
let _height = 0 | ||
|
||
// loadBRFv5Model and openCamera are being done simultaneously thanks to Promises. Both call | ||
// configureTracking which only gets executed once both Promises were successful. Once configured | ||
// trackFaces will do the tracking work and draw the results. | ||
|
||
const loadBRFv5Model = (modelName, numChunksToLoad, pathToModels = '', appId = null, onProgress = null) => { | ||
|
||
console.log('loadBRFv5Model') | ||
|
||
if(!modelName) { throw 'Please provide a modelName.' } | ||
|
||
return new Promise((resolve, reject) => { | ||
|
||
if(_brfv5Manager && _brfv5Config) { | ||
|
||
resolve({ brfv5Manager: _brfv5Manager, brfv5Config: _brfv5Config }) | ||
|
||
} else { | ||
|
||
try { | ||
|
||
brfv5.appId = appId ? appId : _appId | ||
brfv5.binaryLocation = pathToModels + _libraryName | ||
brfv5.modelLocation = pathToModels + modelName + '_c' | ||
brfv5.modelChunks = numChunksToLoad // 4, 6, 8 | ||
brfv5.binaryProgress = onProgress | ||
brfv5.binaryError = (e) => { reject(e) } | ||
brfv5.onInit = (brfv5Manager, brfv5Config) => { | ||
|
||
_brfv5Manager = brfv5Manager | ||
_brfv5Config = brfv5Config | ||
|
||
resolve({ brfv5Manager: _brfv5Manager, brfv5Config: _brfv5Config }) | ||
} | ||
|
||
brfv5Module(brfv5) | ||
|
||
} catch(e) { | ||
|
||
reject(e) | ||
} | ||
} | ||
}) | ||
} | ||
|
||
const loadImage = async (imageURL) => { | ||
|
||
console.log('loadImage: ', imageURL) | ||
|
||
imageBuffer = fs.readFileSync(imageURL); | ||
|
||
const { data, width, height } = await pixels(imageBuffer) | ||
|
||
imageData = data; | ||
|
||
return { width: width, height: height }; | ||
} | ||
|
||
const configureTracking = () => { | ||
|
||
if(_brfv5Config !== null && _width > 0) { | ||
|
||
// Camera stream and BRFv5 are ready. Now configure. Internal defaults are set for a 640x480 resolution. | ||
// So the following isn't really necessary. | ||
|
||
const brfv5Config = _brfv5Config | ||
const imageWidth = _width | ||
const imageHeight = _height | ||
|
||
const inputSize = imageWidth > imageHeight ? imageHeight : imageWidth | ||
|
||
// Setup image data dimensions | ||
|
||
brfv5Config.imageConfig.inputWidth = imageWidth | ||
brfv5Config.imageConfig.inputHeight = imageHeight | ||
|
||
const sizeFactor = inputSize / 480.0 | ||
|
||
// Set face detection region of interest and parameters scaled to the image base size. | ||
|
||
brfv5Config.faceDetectionConfig.regionOfInterest.setTo(0, 0, imageWidth, imageHeight) | ||
|
||
brfv5Config.faceDetectionConfig.minFaceSize = 144 * sizeFactor | ||
brfv5Config.faceDetectionConfig.maxFaceSize = 480 * sizeFactor | ||
|
||
if(imageWidth < imageHeight) { | ||
|
||
// Portrait mode: probably smartphone, faces tend to be closer to the camera, processing time is an issue, | ||
// so save a bit of time and increase minFaceSize. | ||
|
||
brfv5Config.faceDetectionConfig.minFaceSize = 240 * sizeFactor | ||
} | ||
|
||
// Set face tracking region of interest and parameters scaled to the image base size. | ||
|
||
brfv5Config.faceTrackingConfig.regionOfInterest.setTo(0, 0, imageWidth, imageHeight) | ||
|
||
brfv5Config.faceTrackingConfig.minFaceScaleStart = 50.0 * sizeFactor | ||
brfv5Config.faceTrackingConfig.maxFaceScaleStart = 320.0 * sizeFactor | ||
|
||
brfv5Config.faceTrackingConfig.minFaceScaleReset = 35.0 * sizeFactor | ||
brfv5Config.faceTrackingConfig.maxFaceScaleReset = 420.0 * sizeFactor | ||
|
||
brfv5Config.faceTrackingConfig.confidenceThresholdReset = 0.001 | ||
|
||
brfv5Config.faceTrackingConfig.enableStabilizer = true | ||
|
||
brfv5Config.faceTrackingConfig.maxRotationXReset = 35.0 | ||
brfv5Config.faceTrackingConfig.maxRotationYReset = 45.0 | ||
brfv5Config.faceTrackingConfig.maxRotationZReset = 34.0 | ||
|
||
brfv5Config.faceTrackingConfig.numTrackingPasses = 3 | ||
brfv5Config.faceTrackingConfig.enableFreeRotation = true | ||
brfv5Config.faceTrackingConfig.maxRotationZReset = 999.0 | ||
|
||
brfv5Config.faceTrackingConfig.numFacesToTrack = 1 | ||
brfv5Config.enableFaceTracking = true | ||
|
||
// console.log('configureTracking:', _brfv5Config) | ||
|
||
_brfv5Manager.configure(_brfv5Config) | ||
|
||
trackFaces() | ||
} | ||
} | ||
|
||
const trackFaces = () => { | ||
|
||
if(!_brfv5Manager || !_brfv5Config) { return } | ||
|
||
_brfv5Manager.update({ width: _width, height: _height, data: imageData }) | ||
|
||
const faces = _brfv5Manager.getFaces() | ||
|
||
for(let i = 0; i < faces.length; i++) { | ||
|
||
console.log(faces[i].bounds) | ||
} | ||
} | ||
|
||
// TODO: warum geht 7 und 8 nicht bei 68l? Memory issue in nodejs? Not sure about it. | ||
// for 68l, use 6 max model chunks | ||
// for 42l, use 8 max model chunks | ||
loadBRFv5Model('68l', 6, './js/brfv5/models/', _appId, | ||
(progress) => { console.log(progress) }).then(({ brfv5Manager, brfv5Config }) => { | ||
|
||
console.log('loadBRFv5Model: done') | ||
|
||
_brfv5Manager = brfv5Manager | ||
_brfv5Config = brfv5Config | ||
|
||
console.log(brfv5) | ||
|
||
loadImage(imageURL).then(({ width, height }) => { | ||
|
||
console.log('loadImage: done: ' + width + 'x' + height) | ||
|
||
_width = width | ||
_height = height | ||
|
||
configureTracking() | ||
|
||
}).catch((e) => { if(e) { console.error('loadImage failed: ', e) } }) | ||
|
||
}).catch((e) => { console.error('BRFv5 failed: ', e) }) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@@ -0,0 +1,58 @@ | ||
// Set the BRFv5 import and library name here. | ||
// Also set your own appId for reference. | ||
|
||
// THIS FILE IS THE SAME AS brfv5__init.js BUT PREPARED TO USE ASMJS BINARIES. YOU CAN STILL USE brfv5__init.js AND SWAP THE FILE NAMES! | ||
|
||
// import { brfv5Module } from './brfv5_js_tk170320_v5.1.5_trial.js' // WebAssembly is available is every major browser, no need for asm.js | ||
import { brfv5Module } from './brfv5_js_tk170320_v5.1.5_trial.asm.js' // .asm.js is a manual possibility to load asm.js binaries | ||
|
||
// const _libraryName = 'brfv5_js_tk170320_v5.1.5_trial.brfv5' // for WebAssembly | ||
const _libraryName = 'brfv5_js_tk170320_v5.1.5_trial.asm.brfv5' // for asm.js | ||
|
||
const _appId = 'brfv5.browser.examples' // (mandatory): 8 to 64 characters, a-z . 0-9 allowed | ||
|
||
export const brfv5 = {} | ||
|
||
let _brfv5Manager = null | ||
let _brfv5Config = null | ||
|
||
// numChunksToLoad: can be anything from 4 to 8. | ||
export const loadBRFv5Model = (modelName, numChunksToLoad, pathToModels = '', appId = null, onProgress = null) => { | ||
|
||
if(!modelName) { throw 'Please provide a modelName.' } | ||
|
||
return new Promise((resolve, reject) => { | ||
|
||
if(_brfv5Manager && _brfv5Config) { | ||
|
||
resolve({ brfv5Manager: _brfv5Manager, brfv5Config: _brfv5Config }) | ||
|
||
} else { | ||
|
||
try { | ||
|
||
brfv5.appId = appId ? appId : _appId | ||
brfv5.binaryLocation = pathToModels + _libraryName | ||
brfv5.modelLocation = pathToModels + modelName + '_c' | ||
brfv5.modelChunks = numChunksToLoad // 4, 6, 8 | ||
brfv5.binaryProgress = onProgress | ||
brfv5.binaryError = (e) => { reject(e) } | ||
brfv5.onInit = (brfv5Manager, brfv5Config) => { | ||
|
||
_brfv5Manager = brfv5Manager | ||
_brfv5Config = brfv5Config | ||
|
||
resolve({ brfv5Manager: _brfv5Manager, brfv5Config: _brfv5Config }) | ||
} | ||
|
||
brfv5Module(brfv5) | ||
|
||
} catch(e) { | ||
|
||
reject(e) | ||
} | ||
} | ||
}) | ||
} | ||
|
||
export default { loadBRFv5Model, brfv5 } |
Oops, something went wrong.