<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Monitoramento Facial - Versão 1</title>
<style>
body{font-family:Arial,sans-serif;background:#222;color:#fff;text-align:center;padding:20px}
video{width:100%;max-width:640px;border-radius:10px;background:#000}
button{padding:10px 18px;margin:5px;border:none;border-radius:6px;font-weight:bold;cursor:pointer}
#btnStart{background:#00bf72;color:#fff}
#btnStop{background:#d9534f;color:#fff}
#status{margin:15px;font-size:20px;font-weight:bold}
#relatorio{margin-top:20px;text-align:left;max-width:700px;margin-left:auto;margin-right:auto;background:#333;padding:15px;border-radius:8px}
</style>
</head>
<body>
<h2>Monitoramento Facial (Versão 1)</h2>
<button id="btnStart">LIGAR CÂMERA</button>
<button id="btnStop">FINALIZAR MONITORAMENTO</button>
<div id="status">Aguardando...</div>
<video id="video" autoplay playsinline></video>
<div id="relatorio"></div>
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/face_mesh/face_mesh.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_utils.js"></script>
<script>
const video=document.getElementById("video");
const statusDiv=document.getElementById("status");
const relatorio=document.getElementById("relatorio");
let monitoramentoIniciado = false;
let ultimoEstado = null;
let ultimoTempo = null;
const tempos={
"FRENTE":0,
"ESQUERDA":0,
"DIREITA":0,
"CIMA":0,
"BAIXO":0,
"SEM ROSTO":0
};
function atualizarEstado(novo){
if(!monitoramentoIniciado){
return;
}
const agora = Date.now();
if(
ultimoEstado &&
ultimoTempo
){
tempos[ultimoEstado] +=
agora - ultimoTempo;
}
ultimoEstado = novo;
ultimoTempo = agora;
statusDiv.textContent =
"Estado Atual: " + novo;
}
function classificarFace(face){
const nariz=face[1];
const esq=face[234];
const dir=face[454];
const testa=face[10];
const queixo=face[152];
const centroX=(esq.x+dir.x)/2;
const centroY=(testa.y+queixo.y)/2;
const dx=nariz.x-centroX;
const dy=nariz.y-centroY;
if(dx>0.04) return "DIREITA";
if(dx<-0.04) return "ESQUERDA";
if(dy>0.05) return "BAIXO";
if(dy<-0.05) return "CIMA";
return "FRENTE";
}
let camera;
const faceMesh=new FaceMesh({
locateFile:(file)=>`https://cdn.jsdelivr.net/npm/@mediapipe/face_mesh/${file}`
});
faceMesh.setOptions({
maxNumFaces:1,
refineLandmarks:true,
minDetectionConfidence:0.5,
minTrackingConfidence:0.5
});
faceMesh.onResults((results)=>{
if(results.multiFaceLandmarks && results.multiFaceLandmarks.length>0){
atualizarEstado(classificarFace(results.multiFaceLandmarks[0]));
}else{
atualizarEstado("SEM ROSTO");
}
});
document.getElementById("btnStart").onclick=async()=>{
const stream=await navigator.mediaDevices.getUserMedia({video:true});
video.srcObject=stream;
camera=new Camera(video,{
onFrame:async()=>{
await faceMesh.send({image:video});
},
width:640,
height:480
});
monitoramentoIniciado = true;
ultimoEstado = null;
ultimoTempo = Date.now();
camera.start();
};
document.getElementById("btnStop").onclick=()=>{
if(ultimoEstado){
atualizarEstado(ultimoEstado);
}
const total=Object.values(tempos).reduce((a,b)=>a+b,0);
let html="<h3>Relatório</h3>";
for(const k in tempos){
const s=Math.round(tempos[k]/1000);
const m=(s/60).toFixed(2);
const p=total?((tempos[k]/total)*100).toFixed(1):0;
html+=`<p><b>${k}</b>: ${s}s (${m} min) - ${p}%</p>`;
}
relatorio.innerHTML=html;
if(video.srcObject){
video.srcObject.getTracks().forEach(t=>t.stop());
}
monitoramentoIniciado = false;
};
</script>
</body>
</html>