-
Notifications
You must be signed in to change notification settings - Fork 1k
/
index.html
132 lines (123 loc) · 4.03 KB
/
index.html
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
120
121
122
123
124
125
126
127
128
129
130
131
132
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>MNIST with GGML</title>
<script src="mnist.js"></script>
</head>
<body>
<h2>MNIST digit recognizer with <a href="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/ggerganov/ggml">GGML</a></h2>
<p id="msg">Loading model and data set, please wait ...</p>
<canvas id="ggCanvas" width="364" height="364" style="border:2px solid #d3d3d3;">
Your browser does not support the HTML canvas tag.
</canvas>
<div>
<button id="clear" onclick="onClear()">Clear</button>
<button id="random" onclick="onRandom()" disabled>Random</button>
</div>
<div>
<p id="prediction"></p>
</div>
<script>
"use strict";
const DIGIT_SIZE = 28; // digits are 28x28 pixels
var canvas = document.getElementById("ggCanvas");
var ctx = canvas.getContext("2d");
var digit = new Array(DIGIT_SIZE*DIGIT_SIZE).fill(0);
var dragging = false;
function onClear(event) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
digit.fill(0);
document.getElementById("prediction").innerHTML = "";
}
function onRandom(event) {
onClear();
var buf = Module._malloc(digit.length);
if (buf == 0) {
console.log("failed to allocate memory");
return;
}
let ret = Module.ccall('wasm_random_digit', null, ['number'], [buf]);
let digitBytes = new Uint8Array(Module.HEAPU8.buffer, buf, digit.length);
for (let i = 0; i < digit.length; i++) {
digit[i] = digitBytes[i];
let x = i % DIGIT_SIZE;
let y = Math.floor(i / DIGIT_SIZE);
setPixel(x, y, digit[i]);
}
Module._free(buf);
onMouseUp();
}
// Get the position of the mouse relative to the canvas
function getMousePos(event) {
if (event.touches !== undefined && event.touches.length > 0) {
event = event.touches[0];
}
var rect = canvas.getBoundingClientRect();
return [Math.floor(event.clientX) - rect.left, Math.floor(event.clientY) - rect.top];
}
function setPixel(x, y, val) {
digit[y * DIGIT_SIZE + x] = val;
let canvasX = x * 13;
let canvasY = y * 13;
let color = 255 - val;
ctx.fillStyle = "#" + color.toString(16) + color.toString(16) + color.toString(16);
ctx.fillRect(canvasX, canvasY, 13, 13);
}
function onMouseDown(e) {
dragging = true;
let [mouseX, mouseY] = getMousePos(e);
setPixel(Math.floor(mouseX / 13), Math.floor(mouseY / 13), 255);
}
function onMouseUp(e) {
dragging = false;
var buf = Module._malloc(digit.length);
if (buf == 0) {
console.log("failed to allocate memory");
return;
}
Module.HEAPU8.set(digit, buf);
let prediction = Module.ccall('wasm_eval', null, ['number'], [buf]);
Module._free(buf);
if (prediction >= 0) {
document.getElementById("prediction").innerHTML = "Predicted digit is <b>" + prediction + "</b>";
}
}
function onMouseMove(e) {
if (dragging) {
let [mouseX, mouseY] = getMousePos(e);
setPixel(Math.floor(mouseX / 13), Math.floor(mouseY / 13), 255);
}
}
// Prevent scrolling when touching the canvas
document.body.addEventListener("touchstart", function (e) {
if (e.target == canvas) {
e.preventDefault();
}
}, {passive: false});
document.body.addEventListener("touchend", function (e) {
if (e.target == canvas) {
e.preventDefault();
}
}, {passive: false});
document.body.addEventListener("touchmove", function (e) {
if (e.target == canvas) {
e.preventDefault();
}
}, {passive: false});
function onRuntimeInitialized() {
// Use the same handlers for mouse and touch events
canvas.onmousedown = onMouseDown;
canvas.onmouseup = onMouseUp;
canvas.onmousemove = onMouseMove;
canvas.ontouchstart = onMouseDown;
canvas.ontouchend = onMouseUp;
canvas.ontouchmove = onMouseMove;
document.getElementById("msg").innerHTML = "Draw a single digit on the canvas below:"
document.getElementById("random").disabled = false;
}
Module['onRuntimeInitialized'] = onRuntimeInitialized;
</script>
</body>
</html>