はじめに
プログラミングやマイコンボードに初めて触れた超初心者がjavascriptを駆使して表情検出で遊んでみた時の個人用備忘録である。
clmtracker.jsというjavascriptの表情検出APIを使って2種類の表情を捉え、obnizと連動させ、表情に合わせてLEDライトが光る仕組みを考えた。
obniz準備
- 自分のobnizをPCと接続する。
「ドキュメント」→「obnizの始め方」に記載されているようにnodejsがインストールされたVisualStudioCodeを使用する。(Nodejsは入っていなくても動いている気がする。)
obniz公式サイト
Node.jsダウンロードページ - obnizをWifiに接続し、画面上にQRコードと8桁の数字が表示された状態にする。
- 抵抗付き青色LEDを準備し、アノードをobnizのio0に、カソードをio1にさす。
obniz LEDを付ける 参照
clmtracker.js準備(今回はクラウドファイルを使用するためダウンロード不要)
- GitHubにアップロードされているclmtrcker.jsファイルをPCにダウンロードし全て解凍する。
GitHub clmtracker.js - VScodeにて使用できるようにフォルダに名前を付けて保存する。
実装
- VScodeを立ち上げて、clmtrackをダウンロードした同じフォルダの中に新しくhtmlファイルを作成する。
(今回は適当にhtmlファイルを作成する。「新しいファイル作成」→XXX.htmlとすれば作れる。) - 自分のフォルダ内のclmtrackerを使用する場合は4つ分のscript内を自分のフォルダから引用するコードに変更する。
- var obniz = new Obniz("XXXX-XXXX") XXXX-XXXXの部分に自分のobnizの8桁の数字を入力することを忘れずに行う。
- PCのWEBカメラを使用する。
obniz キッズプロジェクト 参考 - サーバーを経由する必要があるためVScodeの拡張機能で[Live Server]を入れておいた。
Live Server 参考
<html>
<head>
<script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
<script src="https://unpkg.com/obniz@2.0.2/obniz.js"></script>
<script src="https://rawgit.com/auduno/clmtrackr/dev/build/clmtrackr.js"></script>
<script src="https://rawgit.com/auduno/clmtrackr/dev/models/model_pca_20_svm.js"></script>
<script src="https://rawgit.com/auduno/clmtrackr/dev/examples/js/emotion_classifier.js"></script>
<script src="https://rawgit.com/auduno/clmtrackr/dev/examples/js/emotionmodel.js"></script>
</head>
<body>
<div id="obniz-debug"></div>
<video id="video" width="400" height="300" autoplay></video>
<canvas id="canvas" width="400" height="300"></canvas>
<div id="print"></div>
<script>
var speaker;
var obniz = new Obniz("XXXX-XXXX") //自分のobnizの8桁の数字を入力する
obniz.onconnect = async () => {
var led = obniz.wired("LED", {anode:0, cathode:1});
await startEmotion()
}
async function startEmotion() {
var video = document.getElementById("video");
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var stream = await navigator.mediaDevices.getUserMedia({
video: {facingMode: "user"},
audio: false
});
video.srcObject = stream;
video.onloadedmetadata = function(e) {
video.play();
};
var tracker = new clm.tracker();
tracker.init(pModel);
tracker.start(video);
var classifier = new emotionClassifier();
classifier.init(emotionModel);
function drawLoop() {
requestAnimationFrame(drawLoop);
var positions = tracker.getCurrentPosition();
var parameters = tracker.getCurrentParameters();
var emotion = classifier.meanPredict(parameters);
context.clearRect(0, 0, canvas.width, canvas.height);
tracker.draw(canvas);
var emotions = {};
for (var i=0; i<emotion.length; i++) {
emotions[emotion[i].emotion] = emotion[i].value;
}
$("#print").html("sad: " + emotions.sad +"happy: " + emotions.happy)
var led = obniz.wired("LED", {anode:0, cathode:1});
if(emotions.happy > emotions.sad){
led.on();
console.log("happy");
} else if (emotions.happy < emotions.sad){
led.off();
console.log("sad");
}
}
drawLoop();
}
</script>
</body>
</html>
フルカラーLEDでも試してみた
WS2811もしくはWS2812円形タイプを購入し、表情によって色が変化するようにした。
今回のコードは楽しいと黄色、悲しいと青になるように設定した。RGBで数値を弄れば色を変えることができる。
配線の方法はパーツライブラリを参照した。
パーツライブラリ
<html>
<head>
<script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
<script src="https://unpkg.com/obniz@2.0.2/obniz.js"></script>
<script src="https://rawgit.com/auduno/clmtrackr/dev/build/clmtrackr.js"></script>
<script src="https://rawgit.com/auduno/clmtrackr/dev/models/model_pca_20_svm.js"></script>
<script src="https://rawgit.com/auduno/clmtrackr/dev/examples/js/emotion_classifier.js"></script>
<script src="https://rawgit.com/auduno/clmtrackr/dev/examples/js/emotionmodel.js"></script>
</head>
<body>
<div id="obniz-debug"></div>
<video id="video" width="400" height="300" autoplay></video>
<canvas id="canvas" width="400" height="300"></canvas>
<div id="print"></div>
<script>
var speaker;
var obniz = new Obniz("XXXX-XXXX") //自分のobnizの8桁の数字を入力する
var emotions = {};
var HAPPY = false;
var SAD = false;
obniz.onconnect = async function () {
const leds = obniz.wired("WS2812", {gnd:0, vcc: 1, din: 2});
var video = document.getElementById("video");
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var stream = await navigator.mediaDevices.getUserMedia({
video: {facingMode: "user"},
audio: false
});
video.srcObject = stream;
video.onloadedmetadata = function(e) {
video.play();
};
var tracker = new clm.tracker();
tracker.init(pModel);
tracker.start(video);
var classifier = new emotionClassifier();
classifier.init(emotionModel);
function drawLoop() {
requestAnimationFrame(drawLoop);
var positions = tracker.getCurrentPosition();
var parameters = tracker.getCurrentParameters();
var emotion = classifier.meanPredict(parameters);
context.clearRect(0, 0, canvas.width, canvas.height);
tracker.draw(canvas);
for (var i=0; i<emotion.length; i++) {
emotions[emotion[i].emotion] = emotion[i].value;
}
$("#print").html("sad: " + emotions.sad +"happy: " + emotions.happy)
if(HAPPY){
leds.rgbs([
[255,215,0],
[255,215,0],
[255,215,0],
[255,215,0],
[255,215,0],
[255,215,0],
[255,215,0],
[255,215,0],
[255,215,0],
[255,215,0],
[255,215,0],
[255,215,0],
[255,215,0],
[255,215,0],
[255,215,0],
[255,215,0],
[255,215,0],
[255,215,0],
[255,215,0],
[255,215,0],
]);
}
else {
leds.rgbs([
[0x00, 0x00, 0xFF] ,
[0x00, 0x00, 0xFF] ,
[0x00, 0x00, 0xFF] ,
[0x00, 0x00, 0xFF] ,
[0x00, 0x00, 0xFF] ,
[0x00, 0x00, 0xFF] ,
[0x00, 0x00, 0xFF] ,
[0x00, 0x00, 0xFF] ,
[0x00, 0x00, 0xFF] ,
[0x00, 0x00, 0xFF] ,
[0x00, 0x00, 0xFF] ,
[0x00, 0x00, 0xFF] ,
[0x00, 0x00, 0xFF] ,
[0x00, 0x00, 0xFF] ,
[0x00, 0x00, 0xFF] ,
[0x00, 0x00, 0xFF] ,
[0x00, 0x00, 0xFF] ,
[0x00, 0x00, 0xFF] ,
[0x00, 0x00, 0xFF] ,
[0x00, 0x00, 0xFF] ,
]);
}
if(emotions.happy > emotions.sad){
HAPPY = true;
SAD = false;
obniz.display.print("happy");
}
else{
SAD =false;
HAPPY = false;
obniz.display.print("sad");
}
}
drawLoop();
}
</script>
</body>
</html>
<html>
<head>
<script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
<script src="https://unpkg.com/obniz@2.0.2/obniz.js"></script>
<script src="https://rawgit.com/auduno/clmtrackr/dev/build/clmtrackr.js"></script>
<script src="https://rawgit.com/auduno/clmtrackr/dev/models/model_pca_20_svm.js"></script>
<script src="https://rawgit.com/auduno/clmtrackr/dev/examples/js/emotion_classifier.js"></script>
<script src="https://rawgit.com/auduno/clmtrackr/dev/examples/js/emotionmodel.js"></script>
</head>
<body>
<div id="obniz-debug"></div>
<video id="video" width="400" height="300" autoplay></video>
<canvas id="canvas" width="400" height="300"></canvas>
<div id="print"></div>
<script>
var speaker;
var obniz = new Obniz("XXXX-XXXX") //自分のobnizの8桁の数字を入力する
var emotions = {};
var HAPPY = false;
var SAD = false;
obniz.onconnect = async function () {
const leds = obniz.wired("WS2811", {gnd:0, vcc: 1, din: 2});
var video = document.getElementById("video");
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var stream = await navigator.mediaDevices.getUserMedia({
video: {facingMode: "user"},
audio: false
});
video.srcObject = stream;
video.onloadedmetadata = function(e) {
video.play();
};
var tracker = new clm.tracker();
tracker.init(pModel);
tracker.start(video);
var classifier = new emotionClassifier();
classifier.init(emotionModel);
function drawLoop() {
requestAnimationFrame(drawLoop);
var positions = tracker.getCurrentPosition();
var parameters = tracker.getCurrentParameters();
var emotion = classifier.meanPredict(parameters);
context.clearRect(0, 0, canvas.width, canvas.height);
tracker.draw(canvas);
for (var i=0; i<emotion.length; i++) {
emotions[emotion[i].emotion] = emotion[i].value;
}
$("#print").html("sad: " + emotions.sad +"happy: " + emotions.happy)
if(HAPPY){
leds.rgbs([
[255,215,0],
]);
}
else {
leds.rgbs([
[0x00, 0x00, 0xFF] ,
]);
}
if(emotions.happy > emotions.sad){
HAPPY = true;
SAD = false;
// obniz.display.print("happy");
}
else{
SAD =false;
HAPPY = false;
// obniz.display.print("sad");
}
}
drawLoop();
}
</script>
</body>
</html>