edge-impulse-linux 1.16.2 → 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.
Files changed (84) hide show
  1. package/build/cli/linux/linux.js +1 -0
  2. package/build/cli/linux/linux.js.map +1 -1
  3. package/build/cli/linux/runner-profiling.d.ts +10 -0
  4. package/build/cli/linux/runner-profiling.js +72 -0
  5. package/build/cli/linux/runner-profiling.js.map +1 -0
  6. package/build/cli/linux/runner-utils.d.ts +1 -0
  7. package/build/cli/linux/runner-utils.js +83 -79
  8. package/build/cli/linux/runner-utils.js.map +1 -1
  9. package/build/cli/linux/runner.js +57 -8
  10. package/build/cli/linux/runner.js.map +1 -1
  11. package/build/cli/linux/webserver/public/inference-server.js +92 -83
  12. package/build/cli/linux/webserver/public/inference-server.js.map +1 -1
  13. package/build/cli/linux/webserver/public/webserver.js +124 -17
  14. package/build/cli/linux/webserver/public/webserver.js.map +1 -1
  15. package/build/cli/linux/webserver/views/index.js +5 -3
  16. package/build/cli/linux/webserver/views/index.js.map +1 -1
  17. package/build/cli-common/model-monitor.d.ts +1 -2
  18. package/build/cli-common/model-monitor.js +5 -5
  19. package/build/cli-common/model-monitor.js.map +1 -1
  20. package/build/cli-common/remote-mgmt-service.d.ts +1 -1
  21. package/build/library/async-pool.d.ts +1 -0
  22. package/build/library/async-pool.js +21 -0
  23. package/build/library/async-pool.js.map +1 -0
  24. package/build/library/classifier/image-classifier.d.ts +16 -3
  25. package/build/library/classifier/image-classifier.js +38 -8
  26. package/build/library/classifier/image-classifier.js.map +1 -1
  27. package/build/library/classifier/libcwrapper.d.ts +26 -0
  28. package/build/library/classifier/libcwrapper.js +37 -0
  29. package/build/library/classifier/libcwrapper.js.map +1 -0
  30. package/build/library/classifier/linux-impulse-runner-types.d.ts +177 -0
  31. package/build/library/classifier/linux-impulse-runner-types.js +28 -0
  32. package/build/library/classifier/linux-impulse-runner-types.js.map +1 -0
  33. package/build/library/classifier/linux-impulse-runner.d.ts +15 -125
  34. package/build/library/classifier/linux-impulse-runner.js +154 -46
  35. package/build/library/classifier/linux-impulse-runner.js.map +1 -1
  36. package/build/library/classifier/valgrind-suppression.d.ts +1 -0
  37. package/build/library/classifier/valgrind-suppression.js +64 -0
  38. package/build/library/classifier/valgrind-suppression.js.map +1 -0
  39. package/build/library/moving-average-filter.d.ts +1 -1
  40. package/build/library/sensors/gstreamer.d.ts +12 -5
  41. package/build/library/sensors/gstreamer.js +217 -66
  42. package/build/library/sensors/gstreamer.js.map +1 -1
  43. package/build/library/sensors/icamera.d.ts +3 -1
  44. package/build/library/sensors/imagesnap.d.ts +2 -0
  45. package/build/library/sensors/imagesnap.js +2 -0
  46. package/build/library/sensors/imagesnap.js.map +1 -1
  47. package/build/library/sensors/prophesee.d.ts +2 -0
  48. package/build/library/sensors/prophesee.js +1 -0
  49. package/build/library/sensors/prophesee.js.map +1 -1
  50. package/build/library/sensors/sensors-helper.d.ts +1 -0
  51. package/build/library/sensors/sensors-helper.js +1 -1
  52. package/build/library/sensors/sensors-helper.js.map +1 -1
  53. package/build/sdk/studio/sdk/api/classifyApi.d.ts +64 -0
  54. package/build/sdk/studio/sdk/api/classifyApi.js +128 -0
  55. package/build/sdk/studio/sdk/api/classifyApi.js.map +1 -1
  56. package/build/sdk/studio/sdk/api/rawDataApi.d.ts +55 -1
  57. package/build/sdk/studio/sdk/api/rawDataApi.js +166 -1
  58. package/build/sdk/studio/sdk/api/rawDataApi.js.map +1 -1
  59. package/build/sdk/studio/sdk/api/testApi.d.ts +16 -0
  60. package/build/sdk/studio/sdk/api/testApi.js +90 -0
  61. package/build/sdk/studio/sdk/api/testApi.js.map +1 -1
  62. package/build/sdk/studio/sdk/model/batchEditBoundingBoxesRequest.d.ts +32 -0
  63. package/build/sdk/studio/sdk/model/batchEditBoundingBoxesRequest.js +34 -0
  64. package/build/sdk/studio/sdk/model/batchEditBoundingBoxesRequest.js.map +1 -0
  65. package/build/sdk/studio/sdk/model/models.d.ts +2 -0
  66. package/build/sdk/studio/sdk/model/models.js +6 -0
  67. package/build/sdk/studio/sdk/model/models.js.map +1 -1
  68. package/build/sdk/studio/sdk/model/permission.d.ts +1 -1
  69. package/build/sdk/studio/sdk/model/permission.js +1 -1
  70. package/build/sdk/studio/sdk/model/permission.js.map +1 -1
  71. package/build/sdk/studio/sdk/model/uploadVersionArchiveRequest.d.ts +34 -0
  72. package/build/sdk/studio/sdk/model/uploadVersionArchiveRequest.js +29 -0
  73. package/build/sdk/studio/sdk/model/uploadVersionArchiveRequest.js.map +1 -0
  74. package/build/shared/views/project/bounding-box-scaling.d.ts +66 -0
  75. package/build/shared/views/project/bounding-box-scaling.js +155 -0
  76. package/build/shared/views/project/bounding-box-scaling.js.map +1 -0
  77. package/cli/linux/webserver/public/assets/mobileclient.css +31 -3
  78. package/cli/linux/webserver/public/inference-server.js +100 -89
  79. package/cli/linux/webserver/public/webserver.js +136 -17
  80. package/examples/js/classify-camera.js +1 -3
  81. package/examples/ts/classify-camera.ts +1 -3
  82. package/package.json +2 -1
  83. package/test/gstreamer.test.ts +28 -23
  84. package/examples/ts/classify-custom-from-test.ts +0 -96
