LoginSignup
4
3

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-10-20

はじめに

プログラミングやマイコンボードに初めて触れた超初心者が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>
4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3