疫情期間,公司選擇讓員工進行遠程辦公,卻又難以監(jiān)督員工保證他們的工時。所以老板想出了通過攝像頭配合人臉識別算法,計算一天內員工在電腦面前的時間占比。
通過瀏覽器開啟攝像頭
這部分代碼是在網上找的,需要兼容多種瀏覽器:
if (navigator.mediaDevices === undefined) {
navigator.mediaDevices = {};
}
if (navigator.mediaDevices.getUserMedia === undefined) {
avigator.mediaDevices.getUserMedia = function (constraints) { // 首先,如果有getUserMedia的話,就獲得它
var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
// 一些瀏覽器根本沒實現它 - 那么就返回一個error到promise的reject來保持一個統(tǒng)一的接口
if (!getUserMedia) {
return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
}
// 否則,為老的navigator.getUserMedia方法包裹一個Promise
return new Promise(function (resolve, reject) {
getUserMedia.call(navigator, constraints, resolve, reject);
});
}
}
const constraints = {
video: true,
audio: false
};
let promise = navigator.mediaDevices.getUserMedia(constraints);
promise.then(stream => {
let v = document.getElementById('v');
// 舊的瀏覽器可能沒有srcObject
if ("srcObject" in v) {
v.srcObject = stream;
} else {
// 防止再新的瀏覽器里使用它,應為它已經不再支持了
v.src = window.URL.createObjectURL(stream);
}
v.onloadedmetadata = function (e) {
v.play();
};}).catch(err => {
console.error(err.name + ": " + err.message);
})
人臉識別
人臉識別使用的是Github上的一個人臉識別庫 face-api.js 。face-api.js可以識別出視頻流中人臉的輪廓和表情,調整識別精度等,Github上有詳細的使用教程。
// 初始化
faceapi.nets.ssdMobilenetv1.loadFromUri(dir),
// faceapi.nets.tinyFaceDetector.loadFromUri(dir),
faceapi.nets.faceLandmark68Net.loadFromUri(dir),
// faceapi.nets.faceRecognitionNet.loadFromUri(dir),
// faceapi.nets.faceExpressionNet.loadFromUri(dir)
var video = document.getElementById('video');
let canvas = faceapi.createCanvasFromMedia(video);
document.body.append(canvas);
faceapi.matchDimensions(canvas, displaySize);
// const options = new faceapi.TinyFaceDetectorOptions({ scoreThreshold: 0.2, inputSize: 608 });
const options = new faceapi.SsdMobilenetv1Options({ minConfidence: 0.5, maxResults: 3 });
let detections = await faceapi.detectAllFaces(video, options).withFaceLandmarks();
// 在畫面中顯示人臉輪廓描邊
const resizedDetections = faceapi.resizeResults(detections, displaySize);
canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
faceapi.draw.drawDetections(canvas, resizedDetections);
faceapi.draw.drawFaceLandmarks(canvas, resizedDetections);
實現實時跟蹤
實現實時跟蹤的思路就是,通過定時器,每隔1秒鐘對當前的圖像進行人臉識別并描邊,這樣間接實現了對視頻的實時人臉跟蹤,如果想要跟蹤速度更加靈敏一點,可以把時間間隔改成0.1秒。
video.addEventListener('play', () => {
console.log('play lisetner')
canvas = faceapi.createCanvasFromMedia(video);
document.body.append(canvas);
faceapi.matchDimensions(canvas, displaySize);
takePhoto();
setInterval(takePhoto,1000);
});
async function takePhoto(){
if (!faceapiReady) {
return;
}
let detections = await detect();
draw(detections);
}
async function detect() {
// const options = new faceapi.TinyFaceDetectorOptions({ scoreThreshold: 0.2, inputSize: 608 });
const options = new faceapi.SsdMobilenetv1Options({ minConfidence: 0.5, maxResults: 3 });
const detections = await faceapi.detectAllFaces(video, options).withFaceLandmarks();
return detections;
}
function draw(detections) {
const resizedDetections = faceapi.resizeResults(detections, displaySize);
canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
faceapi.draw.drawDetections(canvas, resizedDetections);
faceapi.draw.drawFaceLandmarks(canvas, resizedDetections);
}
最后,程序會每分鐘發(fā)送一次識別結果到服務器,服務器最終會計算每個人在一天內第一次的識別時間和最后一次識別時間作為上下班打卡時間,然后計算一天內識別到人臉的比例,可以作為在崗率的參考。
參考資料
文章標題:基于瀏覽器的人臉實時跟蹤
文章作者:Ciel Ni
文章鏈接:http://www.cielni.com/2020/03/07/brower-face-detect/
有問題或建議歡迎與我聯系討論,轉載或引用希望標明出處,感激不盡!