obniz公式サイトにある動作例の一つ
顔検出扇風機
ですが、ソースコードが少し古いようで、そのまま動かないです!
内容がとても面白そうですから
どうしても動かしてみたいです。
動くプログラムはここに!
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>
他のハードウェア接続などは
公式の説明に参照してください。そのままです。
実行
- いつものやり方で、ブラウザーで実行してください。
- 上のプログラムにYOUR_OBNIZ_IDのところに、あたなのobniz個体のIDを上書きしてください。
- その前もちろん、obnizの方も電源を接続して置いてください。
起動すると、カメラの許可を求められます。
もちろん、許可してください。セキュリティー関係はご自身の責任で確認してから行ってください。
許可すると
パソコンのカメラのインジケータが点灯します。
カメラが使用中ですよという合図です。
ちなみに、私は、chromeとsafariが上手くいかず
Firefoxでちゃんとカメラが起動して、動作しました。
そうすると、あなたの顔が検出されて、サーボの回転する角度に変換されます!
いかがですか?
動くと嬉しいですね。
しかも顔を検出して、追跡するという動作まで
本当に簡単に実現できたことに驚きばかりです!
obnizが本当にすごいです!これでウェブエンジニアもすぐIoTができてしまいます!
(ソースコードが動くとは言え、だいぶ急いで殴り書きになっておりまして、もっと綺麗に書ける余地があるかと思います、何か気づいたことがあれば、ご連絡いただければ、嬉しいです。)
[amazonjs asin=”B07DD6FK8G” locale=”JP” title=”obniz (オブナイズ)”]
[amazonjs asin=”B010SLRAAS” locale=”JP” title=”MG996R メタルギア・デジタルサーボ”]