edge-impulse-linux 1.17.1 → 1.17.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cli/linux/runner-utils.d.ts +1 -0
- package/build/cli/linux/runner-utils.js +73 -15
- package/build/cli/linux/runner-utils.js.map +1 -1
- package/build/cli/linux/runner.js +42 -7
- package/build/cli/linux/runner.js.map +1 -1
- package/build/cli/linux/webserver/public/webserver.js +124 -17
- package/build/cli/linux/webserver/public/webserver.js.map +1 -1
- package/build/cli/linux/webserver/views/index.js +5 -3
- package/build/cli/linux/webserver/views/index.js.map +1 -1
- package/build/library/classifier/image-classifier.d.ts +4 -1
- package/build/library/classifier/image-classifier.js +4 -4
- package/build/library/classifier/image-classifier.js.map +1 -1
- package/build/sdk/studio/sdk/api/rawDataApi.d.ts +55 -1
- package/build/sdk/studio/sdk/api/rawDataApi.js +166 -1
- package/build/sdk/studio/sdk/api/rawDataApi.js.map +1 -1
- package/build/sdk/studio/sdk/model/batchEditBoundingBoxesRequest.d.ts +32 -0
- package/build/sdk/studio/sdk/model/batchEditBoundingBoxesRequest.js +34 -0
- package/build/sdk/studio/sdk/model/batchEditBoundingBoxesRequest.js.map +1 -0
- package/build/sdk/studio/sdk/model/models.d.ts +1 -0
- package/build/sdk/studio/sdk/model/models.js +3 -0
- package/build/sdk/studio/sdk/model/models.js.map +1 -1
- package/build/sdk/studio/sdk/model/permission.d.ts +1 -1
- package/build/sdk/studio/sdk/model/permission.js +1 -1
- package/build/sdk/studio/sdk/model/permission.js.map +1 -1
- package/cli/linux/webserver/public/assets/mobileclient.css +26 -3
- package/cli/linux/webserver/public/webserver.js +136 -17
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@ window.WebServer = async () => {
|
|
|
2
2
|
|
|
3
3
|
const els = {
|
|
4
4
|
title: document.querySelector('#header-row h1'),
|
|
5
|
+
cameraOuterContainer: document.querySelector('#capture-camera .capture-camera-outer'),
|
|
5
6
|
cameraContainer: document.querySelector('#capture-camera .capture-camera-inner'),
|
|
6
7
|
cameraImg: document.querySelector('#capture-camera img'),
|
|
7
8
|
timePerInference: document.querySelector('#time-per-inference'),
|
|
@@ -29,6 +30,9 @@ window.WebServer = async () => {
|
|
|
29
30
|
];
|
|
30
31
|
let colorIx = 0;
|
|
31
32
|
const labelToColor = { };
|
|
33
|
+
let isFirstClassification = true;
|
|
34
|
+
let inferenceIx = 0;
|
|
35
|
+
let lastClassification;
|
|
32
36
|
|
|
33
37
|
function switchView(el) {
|
|
34
38
|
for (let k of Object.keys(els.views)) {
|
|
@@ -150,6 +154,7 @@ window.WebServer = async () => {
|
|
|
150
154
|
inputEl.oninput = () => {
|
|
151
155
|
if (typeof threshold[k] === 'number') {
|
|
152
156
|
if (!inputEl.value || isNaN(Number(inputEl.value))) return;
|
|
157
|
+
if (k === 'min_score' && Number(inputEl.value) === 0) return;
|
|
153
158
|
|
|
154
159
|
threshold[k] = Number(inputEl.value);
|
|
155
160
|
}
|
|
@@ -194,14 +199,65 @@ window.WebServer = async () => {
|
|
|
194
199
|
bindThresholdSettings(opts.thresholds);
|
|
195
200
|
});
|
|
196
201
|
|
|
202
|
+
const onWindowResize = () => {
|
|
203
|
+
if (els.cameraContainer.naturalWidth === 0) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
let oldStyleWidth = els.cameraImg.style.width;
|
|
208
|
+
const containerWidth = els.cameraOuterContainer.getBoundingClientRect().width;
|
|
209
|
+
|
|
210
|
+
// height >480
|
|
211
|
+
if (els.cameraImg.naturalHeight > 480) {
|
|
212
|
+
// and fits within the container? just display as is
|
|
213
|
+
if (els.cameraImg.naturalWidth < containerWidth) {
|
|
214
|
+
els.cameraImg.style.width = els.cameraImg.naturalWidth + 'px';
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
// does not fit within container? just use 100%
|
|
218
|
+
els.cameraImg.style.width = containerWidth + 'px';
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
// what if we resize to 480 high?
|
|
223
|
+
const factor = els.cameraImg.naturalWidth / els.cameraImg.naturalHeight;
|
|
224
|
+
let newHeight = 480;
|
|
225
|
+
let newWidth = newHeight * factor;
|
|
226
|
+
|
|
227
|
+
// fits within the container? just display as is
|
|
228
|
+
if (newWidth < containerWidth) {
|
|
229
|
+
els.cameraImg.style.width = newWidth + 'px';
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
// does not fit within container? just use 100%
|
|
233
|
+
els.cameraImg.style.width = containerWidth + 'px';
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (oldStyleWidth !== els.cameraImg.style.width && lastClassification) {
|
|
238
|
+
onClassification({
|
|
239
|
+
dontUpdateTable: true,
|
|
240
|
+
...lastClassification,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
let isFirstImage = true;
|
|
197
246
|
socket.on('image', (opts) => {
|
|
247
|
+
if (isFirstImage) {
|
|
248
|
+
els.cameraImg.onload = () => {
|
|
249
|
+
onWindowResize();
|
|
250
|
+
els.cameraImg.onload = null;
|
|
251
|
+
};
|
|
252
|
+
isFirstImage = false;
|
|
253
|
+
}
|
|
198
254
|
els.cameraImg.src = opts.img;
|
|
199
255
|
});
|
|
256
|
+
window.addEventListener('resize', onWindowResize);
|
|
200
257
|
|
|
201
|
-
|
|
202
|
-
|
|
258
|
+
function onClassification(opts) {
|
|
259
|
+
lastClassification = opts;
|
|
203
260
|
|
|
204
|
-
socket.on('classification', (opts) => {
|
|
205
261
|
let result = opts.result;
|
|
206
262
|
let modelType = opts.modelType;
|
|
207
263
|
|
|
@@ -218,16 +274,39 @@ window.WebServer = async () => {
|
|
|
218
274
|
|
|
219
275
|
els.imageClassify.row.style.display = 'none';
|
|
220
276
|
|
|
221
|
-
if (result.classification) {
|
|
277
|
+
if (result.classification && !opts.dontUpdateTable) {
|
|
278
|
+
const showOnlyTopResults = Object.keys(result.classification).length > 10 && !result.visual_anomaly_grid;
|
|
279
|
+
|
|
222
280
|
if (isFirstClassification) {
|
|
223
|
-
|
|
224
|
-
|
|
281
|
+
if (showOnlyTopResults) {
|
|
282
|
+
// only 1 results th
|
|
283
|
+
{
|
|
284
|
+
let th = document.createElement('th');
|
|
285
|
+
th.scope = 'col';
|
|
286
|
+
th.textContent = th.title = 'Top 5 results';
|
|
287
|
+
th.classList.add('px-0', 'text-center');
|
|
288
|
+
els.resultsThead.appendChild(th);
|
|
289
|
+
}
|
|
225
290
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
291
|
+
// unless also have anomaly...
|
|
292
|
+
if (Object.keys(result.classification).indexOf('anomaly') > -1) {
|
|
293
|
+
let th = document.createElement('th');
|
|
294
|
+
th.scope = 'col';
|
|
295
|
+
th.textContent = th.title = 'anomaly';
|
|
296
|
+
th.classList.add('px-0', 'text-center');
|
|
297
|
+
els.resultsThead.appendChild(th);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
for (let ix = 0; ix < Object.keys(result.classification).length; ix++) {
|
|
302
|
+
const key = Object.keys(result.classification)[ix];
|
|
303
|
+
|
|
304
|
+
let th = document.createElement('th');
|
|
305
|
+
th.scope = 'col';
|
|
306
|
+
th.classList.add('px-0', 'text-center');
|
|
307
|
+
th.textContent = th.title = key;
|
|
308
|
+
els.resultsThead.appendChild(th);
|
|
309
|
+
}
|
|
231
310
|
}
|
|
232
311
|
|
|
233
312
|
if (result.visual_anomaly_grid) {
|
|
@@ -264,15 +343,53 @@ window.WebServer = async () => {
|
|
|
264
343
|
let td1 = document.createElement('td');
|
|
265
344
|
td1.textContent = (++inferenceIx).toString();
|
|
266
345
|
tr.appendChild(td1);
|
|
267
|
-
|
|
346
|
+
if (showOnlyTopResults) {
|
|
347
|
+
// only print top 5
|
|
268
348
|
let td = document.createElement('td');
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
349
|
+
|
|
350
|
+
let results = [];
|
|
351
|
+
for (const key of Object.keys(result.classification)) {
|
|
352
|
+
if (key === 'anomaly') continue;
|
|
353
|
+
|
|
354
|
+
results.push({
|
|
355
|
+
label: key,
|
|
356
|
+
value: result.classification[key],
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const top = results.sort((a, b) => b.value - a.value).slice(0, 5);
|
|
361
|
+
for (let ix = 0; ix < top.length; ix++) {
|
|
362
|
+
let span = ix === 0 ? document.createElement('strong') : document.createElement('span');
|
|
363
|
+
span.textContent = `${top[ix].label}: ${top[ix].value.toFixed(2)}`;
|
|
364
|
+
td.appendChild(span);
|
|
365
|
+
|
|
366
|
+
if (ix !== top.length - 1) {
|
|
367
|
+
let commaSpan = document.createElement('span');
|
|
368
|
+
commaSpan.textContent = ', ';
|
|
369
|
+
td.appendChild(commaSpan);
|
|
370
|
+
}
|
|
273
371
|
}
|
|
274
372
|
tr.appendChild(td);
|
|
373
|
+
|
|
374
|
+
if (Object.keys(result.classification).indexOf('anomaly') > -1) {
|
|
375
|
+
let anomalyTd = document.createElement('td');
|
|
376
|
+
anomalyTd.classList.add('text-center');
|
|
377
|
+
anomalyTd.textContent = result.classification.anomaly.toFixed(2);
|
|
378
|
+
tr.appendChild(anomalyTd);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
for (let k of Object.keys(result.classification)) {
|
|
383
|
+
let td = document.createElement('td');
|
|
384
|
+
td.classList.add('text-center');
|
|
385
|
+
td.textContent = result.classification[k].toFixed(2);
|
|
386
|
+
if (result.classification[k] === highest && !isVisualAnomaly) {
|
|
387
|
+
td.style.fontWeight = 600;
|
|
388
|
+
}
|
|
389
|
+
tr.appendChild(td);
|
|
390
|
+
}
|
|
275
391
|
}
|
|
392
|
+
|
|
276
393
|
if (result.visual_anomaly_grid) {
|
|
277
394
|
let td = document.createElement('td');
|
|
278
395
|
td.classList.add('text-center');
|
|
@@ -406,7 +523,9 @@ window.WebServer = async () => {
|
|
|
406
523
|
els.cameraContainer.appendChild(el);
|
|
407
524
|
}
|
|
408
525
|
}
|
|
409
|
-
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
socket.on('classification', onClassification);
|
|
410
529
|
|
|
411
530
|
if (els.websocketAddress) {
|
|
412
531
|
els.websocketAddress.textContent = `ws://${location.host}`;
|