Implementasi Face Detection di Javascript Browser dengan face-api.js
Halo semuanya, good to see you again reading this post. Kita akan membuat face detection dengan face-api.js javascript. Minggu karantina ini betul-betul bikin kita cepet bosen. Karena virus covid19 ini, kita jadi harus ngelakuin social distancing yang mana gaboleh keluar rumah kalo gak penting-penting amat. Semoga saja wabah ini cepat berlalu.
Nah, disaat itulah saya merasa bosan karena setelah WFH (work from home) selesai, maka kegiatan saya hanya malas-malasan. Disitulah saya berfikir, kenapa saya gabuat tutorial tentang face detection? Bukankah suatu yang bagus juga untuk diposting.
Face Detection adalah proses pendeteksian wajah dari video atau gambar yang dilakukan oleh komputer dan bukan manusia. Face Detection yang kita akan buat diimplementasikan secara realtime melalui video dari webcam laptop kita di browser.
Disini kita akan implementasi face detection menggunakan library yang namanya face-api.js.
Maka kita mulai saja ya caranya.
Let’s start
Requirements
Pertama, kita masuk ke bagian bahan-bahan dulu yang diperlukan yakni,
- Laptop (yang ada webcamnya yaa)
- Code Editor (VSCode, Sublime Text)
- face-api.js (library based on TensorFlow Core yang membantu kita untuk pendeteksian)
- File pre-trained model (file yang berisi data pendeteksian)
- Browser (saya saranin pakai Chrome)
- Internet dan StackOverflow (kalo-kalo stuck)
- Secangkir kopi, semangat, dan kemauan 🙂
Oke, setelah bahan-bahan telah dimiliki, kita mulai ke tutorialnya. Download dulu library face-api.js yang akan kita gunakan disini.
Struktur Direktori
Struktur direktori dari project ini bisa dilihat di bawah ini yaa
project/
--index.html
--main.js
--face-api.js
--model/
---- *all the models
Menampilkan Output Webcam di Browser
Kita masuk ke tahap yang pertama, buat satu file html seperti di bawah ini. Untuk file index.html dan main.js. Untuk library face-api.js nanti akan kita libatkan selanjutnya :).
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CodeSeem Face Detection</title>
<style>
body {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
#videoEl {
transform: rotateY(180deg);
-webkit-transform: rotateY(180deg);
}
</style>
</head>
<body>
<video id="videoEl" width="800" height="600" autoplay muted></video>
<script defer src="main.js"></script>
</body>
</html>
main.js
//Get elemen video untuk menampilkan kamera
const videEl = document.getElementById('videEl');
//Membuat function untuk menampilkan input webcam di elemen video
async function startCamera(){
navigator.mediaDevices.getUserMedia({video: true})
.then(function(stream){
videoEl.srcObject = stream;
})
.catch(function(err){
console.log('Ada yang error');
console.log(err);
})
}
startCamera();
Dengan code diatas, kita sudah bisa menampilkan output dari webcam kita di browser. Hasilnya seperti di bawah ini.
Memulai Implementasi Face Detection
Selanjutnya, setelah kita berhasil menampilkan output dari webcam kita, kita akan mulai untuk mengintegrasikan face-api.js supaya bisa melakukan proses face detection.
Tambahkan satu baris tag script seperti dibawah ini. Kode dibawah diletakkan diatas tag script dari file main.js.
index.html
<script src="js/face-api.js"></script> <--- Tambahkan ini
<script defer src="main.js"></script>
Setelah ditambahkan, kita bisa mencoba untuk cek apakah library sudah terload dengan benar. Dengan cara membuka console log dan akses faceapi seperti dibawah
Jika muncul tidak jauh seperti di atas, alias tidak ada error message maka kalian bisa ke langkah berikutnya. Jika ada error, coba dicek kembali apakah cara memanggilnya sudah benar?
Setelah itu, kita mulai untuk memakai face-api.js. Edit file main.js supaya bisa mendeteksi wajah kita menjadi seperti di bawah ini.
//Get elemen video untuk menampilkan kamera
const videoEl = document.getElementById('videoEl');
//Inisiasi function dari faceapi load model
Promise.all([
faceapi.nets.tinyFaceDetector.loadFromUri('./models'),
faceapi.nets.faceLandmark68Net.loadFromUri('./models'),
faceapi.nets.faceRecognitionNet.loadFromUri('./models'),
faceapi.nets.faceExpressionNet.loadFromUri('./models')
])
.then(startCamera);
//Membuat function untuk menampilkan input webcam di elemen video
async function startCamera(){
navigator.mediaDevices.getUserMedia({video: true})
.then(function(stream){
videoEl.srcObject = stream;
})
.catch(function(err){
console.log('Ada yang error');
console.log(err);
})
}
//Main function untuk deteksi wajah
function startFunction(){
//Set interval setiap 0,1 detik
setInterval(async function(){
//Memanggil function untuk mendeteksi wajah di video webcam
const detection = await faceapi.detectAllFaces(
videoEl,
new faceapi.TinyFaceDetectorOptions()
)
.withFaceLandmarks()
console.log(detection);//Tes berhasil atau tidak
}, 100);
}
//Listen event saat output webcam sudah mulai muncul di browser
videoEl.addEventListener('playing', startFunction)
Yuk baca juga:
a hello world by CodeSeem
Penjelasan
Di bagian atas, kita menggunakan Promise untuk memanggil function loadmodel dari face-api.js. Kemudian menjalankan function startCamera tepat setelah model selesai load.
//Inisiasi function dari faceapi load model
Promise.all([
faceapi.nets.tinyFaceDetector.loadFromUri('./models'),
faceapi.nets.faceLandmark68Net.loadFromUri('./models'),
faceapi.nets.faceRecognitionNet.loadFromUri('./models'),
faceapi.nets.faceExpressionNet.loadFromUri('./models')
])
.then(startCamera);
Lalu di function startFunction, kita menjalankan function setInterval dalam waktu 0,1 detik. Kita disini menggunakan function detectAllFaces untuk mendeteksi wajah.
Pada tahap ini, kita belum benar-benar melihat bukti berhasil mendeteksi wajah secara visual, namun disini kita memanggil console.log(detection) yang akan menampilkan data hasil deteksinya secara teks.
//Main function untuk deteksi wajah
function startFunction(){
//Set interval setiap 0,1 detik
setInterval(async function(){
//Memanggil function untuk mendeteksi wajah di video webcam
const detection = await faceapi.detectAllFaces(
videoEl,
new faceapi.TinyFaceDetectorOptions()
)
.withFaceLandmarks()//Deteksi dengan metode landmark
.withFaceExpressions()//Deteksi dengan metode ekspresi wajah
console.log(detection);//Tes berhasil atau tidak
}, 100);
}
Jika berhasil, maka akan terlihat ouput data di console seperti di bawah ini.
Kemudian, tahap selanjutnya adalah memvisualisasikan hasil deteksi wajah. Kita fokus pada function startFunction pada file main.js.
startFunction()
//Function ketika output webcam mulai muncul
function startFunction(){
//Create canvas untuk detection shape nya
const canvas = faceapi.createCanvasFromMedia(videoEl);
document.body.append(canvas);
//Get video element width dan height nya
const sizeEl = {width:videoEl.width , height: videoEl.height}
//Match ukuran canvas dengan video elemen
faceapi.matchDimensions(canvas, sizeEl);
//Set interval setiap 0,1 detik
setInterval(async function(){
//Memanggil function untuk mendeteksi wajah di video webcam
const detection = await faceapi.detectAllFaces(
videoEl,
new faceapi.TinyFaceDetectorOptions()
)
.withFaceLandmarks()//Sistem deteksi menggunakan face landmark
.withFaceExpressions()//Sistem deteksi menggunakan face expression
//Membuat detection yang diresize menurut ukuran wajah
const resizedSizeDetection = faceapi.resizeResults(detection, sizeEl);
//Mengaplikasikan deteksi di canvas yang telah dibuat tadi,
//juga menghapus hasil deteksi yang sebelumnya
canvas.getContext('2d').clearRect(0,0, canvas.width, canvas.height);
faceapi.draw.drawDetections(canvas, resizedSizeDetection);
}, 100);
}
Penjelasan *lagi
Pertama yang ditambahkan adalah code untuk membuat elemen canvas dan menyamakan ukurannya dengan elemen video.
//Create canvas untuk detection shape nya
const canvas = faceapi.createCanvasFromMedia(videoEl);
document.body.append(canvas);
//Get video element width dan height nya
const sizeEl = {width:videoEl.width , height: videoEl.height}
//Match ukuran canvas dengan video elemen
faceapi.matchDimensions(canvas, sizeEl);
Kemudian, fungsi untuk menampilkan visual deteksi juga ditambahkan. Jangan lupa function clearRect sangat berguna untuk menghapus hasil visual deteksi sebelumnya.
//Membuat detection yang diresize menurut ukuran wajah
const resizedSizeDetection = faceapi.resizeResults(detection, sizeEl);
//Mengaplikasikan deteksi di canvas yang telah dibuat tadi,
//juga menghapus hasil deteksi yang sebelumnya
canvas.getContext('2d').clearRect(0,0, canvas.width, canvas.height);
faceapi.draw.drawDetections(canvas, resizedSizeDetection);
Jangan lupa juga untuk menambah styling pada canvas supaya memiliki posisi di atas elemen lain dan tidak terganggu elemen lain.
canvas {
position: absolute;
transform: rotateY(180deg);
-webkit-transform:rotateY(180deg);
}
Jika styling sudah ditambahkan, maka seharusnya deteksi akan berjalan lancar dan tampil hasil deteksi berupa kotak dengan angka persentase di ujungnya.
Penjelasan Opsional *tapi penting
Pada kode styling di atas, elemen canvas diset posisinya menjadi absolute. Kemudian ditambahkan properti transform dengan value rotasi 180deg. Saya menambahkan itu karena sebelumnya untuk elemen video pun saya melakukan hal yang sama.
Hal itu dilakukan supaya video hasil ouput webcam dan juga hasil deteksinya tidak mirrorred. Namun, kekurangannya styling dengan CSS diatas, karena hasil deteksinya mirrored, angka persentase ketepatan deteksinya juga jadi mirrored.
Ending
Oke setelah kita berhasil membuat deteksi wajah, banyak sekali tentunya kekurangan yang bisa diimprovisasi. Kita telah membuat face detection dengan face-api.js javascript. Tapi, di dunia yang tidak sempurna ini, kita pasti tidak sempurna, tapi dibalik ketidaksempurnaan itu kita jadi selalu memiliki celah untuk terus improvisasi.
Banyak yang bisa diimplementasikan dari face-api.js ini setelah diimprovisasi. Seperti
- Absen menggunakan wajah
- Login atau authentication menggunakan wajah (mungkin less secured)
- Game atau app kecil yang bisa menambah portofolio Kalian.
- — dan banyak lagi
As always, i’ll show you a good quote
“Everyday life is like programming, I guess. If you love something you can put beauty into it.”
Knuth, Donald.
― Donald Knuth
Enjoy, keep learning…