mirror of
https://github.com/wassname/keras-js.git
synced 2026-09-12 12:33:40 +08:00
update ResNet50 ImageNet demo
This commit is contained in:
+2
-1
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user