Skip to content

Commit 01cf7da

Browse files
committed
init commit
0 parents  commit 01cf7da

28 files changed

+991
-0
lines changed

HandsDetect.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
class HandDetect {
2+
constructor() {
3+
this.strokeStyle = '#ff0000';
4+
this.lineWidth = 5;
5+
this.callbackList = [];
6+
this.modelParams = {
7+
flipHorizontal: true, // flip e.g for video
8+
imageScaleFactor: 0.8, // reduce input image size .
9+
maxNumBoxes: 20, // maximum number of boxes to detect
10+
iouThreshold: 0.5, // ioU threshold for non-max suppression
11+
scoreThreshold: 0.9, // confidence threshold for predictions.
12+
}
13+
}
14+
15+
setCamera(cam) {
16+
this.cam = cam;
17+
}
18+
19+
setRectStyle(color, lineWidth) {
20+
this.strokeStyle = color;
21+
this.lineWidth = lineWidth;
22+
}
23+
24+
on(callback) {
25+
this.callbackList.push(callback);
26+
}
27+
28+
start(color, lineWidth) {
29+
//this.strokeStyle = color;
30+
//this.lineWidth = lineWidth;
31+
/*
32+
[{
33+
bbox: [x, y, width, height],
34+
class: "hand",
35+
score: 0.8380282521247864
36+
}, {
37+
bbox: [x, y, width, height],
38+
class: "hand",
39+
score: 0.74644153267145157
40+
}]
41+
*/
42+
handTrack.load(this.modelParams).then(model => {
43+
var hands = [];
44+
var self = this;
45+
self.cam.onCanvas(function (canvas) {
46+
var ctx = canvas.getContext("2d");
47+
ctx.beginPath();
48+
ctx.strokeStyle = self.strokeStyle;
49+
ctx.lineWidth = self.lineWidth;
50+
while (hands.length > 0) {
51+
var hand = hands.pop();
52+
//flip
53+
hand[0] = canvas.width - (hand[0] + hand[2]);
54+
ctx.rect(hand[0], hand[1], hand[2], hand[3]);
55+
// process callback
56+
for (var i = 0; i < self.callbackList.length; i++) {
57+
self.handInfo = hand;
58+
self.callbackList[i](hand);
59+
}
60+
}
61+
ctx.stroke();
62+
model.detect(canvas).then(predictions => {
63+
var amt = predictions.length;
64+
for (var i = 0; i < amt; i++) {
65+
var data = predictions[i]['bbox'];
66+
data.push(predictions[i]['score']);
67+
hands.push(data);
68+
}
69+
});
70+
});
71+
});
72+
}
73+
}

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2018 Webduino
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# webduino-module-waspot
2+
3+
Webduino Module for waspot
4+
5+
6+
## Installation
7+
8+
```shell
9+
bower install https://github.com/webduinoio/webduino-module-face-api.git
10+
```
11+
12+
## License
13+
14+
This project is licensed under the MIT license, see [LICENSE](LICENSE) for more information.

