From 39ce7c85eb57a36f09b3e71609e6511767d89236 Mon Sep 17 00:00:00 2001 From: Leon Chen Date: Sun, 9 Oct 2016 00:54:19 -0400 Subject: [PATCH] update ResNet50 demo --- demos/src/image-urls/index.js | 5 ++++ demos/src/mnist-cnn.js | 2 -- demos/src/mnist-vae.js | 2 -- demos/src/resnet50.css | 23 +++++++++--------- demos/src/resnet50.js | 40 +++++++++++++++++++++++--------- demos/src/resnet50.template.html | 13 ++++------- 6 files changed, 51 insertions(+), 34 deletions(-) create mode 100644 demos/src/image-urls/index.js diff --git a/demos/src/image-urls/index.js b/demos/src/image-urls/index.js new file mode 100644 index 0000000..6103e90 --- /dev/null +++ b/demos/src/image-urls/index.js @@ -0,0 +1,5 @@ +export const IMAGE_URLS = [ + { name: 'cat', value: 'http://i.imgur.com/CzXTtJV.jpg' }, + { name: 'dog', value: 'http://i.imgur.com/OB0y6MR.jpg' }, + { name: 'bridge', value: 'http://i.imgur.com/Bvke53p.jpg' } +] diff --git a/demos/src/mnist-cnn.js b/demos/src/mnist-cnn.js index 23dccb0..7179d4c 100644 --- a/demos/src/mnist-cnn.js +++ b/demos/src/mnist-cnn.js @@ -10,13 +10,11 @@ const MODEL_FILEPATHS_DEV = { weights: '/demos/data/mnist_cnn/mnist_cnn_weights.buf', metadata: '/demos/data/mnist_cnn/mnist_cnn_metadata.json' } - const MODEL_FILEPATHS_PROD = { model: 'demos/data/mnist_cnn/mnist_cnn.json', weights: 'https://transcranial.github.io/keras-js-demos-data/mnist_cnn/mnist_cnn_weights.buf', metadata: 'demos/data/mnist_cnn/mnist_cnn_metadata.json' } - const MODEL_CONFIG = { filepaths: (process.env.NODE_ENV === 'production') ? MODEL_FILEPATHS_PROD : MODEL_FILEPATHS_DEV } diff --git a/demos/src/mnist-vae.js b/demos/src/mnist-vae.js index ecff691..db49cbd 100644 --- a/demos/src/mnist-vae.js +++ b/demos/src/mnist-vae.js @@ -8,13 +8,11 @@ const MODEL_FILEPATHS_DEV = { weights: '/demos/data/mnist_vae/mnist_vae_weights.buf', metadata: '/demos/data/mnist_vae/mnist_vae_metadata.json' } - const MODEL_FILEPATHS_PROD = { model: 'demos/data/mnist_vae/mnist_vae.json', weights: 'https://transcranial.github.io/keras-js-demos-data/mnist_vae/mnist_vae_weights.buf', metadata: 'demos/data/mnist_vae/mnist_vae_metadata.json' } - const MODEL_CONFIG = { filepaths: (process.env.NODE_ENV === 'production') ? MODEL_FILEPATHS_PROD : MODEL_FILEPATHS_DEV } diff --git a/demos/src/resnet50.css b/demos/src/resnet50.css index abb0563..8feced4 100644 --- a/demos/src/resnet50.css +++ b/demos/src/resnet50.css @@ -79,7 +79,7 @@ height: 160px; display: flex; flex-direction: column; - align-items: flex-end; + align-items: flex-start; justify-content: center; user-select: none; cursor: default; @@ -92,8 +92,13 @@ padding: 6px 0; .output-label { + text-align: right; + width: 200px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; font-family: $font-2; - font-size: 20px; + font-size: 18px; color: $color-2; padding: 0 6px; border-right: 2px solid $color-1-lighter; @@ -101,18 +106,14 @@ .output-bar { height: 8px; - transition: height 0.2s ease-out; - } - - .output-bar-rest { - height: 8px; - background: none; + transition: width 0.2s ease-out; } .output-value { - width: 50px; + text-align: left; + margin-left: 5px; font-family: $font-2; - font-size: 16px; + font-size: 14px; color: $color-2; } } @@ -120,7 +121,7 @@ .output-class.predicted { .output-label { color: $color-1; - border-right-color: $color-1; + border-left-color: $color-1; } .output-value { diff --git a/demos/src/resnet50.js b/demos/src/resnet50.js index bba3c24..c81a170 100644 --- a/demos/src/resnet50.js +++ b/demos/src/resnet50.js @@ -5,6 +5,7 @@ import ndarray from 'ndarray' import ops from 'ndarray-ops' import find from 'lodash/find' import * as utils from './utils' +import { IMAGE_URLS } from './image-urls' import { ARCHITECTURE_DIAGRAM, ARCHITECTURE_CONNECTIONS } from './resnet50-arch' const MODEL_FILEPATHS_DEV = { @@ -12,23 +13,15 @@ const MODEL_FILEPATHS_DEV = { weights: '/demos/data/resnet50/resnet50_weights.buf', metadata: '/demos/data/resnet50/resnet50_metadata.json' } - const MODEL_FILEPATHS_PROD = { model: 'demos/data/resnet50/resnet50.json', weights: 'https://transcranial.github.io/keras-js-demos-data/resnet50/resnet50_weights.buf', metadata: 'demos/data/resnet50/resnet50_metadata.json' } - const MODEL_CONFIG = { filepaths: (process.env.NODE_ENV === 'production') ? MODEL_FILEPATHS_PROD : MODEL_FILEPATHS_DEV } -const IMAGE_URL_LIST = [ - { name: 'cat', value: 'http://i.imgur.com/CzXTtJV.jpg' }, - { name: 'dog', value: 'http://i.imgur.com/OB0y6MR.jpg' }, - { name: 'bridge', value: 'http://i.imgur.com/Bvke53p.jpg' } -] - /** * * VUE COMPONENT @@ -46,7 +39,7 @@ export const ResNet50 = Vue.extend({ modelRunning: false, imageURLInput: null, imageURLSelect: null, - imageURLSelectList: IMAGE_URL_LIST, + imageURLSelectList: IMAGE_URLS, imageLoading: false, imageLoadingError: false, output: null, @@ -77,7 +70,13 @@ export const ResNet50 = Vue.extend({ return this.model.layersWithResults }, outputClasses: function () { - if (!this.output) return [] + if (!this.output) { + let empty = [] + for (let i = 0; i < 5; i++) { + empty.push({ name: '.', probability: 0 }) + } + return empty + } return utils.imagenetClassesTopK(this.output, 5) } }, @@ -134,6 +133,11 @@ export const ResNet50 = Vue.extend({ }, loadImageToCanvas: function (url) { + if (!url) { + this.clearAll() + return + } + this.imageLoading = true loadImage( url, @@ -174,7 +178,7 @@ export const ResNet50 = Vue.extend({ // data processing // see https://github.com/fchollet/keras/blob/master/keras/applications/imagenet_utils.py - let dataTensor = ndarray(data, [width, height, 4]) + let dataTensor = ndarray(new Float32Array(data), [width, height, 4]) let dataProcessedTensor = ndarray(new Float32Array(width * height * 3), [width, height, 3]) ops.subseq(dataTensor.pick(null, null, 0), 103.939) ops.subseq(dataTensor.pick(null, null, 1), 116.779) @@ -190,6 +194,20 @@ export const ResNet50 = Vue.extend({ this.output = outputData['fc1000'] this.modelRunning = false }) + }, + + clearAll: function () { + this.modelRunning = false + this.imageURLInput = null + this.imageURLSelect = null + this.imageLoading = false + this.imageLoadingError = false + this.output = null + + this.model.layersWithResults = [] + + const ctx = document.getElementById('input-canvas').getContext('2d') + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height) } } }) diff --git a/demos/src/resnet50.template.html b/demos/src/resnet50.template.html index 604b508..747f793 100644 --- a/demos/src/resnet50.template.html +++ b/demos/src/resnet50.template.html @@ -46,17 +46,14 @@
-
{{ entry.name }}
+
{{ outputClasses[i].name }}
-
-
{{ Math.round(100 * entry.probability) }}%
+
{{ Math.round(100 * outputClasses[i].probability) }}%