Help us understand the problem. What is going on with this article?

clmtraker.jsとobnizを使用して顔の表情からLチカさせる

はじめに

プログラミングやマイコンボードに初めて触れた超初心者が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>
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした