From b0b4a953dbf54707347d62b3fe881d17302bf959 Mon Sep 17 00:00:00 2001 From: ocogeclub Date: Sun, 31 Oct 2021 13:27:59 +0900 Subject: [PATCH] =?UTF-8?q?[update]=20AMG8833=E3=82=92=E4=BD=BF=E3=81=A3?= =?UTF-8?q?=E3=81=9FTensorflow=E3=81=AB=E3=82=88=E3=82=8B=E8=BB=A2?= =?UTF-8?q?=E7=A7=BB=E5=AD=A6=E7=BF=92=E3=83=96=E3=83=AD=E3=83=83=E3=82=AF?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 74 ++-- index.js | 24 +- index_elutil.js | 45 +-- local_modules/@ocogeclub/amg8833/AMG8833.js | 5 + package.json | 7 +- ugj_blocks.js | 397 ++++++++++++-------- yarn.lock | 174 ++++++--- 7 files changed, 426 insertions(+), 300 deletions(-) diff --git a/index.html b/index.html index e9c203d..47bbf6f 100644 --- a/index.html +++ b/index.html @@ -512,38 +512,13 @@ 0x69 + - - サブキャンバス - - - 8 - - - - - 8 - - - - - 160 - - - - - 160 - - - + - #ff4500 - #0000ff - - + #ff0000 + #3333ff 28 @@ -555,6 +530,17 @@ + + + + + + 0 + + + + + @@ -834,7 +820,13 @@ - + + + + storage + + + @@ -914,28 +906,6 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/index.js b/index.js index d5706d5..45740c3 100644 --- a/index.js +++ b/index.js @@ -36,6 +36,9 @@ var theme = Blockly.Theme.defineTheme('ocoge', { 'multimedia_blocks': { "colourPrimary": multimedia_color }, + 'colour_blocks': { + "colourPrimary": multimedia_color + }, 'network_blocks': { "colourPrimary": network_color }, @@ -87,11 +90,7 @@ Blockly.Msg["UGJ_FOREACH_TITLE"] = "リスト %1 の各 %2 について %3 %4"; Blockly.Msg["UGJ_FOREACH_ITEM"] = "項目"; Blockly.Msg["UGJ_FOREACH_TOOLTIP"] = "リストの各項目について、その項目を変数「項目」としてステートメントを実行します。"; -Blockly.Msg["UGJ_CREATE_SUBCANVAS_TITLE"] = "%1 %2 を、幅 %3 px、高さ %4 pxで作成 %5 、幅 %6 px、高さ %7 pxで表示"; -Blockly.Msg["UGJ_CREATE_SUBCANVAS_VAR"] = "サブキャンバス"; -Blockly.Msg["UGJ_CREATE_SUBCANVAS_TOOLTIP"] = "ディスプレイエリアに、右下寄せでキャンバスを作成します。"; - -Blockly.Msg["UGJ_DRAW_GRIDEYEDATA_TITLE"] = "赤外線アレイセンサ画像表示 %1 入力 %2 温度範囲上限 %3 %4 温度範囲下限 %5 %6 描画対象キャンバス %7"; +Blockly.Msg["UGJ_DRAW_GRIDEYEDATA_TITLE"] = "赤外線アレイセンサ画像表示 %1 温度データ %2 温度範囲上限 %3 %4 温度範囲下限 %5 %6"; Blockly.Msg["UGJ_DRAW_GRIDEYEDATA_TOOLTIP"] = "AMG8833の温度データを、画像としてキャンバスに描画します。「着色」をチェックすると、温度範囲で設定されている色をつけて表示します。"; Blockly.Msg["GPIO_OPEN_TITLE"] = "GPIO を使えるようにする"; @@ -154,10 +153,24 @@ Blockly.Msg["UGJ_GESTURE_STOP_TITLE"] = "ジェスチャーセンサーから切 Blockly.Msg["UGJ_GESTURE_STOP_TOOLTIP"] = "センサーとの接続を停止します。"; Blockly.Msg["UGJ_GRIDEYE_INIT_TITLE"] = "赤外線アレイセンサ(アドレス: %1 )を初期化"; Blockly.Msg["UGJ_GRIDEYE_INIT_TOOLTIP"] = "赤外線アレイセンサ AMG8833 の使用準備をします。"; +Blockly.Msg["UGJ_GRIDEYE_THERMISTOR_TITLE"] = "赤外線アレイセンサ本体温度"; +Blockly.Msg["UGJ_GRIDEYE_THERMISTOR_TOOLTIP"] = "AMG8833に内蔵されたサーミスタ(温度センサ)の値を取得します。"; Blockly.Msg["UGJ_GRIDEYE_READ_TITLE"] = "赤外線アレイセンサの値"; Blockly.Msg["UGJ_GRIDEYE_READ_TOOLTIP"] = "AMG8833から読み取った温度データを、8x8の配列で取得します。"; Blockly.Msg["UGJ_GRIDEYE_STOP_TITLE"] = "赤外線アレイセンサから切断"; Blockly.Msg["UGJ_GRIDEYE_STOP_TOOLTIP"] = "センサーとの接続を停止します。"; +Blockly.Msg["UGJ_GRIDEYE_CANVAS_CREATE_TITLE"] = "赤外線アレイセンサデータ表示キャンバスを作成"; +Blockly.Msg["UGJ_GRIDEYE_CANVAS_CREATE_TOOLTIP"] = "ディスプレイエリアにAMG8833データ表示用キャンバスを作成します。"; +Blockly.Msg["UGJ_TEACHABLE_MACHINE_TITLE"] = "TensorFlow.jsによる画像分類器の準備"; +Blockly.Msg["UGJ_TEACHABLE_MACHINE_TOOLTIP"] = "TensorFlow.jsにMobileNet, KNN Classifierを読み込んで、画像認識(分類)を行う準備をします。"; +Blockly.Msg["UGJ_GRIDEYE_PREDICT_CLASS_TITLE"] = "赤外線アレイセンサの画像で推論を行う"; +Blockly.Msg["UGJ_GRIDEYE_PREDICT_CLASS_TOOLTIP"] = "キャンバスに表示されたAMG8833の画像を元に画像分類の推論を行います。推論の結果として定義済みのラベルを返します。"; +Blockly.Msg["UGJ_GRIDEYE_ADD_EXAMPLE_TITLE"] = "赤外線アレイセンサの画像にラベル %1 をつけてデータセットへ追加"; +Blockly.Msg["UGJ_GRIDEYE_ADD_EXAMPLE_TOOLTIP"] = "キャンバスに表示されているAMG8833の画像にラベル(クラス名)をつけてデータセットへ追加します。"; +Blockly.Msg["UGJ_TENSORSET_STRINGIFY_TITLE"] = "学習したクラスデータセットを文字列に変換"; +Blockly.Msg["UGJ_TENSORSET_STRINGIFY_TOOLTIP"] = "学習したクラスデータセットを文字列に変換して保存します。"; +Blockly.Msg["UGJ_TENSORSET_PARSE_TITLE"] = "クラスデータ文字列 %1 を画像分類器にセット"; +Blockly.Msg["UGJ_TENSORSET_PARSE_TOOLTIP"] = "JSONテキストをパースして画像分類器に戻します。"; Blockly.Msg["UGJ_CODECHAR_TITLE"] = "コード %1 の文字"; Blockly.Msg["UGJ_CODECHAR_TOOLTIP"] = "文字コードを文字に変換します。"; @@ -172,7 +185,6 @@ Blockly.Msg["UGJ_CANVAS_INIT_TITLE"] = "キャンバスを表示"; Blockly.Msg["UGJ_CANVAS_INIT_TOOLTIP"] = "キャンバスを表示し、使用できるようにします。"; Blockly.Msg["UGJ_FACEAPI_TITLE"] = "TensorFlowによる顔検出: %1 ランドマークを検出 %2 %3"; Blockly.Msg["UGJ_FACEAPI_TOOLTIP"] = "TensorFlow とFaceAPI をロードし、顔検出をできるようにします。"; - Blockly.Msg["UGJ_SLEEP_TITLE"] = "%1 秒待つ"; Blockly.Msg["UGJ_SLEEP_TOOLTIP"] = "指定した秒数だけ処理を中断します。"; diff --git a/index_elutil.js b/index_elutil.js index b97d270..b7e8d1e 100644 --- a/index_elutil.js +++ b/index_elutil.js @@ -13,7 +13,7 @@ const ugj_const = { localStorage_fname: 'ocoge.json', error_ja_all: 'エラーが発生しました。\n『おこげ倶楽部』までお問い合わせください。', pig: 'pigpio', - lg: 'lgpio', // lgpioがテストフェーズを終えてハードウェアPWMを実装したら切り替えを実装予定 + lg: 'lgpio', // lgpioがハードウェアPWMを実装してRPiOSにプリインストールされるようになったら切り替え予定 i2c_defbus: '6', // 文字列リテラルで指定 dev_hash: '4e9205f9b7e571bec1aa52ab7871f420684fcf96149672a4d550a95863d6b072' } @@ -325,49 +325,12 @@ if (!is_el) { case 'fs': block = 'ファイル'; break; + case 'path': + block = 'キャンバス保存'; + break; default: throw new Error(ugj_const.error_ja_all); } throw `ブロック「${block}」は、Web体験版ではご利用になれません。\n詳しくは https://ocoge.club/ をご覧ください。`; } } - - -// "require" for "BLOCK"s if contextIsolation is true -// ブラウザ動作時にはすべてアラートを表示 -// const require = module_name => { -// if (is_el) { -// switch (module_name) { -// case '@ocogeclub/lgpio': -// return window.ocogeapi.lgpio; -// case '@ocogeclub/bme280': -// return window.ocogeapi.bme280; -// case 'fs': -// return window.ocogeapi.fs; -// case 'path': -// return window.ocogeapi.path; -// case '@tensorflow/tfjs-node': -// return window.ocogeapi.tfjs_node; -// case '@vladmandic/face-api/dist/face-api.node.js': -// return window.ocogeapi.face_api; -// default: -// throw new Error(`Unknown module "${module_name}" required.\nStopped.`); -// } -// } else { -// let block; -// switch (module_name) { -// case '@ocogeclub/lgpio': -// block = 'GPIO'; -// break; -// case '@ocogeclub/bme280': -// block = 'BME280'; -// break; -// case 'fs': -// block = 'ファイル'; -// break; -// default: -// throw new Error(ugj_const.error_ja_all); -// } -// throw `ブロック「${block}」は、Web体験版ではご利用になれません。\n詳しくは https://ocoge.club/ をご覧ください。`; -// } -// } diff --git a/local_modules/@ocogeclub/amg8833/AMG8833.js b/local_modules/@ocogeclub/amg8833/AMG8833.js index 4b05997..46545f3 100644 --- a/local_modules/@ocogeclub/amg8833/AMG8833.js +++ b/local_modules/@ocogeclub/amg8833/AMG8833.js @@ -12,6 +12,11 @@ exports.init = (i2c_bus, i2c_addr) => { pig._i2c_write_byte_data(pi, i2c_hand, 0x02, 0x00); //10FPS } +exports.read_thermistor = () => { + let temp = pig._i2c_read_word_data(pi, i2c_hand, 0x0e); + return temp * 0.0625; +} + exports.read_temp_array = () => { let linedata = []; for (let i = 0; i < 8; i++) { diff --git a/package.json b/package.json index eadc149..ac95d1f 100644 --- a/package.json +++ b/package.json @@ -27,9 +27,12 @@ "@ocogeclub/bme280": "file:local_modules/@ocogeclub/bme280", "@ocogeclub/paj7620": "file:local_modules/@ocogeclub/paj7620", "@ocogeclub/pigpio": "file:local_modules/@ocogeclub/pigpio", - "@tensorflow/tfjs-node": "^3.9.0", + "@tensorflow-models/knn-classifier": "^1.2.2", + "@tensorflow-models/mobilenet": "^2.1.0", + "@tensorflow/tfjs-node": "^3.11.0", "@vladmandic/face-api": "^1.5.3", "axios": "^0.21.1", - "nodemailer": "^6.6.0" + "nodemailer": "^6.6.0", + "tensorset": "^1.2.9" } } diff --git a/ugj_blocks.js b/ugj_blocks.js index 94645fc..1cd0f39 100644 --- a/ugj_blocks.js +++ b/ugj_blocks.js @@ -1264,9 +1264,9 @@ Blockly.Blocks['ugj_grideye_init'] = { Blockly.JavaScript['ugj_grideye_init'] = function (block) { var dropdown_addr = block.getFieldValue('addr'); Blockly.JavaScript.provideFunction_( - 'require_amg8833', [`const amg8833 = require('@ocogeclub/amg8833');`] + 'require_amg8833', [`const _amg8833 = require('@ocogeclub/amg8833');`] ); - var code = `amg8833.init(${elutil.i2c_bus}, ${dropdown_addr});\n`; + var code = `_amg8833.init(${elutil.i2c_bus}, ${dropdown_addr});\n`; return code; }; Blockly.Python['ugj_grideye_init'] = function (block) { @@ -1275,6 +1275,33 @@ Blockly.Python['ugj_grideye_init'] = function (block) { var code = '...\n'; return code; }; +/********************** */ +/** Grid-Eye 本体温度 ** */ +/********************** */ +var ugjGridEyeThermistorDefinition = { + "type": "ugj_grideye_thermistor", + "message0": "%{BKY_UGJ_GRIDEYE_THERMISTOR_TITLE}", + "output": "Number", + "tooltip": "%{BKY_UGJ_GRIDEYE_THERMISTOR_TOOLTIP}", + "helpUrl": "", + "style": "sensor_blocks" +}; +Blockly.Blocks['ugj_grideye_thermistor'] = { + init: function () { + this.jsonInit(ugjGridEyeThermistorDefinition); + } +}; +Blockly.JavaScript['ugj_grideye_thermistor'] = function (block) { + var code = `_amg8833.read_thermistor()`; + return [code, Blockly.JavaScript.ORDER_NONE]; +}; +Blockly.Python['ugj_grideye_thermistor'] = function (block) { + // TODO: Assemble Python into code variable. + var code = '...'; + // TODO: Change ORDER_NONE to the correct strength. + return [code, Blockly.Python.ORDER_NONE]; +}; + /**************************** */ /** Read Temperature Array ** */ /**************************** */ @@ -1293,7 +1320,7 @@ Blockly.Blocks['ugj_grideye_read'] = { } }; Blockly.JavaScript['ugj_grideye_read'] = function (block) { - var code = 'amg8833.read_temp_array()'; + var code = '_amg8833.read_temp_array()'; return [code, Blockly.JavaScript.ORDER_ATOMIC]; }; Blockly.Python['ugj_grideye_read'] = function (block) { @@ -1321,7 +1348,7 @@ Blockly.Blocks['ugj_grideye_stop'] = { } }; Blockly.JavaScript['ugj_grideye_stop'] = function (block) { - var code = 'amg8833.stop();\n'; + var code = '_amg8833.stop();\n'; return code; }; Blockly.Python['ugj_grideye_stop'] = function (block) { @@ -1798,73 +1825,34 @@ Blockly.JavaScript['ugj_canvas_drawrect'] = function (block) { return code; }; -/*********************** */ -/** Create sub canvas ** */ -/*********************** */ -var ugjCreateSubCanvasDefinition = { - "type": "ugj_create_sub_canvas", - "message0": "%{BKY_UGJ_CREATE_SUBCANVAS_TITLE}", - "args0": [ - { - "type": "field_variable", - "name": "sub_canvas", - "variable": "%{BKY_UGJ_CREATE_SUBCANVAS_VAR}" - }, - { - "type": "input_dummy" - }, - { - "type": "input_value", - "name": "width", - "check": "Number" - }, - { - "type": "input_value", - "name": "height", - "check": "Number" - }, - { - "type": "input_dummy" - }, - { - "type": "input_value", - "name": "style_width", - "check": "Number" - }, - { - "type": "input_value", - "name": "style_height", - "check": "Number" - } - ], +/***************************** */ +/** GridEye 表示キャンバス作成 ** */ +/***************************** */ +var ugjGridEyeCanvasCreateDefinition = { + "type": "ugj_grideye_canvas_create", + "message0": "%{BKY_UGJ_GRIDEYE_CANVAS_CREATE_TITLE}", "inputsInline": true, "previousStatement": null, "nextStatement": null, - "tooltip": "%{BKY_UGJ_CREATE_SUBCANVAS_TOOLTIP}", + "tooltip": "%{BKY_UGJ_GRIDEYE_CANVAS_CREATE_TOOLTIP}", "helpUrl": "", "style": "multimedia_blocks" }; -Blockly.Blocks['ugj_create_sub_canvas'] = { +Blockly.Blocks['ugj_grideye_canvas_create'] = { init: function () { - this.jsonInit(ugjCreateSubCanvasDefinition); + this.jsonInit(ugjGridEyeCanvasCreateDefinition); } }; -Blockly.JavaScript['ugj_create_sub_canvas'] = function (block) { - var variable_sub_canvas = Blockly.JavaScript.nameDB_.getName(block.getFieldValue('sub_canvas'), Blockly.Variables.NAME_TYPE); - var value_width = Blockly.JavaScript.valueToCode(block, 'width', Blockly.JavaScript.ORDER_ATOMIC); - var value_height = Blockly.JavaScript.valueToCode(block, 'height', Blockly.JavaScript.ORDER_ATOMIC); - var value_style_width = Blockly.JavaScript.valueToCode(block, 'style_width', Blockly.JavaScript.ORDER_ATOMIC); - var value_style_height = Blockly.JavaScript.valueToCode(block, 'style_height', Blockly.JavaScript.ORDER_ATOMIC); - var code = `${variable_sub_canvas} = {}; -${variable_sub_canvas}.el = document.createElement('canvas'); -${variable_sub_canvas}.el.setAttribute('width', ${value_width}); -${variable_sub_canvas}.el.setAttribute('height', ${value_height}); -${variable_sub_canvas}.el.className = 'subdisplay'; -${variable_sub_canvas}.el.style.width = '${value_style_width}px'; -${variable_sub_canvas}.el.style.height = '${value_style_height}px'; -document.getElementById('display_area').appendChild(${variable_sub_canvas}.el); -${variable_sub_canvas}.ctx = ${variable_sub_canvas}.el.getContext('2d'); -${variable_sub_canvas}.imgData = ${variable_sub_canvas}.ctx.createImageData(${variable_sub_canvas}.el.width, ${variable_sub_canvas}.el.height); +Blockly.JavaScript['ugj_grideye_canvas_create'] = function (block) { + var code = `let _grideye_canvas = document.createElement('canvas'); +_grideye_canvas.setAttribute('width', 8); +_grideye_canvas.setAttribute('height', 8); +_grideye_canvas.className = 'subdisplay'; +_grideye_canvas.style.width = '160px'; +_grideye_canvas.style.height = '160px'; +document.getElementById('display_area').appendChild(_grideye_canvas); +_grideye_ctx = _grideye_canvas.getContext('2d'); +_grideye_imgData = _grideye_ctx.createImageData(8, 8); `; return code; }; @@ -1905,12 +1893,6 @@ var ugjDrawGrideyedataDefinition = { "name": "temp_low", "check": "Number", "align": "RIGHT" - }, - { - "type": "input_value", - "name": "canvas", - "check": "Canvas", - "align": "RIGHT" } ], "inputsInline": false, @@ -1931,7 +1913,6 @@ Blockly.JavaScript['ugj_draw_grideyedata'] = function (block) { var value_temp_high = Blockly.JavaScript.valueToCode(block, 'temp_high', Blockly.JavaScript.ORDER_ATOMIC); var colour_color_low = block.getFieldValue('color_low'); var value_temp_low = Blockly.JavaScript.valueToCode(block, 'temp_low', Blockly.JavaScript.ORDER_ATOMIC); - var value_canvas = Blockly.JavaScript.valueToCode(block, 'canvas', Blockly.JavaScript.ORDER_ATOMIC); var functionName = Blockly.JavaScript.provideFunction_( 'mapVal', ['const ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + ' = (val, inMin, inMax, outMin, outMax) => {', @@ -1947,27 +1928,185 @@ Blockly.JavaScript['ugj_draw_grideyedata'] = function (block) { lr = '0x' + colour_color_low.slice(1, 3); lg = '0x' + colour_color_low.slice(3, 5); lb = '0x' + colour_color_low.slice(5, 7); - var code = `// colour_color_high = ${colour_color_high} - const color_range = [[${lr}, ${hr}], [${lg}, ${hg}], [${lb}, ${hb}]]; //超簡易的な色付け - // const color_range = [[0, 0xff], [0, 0x3f], [0xff, 0]]; - let grideye_data = ${value_amg8833data};//読み取りブロックを入力に直接接続できるようにする - for (let raw = 0; raw < ${value_canvas}.el.height; raw++) { - for (let col = 0; col < ${value_canvas}.el.width; col++) { + var code = ` const _color_range = [[${lr}, ${hr}], [${lg}, ${hg}], [${lb}, ${hb}]]; + let _grideye_data = ${value_amg8833data};//読み取りブロックを入力に直接接続できるようにする + for (let raw = 0; raw < _grideye_canvas.height; raw++) { + for (let col = 0; col < _grideye_canvas.width; col++) { for (let rgb = 0; rgb < 3; rgb++) { - let pixel = ${functionName}(grideye_data[raw][col], ${value_temp_low}, ${value_temp_high}, color_range[rgb][0], color_range[rgb][1]); - ${value_canvas}.imgData.data[((raw * ${value_canvas}.el.width * 4) + col * 4) + rgb] = pixel; + let pixel = ${functionName}(_grideye_data[raw][col], ${value_temp_low}, ${value_temp_high}, _color_range[rgb][0], _color_range[rgb][1]); + _grideye_imgData.data[((raw * _grideye_canvas.width * 4) + col * 4) + rgb] = pixel; } - ${value_canvas}.imgData.data[((raw * ${value_canvas}.el.width * 4) + col * 4) + 3] = 0xff; + _grideye_imgData.data[((raw * _grideye_canvas.width * 4) + col * 4) + 3] = 0xff; } } - ${value_canvas}.ctx.putImageData(${value_canvas}.imgData, 0, 0); + _grideye_ctx.putImageData(_grideye_imgData, 0, 0); `; return code; }; +/**************************** */ +/** Teachable Machine を開始** */ +/**************************** */ +var ugjTeachableMachineDefinition = { + "type": "ugj_teachable_machine", + "message0": "%{BKY_UGJ_TEACHABLE_MACHINE_TITLE}", + "inputsInline": true, + "previousStatement": null, + "nextStatement": null, + "tooltip": "%{BKY_UGJ_TEACHABLE_MACHINE_TOOLTIP}", + "helpUrl": "", + "style": "multimedia_blocks" +}; +Blockly.Blocks['ugj_teachable_machine'] = { + init: function () { + this.jsonInit(ugjTeachableMachineDefinition); + } +}; +Blockly.JavaScript['ugj_teachable_machine'] = function (block) { + Blockly.JavaScript.provideFunction_( + 'require_ts', [`const _tf = require('@tensorflow/tfjs-node');`] + ); + Blockly.JavaScript.provideFunction_( + 'require_mobilenet', [`const _mobilenet = require('@tensorflow-models/mobilenet');`] + ); + Blockly.JavaScript.provideFunction_( + 'require_knn', [`const _knnClassifier = require('@tensorflow-models/knn-classifier');`] + ); - + var code = `const _classifier = _knnClassifier.create(); + const _net = await _mobilenet.load({ version: 1, alpha: 0.25 }); // 高速・低精度 + `; + return code; +}; +/************************* */ +/** GridEye で推論を行う ** */ +/************************* */ +var ugjGridEyePredictClassDefinition = { + "type": "ugj_grideye_predict_class", + "message0": "%{BKY_UGJ_GRIDEYE_PREDICT_CLASS_TITLE}", + "inputsInline": true, + "output": "Number", + "tooltip": "%{BKY_UGJ_GRIDEYE_PREDICT_CLASS_TOOLTIP}", + "helpUrl": "", + "style": "multimedia_blocks" +}; +Blockly.Blocks['ugj_grideye_predict_class'] = { + init: function () { + this.jsonInit(ugjGridEyePredictClassDefinition); + } +}; +Blockly.JavaScript['ugj_grideye_predict_class'] = function (block) { + var functionName = Blockly.JavaScript.provideFunction_( + '_predictClass', + [ + `if (_confidence === undefined) var _confidence;`, + `const ${Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_} = async (img, clsfr, mblnet) => {`, + `if (clsfr.getNumClasses() > 0) {`, + `const result = await clsfr.predictClass(mblnet.infer(img, 'conv_preds'));`, + `_confidence = result.confidences[result.label];`, + `return result.label;`, + `}`, + `else return 0;`, + `}` + ] + ); + var code = `await ${functionName}(_grideye_canvas, _classifier, _net)`; + return [code, Blockly.JavaScript.ORDER_NONE]; +}; +/******************************************** */ +/** ラベルをつけて Example をデータセットに追加 ** */ +/******************************************** */ +var ugjGridEyeAddExampleDefinition = { + "type": "ugj_grideye_add_example", + "message0": "%{BKY_UGJ_GRIDEYE_ADD_EXAMPLE_TITLE}", + "args0": [ + { + "type": "input_value", + "name": "class_id", + "check": "Number" + } + ], + "inputsInline": true, + "previousStatement": null, + "nextStatement": null, + "tooltip": "%{BKY_UGJ_GRIDEYE_ADD_EXAMPLE_TOOLTIP}", + "helpUrl": "", + "style": "multimedia_blocks" +}; +Blockly.Blocks['ugj_grideye_add_example'] = { + init: function () { + this.jsonInit(ugjGridEyeAddExampleDefinition); + } +}; +Blockly.JavaScript['ugj_grideye_add_example'] = function (block) { + var value_class_id = Blockly.JavaScript.valueToCode(block, 'class_id', Blockly.JavaScript.ORDER_ATOMIC); + var functionName = Blockly.JavaScript.provideFunction_( + '_addExample', + [ + `const ${Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_} = async (label, img, clsfr, mblnet) => {`, + `clsfr.addExample(mblnet.infer(img, true), label);`, + `}` + ] + ); + var code = `await ${functionName}(${value_class_id}, _grideye_canvas, _classifier, _net);`; + return code; +}; +/*************************** */ +/** 学習したクラスを文字列化 ** */ +/*************************** */ +var ugjTensorsetStringifyDefinition = { + "type": "ugj_tensorset_stringify", + "message0": "%{BKY_UGJ_TENSORSET_STRINGIFY_TITLE}", + "output": null, + "tooltip": "%{BKY_UGJ_TENSORSET_STRINGIFY_TOOLTIP}", + "helpUrl": "", + "style": "multimedia_blocks" +}; +Blockly.Blocks['ugj_tensorset_stringify'] = { + init: function () { + this.jsonInit(ugjTensorsetStringifyDefinition); + } +}; +Blockly.JavaScript['ugj_tensorset_stringify'] = function (block) { + Blockly.JavaScript.provideFunction_( + 'require_tensorset', [`const _Tensorset = require('tensorset');`] + ); + var code = `await _Tensorset.stringify(_classifier.getClassifierDataset())`; + return [code, Blockly.JavaScript.ORDER_NONE]; +}; +/***************************************** */ +/** jsonをデータセットに戻して分類器にセット ** */ +/***************************************** */ +var ugjTensorsetParseDefinition = { + "type": "ugj_tensorset_parse", + "message0": "%{BKY_UGJ_TENSORSET_PARSE_TITLE}", + "args0": [ + { + "type": "input_value", + "name": "class_data_json", + "check": "String" + } + ], + "previousStatement": null, + "nextStatement": null, + "tooltip": "%{BKY_UGJ_TENSORSET_PARSE_TOOLTIP}", + "helpUrl": "", + "style": "multimedia_blocks" +}; +Blockly.Blocks['ugj_tensorset_parse'] = { + init: function () { + this.jsonInit(ugjTensorsetParseDefinition); + } +}; +Blockly.JavaScript['ugj_tensorset_parse'] = function (block) { + Blockly.JavaScript.provideFunction_( + 'require_tensorset', [`const _Tensorset = require('tensorset');`] + ); + var value_class_data_json = Blockly.JavaScript.valueToCode(block, 'class_data_json', Blockly.JavaScript.ORDER_ATOMIC); + var code = `_classifier.setClassifierDataset(_Tensorset.parse(${value_class_data_json}));\n`; + return code; +}; /****************************** */ @@ -2591,7 +2730,7 @@ Blockly.Blocks['ugj_localstorage_load'] = { this.setInputsInline(true); this.setOutput(true, "String"); this.setOutputShape(Blockly.OUTPUT_SHAPE_ROUND); - this.setStyle('special_blocks') + this.setStyle('special_blocks'); this.setTooltip("ローカルストレージからテキストデータを読み込みます。"); this.setHelpUrl(""); } @@ -2602,39 +2741,29 @@ Blockly.JavaScript['ugj_localstorage_load'] = function (block) { return [code, Blockly.JavaScript.ORDER_NONE]; }; -/**************************** */ -/** Key List in Local Storage */ -/**************************** */ -Blockly.Blocks['ugj_localstorage_keylist'] = { +/******************************* */ +/** Remove Item in Local Storage */ +/******************************* */ +Blockly.Blocks['ugj_localstorage_remove'] = { init: function () { + this.appendValueInput("key") + .setCheck("String") + .appendField("ローカルストレージ"); this.appendDummyInput() - .appendField("ローカルストレージに保存されているデータの一覧"); - this.setInputsInline(true); - this.setOutput(true, null); - this.setOutputShape(Blockly.OUTPUT_SHAPE_ROUND); - this.setStyle('special_blocks') - this.setTooltip("ローカルストレージに保存されているキーの一覧を取得します。"); + .appendField("を削除"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setStyle('special_blocks'); + this.setTooltip("ローカルストレージに保存されたアイテムを削除します。"); this.setHelpUrl(""); } }; -Blockly.JavaScript['ugj_localstorage_keylist'] = function (block) { - var functionName = Blockly.JavaScript.provideFunction_( - 'localStorage_getKeyList', - [ - 'const ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + ' = () => {', - 'let listArray = [];', - 'for (let i=0; i', - 'new Promise(r => setTimeout(r, milisec));'] + ['const ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + ' = sec =>', + 'new Promise(r => setTimeout(r, sec * 1000));'] ); - var code = `await ${functionName}(${value_sec}*1000);\n`; + var code = `await ${functionName}(${value_sec});\n`; return code; }; Blockly.Python['ugj_sleep'] = function (block) { @@ -3254,6 +3352,7 @@ Blockly.Blocks['ugj_set_interval'] = { .setCheck(null); this.setInputsInline(true); this.setPreviousStatement(true, null); + this.setNextStatement(true, null); this.setStyle('special_blocks') this.setTooltip("非同期で繰り返し処理を行います(停止ボタンまたは停止ブロックで停止)。"); this.setHelpUrl(""); @@ -3304,7 +3403,7 @@ Blockly.Blocks['ugj_set_timeout'] = { // .appendField("この下は待たずに実行"); this.setInputsInline(true); this.setPreviousStatement(true, null); - this.setNextStatement(false, null); + this.setNextStatement(true, null); this.setStyle('special_blocks') this.setTooltip("指定した秒数だけ待ってから実行します。");//内側のブロック部を 外側下に接続したものは待たずに直ちに実行されます(非同期動作)。 this.setHelpUrl(""); @@ -3445,17 +3544,3 @@ else console.log('invalid certification'); `; return code; }; -// Blockly.Blocks['ugj_dev_run_js'] = { -// init: function () { -// this.setPreviousStatement(true, null); -// this.setColour(230); -// this.setTooltip(""); -// this.setHelpUrl(""); -// } -// }; -// Blockly.JavaScript['ugj_dev_run_js'] = function (block) { -// // TODO: Assemble JavaScript into code variable. -// // var code = localStorage.getItem('ocoge_dev_code'); -// var code = -// return code; -// }; \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index d5f3145..339c9c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -64,17 +64,17 @@ "@ocogeclub/amg8833@file:local_modules/@ocogeclub/amg8833": version "0.0.1" dependencies: - "@ocogeclub/pigpio" "file:../../.cache/yarn/v6/npm-@ocogeclub-amg8833-0.0.1-8dfa7589-6746-40d4-9530-a4546ba16ad3-1634476251665/node_modules/@ocogeclub/pigpio" + "@ocogeclub/pigpio" "file:../../.cache/yarn/v6/npm-@ocogeclub-amg8833-0.0.1-086d238a-3208-4bc5-8baa-2d63d4e9d068-1635603361158/node_modules/@ocogeclub/pigpio" "@ocogeclub/bme280@file:local_modules/@ocogeclub/bme280": version "0.0.1" dependencies: - "@ocogeclub/pigpio" "file:../../.cache/yarn/v6/npm-@ocogeclub-bme280-0.0.1-54967241-c3ef-4a53-ad34-16acb3e76088-1634476250850/node_modules/@ocogeclub/pigpio" + "@ocogeclub/pigpio" "file:../../.cache/yarn/v6/npm-@ocogeclub-bme280-0.0.1-eeffd664-25e9-4ed6-a266-9dcfc579f450-1635603361179/node_modules/@ocogeclub/pigpio" "@ocogeclub/paj7620@file:local_modules/@ocogeclub/paj7620": version "0.0.1" dependencies: - "@ocogeclub/pigpio" "file:../../.cache/yarn/v6/npm-@ocogeclub-paj7620-0.0.1-6dd29fc9-a1f9-43f4-9e96-a79744ba2494-1634476250888/node_modules/@ocogeclub/pigpio" + "@ocogeclub/pigpio" "file:../../.cache/yarn/v6/npm-@ocogeclub-paj7620-0.0.1-102e6c39-d4e3-4b54-886f-60476a90588b-1635603361184/node_modules/@ocogeclub/pigpio" "@ocogeclub/pigpio@file:local_modules/@ocogeclub/pigpio": version "0.0.1" @@ -106,35 +106,81 @@ dependencies: defer-to-connect "^2.0.0" -"@tensorflow/tfjs-backend-cpu@3.9.0": - version "3.9.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-3.9.0.tgz#27ee581a4765039eb0e84d9d473b6d5f2769c813" - integrity sha512-PUv5B3wdQsA8cysk+oUhA0NqMoo/lwP8EazC/axQc8/72Dc6kU8uw/5qZtE5P4xXSqkNSlh2ifFm+8nH/6B+iA== +"@tensorflow-models/knn-classifier@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@tensorflow-models/knn-classifier/-/knn-classifier-1.2.2.tgz#a5a9045b3d225a06e60f2b1cc2de56bdac6748e8" + integrity sha512-QRnkCf7ErOxSRtvJ6yCwhlLREPcBJGaXRanF46f0iY6ii3Sybjb6Ux0qnNPTrHZChD0izPa3Z4GQEgSAykiHkQ== + +"@tensorflow-models/mobilenet@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@tensorflow-models/mobilenet/-/mobilenet-2.1.0.tgz#58583f0793a7091eda370aa441d09d94b808aeb1" + integrity sha512-JjqT9ijHDFA2FEpUGWg7H2lQ0GrMuE2VmiCRBYmUew6b4JKht8LXDjG5HxZh95YH6c/25sZWTpGeHbquloH+hw== + +"@tensorflow/tfjs-backend-cpu@2.8.6": + version "2.8.6" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-2.8.6.tgz#ef60c3294a04c8c600abb4b438263c06d9b7b7bd" + integrity sha512-x9WTTE9p3Pon2D0d6HH1UCIJsU1w3v9sF3vxJcp+YStrjDefWoW5pwxHCckEKTRra7GWg3CwMKK3Si2dat4H1A== dependencies: "@types/seedrandom" "2.4.27" seedrandom "2.4.3" -"@tensorflow/tfjs-backend-webgl@3.9.0": - version "3.9.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-3.9.0.tgz#103630e23d4325492bfbe2ff65b58c24ad852377" - integrity sha512-oUnyQFF9aCnNZpul9AnJwrt8noDJdMmxgq2+e/0DpEMBERcywtVj9qkKCccMaVFsdQV1lQxpV3kjC3vbFMDWKg== +"@tensorflow/tfjs-backend-cpu@3.11.0": + version "3.11.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-3.11.0.tgz#01d5d68b91faf12bee4854adae56bc956b794f1a" + integrity sha512-ShLkrZ4/rmhZwzGKenMFDfQnaEbyZgWA5F8JRa52Iob/vptlZeuOzjq87CZKmZMUmDswR9A2kjzovT/H1bJdWQ== dependencies: - "@tensorflow/tfjs-backend-cpu" "3.9.0" + "@types/seedrandom" "2.4.27" + seedrandom "2.4.3" + +"@tensorflow/tfjs-backend-webgl@2.8.6": + version "2.8.6" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-2.8.6.tgz#b88b4276a2ff4e23b05470c506b5c720bf6eb8c3" + integrity sha512-kPgm3Dim0Li5MleybYKSZVUCu91ipDjZtTA5RrJx/Dli115qwWdiRGOHYwsIEY61hZoE0m3amjWLUBxtwMW1Nw== + dependencies: + "@tensorflow/tfjs-backend-cpu" "2.8.6" "@types/offscreencanvas" "~2019.3.0" "@types/seedrandom" "2.4.27" "@types/webgl-ext" "0.0.30" "@types/webgl2" "0.0.5" seedrandom "2.4.3" -"@tensorflow/tfjs-converter@3.9.0": - version "3.9.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-converter/-/tfjs-converter-3.9.0.tgz#e00709002cbe04ff5cc43358d4a5662795513071" - integrity sha512-ftegwQlGkyDCxZGhAVfMyWWXqpNhnyESvNY3oFAUV4eN6i/mmBTCSOQ5AX5VR5lr7PNYPWGO5sJ10Q5HeTPfgw== +"@tensorflow/tfjs-backend-webgl@3.11.0": + version "3.11.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-3.11.0.tgz#fbd7f24c164d17c11d964206b4b075b073b1a3bc" + integrity sha512-rNnc/dZ7LIl9O/Pn9W24I1h8kgpJ+XvG8NrdNSfIoWPCW4fvPSlU7B3yMeZXvRneny+z+T3xRs96nWyU2mZBJw== + dependencies: + "@tensorflow/tfjs-backend-cpu" "3.11.0" + "@types/offscreencanvas" "~2019.3.0" + "@types/seedrandom" "2.4.27" + "@types/webgl-ext" "0.0.30" + "@types/webgl2" "0.0.6" + seedrandom "2.4.3" -"@tensorflow/tfjs-core@3.9.0": - version "3.9.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-core/-/tfjs-core-3.9.0.tgz#5ca2356a14a58263840a6e3caee2467780db9450" - integrity sha512-wQ+VMsbvCne2OsogiNtRP8Mc01LnRGvAYQ0SGaDa4+1uwY2jsMk5GZjG66JQvf/Ppw8wyvKF170eh0yyCBgfcg== +"@tensorflow/tfjs-converter@2.8.6": + version "2.8.6" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-converter/-/tfjs-converter-2.8.6.tgz#6182d302ae883e0c45f47674a78bdd33e23db3a6" + integrity sha512-Uv4YC66qjVC9UwBxz0IeLZ8KS2CReh63WlGRtHcSwDEYiwsa7cvp9H6lFSSPT7kiJmrK6JtHeJGIVcTuNnSt9w== + +"@tensorflow/tfjs-converter@3.11.0": + version "3.11.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-converter/-/tfjs-converter-3.11.0.tgz#0842269a83599b52fd167a8a05372018a9a1ca6a" + integrity sha512-rTRIKvBoqL0qdPYpm8UXauZycOiaBHZB2E2v3OoXoHnjvle/Xn/09uZJdrixgGhR+Kahs3Vz27BEEFz6RI5j2w== + +"@tensorflow/tfjs-core@2.8.6": + version "2.8.6" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-core/-/tfjs-core-2.8.6.tgz#d5e9d5fc1d1a83e3fbf80942f3154300a9f82494" + integrity sha512-jS28M1POUOjnWgx3jp1v5D45DUQE8USsAHHkL/01z75KnYCAAmgqJSH4YKLiYACg3eBLWXH/KTcSc6dHAX7Kfg== + dependencies: + "@types/offscreencanvas" "~2019.3.0" + "@types/seedrandom" "2.4.27" + "@types/webgl-ext" "0.0.30" + node-fetch "~2.6.1" + seedrandom "2.4.3" + +"@tensorflow/tfjs-core@3.11.0": + version "3.11.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-core/-/tfjs-core-3.11.0.tgz#1e3986533faaed922bbfc2fe86da506d0e9e5c79" + integrity sha512-JOp+1+LCd0Xg3hu7fu6iQPWZnN8Hc6ssfP7B+625XH5GYY1/OhVASa7Ahe2mJr9gZovY2lw8FUejLh1jMmBb1Q== dependencies: "@types/long" "^4.0.1" "@types/offscreencanvas" "~2019.3.0" @@ -144,26 +190,39 @@ node-fetch "~2.6.1" seedrandom "2.4.3" -"@tensorflow/tfjs-data@3.9.0": - version "3.9.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-data/-/tfjs-data-3.9.0.tgz#9cb4fd6301c4362a8e7dc03bced563bdf1f0be19" - integrity sha512-1/H9VlYlfEX/LflzobSB5sx3FCavWGmzqRnAyyn5ChjgCzIUa+RtJ7nYgK2+6RC2MIDgKt1jmu36mkKZrwPD3w== +"@tensorflow/tfjs-data@2.8.6": + version "2.8.6" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-data/-/tfjs-data-2.8.6.tgz#5888ad0f7b7f8db2b7a5cf4af38e3c04d65efe32" + integrity sha512-zoDUfd5TfkYdviqu2bObwyJGXJiOvBckOTP9j36PUs6s+4DbTIDttyxdfeEaiiLX9ZUFU58CoW+3LI/dlFVyoQ== dependencies: "@types/node-fetch" "^2.1.2" node-fetch "~2.6.1" -"@tensorflow/tfjs-layers@3.9.0": - version "3.9.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-layers/-/tfjs-layers-3.9.0.tgz#0e05116bcd7f55eb39cff322e9940fa46c9fbda2" - integrity sha512-25I20Oy17YZ3y0x/pabeiN6/vai0vqMQ85/Bp0GLOpcN2kmOLcItdWOAqFW5YPI2nrTqnpNQyk9zhmIh8f6X4w== +"@tensorflow/tfjs-data@3.11.0": + version "3.11.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-data/-/tfjs-data-3.11.0.tgz#90dd23a7181f0a744f2882a12c3442b27047383d" + integrity sha512-+cUHUHzjM/zs0JVOwHQm9wP15Y+BZdRcUpMoYWia8r3kaGSyvoz6WqzacEP1PeXgJVnr2gtU3D+bF32th8fZfQ== + dependencies: + "@types/node-fetch" "^2.1.2" + node-fetch "~2.6.1" -"@tensorflow/tfjs-node@^3.9.0": - version "3.9.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-node/-/tfjs-node-3.9.0.tgz#5b3c04aeaaa120c466c0e746627db239938743cb" - integrity sha512-1DauUOIsuypby7OzuYgVHT3T2NAQZchUiFz3IkIwb1aN0i7lkDR79EjxGNg3mcMyt/FteED74RTafyMrl1EYHg== +"@tensorflow/tfjs-layers@2.8.6": + version "2.8.6" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-layers/-/tfjs-layers-2.8.6.tgz#51dec5422fddde289e7915f318676fedeeb6a226" + integrity sha512-fdZ0i/R2dIKmy8OB5tBAsm5IbAHfJpI6AlbjxpgoU3aWj1HCdDo+pMji928MkDJhP01ISgFTgw/7PseGNaUflw== + +"@tensorflow/tfjs-layers@3.11.0": + version "3.11.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-layers/-/tfjs-layers-3.11.0.tgz#456d8dc3fe93937ced329d5d06310da294d3758c" + integrity sha512-BtLgLucJZHv5te1K3yjT3iZdHXgMJArrLuOb/oRPOtTp4R2ad5N0V2m5RtuZJ3sI5/ah0h72xtmTWNyTv3/5dw== + +"@tensorflow/tfjs-node@^3.11.0": + version "3.11.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-node/-/tfjs-node-3.11.0.tgz#6c6f0dc0e2f0eb03658337b53ce3009e97526f8d" + integrity sha512-EFBAkwJDoP4WuiWqjT9ER80dUvilvVFXULlU3WpmVGDluIL/Yq18xEKHvPaYHW5jLq/mvMljLtUBlHqigfvAhw== dependencies: "@mapbox/node-pre-gyp" "1.0.4" - "@tensorflow/tfjs" "3.9.0" + "@tensorflow/tfjs" "3.11.0" adm-zip "^0.5.2" google-protobuf "^3.9.2" https-proxy-agent "^2.2.1" @@ -171,17 +230,34 @@ rimraf "^2.6.2" tar "^4.4.6" -"@tensorflow/tfjs@3.9.0": - version "3.9.0" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs/-/tfjs-3.9.0.tgz#ff3bcbfcb51800ea6791d7a7a020d354909d2c71" - integrity sha512-TyykXiZ6r9rMoXbQZaAkOKJJUrJHQVAjH/K6XRCPpOG//Hf15ZW97ZODskEByj77yNMw4smFUWCFhprhY2PgDQ== +"@tensorflow/tfjs@3.11.0": + version "3.11.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs/-/tfjs-3.11.0.tgz#63d5231f41d57ca11b910664632a8e349eba3967" + integrity sha512-TTYrKdkoh1sHnt4vn6MboLbpi1Es4U1Aw+L3PqwadRvXW4+7ySUtc00McrQ+ooK0q3Qhl3N7cvgchgM7nED3Mg== dependencies: - "@tensorflow/tfjs-backend-cpu" "3.9.0" - "@tensorflow/tfjs-backend-webgl" "3.9.0" - "@tensorflow/tfjs-converter" "3.9.0" - "@tensorflow/tfjs-core" "3.9.0" - "@tensorflow/tfjs-data" "3.9.0" - "@tensorflow/tfjs-layers" "3.9.0" + "@tensorflow/tfjs-backend-cpu" "3.11.0" + "@tensorflow/tfjs-backend-webgl" "3.11.0" + "@tensorflow/tfjs-converter" "3.11.0" + "@tensorflow/tfjs-core" "3.11.0" + "@tensorflow/tfjs-data" "3.11.0" + "@tensorflow/tfjs-layers" "3.11.0" + argparse "^1.0.10" + chalk "^4.1.0" + core-js "3" + regenerator-runtime "^0.13.5" + yargs "^16.0.3" + +"@tensorflow/tfjs@^2.0.1": + version "2.8.6" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs/-/tfjs-2.8.6.tgz#5115081e7424c33905af9565c0d190e1b4093a5b" + integrity sha512-/Hk3YCAreNicuQJsAIG32UGHaQj8UwX8y8ZrKVb/CrXOhrRyZmxGSZt9KMVe8MDoydenuGhZCqJUIaWdIKIA5g== + dependencies: + "@tensorflow/tfjs-backend-cpu" "2.8.6" + "@tensorflow/tfjs-backend-webgl" "2.8.6" + "@tensorflow/tfjs-converter" "2.8.6" + "@tensorflow/tfjs-core" "2.8.6" + "@tensorflow/tfjs-data" "2.8.6" + "@tensorflow/tfjs-layers" "2.8.6" argparse "^1.0.10" chalk "^4.1.0" core-js "3" @@ -265,6 +341,11 @@ resolved "https://registry.yarnpkg.com/@types/webgl2/-/webgl2-0.0.5.tgz#dd925e20ab8ace80eb4b1e46fda5b109c508fb0d" integrity sha512-oGaKsBbxQOY5+aJFV3KECDhGaXt+yZJt2y/OZsnQGLRkH6Fvr7rv4pCt3SRH1somIHfej/c4u7NSpCyd9x+1Ow== +"@types/webgl2@0.0.6": + version "0.0.6" + resolved "https://registry.yarnpkg.com/@types/webgl2/-/webgl2-0.0.6.tgz#1ea2db791362bd8521548d664dbd3c5311cdf4b6" + integrity sha512-50GQhDVTq/herLMiqSQkdtRu+d5q/cWHn4VvKJtrj4DJAjo1MNkWYa2MA41BaBO1q1HgsUjuQvEOk0QHvlnAaQ== + "@vladmandic/face-api@^1.5.3": version "1.5.4" resolved "https://registry.yarnpkg.com/@vladmandic/face-api/-/face-api-1.5.4.tgz#1b3e6f0f5e4e79f7e876d5ae32703ec811952e76" @@ -1904,6 +1985,13 @@ tar@^6.0.2, tar@^6.0.5, tar@^6.1.0, tar@^6.1.2: mkdirp "^1.0.3" yallist "^4.0.0" +tensorset@^1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/tensorset/-/tensorset-1.2.9.tgz#0506cdd7ef0658d8b5d753bf29d0aa2e1275f08f" + integrity sha512-xlMAotSaXkGf3U8/4n/n+svHgvT1HvwrssMTaRgSo2PQcYFVseYWPg9qnppi+/fnf4EdQpQdtqIYXyu8jSK73A== + dependencies: + "@tensorflow/tfjs" "^2.0.1" + to-readable-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771"