mirror of
https://github.com/ocogeclub/ocoge.git
synced 2024-11-21 23:29:48 +00:00
[update] tfjs-node の aarch64 未対応により、ピュアJS(WASM)版へ移行。それに伴って face-api から脱却(ヤレヤレ)
This commit is contained in:
parent
bbb18cbd14
commit
bbf0077d6e
53
index.html
53
index.html
@ -665,16 +665,55 @@
|
|||||||
<field name="sound">meow</field>
|
<field name="sound">meow</field>
|
||||||
</block>
|
</block>
|
||||||
<label text="顔認識" web-line="4.0" web-line-width="200"></label>
|
<label text="顔認識" web-line="4.0" web-line-width="200"></label>
|
||||||
<block type="ugj_faceapi">
|
|
||||||
<field name="with_landmark">FALSE</field>
|
|
||||||
</block>
|
|
||||||
<block type="ugj_face_init"></block>
|
<block type="ugj_face_init"></block>
|
||||||
<block type="ugj_face_display"></block>
|
<block type="ugj_face_display"></block>
|
||||||
<block type="ugj_face_detect"></block>
|
<block type="ugj_face_detect">
|
||||||
<block type="ugj_face_coord">
|
<value name="preditions">
|
||||||
<field name="face_coord">0</field>
|
<block type="variables_get">
|
||||||
|
<field name="VAR" id="TLZRpW`yXuYE3Z31)B=2">検出結果</field>
|
||||||
|
</block>
|
||||||
|
</value>
|
||||||
|
</block>
|
||||||
|
<block type="ugj_face_location">
|
||||||
|
<field name="member">topLeft[0]</field>
|
||||||
|
<value name="prediction">
|
||||||
|
<block type="lists_getIndex">
|
||||||
|
<mutation statement="false" at="true"></mutation>
|
||||||
|
<field name="MODE">GET</field>
|
||||||
|
<field name="WHERE">FROM_START</field>
|
||||||
|
<value name="VALUE">
|
||||||
|
<block type="variables_get">
|
||||||
|
<field name="VAR" id="_W]y2e!_~suF]yM;LQ1~">検出結果</field>
|
||||||
|
</block>
|
||||||
|
</value>
|
||||||
|
<value name="AT">
|
||||||
|
<shadow type="math_number">
|
||||||
|
<field name="NUM">1</field>
|
||||||
|
</shadow>
|
||||||
|
</value>
|
||||||
|
</block>
|
||||||
|
</value>
|
||||||
|
</block>
|
||||||
|
<block type="ugj_face_draw">
|
||||||
|
<field name="with_landmark">TRUE</field>
|
||||||
|
<value name="prediction">
|
||||||
|
<block type="lists_getIndex">
|
||||||
|
<mutation statement="false" at="true"></mutation>
|
||||||
|
<field name="MODE">GET</field>
|
||||||
|
<field name="WHERE">FROM_START</field>
|
||||||
|
<value name="VALUE">
|
||||||
|
<block type="variables_get">
|
||||||
|
<field name="VAR" id="E-Bsl~,RZG]E)v`k![_p">検出結果</field>
|
||||||
|
</block>
|
||||||
|
</value>
|
||||||
|
<value name="AT">
|
||||||
|
<shadow type="math_number">
|
||||||
|
<field name="NUM">1</field>
|
||||||
|
</shadow>
|
||||||
|
</value>
|
||||||
|
</block>
|
||||||
|
</value>
|
||||||
</block>
|
</block>
|
||||||
<block type="ugj_face_drawrect"></block>
|
|
||||||
<label text="_" web-line="4.0" web-line-width="200"></label>
|
<label text="_" web-line="4.0" web-line-width="200"></label>
|
||||||
</category>
|
</category>
|
||||||
|
|
||||||
|
7
index.js
7
index.js
@ -389,9 +389,12 @@ const ugj_createCode = (args) => {
|
|||||||
// await使用のため、必要に応じてコード全体をasync付き即時関数でラップ
|
// await使用のため、必要に応じてコード全体をasync付き即時関数でラップ
|
||||||
if (addAsync) {
|
if (addAsync) {
|
||||||
code = [
|
code = [
|
||||||
'(async () => {',
|
// '(async () => {',
|
||||||
|
'const main = async () => {',
|
||||||
code,
|
code,
|
||||||
'})();'
|
`}`,
|
||||||
|
`main();`,
|
||||||
|
// '})();'
|
||||||
].join('\n');
|
].join('\n');
|
||||||
}
|
}
|
||||||
// コードを綺麗に
|
// コードを綺麗に
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"weights":
|
|
||||||
[
|
|
||||||
{"name":"dense0/conv0/filters","shape":[3,3,3,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008194216092427571,"min":-0.9423348506291708}},
|
|
||||||
{"name":"dense0/conv0/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006839508168837603,"min":-0.8412595047670252}},
|
|
||||||
{"name":"dense0/conv1/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.009194007106855804,"min":-1.2779669878529567}},
|
|
||||||
{"name":"dense0/conv1/pointwise_filter","shape":[1,1,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0036026100317637128,"min":-0.3170296827952067}},
|
|
||||||
{"name":"dense0/conv1/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.000740380117706224,"min":-0.06367269012273527}},
|
|
||||||
{"name":"dense0/conv2/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":1,"min":0}},
|
|
||||||
{"name":"dense0/conv2/pointwise_filter","shape":[1,1,32,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":1,"min":0}},
|
|
||||||
{"name":"dense0/conv2/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0037702228508743585,"min":-0.6220867703942692}},
|
|
||||||
{"name":"dense1/conv0/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0033707996209462483,"min":-0.421349952618281}},
|
|
||||||
{"name":"dense1/conv0/pointwise_filter","shape":[1,1,32,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.014611541991140328,"min":-1.8556658328748217}},
|
|
||||||
{"name":"dense1/conv0/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002832523046755323,"min":-0.30307996600281956}},
|
|
||||||
{"name":"dense1/conv1/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006593170586754294,"min":-0.6329443763284123}},
|
|
||||||
{"name":"dense1/conv1/pointwise_filter","shape":[1,1,64,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.012215249211180444,"min":-1.6001976466646382}},
|
|
||||||
{"name":"dense1/conv1/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002384825547536214,"min":-0.3028728445370992}},
|
|
||||||
{"name":"dense1/conv2/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005859645441466687,"min":-0.7617539073906693}},
|
|
||||||
{"name":"dense1/conv2/pointwise_filter","shape":[1,1,64,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.013121426806730382,"min":-1.7845140457153321}},
|
|
||||||
{"name":"dense1/conv2/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0032247188044529336,"min":-0.46435950784122243}},
|
|
||||||
{"name":"dense2/conv0/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002659512618008782,"min":-0.32977956463308894}},
|
|
||||||
{"name":"dense2/conv0/pointwise_filter","shape":[1,1,64,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.015499923743453681,"min":-1.9839902391620712}},
|
|
||||||
{"name":"dense2/conv0/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0032450980999890497,"min":-0.522460794098237}},
|
|
||||||
{"name":"dense2/conv1/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005911862382701799,"min":-0.792189559282041}},
|
|
||||||
{"name":"dense2/conv1/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.021025861478319356,"min":-2.2077154552235325}},
|
|
||||||
{"name":"dense2/conv1/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.00349616945958605,"min":-0.46149436866535865}},
|
|
||||||
{"name":"dense2/conv2/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008104994250278847,"min":-1.013124281284856}},
|
|
||||||
{"name":"dense2/conv2/pointwise_filter","shape":[1,1,128,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.029337059282789044,"min":-3.5791212325002633}},
|
|
||||||
{"name":"dense2/conv2/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0038808938334969913,"min":-0.4230174278511721}},
|
|
||||||
{"name":"fc/weights","shape":[128,136],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.014016061670639936,"min":-1.8921683255363912}},
|
|
||||||
{"name":"fc/bias","shape":[136],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0029505149698724935,"min":0.088760145008564}}
|
|
||||||
],
|
|
||||||
"paths":
|
|
||||||
[
|
|
||||||
"face_landmark_68_tiny_model.bin"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
Binary file not shown.
@ -1,30 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"weights":
|
|
||||||
[
|
|
||||||
{"name":"conv0/filters","shape":[3,3,3,16],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.009007044399485869,"min":-1.2069439495311063}},
|
|
||||||
{"name":"conv0/bias","shape":[16],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.005263455241334205,"min":-0.9211046672334858}},
|
|
||||||
{"name":"conv1/depthwise_filter","shape":[3,3,16,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.004001977630690033,"min":-0.5042491814669441}},
|
|
||||||
{"name":"conv1/pointwise_filter","shape":[1,1,16,32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.013836609615999109,"min":-1.411334180831909}},
|
|
||||||
{"name":"conv1/bias","shape":[32],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0015159862590771096,"min":-0.30926119685173037}},
|
|
||||||
{"name":"conv2/depthwise_filter","shape":[3,3,32,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002666276225856706,"min":-0.317286870876948}},
|
|
||||||
{"name":"conv2/pointwise_filter","shape":[1,1,32,64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.015265831292844286,"min":-1.6792414422128714}},
|
|
||||||
{"name":"conv2/bias","shape":[64],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0020280554598453,"min":-0.37113414915168985}},
|
|
||||||
{"name":"conv3/depthwise_filter","shape":[3,3,64,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006100742489683862,"min":-0.8907084034938438}},
|
|
||||||
{"name":"conv3/pointwise_filter","shape":[1,1,64,128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.016276211832083907,"min":-2.0508026908425725}},
|
|
||||||
{"name":"conv3/bias","shape":[128],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.003394414279975143,"min":-0.7637432129944072}},
|
|
||||||
{"name":"conv4/depthwise_filter","shape":[3,3,128,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.006716050119961009,"min":-0.8059260143953211}},
|
|
||||||
{"name":"conv4/pointwise_filter","shape":[1,1,128,256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.021875603993733724,"min":-2.8875797271728514}},
|
|
||||||
{"name":"conv4/bias","shape":[256],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.0041141652009066415,"min":-0.8187188749804216}},
|
|
||||||
{"name":"conv5/depthwise_filter","shape":[3,3,256,1],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008423839597141042,"min":-0.9013508368940915}},
|
|
||||||
{"name":"conv5/pointwise_filter","shape":[1,1,256,512],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.030007277283014035,"min":-3.8709387695088107}},
|
|
||||||
{"name":"conv5/bias","shape":[512],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.008402082966823203,"min":-1.4871686851277068}},
|
|
||||||
{"name":"conv8/filters","shape":[1,1,512,25],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.028336129469030042,"min":-4.675461362389957}},
|
|
||||||
{"name":"conv8/bias","shape":[25],"dtype":"float32","quantization":{"dtype":"uint8","scale":0.002268134028303857,"min":-0.41053225912299807}}
|
|
||||||
],
|
|
||||||
"paths":
|
|
||||||
[
|
|
||||||
"tiny_face_detector_model.bin"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
Binary file not shown.
@ -1,8 +0,0 @@
|
|||||||
var count=10;
|
|
||||||
var id = setInterval(() => {
|
|
||||||
console.log(count--);
|
|
||||||
if (count<0) {
|
|
||||||
console.log(' : 終了 - Node Test JS');
|
|
||||||
clearInterval(id);
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
5407
package-lock.json
generated
5407
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ocoge",
|
"name": "ocoge",
|
||||||
"version": "0.1.4",
|
"version": "0.1.5",
|
||||||
"description": "ブロックベースビジュアルプログラム開発・実行環境",
|
"description": "ブロックベースビジュアルプログラム開発・実行環境",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -35,12 +35,11 @@
|
|||||||
"@ocogeclub/bme280": "file:local_modules/@ocogeclub/bme280",
|
"@ocogeclub/bme280": "file:local_modules/@ocogeclub/bme280",
|
||||||
"@ocogeclub/paj7620": "file:local_modules/@ocogeclub/paj7620",
|
"@ocogeclub/paj7620": "file:local_modules/@ocogeclub/paj7620",
|
||||||
"@ocogeclub/pigpio": "file:local_modules/@ocogeclub/pigpio",
|
"@ocogeclub/pigpio": "file:local_modules/@ocogeclub/pigpio",
|
||||||
|
"@tensorflow-models/blazeface": "^0.0.7",
|
||||||
"@tensorflow-models/knn-classifier": "^1.2.2",
|
"@tensorflow-models/knn-classifier": "^1.2.2",
|
||||||
"@tensorflow-models/mobilenet": "^2.1.0",
|
"@tensorflow-models/mobilenet": "^2.1.0",
|
||||||
"@tensorflow/tfjs-converter": "^3.13.0",
|
"@tensorflow/tfjs": "^3.13.0",
|
||||||
"@tensorflow/tfjs-core": "^3.13.0",
|
"@tensorflow/tfjs-backend-wasm": "^3.13.0",
|
||||||
"@tensorflow/tfjs-node": "^3.13.0",
|
|
||||||
"@vladmandic/face-api": "^1.6.5",
|
|
||||||
"axios": "^0.25.0",
|
"axios": "^0.25.0",
|
||||||
"electron-squirrel-startup": "^1.0.0",
|
"electron-squirrel-startup": "^1.0.0",
|
||||||
"nodemailer": "^6.7.2",
|
"nodemailer": "^6.7.2",
|
||||||
|
172
ugj_blocks.js
172
ugj_blocks.js
@ -1288,53 +1288,35 @@ Blockly.Python['ugj_grideye_stop'] = function (block) {
|
|||||||
/******************** */
|
/******************** */
|
||||||
/** Face Detection ** */
|
/** Face Detection ** */
|
||||||
/******************** */
|
/******************** */
|
||||||
var with_landmark;
|
|
||||||
Blockly.Blocks['ugj_faceapi'] = {
|
|
||||||
init: function () {
|
|
||||||
this.appendDummyInput()
|
|
||||||
.appendField("TensorFlowによる顔検出を1秒に")
|
|
||||||
.appendField(new Blockly.FieldDropdown([["1", "1000"], ["2", "500"], ["5", "200"], ["10", "100"]]), "interval_sec")
|
|
||||||
.appendField("回実行:")
|
|
||||||
.appendField(new Blockly.FieldCheckbox("TRUE"), "with_landmark")
|
|
||||||
.appendField("ランドマークを検出");
|
|
||||||
this.appendStatementInput("do")
|
|
||||||
.setCheck(null);
|
|
||||||
this.setTooltip("TensorFlow とFaceAPI をロードし、顔検出をできるようにします。");
|
|
||||||
this.setHelpUrl("");
|
|
||||||
this.setStyle('multimedia_blocks');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Blockly.JavaScript['ugj_faceapi'] = function (block) {
|
|
||||||
var dropdown_interval_sec = block.getFieldValue('interval_sec');
|
|
||||||
with_landmark = block.getFieldValue('with_landmark') == 'TRUE';
|
|
||||||
var statements_do = Blockly.JavaScript.statementToCode(block, 'do');
|
|
||||||
var code = [
|
|
||||||
`require('@tensorflow/tfjs-node');`,
|
|
||||||
`const _faceapi = require('@vladmandic/face-api/dist/face-api.node.js');`,
|
|
||||||
`const _interval_sec = ${dropdown_interval_sec};`,
|
|
||||||
statements_do,
|
|
||||||
''
|
|
||||||
].join('\n');
|
|
||||||
return code;
|
|
||||||
};
|
|
||||||
Blockly.Blocks['ugj_face_init'] = {
|
Blockly.Blocks['ugj_face_init'] = {
|
||||||
init: function () {
|
init: function () {
|
||||||
this.appendDummyInput()
|
this.appendDummyInput()
|
||||||
.appendField("顔検出のビデオを開始");
|
.appendField("顔検出を開始");
|
||||||
this.setInputsInline(true);
|
this.setInputsInline(true);
|
||||||
this.setPreviousStatement(true, null);
|
this.setPreviousStatement(true, null);
|
||||||
this.setNextStatement(true, null);
|
this.setNextStatement(true, null);
|
||||||
this.setStyle('multimedia_blocks');
|
this.setStyle('multimedia_blocks');
|
||||||
this.setTooltip("顔検出のためのビデオストリームを開始します。");
|
this.setTooltip("Blazeface detector モデルによる顔検出を開始します。最初に実行してください");
|
||||||
this.setHelpUrl("");
|
this.setHelpUrl("");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Blockly.JavaScript['ugj_face_init'] = function (block) {
|
Blockly.JavaScript['ugj_face_init'] = function (block) {
|
||||||
|
Blockly.JavaScript.provideFunction_(
|
||||||
|
'require_tfjs', [`const _tf = require('@tensorflow/tfjs');`]
|
||||||
|
);
|
||||||
|
Blockly.JavaScript.provideFunction_(
|
||||||
|
'require_tfjs_wasm', [`require('@tensorflow/tfjs-backend-wasm');`]
|
||||||
|
);
|
||||||
|
Blockly.JavaScript.provideFunction_(
|
||||||
|
'require_blazeface', [`const _blazeface = require('@tensorflow-models/blazeface');`]
|
||||||
|
);
|
||||||
var code = [
|
var code = [
|
||||||
|
`await _tf.setBackend('wasm');`,
|
||||||
"const _videoEl = document.getElementById('subdisplay');",
|
"const _videoEl = document.getElementById('subdisplay');",
|
||||||
`const _displaySize = { width: _videoEl.width, height: _videoEl.height };`,
|
`const _displaySize = { width: _videoEl.width, height: _videoEl.height };`,
|
||||||
"const _stream = await navigator.mediaDevices.getUserMedia({ audio: false, video: _displaySize });",
|
"const _stream = await navigator.mediaDevices.getUserMedia({ audio: false, video: _displaySize });",
|
||||||
"_videoEl.srcObject = _stream;",
|
"_videoEl.srcObject = _stream;",
|
||||||
|
`const _model = await _blazeface.load();`,
|
||||||
""
|
""
|
||||||
].join('\n');
|
].join('\n');
|
||||||
return code;
|
return code;
|
||||||
@ -1342,11 +1324,11 @@ Blockly.JavaScript['ugj_face_init'] = function (block) {
|
|||||||
Blockly.Blocks['ugj_face_display'] = {
|
Blockly.Blocks['ugj_face_display'] = {
|
||||||
init: function () {
|
init: function () {
|
||||||
this.appendDummyInput()
|
this.appendDummyInput()
|
||||||
.appendField("ビデオを表示");
|
.appendField("顔検出ビデオを表示");
|
||||||
this.setInputsInline(true);
|
this.setInputsInline(true);
|
||||||
this.setPreviousStatement(true, null);
|
this.setPreviousStatement(true, null);
|
||||||
this.setNextStatement(true, null);
|
this.setNextStatement(true, null);
|
||||||
this.setStyle('multimedia_blocks')
|
this.setStyle('multimedia_blocks');
|
||||||
this.setTooltip("カメラの映像を画像エリアに表示します。必須ではないブロックです。");
|
this.setTooltip("カメラの映像を画像エリアに表示します。必須ではないブロックです。");
|
||||||
this.setHelpUrl("");
|
this.setHelpUrl("");
|
||||||
}
|
}
|
||||||
@ -1359,108 +1341,91 @@ Blockly.JavaScript['ugj_face_display'] = function (block) {
|
|||||||
`_overlay.setAttribute('height', _videoEl.height);`,
|
`_overlay.setAttribute('height', _videoEl.height);`,
|
||||||
`_overlay.className = 'subdisplay';`,
|
`_overlay.className = 'subdisplay';`,
|
||||||
`document.getElementById('display_area').appendChild(_overlay);`,
|
`document.getElementById('display_area').appendChild(_overlay);`,
|
||||||
|
`const _overlay_ctx = _overlay.getContext('2d');`,
|
||||||
""
|
""
|
||||||
].join('\n');
|
].join('\n');
|
||||||
return code;
|
return code;
|
||||||
};
|
};
|
||||||
Blockly.Blocks['ugj_face_detect'] = {
|
Blockly.Blocks['ugj_face_detect'] = {
|
||||||
init: function () {
|
init: function () {
|
||||||
|
this.appendValueInput("preditions")
|
||||||
|
.setCheck("Variable")
|
||||||
|
.appendField("顔検出を実行し、結果をリスト");
|
||||||
this.appendDummyInput()
|
this.appendDummyInput()
|
||||||
.appendField("顔を検出したら");
|
.appendField("に代入する");
|
||||||
this.appendStatementInput("do")
|
|
||||||
.setCheck(null);
|
|
||||||
this.setInputsInline(true);
|
this.setInputsInline(true);
|
||||||
this.setPreviousStatement(true, null);
|
this.setPreviousStatement(true, null);
|
||||||
this.setTooltip("顔を発見したら動作します。位置データは「顔の座標」ブロックで参照します。");
|
this.setNextStatement(true, null);
|
||||||
|
this.setTooltip("顔検出を実行します。検出結果はリストになります。顔の位置は「顔の座標」ブロックで参照します。");
|
||||||
this.setHelpUrl("");
|
this.setHelpUrl("");
|
||||||
this.setStyle('multimedia_blocks');
|
this.setStyle('multimedia_blocks');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Blockly.JavaScript['ugj_face_detect'] = function (block) {
|
Blockly.JavaScript['ugj_face_detect'] = function (block) {
|
||||||
var statements_do = Blockly.JavaScript.statementToCode(block, 'do');
|
var value_preditions = Blockly.JavaScript.valueToCode(block, 'preditions', Blockly.JavaScript.ORDER_ATOMIC);
|
||||||
var code_model = `await _faceapi.nets.tinyFaceDetector.load('${elutil.path.join(elutil.library_path, 'models/')}');`;
|
var code = `${value_preditions} = await _model.estimateFaces(_videoEl, false);`;
|
||||||
if (with_landmark) { code_model += `\nawait _faceapi.nets.faceLandmark68TinyNet.load('${elutil.path.join(elutil.library_path, 'models/')}');`; }
|
|
||||||
var code_detect_face = " let _result = await _faceapi.detectSingleFace(_videoEl, _options)"
|
|
||||||
if (with_landmark) { code_detect_face += `.withFaceLandmarks(true);` }
|
|
||||||
else { code_detect_face += `;` }
|
|
||||||
var code_rect;
|
|
||||||
if (with_landmark) {
|
|
||||||
code_rect = [
|
|
||||||
` _coord[0] = Math.round(_result.detection.box.x);`,
|
|
||||||
` _coord[1] = Math.round(_result.detection.box.y);`,
|
|
||||||
` _coord[2] = Math.round(_result.detection.box.width);`,
|
|
||||||
` _coord[3] = Math.round(_result.detection.box.height);`,
|
|
||||||
].join('\n');
|
|
||||||
} else {
|
|
||||||
code_rect = [
|
|
||||||
` _coord[0] = Math.round(_result.box.x);`,
|
|
||||||
` _coord[1] = Math.round(_result.box.y);`,
|
|
||||||
` _coord[2] = Math.round(_result.box.width);`,
|
|
||||||
` _coord[3] = Math.round(_result.box.height);`,
|
|
||||||
].join('\n');
|
|
||||||
}
|
|
||||||
var code = [
|
|
||||||
code_model,
|
|
||||||
"const _options = new _faceapi.TinyFaceDetectorOptions({ inputSize: 128, scoreThreshold : 0.3 });",
|
|
||||||
// `const _onPlay = async () => {`,
|
|
||||||
` const _detectInterval = setInterval(async () => {`,
|
|
||||||
code_detect_face,
|
|
||||||
" if (_result) {",
|
|
||||||
` let _coord = [];`,
|
|
||||||
code_rect,
|
|
||||||
statements_do,
|
|
||||||
" }",
|
|
||||||
` }, _interval_sec);`,
|
|
||||||
// " setTimeout(() => onPlay())",
|
|
||||||
// "}",
|
|
||||||
// "_videoEl.onplay = _onPlay;",
|
|
||||||
""
|
|
||||||
].join('\n');
|
|
||||||
return code;
|
return code;
|
||||||
};
|
};
|
||||||
Blockly.Blocks['ugj_face_coord'] = {
|
Blockly.Blocks['ugj_face_location'] = {
|
||||||
init: function () {
|
init: function () {
|
||||||
|
this.appendValueInput("prediction")
|
||||||
|
.setCheck("Array")
|
||||||
|
.appendField("顔");
|
||||||
this.appendDummyInput()
|
this.appendDummyInput()
|
||||||
.appendField("顔の座標")
|
.appendField("の")
|
||||||
.appendField(new Blockly.FieldDropdown([["左", "0"], ["上", "1"], ["幅", "2"], ["高さ", "3"]]), "face_coord");
|
.appendField(new Blockly.FieldDropdown([["左座標", "topLeft[0]"], ["上座標", "topLeft[1]"], ["右座標", "bottomRight[0]"], ["下座標", "bottomRight[1]"]]), "member");
|
||||||
this.setInputsInline(true);
|
this.setInputsInline(true);
|
||||||
this.setOutput(true, null);
|
this.setOutput(true, "Number");
|
||||||
this.setTooltip("顔の座標(位置)を参照します。");
|
this.setTooltip("顔検出結果の座標を参照します。");
|
||||||
this.setHelpUrl("");
|
this.setHelpUrl("");
|
||||||
this.setStyle('multimedia_blocks');
|
this.setStyle('multimedia_blocks');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Blockly.JavaScript['ugj_face_coord'] = function (block) {
|
Blockly.JavaScript['ugj_face_location'] = function (block) {
|
||||||
var dropdown_face_coord = block.getFieldValue('face_coord');
|
var value_prediction = Blockly.JavaScript.valueToCode(block, 'prediction', Blockly.JavaScript.ORDER_NONE);
|
||||||
var code = `_coord[${dropdown_face_coord}]`;
|
var dropdown_member = block.getFieldValue('member');
|
||||||
|
var code = `${value_prediction}.${dropdown_member}`;
|
||||||
return [code, Blockly.JavaScript.ORDER_NONE];
|
return [code, Blockly.JavaScript.ORDER_NONE];
|
||||||
};
|
};
|
||||||
//
|
Blockly.Blocks['ugj_face_draw'] = {
|
||||||
Blockly.Blocks['ugj_face_drawrect'] = {
|
|
||||||
init: function () {
|
init: function () {
|
||||||
|
this.appendValueInput("prediction")
|
||||||
|
.setCheck("Variable")
|
||||||
|
.appendField("顔");
|
||||||
this.appendDummyInput()
|
this.appendDummyInput()
|
||||||
.appendField("検出結果を描画");
|
.appendField("を描画:")
|
||||||
|
.appendField(new Blockly.FieldCheckbox("TRUE"), "with_landmark")
|
||||||
|
.appendField("ランドマーク");
|
||||||
this.setInputsInline(true);
|
this.setInputsInline(true);
|
||||||
this.setPreviousStatement(true, null);
|
this.setPreviousStatement(true, null);
|
||||||
this.setNextStatement(true, null);
|
this.setNextStatement(true, null);
|
||||||
this.setStyle('multimedia_blocks');
|
this.setTooltip("顔検出結果をビデオ画面に描画します。「ビデオを表示」ブロックが必要です。");
|
||||||
this.setTooltip("ビデオに検出結果を四角や点で表示します。「ビデオを表示」ブロックが必要です。");
|
|
||||||
this.setHelpUrl("");
|
this.setHelpUrl("");
|
||||||
|
this.setStyle('multimedia_blocks');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Blockly.JavaScript['ugj_face_drawrect'] = function (block) {
|
Blockly.JavaScript['ugj_face_draw'] = function (block) {
|
||||||
var code_draw = ` _faceapi.draw.drawDetections(_overlay, _resizedDetections);`;
|
var value_prediction = Blockly.JavaScript.valueToCode(block, 'prediction', Blockly.JavaScript.ORDER_NONE);
|
||||||
if (with_landmark) { code_draw += `\n _faceapi.draw.drawFaceLandmarks(_overlay, _resizedDetections);`; }
|
var checkbox_with_landmark = block.getFieldValue('with_landmark') === 'TRUE';
|
||||||
var code = [
|
var code = `const _start = ${value_prediction}.topLeft;
|
||||||
` _faceapi.matchDimensions(_overlay, _displaySize);`,
|
const _end = ${value_prediction}.bottomRight;
|
||||||
` const _resizedDetections = _faceapi.resizeResults(_result, _displaySize);`,
|
const _size = [_end[0] - _start[0], _end[1] - _start[1]];
|
||||||
code_draw,
|
_overlay_ctx.clearRect(0, 0, _displaySize.width, _displaySize.height)
|
||||||
""
|
_overlay_ctx.fillStyle = 'rgba(255, 0, 0, 0.5)';
|
||||||
].join('\n');
|
_overlay_ctx.fillRect(_start[0], _start[1], _size[0], _size[1]);
|
||||||
|
if (${checkbox_with_landmark}) {
|
||||||
|
const _landmarks = ${value_prediction}.landmarks;
|
||||||
|
_overlay_ctx.fillStyle = 'blue';
|
||||||
|
for (let _j = 0; _j < _landmarks.length; _j++) {
|
||||||
|
const _x = _landmarks[_j][0];
|
||||||
|
const _y = _landmarks[_j][1];
|
||||||
|
_overlay_ctx.fillRect(_x, _y, 5, 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
return code;
|
return code;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**************************** */
|
/**************************** */
|
||||||
/** Say while some seconds ** */
|
/** Say while some seconds ** */
|
||||||
/**************************** */
|
/**************************** */
|
||||||
@ -1883,7 +1848,11 @@ Blockly.Blocks['ugj_teachable_machine'] = {
|
|||||||
};
|
};
|
||||||
Blockly.JavaScript['ugj_teachable_machine'] = function (block) {
|
Blockly.JavaScript['ugj_teachable_machine'] = function (block) {
|
||||||
Blockly.JavaScript.provideFunction_(
|
Blockly.JavaScript.provideFunction_(
|
||||||
'require_ts', [`const _tf = require('@tensorflow/tfjs-node');`]
|
'require_ts', [`const _tf = require('@tensorflow/tfjs');`]
|
||||||
|
// 'require_ts', [`const _tf = require('@tensorflow/tfjs-node');`]
|
||||||
|
);
|
||||||
|
Blockly.JavaScript.provideFunction_(
|
||||||
|
'require_wasm', [`const _wasm = require('@tensorflow/tfjs-backend-wasm');`]
|
||||||
);
|
);
|
||||||
Blockly.JavaScript.provideFunction_(
|
Blockly.JavaScript.provideFunction_(
|
||||||
'require_mobilenet', [`const _mobilenet = require('@tensorflow-models/mobilenet');`]
|
'require_mobilenet', [`const _mobilenet = require('@tensorflow-models/mobilenet');`]
|
||||||
@ -1892,8 +1861,9 @@ Blockly.JavaScript['ugj_teachable_machine'] = function (block) {
|
|||||||
'require_knn', [`const _knnClassifier = require('@tensorflow-models/knn-classifier');`]
|
'require_knn', [`const _knnClassifier = require('@tensorflow-models/knn-classifier');`]
|
||||||
);
|
);
|
||||||
|
|
||||||
var code = `const _classifier = _knnClassifier.create();
|
var code = `await _tf.setBackend('wasm');
|
||||||
const _net = await _mobilenet.load({ version: 1, alpha: 0.25 }); // 高速・低精度
|
const _net = await _mobilenet.load({ version: 1, alpha: 0.25 }); // 高速・低精度
|
||||||
|
const _classifier = _knnClassifier.create();
|
||||||
`;
|
`;
|
||||||
return code;
|
return code;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user