edge-impulse-linux 1.17.2 → 1.17.4
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-downloader.js +7 -2
- package/build/cli/linux/runner-downloader.js.map +1 -1
- package/build/cli/linux/runner-utils.d.ts +9 -3
- package/build/cli/linux/runner-utils.js +112 -79
- package/build/cli/linux/runner-utils.js.map +1 -1
- package/build/cli/linux/runner.js +35 -0
- package/build/cli/linux/runner.js.map +1 -1
- package/build/cli/linux/webserver/public/webserver.js +125 -8
- package/build/cli/linux/webserver/public/webserver.js.map +1 -1
- package/build/cli/linux/webserver/views/index.d.ts +2 -0
- package/build/cli/linux/webserver/views/index.js +28 -4
- package/build/cli/linux/webserver/views/index.js.map +1 -1
- package/build/cli-common/config.d.ts +10 -0
- package/build/cli-common/config.js +34 -2
- package/build/cli-common/config.js.map +1 -1
- package/build/cli-common/init-cli-app.js +4 -0
- package/build/cli-common/init-cli-app.js.map +1 -1
- package/build/cli-common/model-monitor.js +6 -1
- package/build/cli-common/model-monitor.js.map +1 -1
- package/build/library/classifier/linux-impulse-runner-types.d.ts +1 -0
- package/build/sdk/studio/sdk/api/classifyApi.d.ts +1 -33
- package/build/sdk/studio/sdk/api/classifyApi.js +1 -65
- package/build/sdk/studio/sdk/api/classifyApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/rawDataApi.d.ts +12 -12
- package/build/sdk/studio/sdk/api/rawDataApi.js +12 -12
- package/build/sdk/studio/sdk/model/classifyJobResponsePage.d.ts +4 -0
- package/build/sdk/studio/sdk/model/classifyJobResponsePage.js +5 -0
- package/build/sdk/studio/sdk/model/classifyJobResponsePage.js.map +1 -1
- package/build/sdk/studio/sdk/model/classifyJobResponsePageAllOf.d.ts +4 -0
- package/build/sdk/studio/sdk/model/classifyJobResponsePageAllOf.js +5 -0
- package/build/sdk/studio/sdk/model/classifyJobResponsePageAllOf.js.map +1 -1
- package/build/sdk/studio/sdk/model/getOrganizationPortalResponse.d.ts +4 -0
- package/build/sdk/studio/sdk/model/getOrganizationPortalResponse.js +5 -0
- package/build/sdk/studio/sdk/model/getOrganizationPortalResponse.js.map +1 -1
- package/build/sdk/studio/sdk/model/getOrganizationPortalResponseAllOf.d.ts +4 -0
- package/build/sdk/studio/sdk/model/getOrganizationPortalResponseAllOf.js +5 -0
- package/build/sdk/studio/sdk/model/getOrganizationPortalResponseAllOf.js.map +1 -1
- package/build/sdk/studio/sdk/model/listOrganizationPortalsResponseAllOfPortals.d.ts +1 -0
- package/build/sdk/studio/sdk/model/listOrganizationPortalsResponseAllOfPortals.js +5 -0
- package/build/sdk/studio/sdk/model/listOrganizationPortalsResponseAllOfPortals.js.map +1 -1
- package/build/sdk/studio/sdk/model/modelPrediction.d.ts +5 -0
- package/build/sdk/studio/sdk/model/modelPrediction.js +5 -0
- package/build/sdk/studio/sdk/model/modelPrediction.js.map +1 -1
- package/cli/linux/webserver/public/assets/mobileclient.css +10 -0
- package/cli/linux/webserver/public/webserver.js +144 -8
- package/package.json +1 -1
|
@@ -60,6 +60,11 @@ ListOrganizationPortalsResponseAllOfPortals.attributeTypeMap = [
|
|
|
60
60
|
"baseName": "bucketUrl",
|
|
61
61
|
"type": "string"
|
|
62
62
|
},
|
|
63
|
+
{
|
|
64
|
+
"name": "storageProvider",
|
|
65
|
+
"baseName": "storageProvider",
|
|
66
|
+
"type": "string"
|
|
67
|
+
},
|
|
63
68
|
{
|
|
64
69
|
"name": "created",
|
|
65
70
|
"baseName": "created",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listOrganizationPortalsResponseAllOfPortals.js","sourceRoot":"","sources":["../../../../../sdk/studio/sdk/model/listOrganizationPortalsResponseAllOfPortals.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;AAGH,MAAa,2CAA2C;
|
|
1
|
+
{"version":3,"file":"listOrganizationPortalsResponseAllOfPortals.js","sourceRoot":"","sources":["../../../../../sdk/studio/sdk/model/listOrganizationPortalsResponseAllOfPortals.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;AAGH,MAAa,2CAA2C;IAkEpD,MAAM,CAAC,mBAAmB;QACtB,OAAO,2CAA2C,CAAC,gBAAgB,CAAC;IACxE,CAAC;;AApEL,kGAqEC;AAzDU,yDAAa,GAAuB,SAAS,CAAC;AAE9C,4DAAgB,GAA0D;IAC7E;QACI,MAAM,EAAE,IAAI;QACZ,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,QAAQ;KACnB;IACD;QACI,MAAM,EAAE,MAAM;QACd,UAAU,EAAE,MAAM;QAClB,MAAM,EAAE,QAAQ;KACnB;IACD;QACI,MAAM,EAAE,aAAa;QACrB,UAAU,EAAE,aAAa;QACzB,MAAM,EAAE,QAAQ;KACnB;IACD;QACI,MAAM,EAAE,KAAK;QACb,UAAU,EAAE,KAAK;QACjB,MAAM,EAAE,QAAQ;KACnB;IACD;QACI,MAAM,EAAE,UAAU;QAClB,UAAU,EAAE,UAAU;QACtB,MAAM,EAAE,QAAQ;KACnB;IACD;QACI,MAAM,EAAE,YAAY;QACpB,UAAU,EAAE,YAAY;QACxB,MAAM,EAAE,QAAQ;KACnB;IACD;QACI,MAAM,EAAE,YAAY;QACpB,UAAU,EAAE,YAAY;QACxB,MAAM,EAAE,QAAQ;KACnB;IACD;QACI,MAAM,EAAE,WAAW;QACnB,UAAU,EAAE,WAAW;QACvB,MAAM,EAAE,QAAQ;KACnB;IACD;QACI,MAAM,EAAE,iBAAiB;QACzB,UAAU,EAAE,iBAAiB;QAC7B,MAAM,EAAE,QAAQ;KACnB;IACD;QACI,MAAM,EAAE,SAAS;QACjB,UAAU,EAAE,SAAS;QACrB,MAAM,EAAE,MAAM;KACjB;CAAK,CAAC"}
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* https://openapi-generator.tech
|
|
10
10
|
* Do not edit the class manually.
|
|
11
11
|
*/
|
|
12
|
+
import { BoundingBoxWithScore } from './boundingBoxWithScore';
|
|
12
13
|
export declare class ModelPrediction {
|
|
13
14
|
'sampleId': number;
|
|
14
15
|
'startMs': number;
|
|
@@ -24,6 +25,10 @@ export declare class ModelPrediction {
|
|
|
24
25
|
* Only set for visual anomaly projects. 2D array of shape (n, n) with raw anomaly scores, where n varies based on the image input size and the specific visual anomaly algorithm used. The scores corresponds to each grid cell in the image\'s spatial matrix.
|
|
25
26
|
*/
|
|
26
27
|
'anomalyScores'?: Array<Array<number>>;
|
|
28
|
+
/**
|
|
29
|
+
* Only set for object detection projects. Coordinates are scaled 0..1, not absolute values.
|
|
30
|
+
*/
|
|
31
|
+
'boundingBoxes'?: Array<BoundingBoxWithScore>;
|
|
27
32
|
static discriminator: string | undefined;
|
|
28
33
|
static attributeTypeMap: Array<{
|
|
29
34
|
name: string;
|
|
@@ -59,6 +59,11 @@ ModelPrediction.attributeTypeMap = [
|
|
|
59
59
|
"name": "anomalyScores",
|
|
60
60
|
"baseName": "anomalyScores",
|
|
61
61
|
"type": "Array<Array<number>>"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "boundingBoxes",
|
|
65
|
+
"baseName": "boundingBoxes",
|
|
66
|
+
"type": "Array<BoundingBoxWithScore>"
|
|
62
67
|
}
|
|
63
68
|
];
|
|
64
69
|
//# sourceMappingURL=modelPrediction.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modelPrediction.js","sourceRoot":"","sources":["../../../../../sdk/studio/sdk/model/modelPrediction.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;
|
|
1
|
+
{"version":3,"file":"modelPrediction.js","sourceRoot":"","sources":["../../../../../sdk/studio/sdk/model/modelPrediction.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;AAIH,MAAa,eAAe;IAqExB,MAAM,CAAC,mBAAmB;QACtB,OAAO,eAAe,CAAC,gBAAgB,CAAC;IAC5C,CAAC;;AAvEL,0CAwEC;AApDU,6BAAa,GAAuB,SAAS,CAAC;AAE9C,gCAAgB,GAA0D;IAC7E;QACI,MAAM,EAAE,UAAU;QAClB,UAAU,EAAE,UAAU;QACtB,MAAM,EAAE,QAAQ;KACnB;IACD;QACI,MAAM,EAAE,SAAS;QACjB,UAAU,EAAE,SAAS;QACrB,MAAM,EAAE,QAAQ;KACnB;IACD;QACI,MAAM,EAAE,OAAO;QACf,UAAU,EAAE,OAAO;QACnB,MAAM,EAAE,QAAQ;KACnB;IACD;QACI,MAAM,EAAE,OAAO;QACf,UAAU,EAAE,OAAO;QACnB,MAAM,EAAE,QAAQ;KACnB;IACD;QACI,MAAM,EAAE,YAAY;QACpB,UAAU,EAAE,YAAY;QACxB,MAAM,EAAE,QAAQ;KACnB;IACD;QACI,MAAM,EAAE,mBAAmB;QAC3B,UAAU,EAAE,mBAAmB;QAC/B,MAAM,EAAE,SAAS;KACpB;IACD;QACI,MAAM,EAAE,SAAS;QACjB,UAAU,EAAE,SAAS;QACrB,MAAM,EAAE,QAAQ;KACnB;IACD;QACI,MAAM,EAAE,eAAe;QACvB,UAAU,EAAE,eAAe;QAC3B,MAAM,EAAE,sBAAsB;KACjC;IACD;QACI,MAAM,EAAE,eAAe;QACvB,UAAU,EAAE,eAAe;QAC3B,MAAM,EAAE,6BAA6B;KACxC;CAAK,CAAC"}
|
|
@@ -4239,3 +4239,13 @@ video {
|
|
|
4239
4239
|
.embed-view #capture-camera {
|
|
4240
4240
|
margin-top: -68px !important;
|
|
4241
4241
|
}
|
|
4242
|
+
|
|
4243
|
+
.classification-top-overlay {
|
|
4244
|
+
position: absolute;
|
|
4245
|
+
left: 0.5rem;
|
|
4246
|
+
top: 0.5rem;
|
|
4247
|
+
color: white;
|
|
4248
|
+
text-align: left;;
|
|
4249
|
+
font-family: monospace;
|
|
4250
|
+
font-size: 0.75rem;
|
|
4251
|
+
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
window.WebServer = async () => {
|
|
1
|
+
window.WebServer = async (vmStr) => {
|
|
2
|
+
|
|
3
|
+
const vm = JSON.parse(decodeURIComponent(vmStr));
|
|
4
|
+
console.log('vm', vm);
|
|
2
5
|
|
|
3
6
|
const els = {
|
|
4
7
|
title: document.querySelector('#header-row h1'),
|
|
@@ -255,6 +258,8 @@ window.WebServer = async () => {
|
|
|
255
258
|
});
|
|
256
259
|
window.addEventListener('resize', onWindowResize);
|
|
257
260
|
|
|
261
|
+
let lastFivePerfCalPredictions = [];
|
|
262
|
+
|
|
258
263
|
function onClassification(opts) {
|
|
259
264
|
lastClassification = opts;
|
|
260
265
|
|
|
@@ -263,7 +268,9 @@ window.WebServer = async () => {
|
|
|
263
268
|
|
|
264
269
|
els.timePerInference.textContent = opts.timeMs;
|
|
265
270
|
els.additionalInfo.textContent = opts.additionalInfo;
|
|
266
|
-
|
|
271
|
+
if (!vm.isEmbedView) {
|
|
272
|
+
els.timePerInferenceContainer.style.display = '';
|
|
273
|
+
}
|
|
267
274
|
els.additionalInfoContainer.style.display = '';
|
|
268
275
|
|
|
269
276
|
console.log('classification', opts.result, opts.timeMs);
|
|
@@ -323,12 +330,31 @@ window.WebServer = async () => {
|
|
|
323
330
|
|
|
324
331
|
els.imageClassify.row.style.display = '';
|
|
325
332
|
|
|
326
|
-
let conclusion = 'uncertain';
|
|
333
|
+
let conclusion = vm.hasPerformanceCalibration ? '...' : 'uncertain';
|
|
327
334
|
let highest = Math.max(...Object.values(result.classification));
|
|
328
335
|
|
|
329
336
|
for (let k of Object.keys(result.classification)) {
|
|
330
337
|
if (result.classification[k] >= 0.55) {
|
|
331
|
-
|
|
338
|
+
if (vm.hasPerformanceCalibration) {
|
|
339
|
+
conclusion = k;
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
conclusion = k + ' (' + result.classification[k].toFixed(2) + ')';
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// for perfcal models, if one of the last 5 predictions was the keyword => select that
|
|
348
|
+
if (vm.hasPerformanceCalibration) {
|
|
349
|
+
lastFivePerfCalPredictions.push(conclusion);
|
|
350
|
+
if (lastFivePerfCalPredictions.length > 5) {
|
|
351
|
+
lastFivePerfCalPredictions = lastFivePerfCalPredictions.slice(
|
|
352
|
+
lastFivePerfCalPredictions.length - 5);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const dedup = Array.from(new Set(lastFivePerfCalPredictions));
|
|
356
|
+
if (dedup.length === 2 && dedup.find(x => x === '...')) {
|
|
357
|
+
conclusion = dedup.find(x => x !== '...');
|
|
332
358
|
}
|
|
333
359
|
}
|
|
334
360
|
|
|
@@ -417,18 +443,61 @@ window.WebServer = async () => {
|
|
|
417
443
|
}
|
|
418
444
|
|
|
419
445
|
els.imageClassify.text.textContent = conclusion;
|
|
446
|
+
|
|
447
|
+
// for image classification models, draw overlay on top of the image with top 3 conclusions in embed mode
|
|
448
|
+
if (vm.sensorType === 'camera' && vm.isEmbedView) {
|
|
449
|
+
let results = [];
|
|
450
|
+
for (const key of Object.keys(result.classification)) {
|
|
451
|
+
if (key === 'anomaly') continue;
|
|
452
|
+
|
|
453
|
+
results.push({
|
|
454
|
+
label: key,
|
|
455
|
+
value: result.classification[key],
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// don't change order if we only have 3
|
|
460
|
+
const top = results.length > 3 ?
|
|
461
|
+
results.sort((a, b) => b.value - a.value).slice(0, 3) :
|
|
462
|
+
results;
|
|
463
|
+
if (result.visual_anomaly_grid) {
|
|
464
|
+
// also visual AD? add to top results
|
|
465
|
+
top.push({
|
|
466
|
+
label: 'anomaly',
|
|
467
|
+
value: result.visual_anomaly_max,
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
let classificationOverlayEl = els.cameraContainer.querySelector('.classification-top-overlay');
|
|
472
|
+
if (!classificationOverlayEl) {
|
|
473
|
+
classificationOverlayEl = document.createElement('div');
|
|
474
|
+
classificationOverlayEl.classList.add('classification-top-overlay');
|
|
475
|
+
els.cameraContainer.appendChild(classificationOverlayEl);
|
|
476
|
+
}
|
|
477
|
+
classificationOverlayEl.textContent = '';
|
|
478
|
+
|
|
479
|
+
for (const topRes of top) {
|
|
480
|
+
const topDiv = document.createElement('div');
|
|
481
|
+
topDiv.textContent = `${topRes.label} (${topRes.value.toFixed(2)})`;
|
|
482
|
+
classificationOverlayEl.appendChild(topDiv);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
els.imageClassify.row.style.display = 'none';
|
|
486
|
+
}
|
|
420
487
|
}
|
|
421
488
|
if (result.bounding_boxes) {
|
|
422
489
|
let factor = els.cameraImg.naturalHeight / els.cameraImg.clientHeight;
|
|
423
490
|
|
|
424
|
-
for (let b of result.bounding_boxes) {
|
|
491
|
+
for (let b of result.object_tracking || result.bounding_boxes) {
|
|
425
492
|
let bb = {
|
|
426
493
|
x: b.x / factor,
|
|
427
494
|
y: b.y / factor,
|
|
428
495
|
width: b.width / factor,
|
|
429
496
|
height: b.height / factor,
|
|
430
|
-
label: b
|
|
431
|
-
|
|
497
|
+
label: 'object_id' in b ?
|
|
498
|
+
`${b.label} (ID ${b.object_id})` :
|
|
499
|
+
b.label,
|
|
500
|
+
value: 'value' in b ? b.value : undefined,
|
|
432
501
|
};
|
|
433
502
|
|
|
434
503
|
if (!labelToColor[bb.label]) {
|
|
@@ -462,7 +531,10 @@ window.WebServer = async () => {
|
|
|
462
531
|
let label = document.createElement('div');
|
|
463
532
|
label.classList.add('bounding-box-label');
|
|
464
533
|
label.style.background = color;
|
|
465
|
-
label.textContent = bb.label
|
|
534
|
+
label.textContent = bb.label;
|
|
535
|
+
if (typeof bb.value === 'number') {
|
|
536
|
+
label.textContent += ' (' + bb.value.toFixed(2) + ')';
|
|
537
|
+
}
|
|
466
538
|
if (modelType === 'constrained_object_detection') {
|
|
467
539
|
el.style.whiteSpace = 'nowrap';
|
|
468
540
|
}
|
|
@@ -530,4 +602,68 @@ window.WebServer = async () => {
|
|
|
530
602
|
if (els.websocketAddress) {
|
|
531
603
|
els.websocketAddress.textContent = `ws://${location.host}`;
|
|
532
604
|
}
|
|
605
|
+
|
|
606
|
+
// Here's a helper function that'll loop every second, checks if "classification-top-overlay" is present
|
|
607
|
+
// and then switches between white/black text automatically. If this element is not created, it just sits idle
|
|
608
|
+
(async () => {
|
|
609
|
+
function getAvgBrightness(img, x, y, w, h) {
|
|
610
|
+
const canvas = document.createElement('canvas');
|
|
611
|
+
const ctx = canvas.getContext('2d');
|
|
612
|
+
canvas.width = img.naturalWidth;
|
|
613
|
+
canvas.height = img.naturalHeight;
|
|
614
|
+
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
|
615
|
+
|
|
616
|
+
// Scale from CSS coords (relative to image on page) to natural pixel coords
|
|
617
|
+
const scaleX = img.naturalWidth / img.clientWidth;
|
|
618
|
+
const scaleY = img.naturalHeight / img.clientHeight;
|
|
619
|
+
|
|
620
|
+
const sx = (x - img.getBoundingClientRect().x) * scaleX;
|
|
621
|
+
const sy = (y - img.getBoundingClientRect().y) * scaleY;
|
|
622
|
+
const sw = w * scaleX;
|
|
623
|
+
const sh = h * scaleY;
|
|
624
|
+
|
|
625
|
+
const data = ctx.getImageData(sx, sy, sw, sh).data;
|
|
626
|
+
|
|
627
|
+
let total = 0;
|
|
628
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
629
|
+
const r = data[i];
|
|
630
|
+
const g = data[i + 1];
|
|
631
|
+
const b = data[i + 2];
|
|
632
|
+
total += (r * 299 + g * 587 + b * 114) / 1000;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// debug info
|
|
636
|
+
// const cropCanvas = document.createElement('canvas');
|
|
637
|
+
// cropCanvas.width = sw;
|
|
638
|
+
// cropCanvas.height = sh;
|
|
639
|
+
// const cctx = cropCanvas.getContext('2d');
|
|
640
|
+
// cctx.drawImage(img, sx, sy, sw, sh, 0, 0, sw, sh);
|
|
641
|
+
// const cropEl = document.querySelector('#crop') || document.createElement('img');
|
|
642
|
+
// cropEl.id = 'crop';
|
|
643
|
+
// cropEl.src = cropCanvas.toDataURL('image/png');
|
|
644
|
+
// document.body.appendChild(cropEl);
|
|
645
|
+
|
|
646
|
+
return total / (data.length / 4);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
if (!vm.isEmbedView || vm.sensorType !== 'camera') return;
|
|
650
|
+
|
|
651
|
+
while (1) {
|
|
652
|
+
const labelEl = document.querySelector('.classification-top-overlay');
|
|
653
|
+
if (!labelEl) {
|
|
654
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
655
|
+
continue;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
const rect = labelEl.getBoundingClientRect();
|
|
659
|
+
const brightness = getAvgBrightness(els.cameraImg, rect.x, rect.y, rect.width, rect.height);
|
|
660
|
+
if (brightness > 180) {
|
|
661
|
+
labelEl.style.color = 'black';
|
|
662
|
+
}
|
|
663
|
+
else {
|
|
664
|
+
labelEl.style.color = 'white';
|
|
665
|
+
}
|
|
666
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
667
|
+
}
|
|
668
|
+
})();
|
|
533
669
|
};
|