MINI
C:
/
xampp
/
htdocs
/
absensi-face
/
js
/
Upload File:
files >> C:/xampp/htdocs/absensi-face/js/app.js
// app.js - combined logic for register & attendance const MODEL_URL = '/absensi-face/models'; async function loadModels(){ try{ await faceapi.nets.tinyFaceDetector.loadFromUri(MODEL_URL); await faceapi.nets.faceLandmark68Net.loadFromUri(MODEL_URL); await faceapi.nets.faceRecognitionNet.loadFromUri(MODEL_URL); }catch(e){ console.warn('Load models from local failed, face-api may fallback to CDN or require internet.', e); } } async function ensureModels(){ await loadModels(); } let video = null; async function startCamera(){ video = document.getElementById('video'); if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { alert('Kamera tidak tersedia di browser ini.'); return; } const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: false }); video.srcObject = stream; await video.play(); } function dataURLtoBlob(dataurl) { const arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); for (let i = 0; i < n; i++) u8arr[i] = bstr.charCodeAt(i); return new Blob([u8arr], { type: mime }); } function euclidean(a,b){ let sum=0; for(let i=0;i<a.length;i++){ const d=a[i]-b[i]; sum+=d*d; } return Math.sqrt(sum); } if(window.pageMode === 'register'){ window.addEventListener('load', async ()=>{ await ensureModels(); document.getElementById('startCam').onclick = startCamera; document.getElementById('captureBtn').onclick = async ()=>{ const canvas = document.getElementById('canvas'); const videoEl = document.getElementById('video'); canvas.getContext('2d').drawImage(videoEl,0,0,canvas.width,canvas.height); document.getElementById('status').innerText = 'Mendeteksi wajah...'; const detection = await faceapi.detectSingleFace(canvas, new faceapi.TinyFaceDetectorOptions()).withFaceLandmarks().withFaceDescriptor(); if(!detection){ document.getElementById('status').innerText = 'Tidak ada wajah terdeteksi. Coba ulang.'; return; } window.latestDescriptor = Array.from(detection.descriptor); document.getElementById('status').innerText = 'Wajah terdeteksi. Siap disimpan.'; }; document.getElementById('formRegister').onsubmit = async (e)=>{ e.preventDefault(); const emp = document.getElementById('employee_id').value.trim(); const nama = document.getElementById('nama').value.trim(); if(!emp || !nama) return alert('isi lengkap'); if(!window.latestDescriptor) return alert('capture wajah dulu'); const canvas = document.getElementById('canvas'); const dataUrl = canvas.toDataURL('image/jpeg'); const blob = dataURLtoBlob(dataUrl); const fd = new FormData(); fd.append('employee_id', emp); fd.append('nama', nama); fd.append('descriptor', JSON.stringify(window.latestDescriptor)); fd.append('photo', blob, emp + '.jpg'); const res = await fetch('/absensi-face/php/save_user.php', { method: 'POST', body: fd }); const j = await res.json(); if(j.success){ alert('Pegawai tersimpan!'); window.latestDescriptor = null; document.getElementById('status').innerText = 'Selesai.'; } else { alert('Gagal: ' + (j.error || 'unknown')); } }; }); } if(window.pageMode === 'attendance'){ window.addEventListener('load', async ()=>{ await ensureModels(); document.getElementById('startCam').onclick = startCamera; const startRecognition = async ()=>{ const videoEl = document.getElementById('video'); const canvasEl = document.getElementById('canvas'); const ctx = canvasEl.getContext('2d'); const resp = await fetch('/absensi-face/php/get_descriptors.php'); const descriptorsData = await resp.json(); if(!descriptorsData || descriptorsData.length===0){ document.getElementById('msg').innerText = 'Belum ada pegawai terdafar.'; return; } const checkOnce = async ()=>{ ctx.drawImage(videoEl,0,0,canvasEl.width, canvasEl.height); const detection = await faceapi.detectSingleFace(canvasEl, new faceapi.TinyFaceDetectorOptions()).withFaceLandmarks().withFaceDescriptor(); if(!detection){ document.getElementById('msg').innerText = 'Tidak terdeteksi wajah.'; return; } const descriptor = Array.from(detection.descriptor); let best = {dist:999, user:null}; for(const p of descriptorsData){ if(!p.descriptor) continue; const d = euclidean(descriptor, p.descriptor); if(d < best.dist){ best.dist = d; best.user = p; } } const threshold = 0.5; if(best.user && best.dist <= threshold){ document.getElementById('msg').innerText = `Teridentifikasi: ${best.user.nama} (jarak ${best.dist.toFixed(3)})`; const dataUrl = canvasEl.toDataURL('image/jpeg'); const blob = dataURLtoBlob(dataUrl); const fd = new FormData(); fd.append('pegawai_id', best.user.id); fd.append('tipe', document.getElementById('tipe').value); fd.append('confidence', best.dist); fd.append('photo', blob, 'snap.jpg'); const r = await fetch('/absensi-face/php/save_attendance.php', { method:'POST', body: fd }); const j = await r.json(); if(j.success){ document.getElementById('msg').innerText += ' — absensi tercatat.'; } else { document.getElementById('msg').innerText += ' — gagal simpan.'; } } else { document.getElementById('msg').innerText = 'Wajah tidak dikenal (unknown).'; } }; document.getElementById('msg').innerText = 'Siap mendeteksi. Menangkap sekarang...'; await new Promise(r=>setTimeout(r,500)); await checkOnce(); }; document.getElementById('startCam').addEventListener('click', async ()=>{ await startCamera(); setTimeout(()=>{ startRecognition(); }, 800); }); }); }
Copyright ©2021 || Defacer Indonesia