<!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;


let contadorOlhosFechados = 0;


const tempos={

"FRENTE":0,

"ESQUERDA":0,

"DIREITA":0,

"CIMA":0,

"BAIXO":0,

"OLHOS FECHADOS":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 distancia(p1,p2){


  const dx = p1.x - p2.x;

  const dy = p1.y - p2.y;


  return Math.sqrt(

    dx*dx + dy*dy

  );


}

function olhosFechados(face){


  const olhoEsqSuperior = face[159];

  const olhoEsqInferior = face[145];


  const olhoDirSuperior = face[386];

  const olhoDirInferior = face[374];


  const aberturaEsq =

    distancia(

      olhoEsqSuperior,

      olhoEsqInferior

    );


  const aberturaDir =

    distancia(

      olhoDirSuperior,

      olhoDirInferior

    );


  const aberturaMedia =

    (aberturaEsq + aberturaDir) / 2;


  return aberturaMedia < 0.018;


}

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

 ){


   const face =

     results.multiFaceLandmarks[0];


   if(

     olhosFechados(face)

   ){


     contadorOlhosFechados++;


   }else{


     contadorOlhosFechados = 0;


   }


   if(

     contadorOlhosFechados > 8

   ){


     atualizarEstado(

       "OLHOS FECHADOS"

     );


   }else{


     atualizarEstado(

       classificarFace(face)

     );


   }


 }else{


   contadorOlhosFechados = 0;


   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>