Code viewer for World: Improved Doodle Recognitio...

// Cloned by joey on 18 Nov 2021 from World "Improved Doodle Recognition Using TensorFlow.js" by Michael Ryan 
// Please leave this clone trail here.
 
const colourMap={GREEN:"#00FF00",YELLOW:"#FFFF00",ORANGE:"#FFA500",RED:"#B20000",WHITE:"#FFFFFF"};function clearCanvas(){var e=document.getElementById("doodleCanvas").getContext("2d");e.clearRect(0,0,e.canvas.width,e.canvas.height),clickX=new Array,clickY=new Array,clickDrag=new Array,e.fillStyle="black",e.fillRect(0,0,e.canvas.width,e.canvas.height),e.fill()}document.write('\n\x3c!-- Bootstrap CSS --\x3e\n<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">\n<style>\ntable, td, th {\n  border: 1px solid black;\n    text-align: center;\n}\n\ntd:hover {\n    background-color: lightblue;\n}\n\n.table {\n  border-collapse: collapse;\n  width: 100%;\n}\n\n.slider {\n  -webkit-appearance: none;\n  height: 25px;\n  background: #d3d3d3;\n  outline: none;\n  opacity: 0.7;\n  -webkit-transition: .2s;\n  transition: opacity .2s;\n}\n\n.slider:hover {\n  opacity: 1;\n}\n\n.slider::-webkit-slider-thumb {\n  -webkit-appearance: none;\n  appearance: none;\n  width: 25px;\n  height: 25px;\n  background: #4CAF50;\n  cursor: pointer;\n}\n\n.slider::-moz-range-thumb {\n  width: 25px;\n  height: 25px;\n  background: #4CAF50;\n  cursor: pointer;\n}\n\n</style>\n<div style="text-align: center;">\n    <canvas id="doodleCanvas" width="280" height="280" style="border:1px solid black;"></canvas>\n    <div>\n        <button type="button" style="margin:5px" class="btn btn-secondary" onclick="clearCanvas()">Clear or click spacebar</button>\n    </div>\n    \n    <div>\n        <canvas id="smallCanvas" width="28" height="28" style="height:100;width:100; border:1px solid black;" >\n    </div>\n    \n    <p>Brush Size:</p>\n    <input type="range" min="1" max="100" value="25" class="slider" id="brushSize" onchange="updateBrushSize(this.value)">\n    \n    <p>Brush Type:</p>\n    <input type="range" min="0" max="2" value="0" class="slider" id="brushType" onchange="updateBrushType(this.value)">\n    \n    <div>\n        <h2>Select Correct Result To Retrain</h2>\n        <table class="table" id="predictionTable">\n        </table>\n    </div>\n</div>\n\n');var lineJoin=["round","bevel","miter"],BRUSH_STYLE=0,BRUSH_SIZE=25;const PIXELS=28,PIXELSSQUARED=784;var inputs,paint,models=[],clickX=[],clickY=[],clickDrag=[];function updateBrushSize(e){BRUSH_SIZE=e,redraw(),makePredictions()}function updateBrushType(e){BRUSH_STYLE=e,redraw(),makePredictions()}function loadTensorFlowLibraries(){return $.when($.getScript("https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.0.0/dist/tf.min.js"),$.getScript("https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-vis@1.0.2/dist/tfjs-vis.umd.min.js"),$.getScript("uploads/michaelryan/data.js"))}function getColourForPredictionValue(e){let t;return e>=.8?t=colourMap.GREEN:e>=.6&&e<.8?t=colourMap.YELLOW:e>=.4&&e<.6?t=colourMap.ORANGE:e>=.2&&e<.4&&(t=colourMap.RED),t}function fillPredictionTable(e,t){e+=1;let n=0;for(let a=0;a<t.length;a++)t[a]>t[n]&&(n=a),$(`#${e}_${a}`).css("background-color",colourMap.WHITE),$(`#${e}_${a}`).html(t[a].toFixed(2));let a=getColourForPredictionValue(t[n]);$(`#${e}_${n}`).css("background-color",a)}async function selectCorrectValue(e){console.log(e);let t=[0,0,0,0,0,0,0,0,0,0];t[e]=1;const[n,a]=tf.tidy(()=>{const e=data.nextTrainBatch(1);return[e.xs,e.labels]});tf.tensor2d(inputs,[1,784]),tf.tensor2d(t,[1,10]);let o=data.nextTrainArray();o.batchImagesArray.set(inputs,IMAGE_SIZE),o.batchLabelsArray.set(t,NUM_CLASSES);const l=tf.tensor2d(o.batchImagesArray,[2,IMAGE_SIZE]),i=tf.tensor2d(o.batchLabelsArray,[2,NUM_CLASSES]);console.log("Retraining models...."),await retrainModels(l,i),console.log("Complete...."),makePredictions()}async function retrainModels(e,t){const n=models.map(async n=>{await n.fit(e.reshape([2,28,28,1]),t)});await Promise.all(n)}function createPredictionTable(){var e=$("#predictionTable"),t="Model 500";for(let a=0;a<=models.length;a++){var n="<tr>";for(let e=-1;e<10;e++)0===a?n+=-1===e?"<td></td>":`<td onclick="selectCorrectValue(${e})">${e}</td>`:-1===e?(n+=`<td>${t}</td>`,t+="0"):n+=`<td id=${a}_${e}>0.00</td>`;n+="</tr>",e.append(n)}}function makePredictions(){let e=document.getElementById("smallCanvas").getContext("2d"),t=e.getImageData(0,0,e.canvas.width,e.canvas.height);inputs=new Float32Array(PIXELSSQUARED);for(let e=0;e<PIXELSSQUARED;e++)inputs[e]=t.data[4*e]/255;currentTensor=tf.tensor2d(inputs,[1,PIXELSSQUARED]);for(let e=0;e<models.length;e++){fillPredictionTable(e,models[e].predict(currentTensor.reshape([1,28,28,1])).dataSync())}}async function setupCanvas(){var e=document.getElementById("doodleCanvas").getContext("2d");function t(e,t,n){clickX.push(e),clickY.push(t),clickDrag.push(n)}document.getElementById("smallCanvas").getContext("2d").scale(.1,.1),e.fillStyle="black",e.fillRect(0,0,e.canvas.width,e.canvas.height),e.fill(),createPredictionTable(),$("#doodleCanvas").mousedown(function(n){n.pageX,this.offsetLeft,n.pageY,this.offsetTop;paint=!0,t(n.pageX-this.offsetLeft,n.pageY-this.offsetTop),redraw(e)}),$("#doodleCanvas").mousemove(function(n){paint&&(t(n.pageX-this.offsetLeft,n.pageY-this.offsetTop,!0),redraw(e))}),$("#doodleCanvas").mouseup(function(e){paint=!1,makePredictions()}),$("#doodleCanvas").mouseleave(function(e){paint=!1}),$("body").keyup(function(e){32==e.keyCode&&clearCanvas()})}function redraw(e){(e=document.getElementById("doodleCanvas").getContext("2d")).clearRect(0,0,e.canvas.width,e.canvas.height),e.fillStyle="black",e.fillRect(0,0,e.canvas.width,e.canvas.height),e.fill(),e.strokeStyle="white",e.lineJoin=lineJoin[BRUSH_STYLE],e.lineWidth=BRUSH_SIZE;for(var t=0;t<clickX.length;t++)e.beginPath(),clickDrag[t]&&t?e.moveTo(clickX[t-1],clickY[t-1]):e.moveTo(clickX[t]-1,clickY[t]),e.lineTo(clickX[t],clickY[t]),e.closePath(),e.stroke();e.filter="blur(2px)",drawSmallCanvas(doodleCanvas)}function drawSmallCanvas(e){const t=document.getElementById("smallCanvas").getContext("2d");t.clearRect(0,0,t.canvas.width,t.canvas.height),t.fillStyle="black",t.fillRect(0,0,t.canvas.width,t.canvas.height),t.fill(),t.drawImage(document.getElementById("doodleCanvas"),0,0)}function compileModels(e){console.log("compiling...");const t=tf.train.adam();for(let n=0;n<e.length;n++)e[n].compile({optimizer:t,loss:"categoricalCrossentropy",metrics:["accuracy"]});console.log("Neural Networks loaded...")}let data;async function setup(){console.log("Load external scripts..."),await loadTensorFlowLibraries(),console.log("Scripts loaded..."),models.push(await tf.loadLayersModel("uploads/michaelryan/500-model.json")),models.push(await tf.loadLayersModel("uploads/michaelryan/5000-model.json")),models.push(await tf.loadLayersModel("uploads/michaelryan/50000-model.json")),compileModels(models),data=new MnistData,await data.load(),setupCanvas(),console.log("Ready to go")}setup();