update ResNet50 ImageNet demo

This commit is contained in:
Leon Chen
2016-10-06 05:06:29 -04:00
parent 5cf643499d
commit 6a5cd57f7d
7 changed files with 112 additions and 18 deletions
+2 -1
View File
@@ -26,7 +26,8 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/material-design-lite/1.2.1/material.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.6/d3.min.js"></script>
<script src="https://rawgit.com/posva/vue-mdl/master/dist/vue-mdl.min.js"></script>
<script src="https://cdn.rawgit.com/posva/vue-mdl/v0.9.4/dist/vue-mdl.min.js"></script>
<script src="https://cdn.rawgit.com/blueimp/JavaScript-Load-Image/v2.6.2/js/load-image.all.min.js"></script>
<script src="/lib/weblas.js"></script>
<script src="/dist/keras.js"></script>
<script src="dist/bundle.js"></script>
+1
View File
@@ -3,6 +3,7 @@ $color-1-light: rgba(27, 188, 155, 0.6);
$color-1-lighter: rgba(27, 188, 155, 0.3);
$color-2: #69707a;
$color-3: #393E46;
$color-err: #D24D57;
$font-1: 'Fira Sans', sans-serif;
$font-2: 'Inconsolata', sans-serif;
+3 -3
View File
@@ -218,9 +218,9 @@ export const MnistVae = Vue.extend({
this.layerResultImages.forEach((result, layerNum) => {
const scalingFactor = this.layerDisplayConfig[result.name].scalingFactor
result.images.forEach((image, imageNum) => {
let ctx = document.getElementById(`intermediate-result-${layerNum}-${imageNum}`).getContext('2d')
const ctx = document.getElementById(`intermediate-result-${layerNum}-${imageNum}`).getContext('2d')
ctx.putImageData(image, 0, 0)
let ctxScaled = document.getElementById(`intermediate-result-${layerNum}-${imageNum}-scaled`).getContext('2d')
const ctxScaled = document.getElementById(`intermediate-result-${layerNum}-${imageNum}-scaled`).getContext('2d')
ctxScaled.save()
ctxScaled.scale(scalingFactor, scalingFactor)
ctxScaled.clearRect(0, 0, ctxScaled.canvas.width, ctxScaled.canvas.height)
@@ -234,7 +234,7 @@ export const MnistVae = Vue.extend({
this.layerResultImages.forEach((result, layerNum) => {
const scalingFactor = this.layerDisplayConfig[result.name].scalingFactor
result.images.forEach((image, imageNum) => {
let ctxScaled = document.getElementById(`intermediate-result-${layerNum}-${imageNum}-scaled`).getContext('2d')
const ctxScaled = document.getElementById(`intermediate-result-${layerNum}-${imageNum}-scaled`).getContext('2d')
ctxScaled.save()
ctxScaled.scale(scalingFactor, scalingFactor)
ctxScaled.clearRect(0, 0, ctxScaled.canvas.width, ctxScaled.canvas.height)
+18
View File
@@ -36,6 +36,24 @@
.column.input-column {
justify-content: flex-end;
.loading-indicator {
display: flex;
flex-direction: column;
align-self: flex-start;
.mdl-spinner {
margin: 20px;
align-self: center;
}
.error {
color: $color-err;
font-size: 14px;
font-family: $font-1;
margin: 20px;
}
}
.canvas-container {
display: inline-flex;
justify-content: flex-end;
+73 -8
View File
@@ -1,4 +1,4 @@
/* global Vue */
/* global Vue, loadImage */
import './resnet50.css'
import * as utils from './utils'
@@ -37,12 +37,14 @@ export const ResNet50 = Vue.extend({
return {
model: new KerasJS.Model(MODEL_CONFIG),
modelLoading: true,
imageURL: '',
imageURLInput: null,
imageURLSelect: null,
imageURLSelectList: [
{ name: 'cat', value: 'URL1' },
{ name: 'cat', value: 'http://i.imgur.com/CzXTtJV.jpg' },
{ name: 'dog', value: 'URL2' }
],
input: new Float32Array(224 * 224 * 3),
imageLoading: false,
imageLoadingError: false,
output: new Float32Array(1000),
layerResultImages: [],
layerDisplayConfig: LAYER_DISPLAY_CONFIG,
@@ -61,7 +63,7 @@ export const ResNet50 = Vue.extend({
this.model.initialize()
this.model.ready().then(() => {
this.modelLoading = false
this.getIntermediateResults()
//this.getIntermediateResults()
})
},
@@ -71,6 +73,69 @@ export const ResNet50 = Vue.extend({
this.model.gpu = !this.useGpu
},
imageURLInputChanged: function (e) {
this.imageURLSelect = null
this.loadImageToCanvas(this.imageURLInput)
},
imageURLSelectChanged: function (e) {
this.imageURLInput = this.imageURLSelect
this.loadImageToCanvas(this.imageURLSelect)
},
loadImageToCanvas: function (url) {
this.imageLoading = true
loadImage(
url,
img => {
if (img.type === 'error') {
this.imageLoadingError = true
this.imageLoading = false
} else {
// load image data onto input canvas
const ctx = document.getElementById('input-canvas').getContext('2d')
ctx.drawImage(img, 0, 0)
this.imageLoadingError = false
this.imageLoading = false
// model predict
this.runModel()
}
},
{
maxWidth: 224,
maxHeight: 224,
cover: true,
crop: true,
canvas: true,
crossOrigin: 'Anonymous'
}
)
},
runModel: function () {
const ctx = document.getElementById('input-canvas').getContext('2d')
const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height)
const { data, width, height } = imageData
// data processing
// see https://github.com/fchollet/keras/blob/master/keras/applications/imagenet_utils.py
let dataProcessed = new Float32Array(width * height * 3)
for (let i = 0, len = data.length; i < len; i += 4) {
// RGB -> BGR
dataProcessed[i / 4 + 2] = data[i] - 103.939
dataProcessed[i / 4 + 1] = data[i + 1] - 116.779
dataProcessed[i / 4] = data[i + 2] - 123.68
}
const inputData = {
'input_1': dataProcessed
}
const outputData = this.model.predict(inputData)
this.output = outputData['fc1000']
console.log(this.output)
//this.getIntermediateResults()
},
getIntermediateResults: function () {
let results = []
for (let [name, layer] of this.model.modelLayersMap.entries()) {
@@ -101,9 +166,9 @@ export const ResNet50 = Vue.extend({
this.layerResultImages.forEach((result, layerNum) => {
const scalingFactor = this.layerDisplayConfig[result.name].scalingFactor
result.images.forEach((image, imageNum) => {
let ctx = document.getElementById(`intermediate-result-${layerNum}-${imageNum}`).getContext('2d')
const ctx = document.getElementById(`intermediate-result-${layerNum}-${imageNum}`).getContext('2d')
ctx.putImageData(image, 0, 0)
let ctxScaled = document.getElementById(`intermediate-result-${layerNum}-${imageNum}-scaled`).getContext('2d')
const ctxScaled = document.getElementById(`intermediate-result-${layerNum}-${imageNum}-scaled`).getContext('2d')
ctxScaled.save()
ctxScaled.scale(scalingFactor, scalingFactor)
ctxScaled.clearRect(0, 0, ctxScaled.canvas.width, ctxScaled.canvas.height)
@@ -117,7 +182,7 @@ export const ResNet50 = Vue.extend({
this.layerResultImages.forEach((result, layerNum) => {
const scalingFactor = this.layerDisplayConfig[result.name].scalingFactor
result.images.forEach((image, imageNum) => {
let ctxScaled = document.getElementById(`intermediate-result-${layerNum}-${imageNum}-scaled`).getContext('2d')
const ctxScaled = document.getElementById(`intermediate-result-${layerNum}-${imageNum}-scaled`).getContext('2d')
ctxScaled.save()
ctxScaled.scale(scalingFactor, scalingFactor)
ctxScaled.clearRect(0, 0, ctxScaled.canvas.width, ctxScaled.canvas.height)
+12 -4
View File
@@ -9,13 +9,21 @@
<div class="input-container">
<div class="input-label">Enter an image URL or select from dropdown</div>
<div class="image-url">
<mdl-textfield floating-label="enter image url" :value.sync="imageURL" spellcheck="false"></mdl-textfield>
<mdl-textfield floating-label="enter image url" :value.sync="imageURLInput" spellcheck="false"
@change="imageURLInputChanged"
></mdl-textfield>
<span>or</span>
<mdl-select label="select image" id="image-url-select" :value.sync="imageURL" :options="imageURLSelectList" style="width:200px;"></mdl-select>
<mdl-select label="select image" id="image-url-select" :value.sync="imageURLSelect" :options="imageURLSelectList" style="width:200px;"
@change="imageURLSelectChanged"
></mdl-select>
</div>
</div>
<div class="columns input-output">
<div class="column input-column">
<div class="loading-indicator">
<mdl-spinner v-if="imageLoading"></mdl-spinner>
<div class="error" v-if="imageLoadingError">Error loading URL</div>
</div>
<div class="canvas-container">
<canvas id="input-canvas" width="224" height="224"></canvas>
</div>
@@ -28,7 +36,7 @@
</div>
</div>
</div>
<div class="layer-results-container">
<!--<div class="layer-results-container">
<div
v-for="layerResult in layerResultImages"
class="layer-result"
@@ -51,5 +59,5 @@
></canvas>
</div>
</div>
</div>
</div>-->
</div>
+3 -2
View File
@@ -16,7 +16,7 @@
<div id="app">
<div class="columns">
<div class="column is-3" style="min-width: 350px; max-width: 450px;">
<menu></menu>
<menu :current-view="currentView"></menu>
</div>
<div class="column is-9">
<component :is="currentView"></component>
@@ -26,7 +26,8 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/material-design-lite/1.2.1/material.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.6/d3.min.js"></script>
<script src="https://rawgit.com/posva/vue-mdl/master/dist/vue-mdl.min.js"></script>
<script src="https://cdn.rawgit.com/posva/vue-mdl/v0.9.4/dist/vue-mdl.min.js"></script>
<script src="https://cdn.rawgit.com/blueimp/JavaScript-Load-Image/v2.6.2/js/load-image.all.min.js"></script>
<script src="lib/weblas.js"></script>
<script src="dist/keras.min.js"></script>
<script src="demos/dist/bundle.min.js"></script>