Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,015 changes: 989 additions & 26 deletions package-lock.json

Large diffs are not rendered by default.

9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
"download:yolo": "node ./scripts/download-models/index.js yolo",
"download:posenet": "node ./scripts/download-models/index.js posenet",
"download:posenet2": "node ./scripts/download-models/index.js posenet2",
"download:handpose": "node ./scripts/download-models/index.js handpose",
"download:all": "node ./scripts/download-models/index.js all",
"download": "node ./scripts/download-models/index.js",
"serve": "node ./index.js"
},
"repository": {
Expand All @@ -29,10 +31,13 @@
},
"homepage": "https://github.com/ml5js/ml5-data-and-models-server#readme",
"dependencies": {
"@tensorflow/tfjs-converter": "^3.9.0",
"@tensorflow/tfjs-node": "^3.9.0",
"es6-promise": "^4.2.8",
"express": "^4.17.1",
"isomorphic-fetch": "^2.2.1",
"morgan": "^1.9.1"
"isomorphic-fetch": "^3.0.0",
"morgan": "^1.9.1",
"promise-sequence": "^1.0.0"
},
"devDependencies": {
"mkdirp": "^0.5.1",
Expand Down
23 changes: 23 additions & 0 deletions scripts/download-models/Handpose/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require('isomorphic-fetch');
const mkdirp = require('mkdirp');
const tfconv = require('@tensorflow/tfjs-converter');
const fs = require('fs')

require('@tensorflow/tfjs-node');


const STORAGEPATH = 'https://tfhub.dev/mediapipe/tfjs-model/handdetector/1/default/1';
const OUTPATH = './models/handpose';

async function downloadHandpose() {
mkdirp.sync(OUTPATH);
console.log(`Output directory created at: ${OUTPATH}`);
if (!fs.existsSync(`${OUTPATH}/model.json`) || !fs.existsSync(`${OUTPATH}/weights.bin`)) {
const model = await tfconv.loadGraphModel(STORAGEPATH, {fromTFHub: true});
await model.save(`file://${OUTPATH}/`);
} else {
console.log('handpose model already exists')
}
}

module.exports = downloadHandpose
11 changes: 5 additions & 6 deletions scripts/download-models/Mobilenet/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ async function getMobilenetByVersion(mobilenetVersion) {
// set the output folders
const mobilenetOutputFolder = `./models/mobilenet/${imagenetMeta.outputFolderRoot}`;
const imagenetOutputFolder = `./models/mobilenet/${imagenetMeta.outputFolderImagenet}`

// create new downloader utils
const mobilenetDownloader = new DownloaderUtils(mobilenetStoragePath, mobilenetOutputFolder)
const imagenetDownloader = new DownloaderUtils(imagenetStoragePath, imagenetOutputFolder)

// NOTE: paths are relative to where the script is being called
mobilenetDownloader.makeOutputPath();
imagenetDownloader.makeOutputPath();


// get the modelJson
const modelJson = await mobilenetDownloader.saveJson('model.json');
Expand All @@ -50,9 +50,8 @@ async function getMobilenetByVersion(mobilenetVersion) {
const labelArray = Object.values(IMAGENET_CLASSES).map( (item) => item);

const metadataJson = {labels: labelArray}
await fs.writeFile(`${mobilenetOutputFolder}/metadata.json`, JSON.stringify(metadataJson), () => {
console.log(`finished writing: metadata.json`)
});
fs.writeFileSync(`${mobilenetOutputFolder}/metadata.json`, JSON.stringify(metadataJson));
console.log(`finished writing: metadata.json`)

}

Expand Down Expand Up @@ -80,4 +79,4 @@ function getImagenetPath(mobilenetVersion) {



module.exports = downloadMobilenet
module.exports = downloadMobilenet
21 changes: 13 additions & 8 deletions scripts/download-models/Posenet/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,26 @@ async function getWeights(storagePath, outputPath, manifest){
const weightsPromiseArray = keys.map( async(prop) => {
const fileName = manifest[prop].filename;
let weightFile;

const weightUrl = `${storagePath}/${fileName}`;
const localFilePath = `${outputPath}/${fileName}`;

weightFile = await fetch(weightUrl);
weightFile = await weightFile.buffer();
if (!fs.existsSync(localFilePath)) {
weightFile = await fetch(weightUrl);
weightFile = await weightFile.buffer();

fs.writeFile(`${outputPath}/${fileName}`, weightFile, () => {
console.log(`finished writing: ${fileName}`)
});
fs.writeFile(localFilePath, weightFile, () => {
console.log(`finished writing: ${fileName}`)
});
} else {
console.log('weight already exists: ', fileName)
}

})

Promise.all(weightsPromiseArray)
}



module.exports = downloadPosenet
module.exports = downloadPosenet
66 changes: 32 additions & 34 deletions scripts/download-models/Posenet2/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,24 @@ const RESNET_STORAGE_PATH = `https://storage.googleapis.com/tfjs-models/savedmod
async function downloadPosenet() {
// mobilenet
// quant 1
getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${1}/050`, `MOBILENETV1_050_quant1_stride8`, `model-stride8.json`);
getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${1}/050`, `MOBILENETV1_050_quant1_stride16`, `model-stride16.json`);

getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${1}/075`, `MOBILENETV1_075_quant1_stride8`, `model-stride8.json`);
getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${1}/075`, `MOBILENETV1_075_quant1_stride16`, `model-stride16.json`);

getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${1}/100`, `MOBILENETV1_100_quant1_stride8`, `model-stride8.json`);
getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${1}/100`, `MOBILENETV1_100_quant1_stride16`, `model-stride16.json`);

await getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${1}/050`, `MOBILENETV1_050_quant1_stride8`, `model-stride8.json`);
await getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${1}/050`, `MOBILENETV1_050_quant1_stride16`, `model-stride16.json`);
await getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${1}/075`, `MOBILENETV1_075_quant1_stride8`, `model-stride8.json`);
await getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${1}/075`, `MOBILENETV1_075_quant1_stride16`, `model-stride16.json`);
await getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${1}/100`, `MOBILENETV1_100_quant1_stride8`, `model-stride8.json`);
await getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${1}/100`, `MOBILENETV1_100_quant1_stride16`, `model-stride16.json`);
// // quant 2
getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${2}/050`, `MOBILENETV1_050_quant2_stride8`, `model-stride8.json`);
getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${2}/050`, `MOBILENETV1_050_quant2_stride16`, `model-stride16.json`);
await getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${2}/050`, `MOBILENETV1_050_quant2_stride8`, `model-stride8.json`);
await getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${2}/050`, `MOBILENETV1_050_quant2_stride16`, `model-stride16.json`);
await getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${2}/075`, `MOBILENETV1_075_quant2_stride8`, `model-stride8.json`);
await getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${2}/075`, `MOBILENETV1_075_quant2_stride16`, `model-stride16.json`);
await getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${2}/100`, `MOBILENETV1_100_quant2_stride8`, `model-stride8.json`);
await getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${2}/100`, `MOBILENETV1_100_quant2_stride16`, `model-stride16.json`);

getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${2}/075`, `MOBILENETV1_075_quant2_stride8`, `model-stride8.json`);
getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${2}/075`, `MOBILENETV1_075_quant2_stride16`, `model-stride16.json`);

getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${2}/100`, `MOBILENETV1_100_quant2_stride8`, `model-stride8.json`);
getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${2}/100`, `MOBILENETV1_100_quant2_stride16`, `model-stride16.json`);

// quant4
await getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/float/050`, `MOBILENETV1_050_quant4_stride8`, `model-stride8.json`);
await getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/float/075`, `MOBILENETV1_075_quant4_stride16`, `model-stride16.json`);

// TODO: not working v101 and quant4
// getPosenetByVersion(`${MOBILENET_STORAGE_PATH}/quant${1}/101`, `MOBILENETV1_101_quant1_stride8`, `model-stride8.json`);
Expand All @@ -55,16 +54,12 @@ async function downloadPosenet() {


// resnet50
getPosenetByVersion(`${RESNET_STORAGE_PATH}/quant${1}`, `RESENET50_quant1_stride16`, `model-stride16.json`);
getPosenetByVersion(`${RESNET_STORAGE_PATH}/quant${2}`, `RESENET50_quant2_stride16`, `model-stride16.json`);

getPosenetByVersion(`${RESNET_STORAGE_PATH}/quant${1}`, `RESENET50_quant1_stride32`, `model-stride32.json`);
getPosenetByVersion(`${RESNET_STORAGE_PATH}/quant${2}`, `RESENET50_quant2_stride32`, `model-stride32.json`);
// TODO: quant4 currently not working
// getPosenetByVersion(`${RESNET_STORAGE_PATH}/quant${4}`, `RESENET50_quant4_stride32`, `model-stride32.json`);

// TODO: quant4 currently not working
// getPosenetByVersion(`${RESNET_STORAGE_PATH}/quant${4}`, `RESENET50_quant4_stride16`, `model-stride16.json`);
await getPosenetByVersion(`${RESNET_STORAGE_PATH}/quant${1}`, `RESENET50_quant1_stride16`, `model-stride16.json`);
await getPosenetByVersion(`${RESNET_STORAGE_PATH}/quant${2}`, `RESENET50_quant2_stride16`, `model-stride16.json`);
await getPosenetByVersion(`${RESNET_STORAGE_PATH}/quant${1}`, `RESENET50_quant1_stride32`, `model-stride32.json`);
await getPosenetByVersion(`${RESNET_STORAGE_PATH}/quant${2}`, `RESENET50_quant2_stride32`, `model-stride32.json`);
await getPosenetByVersion(`${RESNET_STORAGE_PATH}/float`, `RESENET50_quant4_stride32`, `model-stride32.json`);
await getPosenetByVersion(`${RESNET_STORAGE_PATH}/float`, `RESENET50_quant4_stride16`, `model-stride16.json`);
}

async function getPosenetByVersion(STORAGEPATH, OUTPUTDIR, FNAME) {
Expand All @@ -76,7 +71,7 @@ async function getPosenetByVersion(STORAGEPATH, OUTPUTDIR, FNAME) {
posenetDownloader.makeOutputPath();

const posenetManifest = await posenetDownloader.saveJson(FNAME);
console.log(posenetManifest)
// console.log(posenetManifest)

await getWeights(storagePath, outputPath, posenetManifest);

Expand All @@ -93,19 +88,22 @@ async function getWeights(storagePath, outputPath, manifest) {
let weightFile;

const weightUrl = `${storagePath}/${fileName}`;
const localFilePath = `${outputPath}/${fileName}`;

weightFile = await fetch(weightUrl);
weightFile = await weightFile.buffer();
if (!fs.existsSync(localFilePath)) {
weightFile = await fetch(weightUrl);
weightFile = await weightFile.buffer();

fs.writeFile(`${outputPath}/${fileName}`, weightFile, () => {
fs.writeFileSync(localFilePath, weightFile);
console.log(`finished writing: ${fileName}`)
});

} else {
console.log('weight already exists: ', fileName)
}
})

Promise.all(weightsPromiseArray)
return Promise.all(weightsPromiseArray)
}



module.exports = downloadPosenet
module.exports = downloadPosenet
25 changes: 16 additions & 9 deletions scripts/download-models/SketchRNN/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
require('es6-promise').polyfill();
require('isomorphic-fetch');

const sequence = require('promise-sequence');
const fs = require('fs');
const mkdirp = require('mkdirp');
const modelList = require('./modelList');
Expand All @@ -15,19 +17,24 @@ async function downloadSketchRnn(){
mkdirp.sync(outputFolder);

// console.log(modelList)
Promise.all(
modelList.map( async (modelName) => {
const fileName = `${modelName}.gen.json`
let modelJson = await fetch(`${STORAGEPATH}/${fileName}`);
modelJson = await modelJson.json();
await sequence(
modelList.map( (modelName) => async () => {
const fileName = `${modelName}.gen.json`;
const localFilePath = `${outputFolder}/${fileName}`;
const url = `${STORAGEPATH}/${fileName}`
if (!fs.existsSync(localFilePath)) {
let modelJson = await fetch(url);
modelJson = await modelJson.json();

fs.writeFile(`${outputFolder}/${fileName}`, JSON.stringify(modelJson), () => {
fs.writeFileSync(`${outputFolder}/${fileName}`, JSON.stringify(modelJson));
console.log('finished writing: ', fileName)
});
} else {
console.log('already exists: ', fileName)
}

})
)

}

module.exports = downloadSketchRnn;
module.exports = downloadSketchRnn;
99 changes: 41 additions & 58 deletions scripts/download-models/index.js
Original file line number Diff line number Diff line change
@@ -1,60 +1,43 @@
const downloadBodyPix = require('./BodyPix');
const downloadSketchRnn = require('./SketchRnn');
const downloadUNet = require('./UNet');
const downloadSentiment = require('./Sentiment');
const downloadFaceApi = require('./FaceApi');
const downloadSoundClassification = require('./SoundClassification');
const downloadMobilenet = require('./Mobilenet');
const downloadYolo = require('./YOLO');
const downloadPosenet = require('./Posenet');
const downloadPosenet2 = require('./Posenet2');
const sequence = require('promise-sequence');

const selected = process.argv[2];
console.log(selected.toLowerCase());
const modelDownloaders = {
bodypix : require('./BodyPix'),
sketchrnn : require('./SketchRNN'),
unet : require('./UNet'),
sentiment : require('./Sentiment'),
faceapi : require('./FaceApi'),
soundclassification : require('./SoundClassification'),
mobilenet : require('./Mobilenet'),
yolo : require('./YOLO'),
posenet : require('./Posenet'),
posenet2 : require('./Posenet2'),
handpose : require('./Handpose'),
}

switch (selected.toLowerCase()) {
case 'bodypix':
downloadBodyPix();
return;
case 'sketchrnn':
downloadSketchRnn();
return;
case 'unet':
downloadUNet();
return;
case 'sentiment':
downloadSentiment();
return;
case 'faceapi':
downloadFaceApi();
return;
case 'soundclassification':
downloadSoundClassification();
return;
case 'mobilenet':
downloadMobilenet();
return;
case 'yolo':
downloadYolo();
return;
case 'posenet':
downloadPosenet();
return;
case 'posenet2':
downloadPosenet2();
return;
case 'all':
downloadBodyPix();
downloadSketchRnn();
downloadSentiment();
downloadFaceApi();
downloadSoundClassification();
downloadMobilenet();
downloadYolo();
downloadPosenet();
downloadPosenet2();
return;
default:
console.log("nothing selected!")
return;
}
const selected = process.argv.length >=3 && process.argv[2]?.toLowerCase() || 'all';
console.log(selected);

async function download(model) {
const dn = modelDownloaders[model];
if (dn) {
console.log(`downloading ${model}...`)
await dn();
console.log(`downloaded ${model}\n`)
} else {
console.log(`no such ${model} to download`);
}
}

(async () => {
if (selected == 'all') {
const tasks = Object.keys(modelDownloaders).map(model => {
return download.bind(undefined, model);
})
await sequence(tasks);
} else {
await download(selected);
}
})().catch(e => {
// Deal with the fact the chain failed
console.log(e)
});
Loading