actor.js

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
class Actor {
2+
constructor(cv, info) {
3+
var self = this;
4+
self.running = false;
5+
self.cv = cv;
6+
self.info = info;
7+
self.img = null;
8+
self.imgReady = false;
9+
self.touching = false;
10+
this.lastInsideTime = -1;
11+
self.stage = info.stage; // camera
12+
self.moveArray = [];
13+
self.isFlip = self.stage.getFlip();
14+
self.body = document.getElementsByTagName('body')[0];
15+
self.originImgURL = info.img;
16+
self.originSize = [info.pos[3], info.pos[4]];
17+
self.setImg(info.img, info.pos);
18+
self.hide();
19+
if (typeof info.snd == 'undefined') {
20+
info.snd = "";
21+
}
22+
self.audio = new Audio(info.snd);
23+
self.jsonInfo = {
24+
"history": 500,
25+
"varThreshold": 25,
26+
"learningRate": 0.0025,
27+
"detectShadows": false,
28+
"objMinSize": 10,
29+
"touchTime": 1000,
30+
"filter": ["e5", "g1", "d3"]
31+
};
32+
self.onTouchCallback = function () { };
33+
self.setTracking({
34+
'inside': function (pos) {
35+
var nowTime = new Date().getTime();
36+
if (nowTime - this.lastInsideTime < self.jsonInfo.touchTime) {
37+
self.touching = true;
38+
return;
39+
}
40+
self.touching = false;
41+
this.lastInsideTime = nowTime;
42+
if (self.isHide()) return;
43+
self.inPos = pos;
44+
self.onTouchCallback(pos);
45+
},
46+
'outside': function (pos) {
47+
self.outPos = pos;
48+
}
49+
});
50+
}
51+
52+
play() {
53+
this.audio.play();
54+
return this;
55+
}
56+
57+
showTime() {
58+
this.tracking.scan();
59+
}
60+
61+
switchImg(url, switchTime) {
62+
var self = this;
63+
self.jsonInfo.touchTime = switchTime * 1000;
64+
if (self.touching) return;
65+
var lastPos = [self.x, self.y, self.width, self.height];
66+
self.setImg(url, lastPos);
67+
setTimeout(function () {
68+
self.setImg(self.originImgURL, lastPos);
69+
}, self.jsonInfo.touchTime);
70+
}
71+
72+
setSndURL(url) {
73+
this.audio = new Audio(url);
74+
}
75+
76+
setImgSize(width, height) {
77+
this.width = width;
78+
this.height = height;
79+
this.img.style.width = this.width + 'px';
80+
this.img.style.height = this.height + 'px';
81+
}
82+
83+
setImg(url, pos) {
84+
var self = this;
85+
if (arguments.length == 1) {
86+
pos = [self.x, self.y];
87+
}
88+
if (self.img != null && self.imgReady) {
89+
self.body.removeChild(this.img);
90+
}
91+
var canvas = self.stage.getCanvas();
92+
self.img = new Image();
93+
self.imgReady = false;
94+
self.img.onload = function () {
95+
self.imgReady = true;
96+
this.style.position = 'absolute';
97+
this.style.left = self.getCanvas().offsetLeft + pos[0] + 'px';
98+
this.style.top = self.getCanvas().offsetTop + pos[1] + 'px';
99+
self.body.appendChild(this);
100+
};
101+
self.img.src = url;
102+
self.x = pos[0];
103+
self.y = pos[1];
104+
self.width = self.img.width;
105+
self.height = self.img.height;
106+
if (pos.length == 4) {
107+
self.width = this.info.pos[2];
108+
self.height = this.info.pos[3];
109+
self.img.style.width = self.width + 'px';
110+
self.img.style.height = self.height + 'px';
111+
}
112+
return this;
113+
}
114+
115+
getCanvas() {
116+
return this.stage.getCanvas();
117+
}
118+
119+
moveTo(x, y) {
120+
//support array [x,y]
121+
if (arguments.length == 1) {
122+
y = x[1];
123+
x = x[0];
124+
}
125+
if (this.running) {
126+
this.x = x;
127+
this.y = y;
128+
this.img.style.display = '';
129+
var offsetLeft = this.getCanvas().offsetLeft;
130+
var offsetTop = this.getCanvas().offsetTop;
131+
this.img.style.left = offsetLeft + this.x + "px";
132+
this.img.style.top = offsetTop + this.y + "px";
133+
this.tracking.moveTo(x, y);
134+
} else {
135+
this.moveArray.push([x, y]);
136+
}
137+
return this;
138+
}
139+
140+
isHide() {
141+
return this.img.style.display == 'none';
142+
}
143+
144+
hide() {
145+
this.img.style.display = 'none';
146+
}
147+
148+
show() {
149+
this.img.style.display = '';
150+
}
151+
152+
getStage() {
153+
return this.stage;
154+
}
155+
156+
onTouch(callback) {
157+
this.onTouchCallback = callback;
158+
}
159+
160+
setTracking(callback) {
161+
var x = this.x;
162+
var y = this.y;
163+
this.tracking =
164+
new Hotspot(this.getCanvas(), this.getCanvas(), true,
165+
x, y,
166+
x + this.width, y,
167+
x + this.width, y + this.height,
168+
x, y + this.height);
169+
this.tracking.setFlip(this.isFlip);
170+
this.tracking.jsonInfo = this.jsonInfo;
171+
//this.tracking.debug();
172+
this.tracking.setCvProcess(this.cv.imgFilter);
173+
174+
if (typeof callback['inside'] == "function") {
175+
this.tracking.inside(callback['inside']);
176+
}
177+
if (typeof callback['outside'] == "function") {
178+
this.tracking.outside(callback['outside']);
179+
}
180+
return this;
181+
}
182+
183+
start() {
184+
var self = this;
185+
self.stage.onReady(function () {
186+
console.log("stage ready , Actor start...","0419");
187+
self.tracking.start();
188+
self.running = true;
189+
for (var i = 0; i < self.moveArray.length; i++) {
190+
self.moveTo(self.moveArray.shift());
191+
}
192+
});
193+
self.stage.onCanvas(function (c) {
194+
self.showTime();
195+
});
196+
}
197+
}

