看完「語音辨識」之後,接著來看看「人臉追蹤」,這邊所謂的人臉追蹤並不是人臉辨識,而是純粹判斷五官而追蹤人臉 ( 畢竟如果只是「純前端」而沒有後端資料庫,要做到人臉辨識應該有難度 ),人臉辨識其實可以參考微軟的人臉辨識 API ( Face API ),在這邊就純粹介紹純前端的用法。
如果是透過 Webduino Blockly 線上編輯工具 ( https://blockly.webduino.io ),可以透過現成的人臉追蹤或顏色追蹤積木,來執行相對應的動作。( 要執行的話切記一定要是「https」,因啟動相機無法在 http 的模式下進行 )
Webduino Blockly 人臉追蹤 ( https://goo.gl/B3Cce0 )
Webduino Blockly 顏色追蹤 ( https://goo.gl/zJfTRv )
而我這邊使用的方法和 Webduino 一模一樣,是採用一個名為「tracking.js」的 JavaScript,它提供了人臉、顏色...等追蹤的方法。( https://trackingjs.com/ )
要使用 tracking.js,首先必須載入相對應的 JavaScript,tracking.js 預設可以追蹤顏色。
<script src="https://blockly.webduino.io/lib/tracking-min.js"></script>
追蹤的方式是先透過電腦的攝影機擷取影像,透過網頁 video
的標籤顯示出來,因此 HTML 一開始要先放入 video
,然後這裡我習慣在外層多加一個 div
作為定位。
<div id=”demo>
<video id="demo-vedio" preload="" autoplay="" loop="" muted="" controls=""></video>
</div>
然後因為我這邊要把追蹤到的顏色或是人臉,用一個對應的顏色方框顯示出來 ( 有這個顏色的區域外層用一個矩形框住,矩形邊框的顏色就是偵測到的顏色,如果是人臉也會指定一個外框顏色 ),雖然標記用的矩形是動態產生,我們仍然可以先從 CSS 設定好它的一些基本屬性,到這邊一些基本的步驟就完成了。
#demo {
position: relative;
width: 400px;
height: 300px;
}
#demo-video {
position: absolute;
z-index:1;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#demo div{
position:absolute;
z-index:2;
}
首先看到顏色追蹤 ( 因為是預設功能 ),官方範例提供三種預設可追蹤的顏色。
track.myTracker = new tracking.ColorTracker(["magenta", "cyan", "yellow"]);
不過因為只有追蹤三種顏色還是太少,我們可以自己添加追蹤的顏色數量,透過 .registerColor
的方法,我們可以自行添加顏色,不過這邊要注意的是,添加的顏色是用 RGB 的範圍來定義,因為雖然我們眼睛以為是紅色,透過攝影機的電腦卻不見得認為是紅色 ( 舉例來說,藍色的東西在紅色的光下面,看起來就偏紫色,白紙在黃光下就會變成黃色是一樣的道理 ),所以才需要定義範圍。( 不過同樣的,環境光線常會影響顏色判斷,最好是用白光測試比較準確 )
tracking.ColorTracker.registerColor("red", function(r, g, b) {
if (r > 160 && g < 80 && b < 80) {
return true;
}
return false;
});
tracking.ColorTracker.registerColor("green", function(r, g, b) {
if (r < 80 && g > 160 && b < 80) {
return true;
}
return false;
});
tracking.ColorTracker.registerColor("blue", function(r, g, b) {
if (r < 80 && g < 80 && b > 160) {
return true;
}
return false;
});
定義好顏色後,我這邊另外用了一個物件,把對應邊框的顏色寫在裡面。
track.storkColor = {
magenta: "#f0a",
red: "#f00",
cyan: "#0ff",
yellow: "#ff0",
green: "#0c0",
blue: "#00f"
};
接著就是要啟動攝影機。
track.trackerTask = tracking.track("#demo-video", track.myTracker, {
camera: true
});
透過 .on(‘track’
的方法,就可以開始追蹤顏色,而這邊 event.data.length
表示追蹤到的顏色總數,如果你拿兩個黃色物體,長度就會是 2,你拿一個紅一個黃,長度也會是 2,也因此當數量不為 0,就表示有追蹤到顏色。
track.myTracker.on('track', function(event) {
if (event.data.length === 0) {
// No colors were detected in this frame.
} else {
event.data.forEach(function(rect) {
// rect.x, rect.y, rect.height, rect.width, rect.color
});
}
});
到這邊差不多就完成顏色追蹤了,看一下完整的 JavaScript,最主要就是根據顏色的數量,產生對應數量的 div 作為方框來追蹤,當顏色數量改變或沒有追蹤到顏色時,在動態的調整 div 的數量,而 div 的顏色則是根據我們剛剛設定的邊框顏色物件來決定。
$(function(){
var track = {};
var $demo = $('#demo');
tracking.ColorTracker.registerColor("red", function(r, g, b) {
if (r > 160 && g < 80 && b < 80) {
return true;
}
return false;
});
tracking.ColorTracker.registerColor("green", function(r, g, b) {
if (r < 80 && g > 160 && b < 80) {
return true;
}
return false;
});
tracking.ColorTracker.registerColor("blue", function(r, g, b) {
if (r < 80 && g < 80 && b > 160) {
return true;
}
return false;
});
track.myTracker = new tracking.ColorTracker(["magenta", "cyan", "yellow", "red", "green", "blue"]);
track.storkColor = {
magenta: "#f0a",
red: "#f00",
cyan: "#0ff",
yellow: "#ff0",
green: "#0c0",
blue: "#00f"
};
track.trackerTask = tracking.track("#demo-video", track.myTracker, {
camera: true
});
track.myTracker.on("track", function(event) {
if (event.data.length === 0) {
$('#demo div').remove(); //如果沒偵測到顏色,移除所有自動產生的追蹤方框
} else {
$('#demo div').remove(); //一開始搜尋到顏色時,先清空對應的追蹤方框
var divLength = event.data.length; //獲取顏色數量
event.data.forEach(function(e,i){
if($('#demo .div'+i).length === 0){
$('#demo').append('<div class="div'+i+'"></div>'); //產生對應的追蹤方框
}
//設定追蹤方框樣式
$('#demo .div'+i).css({
'border-width':'3px',
'border-style':'solid',
'border-color':track.storkColor[e.color],
'left':e.x,
'top':e.y,
'width':e.width,
'height':e.height
});
});
}
});
});
( 程式:https://bin.webduino.io/corav/1/edit?html,css,js,output )
( 要執行的話切記一定要是「https」,因啟動相機無法在 http 的模式下進行 )
看完了顏色追蹤接著看人臉追蹤,原理其實都差不多,只是如果要追蹤人臉,必須額外載入「face-min.js」
<script src="https://blockly.webduino.io/lib/face-min.js"></script>
和顏色追蹤的差別只在於第一段,顏色追蹤是設定追蹤的顏色名稱以及範圍,而人臉追蹤則是一些預設的參數。( 官方預設是這些參數 )
track.myTracker = new tracking.ObjectTracker("face");
tracker.setInitialScale(4);
tracker.setStepSize(2);
tracker.setEdgesDensity(0.1);
最後的程式碼長相,CSS 的部分和剛剛顏色追蹤一模一樣,JavaScript 就只是把追蹤到的人臉用紅色方框表示出來。
$(function(){
var track = {};
var $demo = $('#demo');
track.myTracker = new tracking.ObjectTracker("face");
track.myTracker.setInitialScale(4);
track.myTracker.setStepSize(0.5); //官方預設2,數值比較小比較不會抖動,但相對較吃效能
track.myTracker.setEdgesDensity(0.1);
track.trackerTask = tracking.track("#demo-video", track.myTracker, {
camera: true
});
track.myTracker.on("track", function(event) {
if (event.data.length === 0) {
$('#demo div').remove(); //如果沒偵測到人臉,移除所有自動產生的追蹤方框
} else {
$('#demo div').remove(); //一開始搜尋到人臉時,先清空對應的追蹤方框
var divLength = event.data.length; //獲取人臉數量
event.data.forEach(function(e,i){
if($('#demo .div'+i).length === 0){
$('#demo').append('<div class="div'+i+'"></div>'); //產生對應的追蹤方框
}
//設定追蹤方框樣式
$('#demo .div'+i).css({
'border-width':'3px',
'border-style':'solid',
'border-color':'#f00',
'left':e.x,
'top':e.y,
'width':e.width,
'height':e.height
});
});
}
});
});
( 程式:https://bin.webduino.io/mofor/1/edit?html,css,js,output )
( 要執行的話切記一定要是「https」,因啟動相機無法在 http 的模式下進行 )
到這邊大致上已經掌握顏色追蹤以及人臉追蹤的原理,再來就是和智慧插座結合,首先我們用顏色追蹤,讓追蹤到黃色的時候會開燈,追蹤到藍色的時候會熄燈。
$(function(){
var track = {};
var $demo = $('#demo');
var led;
tracking.ColorTracker.registerColor("red", function(r, g, b) {
if (r > 160 && g < 80 && b < 80) {
return true;
}
return false;
});
tracking.ColorTracker.registerColor("green", function(r, g, b) {
if (r < 80 && g > 160 && b < 80) {
return true;
}
return false;
});
tracking.ColorTracker.registerColor("blue", function(r, g, b) {
if (r < 80 && g < 80 && b > 160) {
return true;
}
return false;
});
track.myTracker = new tracking.ColorTracker(["magenta", "cyan", "yellow", "red", "green", "blue"]);
track.storkColor = {
magenta: "#f0a",
red: "#f00",
cyan: "#0ff",
yellow: "#ff0",
green: "#0c0",
blue: "#00f"
};
track.trackerTask = tracking.track("#demo-video", track.myTracker, {
camera: true
});
boardReady({device: '你的裝置 ID'}, function (board) {
board.systemReset();
board.samplingInterval = 250;
led = getLed(board, 10);
track.myTracker.on("track", function(event) {
if (event.data.length === 0) {
$('#demo div').remove(); //如果沒偵測到顏色,移除所有自動產生的追蹤方框
} else {
$('#demo div').remove(); //一開始搜尋到顏色時,先清空對應的追蹤方框
var divLength = event.data.length; //獲取顏色數量
event.data.forEach(function(e,i){
if($('#demo .div'+i).length === 0){
$('#demo').append('<div class="div'+i+'"></div>'); //產生對應的追蹤方框
}
//設定追蹤方框樣式
$('#demo .div'+i).css({
'border-width':'3px',
'border-style':'solid',
'border-color':track.storkColor[e.color],
'left':e.x,
'top':e.y,
'width':e.width,
'height':e.height
});
if(e.color=='yellow'){
console.log('yellow'); //追蹤到黃色的時候亮燈
led.on();
}else{
led.off(); //不然就是都熄燈
}
});
}
});
});
});
( 程式:https://bin.webduino.io/neba/1/edit?html,css,js,output )
至於人臉追蹤,我這邊用人臉的 x 數值來追蹤,預設追蹤到的 x,y 數值是對應到 video 的左上角,這也是為什麼我們可以拿來作為 CSS 位置的主要原因,因為我用的 video 寬度為 360,所以我讓 x 數值大於 ( 180 - 追蹤框寬度/2 ) 的時候就亮燈,也就是臉往右邊移動超過中線的時候會開燈。
$(function(){
var track = {};
var $demo = $('#demo');
var led;
track.myTracker = new tracking.ObjectTracker("face");
track.myTracker.setInitialScale(4);
track.myTracker.setStepSize(0.5);
track.myTracker.setEdgesDensity(0.1);
track.trackerTask = tracking.track("#demo-video", track.myTracker, {
camera: true
});
boardReady({device: 'evkG'}, function (board) {
board.systemReset();
board.samplingInterval = 250;
led = getLed(board, 10);
track.myTracker.on("track", function(event) {
if (event.data.length === 0) {
$('#demo div').remove(); //如果沒偵測到人臉,移除所有自動產生的追蹤方框
} else {
$('#demo div').remove(); //一開始搜尋到人臉時,先清空對應的追蹤方框
var divLength = event.data.length; //獲取人臉數量
event.data.forEach(function(e,i){
if($('#demo .div'+i).length === 0){
$('#demo').append('<div class="div'+i+'"></div>'); //產生對應的追蹤方框
}
//設定追蹤方框樣式
$('#demo .div'+i).css({
'border-width':'3px',
'border-style':'solid',
'border-color':'#f00',
'left':e.x,
'top':e.y,
'width':e.width,
'height':e.height
});
//設定超過中線會亮燈
if(e.x>(180-e.width/2)){
led.on();
}else{
led.off();
}
});
}
});
});
});
( 程式:https://bin.webduino.io/pufaqe/1/edit?html,css,js,output )
整體而言了解智慧插座的控制後,就可以用各種方法來操控,當然人臉追蹤與顏色追蹤,都只是廣大控制方式的一部分,後續會介紹更多有趣的控制方法喔!
參考: