サイトアイコン KOKENSHAの技術ブログ

obniz公式の顔検出扇風機サンプル 動かない人は、こちらへどうぞ

obniz公式サイトにある動作例の一つ

顔検出扇風機

ですが、ソースコードが少し古いようで、そのまま動かないです!

https://obniz.io/explore/25

内容がとても面白そうですから

どうしても動かしてみたいです。

動くプログラムはここに!

opencv.jsも利用して、顔を検出して、追跡する訳ですから、とても動作して欲しかったです。

もし、あなたも同じことで悩んでいるのならば

もう、ここに来てよかったです!

はい、前置きはこのぐらいにして、動くソースコードはこちらです!どうぞ!

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Video Capture Example</title>
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <script src="https://docs.opencv.org/3.4/opencv.js"></script>
  <script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
  <script src="https://unpkg.com/obniz@1.5.2/obniz.js"></script>
  <style>
.refrect-lr{
  -webkit-transform: scaleX(-1);
  -o-transform: scaleX(-1);
  -moz-transform: scaleX(-1);
  transform: scaleX(-1);
  filter: FlipH;
  -ms-filter: "FlipH";
}
  </style>
</head>
<body>

<div id="obniz-debug"></div>

<div>
  <div class="control">
    <button id="startAndStop">Start</button>
  </div>
</div>
<p class="err" id="errorMessage"></p>
<div>
  <table cellpadding="0" cellspacing="0" width="0" border="0">
    <tr>
      <td>
        <video id="videoInput" autoplay playsinline width=320 height=240 class="refrect-lr"></video>
      </td>
      <td>
        <canvas id="canvasOutput" width=320 height=240 style="-webkit-font-smoothing:none"
                
                class="refrect-lr"></canvas>
      </td>
      <td></td>
      <td></td>
    </tr>
    <tr>
      <td>
        <div class="caption">videoInput</div>
      </td>
      <td>
        <div class="caption">canvasOutput</div>
      </td>
      <td></td>
      <td></td>
    </tr>
  </table>
</div>

<script src="https://webrtc.github.io/adapter/adapter-5.0.4.js" type="text/javascript"></script>
<script src="https://docs.opencv.org/3.4/utils.js" type="text/javascript"></script>
<script type="text/javascript">

  var servo;

  obniz = new Obniz("YOUR_OBNIZ_ID");

  obniz.onconnect = async () => {
    obniz.display.print("ready")
    var usb = obniz.wired("USB" , {gnd:11, vcc:8} );
    usb.on();
  
    servo = obniz.wired("ServoMotor", {signal:0,vcc:1, gnd:2});
  
  }

  let utils = new Utils('errorMessage');

  let faceCascadeFile = 'haarcascade_frontalface_default.xml';
  utils.createFileFromUrl(faceCascadeFile, 'https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_default.xml', () => {
    startAndStop.removeAttribute('disabled');
  });


  let streaming = false;
  let videoInput = document.getElementById('videoInput');
  let startAndStop = document.getElementById('startAndStop');
  let canvasOutput = document.getElementById('canvasOutput');
  let canvasContext = canvasOutput.getContext('2d');


  function successCallback(stream) {
    document.getElementById("videoInput").srcObject = stream;
    onVideoStarted();
  };

  function errorCallback(err) {
    console.error('mediaDevice.getUserMedia() error:', error);
  };

  startAndStop.addEventListener('click', () => {


    if (!streaming) {
      utils.clearError();

      const medias = {
        audio: false, video: {
          facingMode: "user" 
        }
      };


navigator.mediaDevices = navigator.mediaDevices || ((navigator.mozGetUserMedia || navigator.webkitGetUserMedia) ? {
   getUserMedia: function(c) {
     return new Promise(function(y, n) {
       (navigator.mozGetUserMedia ||
        navigator.webkitGetUserMedia).call(navigator, c, y, n);
     });
   }
} : null);

if (!navigator.mediaDevices) {
  console.log("getUserMedia() not supported.");
  return;
}

// Prefer camera resolution nearest to 1280x720.

var constraints = { audio: true, video: true };

navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream) {
  streaming=true;
  var video = document.querySelector('video');
  video.src = window.URL.createObjectURL(stream);
  video.onloadedmetadata = function(e) {
    video.play();
    start();
  };
})
.catch(function(err) {
  console.log(err.name + ": " + err.message);
});

    } else {
      utils.stopCamera();
      onVideoStopped();
    }

  });

  function onVideoStarted() {
    streaming = true;
    startAndStop.innerText = 'Stop';
    start();
  }

  function onVideoStopped() {
    streaming = false;
    canvasContext.clearRect(0, 0, canvasOutput.width, canvasOutput.height);
    startAndStop.innerText = 'Start';
  }

  async function start() {
    let video = document.getElementById('videoInput');
    let src = new cv.Mat(video.height, video.width, cv.CV_8UC4);
    let dst = new cv.Mat(video.height, video.width, cv.CV_8UC4);
    let gray = new cv.Mat();
    let cap = new cv.VideoCapture(video);
    let faces = new cv.RectVector();
    let classifier = new cv.CascadeClassifier();


    let result = classifier.load("haarcascade_frontalface_default.xml");

    const FPS = 30;

    function processVideo() {
      try {
        if (!streaming) {
          // clean and stop.
          src.delete();
          dst.delete();
          gray.delete();
          faces.delete();
          classifier.delete();
          return;
        }
        let begin = Date.now();
        // start processing.
        cap.read(src);
        src.copyTo(dst);
        cv.cvtColor(dst, gray, cv.COLOR_RGBA2GRAY, 0);
        // detect faces.
        classifier.detectMultiScale(gray, faces, 1.1, 3, 0);
        // draw faces.
        for (let i = 0; i < faces.size(); ++i) {
          let face = faces.get(i);
          let point1 = new cv.Point(face.x, face.y);
          let point2 = new cv.Point(face.x + face.width, face.y + face.height);
          cv.rectangle(dst, point1, point2, [255, 0, 0, 255]);
        }
        cv.imshow('canvasOutput', dst);
        if(servo && faces.size() > 0){
           	let face = faces.get(0);
          	console.log('servo.angle((320-(face.x + face.width/2)) * 180 / 320) -->',(320-(face.x + face.width/2)) * 180 / 320);
        	servo.angle((320-(face.x + face.width/2)) * 180 / 320)
        }
        
        // schedule the next one.
        let delay = 100 / FPS - (Date.now() - begin);
        setTimeout(processVideo, delay);
      } catch (err) {
        console.error(err);
      }
    };

    // schedule the first one.
    setTimeout(processVideo, 0);

  }
</script>
</body>
</html>

他のハードウェア接続などは

公式の説明に参照してください。そのままです。

実行

起動すると、カメラの許可を求められます。

もちろん、許可してください。セキュリティー関係はご自身の責任で確認してから行ってください。

許可すると

パソコンのカメラのインジケータが点灯します。

カメラが使用中ですよという合図です。

ちなみに、私は、chromeとsafariが上手くいかず

Firefoxでちゃんとカメラが起動して、動作しました。

そうすると、あなたの顔が検出されて、サーボの回転する角度に変換されます!

いかがですか?

動くと嬉しいですね。

しかも顔を検出して、追跡するという動作まで

本当に簡単に実現できたことに驚きばかりです!

obnizが本当にすごいです!これでウェブエンジニアもすぐIoTができてしまいます!

(ソースコードが動くとは言え、だいぶ急いで殴り書きになっておりまして、もっと綺麗に書ける余地があるかと思います、何か気づいたことがあれば、ご連絡いただければ、嬉しいです。)

[amazonjs asin=”B07DD6FK8G” locale=”JP” title=”obniz (オブナイズ)”]

[amazonjs asin=”B010SLRAAS” locale=”JP” title=”MG996R メタルギア・デジタルサーボ”]

モバイルバージョンを終了