blockly.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"types": [
3+
"hands_create_detect"
4+
],
5+
"category": "catPlus",
6+
"scripts": [
7+
"blockly/blocks.js",
8+
"blockly/javascript.js"
9+
],
10+
"dependencies": [
11+
"camera.js",
12+
13+
"handtrack.min.js",
14+
"HandsDetect.js",
15+
"hands-blockly.js"
16+
],
17+
"msg": "blockly/msg",
18+
"blocksMsg": "blockly/msg/blocks",
19+
"toolbox": "blockly/toolbox.xml"
20+
}

blockly/blocks.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
Blockly.Blocks['hands_get_camera'] = {
2+
init: function () {
3+
this.appendDummyInput()
4+
.appendField("設定")
5+
.appendField(new Blockly.FieldVariable("camera"), "camera")
6+
.appendField("並啟動,影像來源:")
7+
.appendField(new Blockly.FieldTextInput("0"), "src")
8+
.appendField("旋轉鏡頭")
9+
.appendField(new Blockly.FieldCheckbox("FALSE"), "rotate");
10+
this.setPreviousStatement(true, null);
11+
this.setNextStatement(true, null);
12+
this.setColour(330);
13+
this.setTooltip('');
14+
this.setHelpUrl('https://webduino.io/');
15+
}
16+
};
17+
18+
//https://blockly-demo.appspot.com/static/demos/blockfactory_old/index.html#y6tnd2
19+
Blockly.Blocks['hands_create_detect'] = {
20+
init: function () {
21+
this.appendValueInput("camera")
22+
.setCheck(null)
23+
.appendField("建立手掌偵測")
24+
.appendField(new Blockly.FieldVariable("hands"), "hands")
25+
.appendField(" ,影像來源");
26+
this.setPreviousStatement(true, null);
27+
this.setNextStatement(true, null);
28+
this.setColour(330);
29+
this.setTooltip('');
30+
this.setHelpUrl('https://webduino.io/');
31+
}
32+
};
33+
34+
//https://blockly-demo.appspot.com/static/demos/blockfactory_old/index.html#ro7vws
35+
Blockly.Blocks['hands_on_detect'] = {
36+
init: function() {
37+
this.appendDummyInput()
38+
.appendField(new Blockly.FieldVariable("hands"), "hands")
39+
.appendField("辨識率高於")
40+
.appendField(new Blockly.FieldTextInput("0.9"), "conf")
41+
.appendField("觸發");
42+
this.appendStatementInput("exec")
43+
.setCheck(null)
44+
.appendField("執行");
45+
this.setPreviousStatement(true, null);
46+
this.setNextStatement(true, null);
47+
this.setColour(45);
48+
this.setTooltip('');
49+
this.setHelpUrl('https://webduino.io/');
50+
}
51+
};
52+
53+
54+
Blockly.Blocks['hands_rtn_param'] = {
55+
init: function() {
56+
this.appendDummyInput()
57+
.appendField("取得")
58+
.appendField(new Blockly.FieldVariable("hands"), "hands")
59+
.appendField("的")
60+
.appendField(new Blockly.FieldDropdown([["x 座標", "0"], ["y 座標", "1"], ["寬度", "2"], ["高度", "3"], ["準確度", "4"]]), "info");
61+
this.setOutput(true, null);
62+
this.setColour(45);
63+
this.setTooltip('');
64+
this.setHelpUrl('http://www.example.com/');
65+
}
66+
};

0 commit comments

Comments
 (0)