-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
154 lines (118 loc) · 4.14 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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<div>Minion/Goblins</div>
<button type="button" onclick="init()">Start</button>
<div id="webcam-container"></div>
<div id="debug-container"></div>
<img id="card-image"></img>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest/dist/tf.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@teachablemachine/image@latest/dist/teachablemachine-image.min.js"></script>
<script type="text/javascript">
class ValueMonitor {
value = null;
lastChangeAt = 0;
update(newValue) {
if (this.value != newValue) {
this.value = newValue;
this.lastChangeAt = new Date().getTime();
return true;
}
return false;
}
hasValue() {
return this.value != null;
}
age() {
return new Date().getTime() - this.lastChangeAt;
}
status() {;
console.log("hasValue: " + this.hasValue() + " age: " + this.age());
}
}
class Model {
_baseUrl = "";
_model = null;
_value = new ValueMonitor();
constructor(baseUrl) {
this._baseUrl = baseUrl;
}
async load() {
const modelUrl = this._baseUrl + "model.json";
const metadataUrl = this._baseUrl + "metadata.json";
this._model = await tmImage.load(modelUrl, metadataUrl);
}
async predict(canvas, threshold) {
const prediction = await this._model.predict(canvas);
for (let i = 0; i < prediction.length; i++) {
if (prediction[i].probability >= threshold) {
this._value.update(prediction[i].className);
return prediction[i];
}
}
this._value.update(null);
return null;
}
value() {
return this._value.value;
}
age() {
return this._value.age();
}
hasValue() {
return this._value.hasValue();
}
}
let webcam, isInit;
let debugContainer, cardImage;
let categoriesModel = new Model("./models/categories/");
let models = {
"minion": new Model("./models/minion/"),
"goblin": new Model("./models/goblin/"),
};
// Load the image model and setup the webcam
async function init() {
if (isInit) {
return;
}
isInit = true;
await categoriesModel.load();
for (const prop in models) {
await models[prop].load();
}
webcam = new tmImage.Webcam(200, 200, false);
await webcam.setup({ facingMode: "environment" })
await webcam.play();
window.requestAnimationFrame(loop);
// append elements to the DOM
document.getElementById("webcam-container").appendChild(webcam.canvas);
debugContainer = document.getElementById("debug-container");
cardImage = document.getElementById("card-image");
}
async function loop() {
webcam.update(); // update the webcam frame
await predict();
window.requestAnimationFrame(loop);
}
async function predict() {
let category, card;
let model = categoriesModel;
let bestPrediction = await model.predict(webcam.canvas, 0.75);
if (bestPrediction != null && models[bestPrediction.className] != null) {
category = bestPrediction.className;
model = models[bestPrediction.className];
bestPrediction = await model.predict(webcam.canvas, 0.75);
if (bestPrediction != null) {
card = bestPrediction.className;
}
}
if (!model.hasValue()) {
debugContainer.innerText = "?"
+ "\n" + model.age();
return;
}
debugContainer.innerText = model.value()
+ "\n" + model.age()
+ "\n" + bestPrediction.probability.toFixed(2);
if (card != null && model.age() > 1000) {
cardImage.src = "./images/" + card + ".jpg";
}
}
</script>