@@ -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
- let isFirstClassification = true;
202
- let inferenceIx = 0;
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
- for (let ix = 0; ix < Object.keys(result.classification).length; ix++) {
224
- const key = Object.keys(result.classification)[ix];
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
- let th = document.createElement('th');
227
- th.scope = 'col';
228
- th.classList.add('px-0', 'text-center');
229
- th.textContent = th.title = key;
230
- els.resultsThead.appendChild(th);
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
- for (let k of Object.keys(result.classification)) {
346
+ if (showOnlyTopResults) {
347
+ // only print top 5
268
348
  let td = document.createElement('td');
269
- td.classList.add('text-center');
270
- td.textContent = result.classification[k].toFixed(2);
271
- if (result.classification[k] === highest && !isVisualAnomaly) {
272
- td.style.fontWeight = 600;
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}`;
@@ -48,9 +48,7 @@ const { ImageClassifier, LinuxImpulseRunner, Ffmpeg, Imagesnap, RunnerHelloHasAn
48
48
  camera = new Imagesnap();
49
49
  }
50
50
  else if (process.platform === 'linux') {
51
- camera = new Ffmpeg(false /* verbose */, {
52
- scaleAndCropInPipeline: true,
53
- });
51
+ camera = new Ffmpeg(false /* verbose */);
54
52
  }
55
53
  else {
56
54
  throw new Error('Unsupported platform "' + process.platform + '"');
@@ -49,9 +49,7 @@ import { RunnerHelloHasAnomaly } from "../../library/classifier/linux-impulse-ru
49
49
  camera = new Imagesnap();
50
50
  }
51
51
  else if (process.platform === 'linux') {
52
- camera = new GStreamer(false /* verbose */, {
53
- scaleAndCropInPipeline: true,
54
- });
52
+ camera = new GStreamer(false /* verbose */);
55
53
  }
56
54
  else {
57
55
  throw new Error('Unsupported platform "' + process.platform + '"');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edge-impulse-linux",
3
- "version": "1.16.2",
3
+ "version": "1.17.2",
4
4
  "description": "Node.js SDK and tools for Edge Impulse for Linux",
5
5
  "directories": {
6
6
  "example": "examples"
@@ -42,6 +42,7 @@
42
42
  "form-data": "4.0.4",
43
43
  "inquirer": "7.0.0",
44
44
  "inquirer-search-list": "1.2.6",
45
+ "koffi": "2.12.1",
45
46
  "multer": "1.4.5-lts.1",
46
47
  "node-fetch": "2.7.0",
47
48
  "npm-registry-fetch": "17.1.0",
@@ -1288,8 +1288,6 @@ Device found:
1288
1288
 
1289
1289
  });
1290
1290
 
1291
-
1292
-
1293
1291
  // https://forum.edgeimpulse.com/t/edge-impulse-on-coral-edgetpu/2311
1294
1292
  it("coral edge tpu with iMX6S", async () => {
1295
1293
  const gstOutput = `Probing devices...
@@ -5234,7 +5232,7 @@ Freeing pipeline ...
5234
5232
 
5235
5233
  const gstreamer = new GStreamer(false, {
5236
5234
  spawnHelperOverride: spawnHelper,
5237
- scaleAndCropInPipeline: true,
5235
+ dontRunCleanupLoop: true,
5238
5236
  });
5239
5237
  await gstreamer.init();
5240
5238
  const launchResp = await gstreamer.getGstreamerLaunchCommand({
@@ -5251,10 +5249,9 @@ Freeing pipeline ...
5251
5249
 
5252
5250
  // console.log('launchResp', launchResp);
5253
5251
 
5254
- assert.equal(launchResp.invokeProcess, 'spawn');
5255
5252
  assert.equal(launchResp.command, 'gst-launch-1.0');
5256
- assert.equal(launchResp.args.join(' '),
5257
- 'pylonsrc ! video/x-raw,width=1440,height=1080 ! videoconvert ! jpegenc ! multifilesink location=test%05d.jpg');
5253
+ assert.equal(launchResp.pipeline,
5254
+ 'pylonsrc ! video/x-raw,width=1440,height=1080 ! videoconvert ! jpegenc ! multifilesink location=resized%05d.jpg');
5258
5255
  });
5259
5256
 
5260
5257
  it("w/ inference dims #1", async () => {
@@ -5277,7 +5274,7 @@ Freeing pipeline ...
5277
5274
 
5278
5275
  const gstreamer = new GStreamer(false, {
5279
5276
  spawnHelperOverride: spawnHelper,
5280
- scaleAndCropInPipeline: true,
5277
+ dontRunCleanupLoop: true,
5281
5278
  });
5282
5279
  await gstreamer.init();
5283
5280
  const launchResp = await gstreamer.getGstreamerLaunchCommand({
@@ -5298,10 +5295,13 @@ Freeing pipeline ...
5298
5295
 
5299
5296
  // console.log('launchResp', launchResp);
5300
5297
 
5301
- assert.equal(launchResp.invokeProcess, 'spawn');
5302
5298
  assert.equal(launchResp.command, 'gst-launch-1.0');
5303
- assert.equal(launchResp.args.join(' '),
5304
- 'pylonsrc ! video/x-raw,width=1440,height=1080 ! videoconvert ! videocrop left=180 right=180 ! videoscale method=lanczos ! video/x-raw,width=320,height=320 ! jpegenc ! multifilesink location=test%05d.jpg');
5299
+ assert.equal(launchResp.pipeline,
5300
+ 'pylonsrc ! video/x-raw,width=1440,height=1080 ! videoconvert ! ' +
5301
+ 'tee name=t ' +
5302
+ 't. ! queue ! jpegenc ! multifilesink location=original%05d.jpg ' +
5303
+ 't. ! queue ! videocrop left=180 right=180 ! videoscale method=lanczos ! video/x-raw,width=320,height=320 ! jpegenc ! multifilesink location=resized%05d.jpg'
5304
+ );
5305
5305
  });
5306
5306
 
5307
5307
  it("w/ inference dims #2", async () => {
@@ -5324,7 +5324,7 @@ Freeing pipeline ...
5324
5324
 
5325
5325
  const gstreamer = new GStreamer(false, {
5326
5326
  spawnHelperOverride: spawnHelper,
5327
- scaleAndCropInPipeline: true,
5327
+ dontRunCleanupLoop: true,
5328
5328
  });
5329
5329
  await gstreamer.init();
5330
5330
  const launchResp = await gstreamer.getGstreamerLaunchCommand({
@@ -5345,10 +5345,13 @@ Freeing pipeline ...
5345
5345
 
5346
5346
  // console.log('launchResp', launchResp);
5347
5347
 
5348
- assert.equal(launchResp.invokeProcess, 'spawn');
5349
5348
  assert.equal(launchResp.command, 'gst-launch-1.0');
5350
- assert.equal(launchResp.args.join(' '),
5351
- 'pylonsrc ! video/x-raw,width=1440,height=1080 ! videoconvert ! videoscale method=lanczos ! video/x-raw,width=320,height=320 ! jpegenc ! multifilesink location=test%05d.jpg');
5349
+ assert.equal(launchResp.pipeline,
5350
+ 'pylonsrc ! video/x-raw,width=1440,height=1080 ! videoconvert ! ' +
5351
+ 'tee name=t ' +
5352
+ 't. ! queue ! jpegenc ! multifilesink location=original%05d.jpg ' +
5353
+ 't. ! queue ! videoscale method=lanczos ! video/x-raw,width=320,height=320 ! jpegenc ! multifilesink location=resized%05d.jpg'
5354
+ );
5352
5355
  });
5353
5356
 
5354
5357
  it("w/ inference dims #3", async () => {
@@ -5371,7 +5374,7 @@ Freeing pipeline ...
5371
5374
 
5372
5375
  const gstreamer = new GStreamer(false, {
5373
5376
  spawnHelperOverride: spawnHelper,
5374
- scaleAndCropInPipeline: true,
5377
+ dontRunCleanupLoop: true,
5375
5378
  });
5376
5379
  await gstreamer.init();
5377
5380
  const launchResp = await gstreamer.getGstreamerLaunchCommand({
@@ -5392,10 +5395,9 @@ Freeing pipeline ...
5392
5395
 
5393
5396
  // console.log('launchResp', launchResp);
5394
5397
 
5395
- assert.equal(launchResp.invokeProcess, 'spawn');
5396
5398
  assert.equal(launchResp.command, 'gst-launch-1.0');
5397
- assert.equal(launchResp.args.join(' '),
5398
- 'pylonsrc ! video/x-raw,width=1440,height=1080 ! videoconvert ! jpegenc ! multifilesink location=test%05d.jpg');
5399
+ assert.equal(launchResp.pipeline,
5400
+ 'pylonsrc ! video/x-raw,width=1440,height=1080 ! videoconvert ! jpegenc ! multifilesink location=resized%05d.jpg');
5399
5401
  });
5400
5402
 
5401
5403
  it("w/ inference dims #4", async () => {
@@ -5418,7 +5420,7 @@ Freeing pipeline ...
5418
5420
 
5419
5421
  const gstreamer = new GStreamer(false, {
5420
5422
  spawnHelperOverride: spawnHelper,
5421
- scaleAndCropInPipeline: undefined,
5423
+ dontRunCleanupLoop: true,
5422
5424
  });
5423
5425
  await gstreamer.init();
5424
5426
  const launchResp = await gstreamer.getGstreamerLaunchCommand({
@@ -5439,10 +5441,13 @@ Freeing pipeline ...
5439
5441
 
5440
5442
  // console.log('launchResp', launchResp);
5441
5443
 
5442
- assert.equal(launchResp.invokeProcess, 'spawn');
5443
5444
  assert.equal(launchResp.command, 'gst-launch-1.0');
5444
- assert.equal(launchResp.args.join(' '),
5445
- 'pylonsrc ! video/x-raw,width=1440,height=1080 ! videoconvert ! jpegenc ! multifilesink location=test%05d.jpg');
5445
+ assert.equal(launchResp.pipeline,
5446
+ 'pylonsrc ! video/x-raw,width=1440,height=1080 ! videoconvert ! ' +
5447
+ 'tee name=t ' +
5448
+ 't. ! queue ! jpegenc ! multifilesink location=original%05d.jpg ' +
5449
+ 't. ! queue ! videoscale method=lanczos ! video/x-raw,width=320,height=320 ! jpegenc ! multifilesink location=resized%05d.jpg'
5450
+ );
5446
5451
  });
5447
5452
  });
5448
5453
  });
@@ -5491,7 +5496,7 @@ async function testGetDevices(output: {
5491
5496
  const gstreamer = new GStreamer(false, {
5492
5497
  spawnHelperOverride: spawnHelper,
5493
5498
  modeOverride: output?.modeOverride,
5494
- scaleAndCropInPipeline: true,
5499
+ dontRunCleanupLoop: true,
5495
5500
  });
5496
5501
  await gstreamer.init();
5497
5502
  const devices = await gstreamer.getAllDevices();
@@ -1,96 +0,0 @@
1
- import { LinuxImpulseRunner } from "../../library";
2
- import fs from 'fs';
3
-
4
- // This script expects two arguments:
5
- // 1. The model file
6
- // 2. A features file with raw data. You can get this by going to **Live classification > Load sample**
7
- // then copy the features from the 'Raw features' block.
8
-
9
- (async () => {
10
- try {
11
- if (!process.argv[2]) {
12
- console.log('Missing one argument (model file)');
13
- process.exit(1);
14
- }
15
-
16
- if (!process.argv[3]) {
17
- console.log('Missing second argument (features file)');
18
- process.exit(1);
19
- }
20
-
21
- // Load the model
22
- let runner = new LinuxImpulseRunner(process.argv[2]);
23
- let model = await runner.init();
24
-
25
- const windowLengthMs = ((model.modelParameters.input_features_count /
26
- model.modelParameters.frequency /
27
- model.modelParameters.axis_count) * 1000);
28
-
29
- console.log('Starting the custom classifier for',
30
- model.project.owner + ' / ' + model.project.name, '(v' + model.project.deploy_version + ')');
31
- console.log('Parameters', 'freq', model.modelParameters.frequency + 'Hz',
32
- 'window length', windowLengthMs + 'ms.',
33
- 'classes', model.modelParameters.labels);
34
-
35
- // read the features file (comma separated numbers)
36
- // Newlines deliminate samples
37
- // Create an array of array of Numbers. Each inner array is a sample.
38
- let samples = (<string>await fs.promises.readFile(process.argv[3], 'utf-8'))
39
- .trim().split('\n').map(line => line.split(',').map(n => Number(n)));
40
-
41
- for (let features of samples) {
42
- // and classify the data, this should match the classification in the Studio
43
- let res = await runner.classify(features);
44
-
45
- console.log('Begin output');
46
- if (res.result.classification) {
47
- let ret: number[] = [];
48
- for (let k of Object.keys(res.result.classification)) {
49
- ret.push(res.result.classification[k]);
50
- }
51
- if (typeof res.result.visual_anomaly_max === 'number') {
52
- ret.push(res.result.visual_anomaly_max);
53
- }
54
- else if (typeof res.result.anomaly === 'number') {
55
- ret.push(res.result.anomaly);
56
- }
57
- console.log('[' + ret.map(x => x.toFixed(5)).join(', ') + ']');
58
- }
59
- if (res.result.bounding_boxes) {
60
- for (let bb of res.result.bounding_boxes) {
61
- if (bb.value === 0) {
62
- continue;
63
- }
64
- console.log(`${bb.label} (${bb.value.toFixed(5)}) ` +
65
- `[ x: ${bb.x}, y: ${bb.y}, width: ${bb.width}, height: ${bb.height} ]`);
66
- }
67
- }
68
- if (res.result.visual_anomaly_grid) {
69
- for (let bb of res.result.visual_anomaly_grid) {
70
- console.log(`${bb.label} (${bb.value.toFixed(5)}) ` +
71
- `[ x: ${bb.x}, y: ${bb.y}, width: ${bb.width}, height: ${bb.height} ]`);
72
- }
73
- }
74
- console.log('End output');
75
-
76
- // if you want to fill in data on the fly you can also do this; e.g. if you have 3-axis accelerometer
77
- // with 2 second window and 100Hz, then input_features_count=600, axis_count=3
78
- // let features = [];
79
- // for (let ix = 0; ix <
80
- // model.modelParameters.input_features_count; ix += model.modelParameters.axis_count) {
81
- // features.push(x);
82
- // features.push(y);
83
- // features.push(z);
84
- // }
85
- // and classify features
86
- }
87
- await runner.stop();
88
- }
89
- catch (ex) {
90
- console.error(ex);
91
- process.exit(1);
92
- }
93
- finally {
94
- process.exit(0);
95
- }
96
- })();