Last active
April 24, 2020 16:38
-
-
Save miraculixx/67ca531ff0b06728885b04203aff1dbc to your computer and use it in GitHub Desktop.
test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <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> </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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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