Skip to content

ovelazquezj/GazeFocus

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GazeFocus

GazeFocus cambia automaticamente el foco de ventana entre monitores segun la orientacion de la cabeza (head pose, yaw): un unico proceso sincrono en Windows 11.

1. Que es GazeFocus

Un solo proceso que lee la pose de la cabeza desde la webcam, decide a que monitor estas mirando (yaw) y trae al primer plano una ventana de ese monitor, todo de forma automatica y sincrona en Windows 11.

2. Requisitos

  • Windows 11.
  • Una webcam.
  • Conda (Miniconda o Anaconda).

El stack completo se define en environment.yml (Python 3.11, OpenCV, MediaPipe, NumPy, pywin32). No hay dependencias fuera de environment.yml.

3. Instalacion

Crea el entorno conda a partir de environment.yml y activalo:

conda env create -f environment.yml
conda activate gazefocus

Todos los comandos de las secciones siguientes se ejecutan dentro de conda activate gazefocus.

4. Calibracion

Antes del modo normal hay que calibrar una vez. La calibracion te pide mirar a cada monitor de izquierda a derecha y pulsar Enter; con eso aprende el yaw asociado a cada frontera y escribe config/calibration.json.

python src/main.py --calibrate

Opcionalmente puedes indicar la webcam y los FPS de captura:

python src/main.py --calibrate --cam-index 0 --fps 15

Sigue los prompts en consola (mira cada monitor de izquierda a derecha y pulsa Enter). Al terminar, el programa imprime la ruta del archivo escrito (config/calibration.json) y la instruccion para arrancar el modo normal. La calibracion debe completarse antes de ejecutar el modo normal.

Webcams espejadas: si tu camara entrega la imagen en espejo (lo que invierte el signo del yaw), la calibracion lo detecta y corrige automaticamente —persiste un flag mirror en config/calibration.json y emite un aviso por log—; no tienes que configurar nada. En modo normal, M6 lee ese flag y lo aplica a la estimacion en vivo, de modo que el angulo en runtime y las anclas calibradas quedan en el mismo marco. Una secuencia de angulos genuinamente inconsistente (ni creciente ni decreciente) si aborta con un error claro y no escribe el archivo.

5. Ejecucion (modo normal)

python src/main.py

Flags opcionales:

python src/main.py --cam-index 0 --fps 15 --debounce-ms 500.0 --dead-band 0.1 --log-level INFO
Flag Tipo Default Que hace
--cam-index int 0 Indice de la webcam (M1).
--fps int 15 FPS de procesamiento y cadencia del lazo.
--debounce-ms float 500.0 Ventana de debounce del decisor (M4) en ms.
--dead-band float (sin valor) Banda muerta que sobreescribe la del mapa; si se omite, se usa la dead_band por frontera de la calibracion.
--calibrate flag False Ejecuta la calibracion y termina (no entra al lazo).
--log-level {DEBUG,INFO,WARNING,ERROR} INFO Nivel de logging.

El modo normal requiere una calibracion previa. Si config/calibration.json falta o es invalido, el programa imprime un mensaje claro instando a ejecutar python src/main.py --calibrate y sale con un codigo distinto de cero (sin abrir la camara).

6. Cierre

Pulsa Ctrl+C para un cierre limpio: el proceso libera la camara antes de salir.

Tambien Ctrl+Break (SIGBREAK) y SIGTERM convergen en el mismo cierre limpio. Nota: en Windows 11 la entrega de SIGTERM es best-effort; Ctrl+C y Ctrl+Break son las rutas fiables en consola.

7. Logs

Se registran:

  • El arranque (modo, cam_index, fps, debounce_ms, dead_band, log_level).
  • Cada evento de foco (FocusEvent con su target_order y ts) y el resultado booleano de la actuacion de foco: True (el foco fue efectivo) o False.
  • El cierre solicitado.

El nivel es INFO por defecto y se configura con --log-level (DEBUG/INFO/WARNING/ERROR). Un resultado False significa que el foco no pego (la ventana no quedo al frente, p.ej. monitor sin ventana elegible o monitor desconectado): es la degradacion con gracia del punto fragil de M5, y se registra a nivel WARNING.

8. Aceptacion manual del foco real (M5 via M6)

El cambio de foco real en Windows 11 no se puede automatizar (depende de la mitigacion fragil de M5 y del estado de la sesion de escritorio), por lo que se valida manualmente y no en CI. El procedimiento y el registro estan en docs/manual_acceptance.md.

La prueba se lanza a traves del entry point de M6 (python src/main.py), que declara Per-Monitor-V2 DPI awareness al arrancar; no invocando el actuador en un proceso crudo sin esa declaracion. Escenarios resumidos:

  • Base (1 monitor): dos ventanas reales; focus_monitor(0) activa la esperada y devuelve True.
  • Multi-monitor: una ventana por monitor; focus_monitor(order) activa la del monitor correcto en cada caso (valida la coincidencia del espacio de coordenadas M2 <-> M5).
  • Fallo controlado: monitor sin ventana elegible (o order inexistente); focus_monitor devuelve False sin excepcion y sin cambio de foco.

El cambio de foco real es la unica parte validada manualmente; el resto se cubre en CI.

9. Notas

  • Todo se ejecuta dentro de conda activate gazefocus.
  • El cambio de foco efectivo en background es el unico punto fragil del sistema (mitigacion de M5) y por eso se valida manualmente (seccion 8).
  • El proceso declara Per-Monitor-V2 DPI awareness al arrancar para que las coordenadas de monitores y ventanas compartan el mismo espacio fisico.

About

Hands-free multi-monitor window focus switcher for Windows 11 driven by head pose. Estimates head yaw from your webcam (MediaPipe Face Mesh + OpenCV solvePnP) to automatically bring the window on the monitor you're facing to the foreground. CPU-only, single-process Python 3.11, no GPU required.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages