-
Notifications
You must be signed in to change notification settings - Fork 0
/
script.js
119 lines (100 loc) · 3.5 KB
/
script.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
const canvas = document.getElementById("main-canvas");
const smallCanvas = document.getElementById("small-canvas");
const displayBox = document.getElementById("prediction");
const confidence = document.getElementById("confidence");
const inputBox = canvas.getContext("2d");
const smBox = smallCanvas.getContext("2d");
let isDrawing = false;
let model;
async function init() {
model = await tf.loadLayersModel("model/model/model.json");
}
function drawStartEvent(event) {
isDrawing = true;
inputBox.strokeStyle = "white";
inputBox.lineWidth = "15";
inputBox.lineJoin = inputBox.lineCap = "round";
inputBox.beginPath();
}
canvas.addEventListener("mousedown", drawStartEvent);
canvas.addEventListener("ontouchstart", drawStartEvent);
function drawMoveEvent(event) {
if (isDrawing) {
drawStroke(event.clientX, event.clientY);
}
}
canvas.addEventListener("mousemove", drawMoveEvent);
canvas.addEventListener("ontouchmove", drawMoveEvent);
function drawEndEvent(event) {
isDrawing = false;
updateDisplay(predict());
}
canvas.addEventListener("mouseup", drawEndEvent);
canvas.addEventListener("ontouchend", drawEndEvent);
/* Draws on canvas */
function drawStroke(clientX, clientY) {
// get mouse coordinates on canvas
const rect = canvas.getBoundingClientRect();
const x = clientX - rect.left;
const y = clientY - rect.top;
// draw
inputBox.lineTo(x, y);
inputBox.stroke();
inputBox.moveTo(x, y);
}
/* Makes predictions */
function predict() {
let values = getPixelData();
let predictions = model.predict(values).dataSync();
return predictions;
}
/* Returns pixel data from canvas after applying transformations */
function getPixelData() {
smBox.drawImage(
inputBox.canvas,
0,
0,
smallCanvas.width,
smallCanvas.height
);
const imgData = smBox.getImageData(
0,
0,
smallCanvas.width,
smallCanvas.height
);
// preserve and normalize values from red channel only
let values = [];
for (let i = 0; i < imgData.data.length; i += 4) {
values.push(imgData.data[i] / 255);
}
values = tf.reshape(values, [1, 28, 28, 1]);
return values;
}
/* Displays predictions on screen */
function updateDisplay(predictions) {
// Find index of best prediction, which corresponds to the predicted value
const maxValue = Math.max(...predictions);
const bestPred = predictions.indexOf(maxValue);
/*
characters = [
'0','1','2','3','4','5','6','7','8','9',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
confidence.innerHTML = `<strong>${Math.round(maxValue * 100)}%</strong> confiance`
displayBox.innerText = characters[bestPred];
*/
const label = String.fromCharCode(bestPred < 10 ? bestPred + 48 : (bestPred < 36 ? bestPred + 55 : bestPred + 61));
confidence.innerHTML = `<strong>${Math.round(maxValue * 100)}%</strong> confiance`
displayBox.innerText = label;
}
document.getElementById("erase").addEventListener("click", erase);
/* Clears canvas */
function erase() {
inputBox.fillStyle = "#111";
inputBox.fillRect(0, 0, canvas.width, canvas.height);
displayBox.innerText = "";
confidence.innerHTML = "—";
}
erase();
init();