Skip to content

Instantly share code, notes, and snippets.

@miraculixx
Last active April 24, 2020 16:38
Show Gist options
  • Save miraculixx/67ca531ff0b06728885b04203aff1dbc to your computer and use it in GitHub Desktop.
Save miraculixx/67ca531ff0b06728885b04203aff1dbc to your computer and use it in GitHub Desktop.
test
<html>
<head>
<style>
#canvas {
border-color: black;
border-style: solid;
width: 128px;
height: 128px;
}
#resized {
border-color: green;
border-style: solid;
width: 28px;
height: 28px;
}
div {
padding-top: 5px;
}
</style>
</head>
<div>
<img src="https://hub.omegaml.io/static/logo.jpg">
<h1>MNIST Digits Recognition using Machine Learning</h1>
<p>This is a live implementation of the MNIST digits recognition problem using a model trained & deployed by omega|ml</p>
<p>The model is adopted from this <a href="https://scikit-learn.org/stable/auto_examples/classification/plot_digits_classification.html">scikit-learn example</a>.
The model has been trained with and deployed by omega|ml with just one line of code.</p>
</div>
<div>
<input type="text" id="creds" placeholder="userid:apikey"></input>
<br>&nbsp;</br>
</div>
<div>
<p>Draw some digit in the black box, then click predict. The data sent to the model is shown in the green box.
Not happy with results? See what the <a target=_blank href="https://en.wikipedia.org/wiki/MNIST_database#/media/File:MnistExamples.png">model knows</a></p>
<canvas id="canvas" width="128" height="128"></canvas>
<canvas id="resized" width="28" height="28"></canvas>
<div>
<a id="convert" href="#">predict</a>
<a id="clear" href="#">clear</a>
</div>
<div id="status">result will be displayed here. </div>
<div>
<table id="results">
<tr id="header">
<th>Input</th>
<th>Output</th>
</tr>
</table>
</div>
<div>
<p>parameters</p>
<ul>
<li>Linewidth <input type="text" id="linewidth" placeholder="linewidth (6)"></input></li>
<li>Model name <input type="text" id="modelname" placeholder="model name (mnist-test)"></input></li>
</ul>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<script src="https://gist.githack.com/miraculixx/67ca531ff0b06728885b04203aff1dbc/raw/48f14dc96d26effd36820be544473afc5d3ecc2c/signtool.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/string-format/0.5.0/string-format.min.js"></script>
<script>
$(function() {
$(function() {
var linewidth = parseInt($("#linewidth").text())
window.signtool = new SignTool("#canvas", 6);
format.extend(String.prototype, {});
if(urlParam("userid")) {
var creds = "{}:{}".format(urlParam("userid"), urlParam('apikey'));
$("#creds").val(creds);
}
$("#linewidth").val(urlParam("linewidth"));
$("#modelname").val(urlParam("modelname"));
});
$("#convert").click(function() {
var resized = $("#resized").get()[0];
var ctx_resized = resized.getContext('2d');
var source_data = getCanvasImage("#canvas");
var image = getCanvasImage("#canvas");
var credentials = $('#creds').val();
var modelname = $('#modelname').val() || 'mnist-test';
var dsname = 'stream-{}'.format(modelname);
$("#result").text('calculating...');
$(image).on('load', function() {
resizeImageOnCanvas(image, '#resized', 28, 28)
var imgData = getCanvasImageData('#resized');
var pixels = grayScaleImageData(imgData);
var dataset = prepareDataset(pixels);
var promise = putDataset(dataset, dsname, credentials);
promise.done(function() {
var promise = getPrediction(modelname, dsname, credentials);
promise.done(function(value) {
console.log('prediction is', value.result);
$("#status").text(value.result);
$("#results #header").after('<tr class="record"><td><img></td><td><p></p></tr>');
$("#results .record:first img").attr('src', resized.toDataURL('image/png'));
$("#results .record:first p").text(value.result);
});
}).fail(function(error, msg) {
$("#status").text(error.statusText)
});
console.log(pixels);
});
});
$("#clear").click(function() {
clearCanvas('#canvas');
clearCanvas('#resized');
window.signtool.lineWidth = parseInt($("#linewidth").val());
});
});
function grayScaleImageData(imgData) {
var data = imgData.data;
var pixels = new Array(data.length / 4);
for (var i = 0, j = 0; i < pixels.length; i++, j += 4) {
var lightness = (data[j] + data[j + 1] + data[j + 2] + data[j + 3]);
pixels[i] = lightness / 255;
}
return pixels;
};
function getCanvasImageData(canvasId) {
var canvas = $(canvasId).get()[0];
var ctx = canvas.getContext('2d');
return ctx.getImageData(0, 0, canvas.width, canvas.height);
};
function getCanvasImage(canvasId) {
var canvas = $(canvasId).get()[0];
var image = new Image();
image.src = canvas.toDataURL('image/png');
return image;
};
function resizeImageOnCanvas(image, canvasId, w, h) {
var canvas = $(canvasId).get()[0];
var ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0, w, h);
};
function clearCanvas(canvasId) {
console.log('clearing')
var cv = $(canvasId).get()[0];
var ctx = cv.getContext('2d');
console.log(canvasId, cv.width, cv.height, ctx);
ctx.clearRect(0, 0, cv.width, cv.height);
var data = ctx.getImageData(0, 0, cv.width, cv.height);
ctx.putImageData(data, 0, 0);
};
function prepareDataset(pixels) {
var data = {
"data": { "x": pixels },
"columns": ["x"],
"orient": "index",
};
return data;
};
function getPrediction(model, datax, credentials) {
var url = 'https://hub.omegaml.io/api/v1/model/{}/predict/?datax={}';;
var promise = $.ajax({
type: 'PUT',
headers: {
"Authorization": "ApiKey " + credentials,
"Content-Type": "application/json",
},
url: url.format(model, datax),
contentType: 'application/json',
});
promise.done(function () {
console.log('SUCCESS');
}).fail(function (msg) {
console.log('FAIL');
}).always(function (msg) {
console.log('ALWAYS');
});
return promise;
};
function putDataset(dataset, name, credentials) {
var url = 'https://hub.omegaml.io/api/v1/dataset/{}/?append=0';
var promise = $.ajax({
type: 'PUT',
headers: {
"Authorization": "ApiKey " + credentials,
"Content-Type": "application/json",
},
url: url.format(name),
contentType: 'application/json',
data: JSON.stringify(dataset), // access in body
});
promise.done(function () {
console.log('SUCCESS');
}).fail(function (msg) {
console.log('FAIL');
}).always(function (msg) {
console.log('ALWAYS');
});
return promise;
};
// https://stackoverflow.com/a/41152400/890242
function urlParam(name) {
var search = window.location.search || window.parent.location.search;
var results = new RegExp('[\?&]' + name + '=([^&#]*)')
.exec();
return (results !== null) ? results[1] || 0 : undefined;
}
</script>
</html>
class SignTool {
constructor(canvasid, lw) {
this.initVars(canvasid, lw)
this.initEvents()
}
initVars(canvasid, lw) {
this.canvas = $(canvasid || '#canvas')[0]
this.ctx = this.canvas.getContext("2d")
this.isMouseClicked = false
this.isMouseInCanvas = false
this.prevX = 0
this.currX = 0
this.prevY = 0
this.currY = 0
this.lineWidth = lw || 8;
}
initEvents() {
$(this.canvas).on("mousemove", (e) => this.onMouseMove(e))
$(this.canvas).on("mousedown", (e) => this.onMouseDown(e))
$(this.canvas).on("mouseup", () => this.onMouseUp())
$(this.canvas).on("mouseout", () => this.onMouseOut())
$(this.canvas).on("mouseenter", (e) => this.onMouseEnter(e))
}
onMouseDown(e) {
this.isMouseClicked = true
this.updateCurrentPosition(e)
}
onMouseUp() {
this.isMouseClicked = false
}
onMouseEnter(e) {
this.isMouseInCanvas = true
this.updateCurrentPosition(e)
}
onMouseOut() {
this.isMouseInCanvas = false
}
onMouseMove(e) {
if (this.isMouseClicked && this.isMouseInCanvas) {
this.updateCurrentPosition(e)
this.draw()
}
}
updateCurrentPosition(e) {
this.prevX = this.currX
this.prevY = this.currY
this.currX = e.clientX - this.canvas.offsetLeft
this.currY = e.clientY - this.canvas.offsetTop
}
draw() {
this.ctx.beginPath()
this.ctx.moveTo(this.prevX, this.prevY)
this.ctx.lineTo(this.currX, this.currY)
this.ctx.strokeStyle = "black"
this.ctx.lineWidth = this.lineWidth
this.ctx.stroke()
this.ctx.closePath()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment