Files
jarvis/jarvis/vision/face_detector.py
T
Adolfo Reyna 199f762616 feat: Jarvis v2 - CPU optimized always-listening for iMac Ubuntu
- PipeWire/pw-record backend (no PortAudio needed) - tested mic live
- VAD: Energy (immediate) + Silero (torch CPU) switchable
- Wakeword: openWakeWord TFLite hey_jarvis 0.4
- STT: faster-whisper base int8 CPU - model loads OK on i3
- SpeakerID: ECAPA embeddings + fallback stats, enrollment store
- Vision: OpenCV Haar + face_recognition + webcam cam0 640x480 verified
- LLM: ollama/qwen2.5:3b, gemini_cli, hermes_api, echo strategies
- TTS: Piper + espeak + echo fallbacks
- Core pipeline: IDLE -> WAKE -> RECORDING -> STT -> SpeakerID/FaceID fusion -> LLM -> TTS -> followup window
- Config via jarvis.yaml, soul.md persona
- CLI tools: run, devices, enroll-speaker, enroll-face, test-vad, test-mic
- Systemd user service ready
- Tested on iMac 2010 i3 550 15GB Ubuntu 26.04 CPU-only
2026-07-10 12:16:03 -04:00

26 lines
1.0 KiB
Python

import cv2, numpy as np, logging, os
from typing import List, Tuple
log = logging.getLogger(__name__)
class FaceDetector:
def __init__(self):
self.cascade=None
self._load()
def _load(self):
try:
cascade_path = cv2.data.haarcascades + 'haarcascade_frontalface_default.xml'
if os.path.exists(cascade_path):
self.cascade = cv2.CascadeClassifier(cascade_path)
log.info("Haar face detector loaded")
except Exception as e:
log.warning(f"Face detector load failed: {e}")
def detect(self, frame: np.ndarray) -> List[Tuple[int,int,int,int]]:
if self.cascade is None:
return []
try:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = self.cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(80,80))
return [(int(x),int(y),int(w),int(h)) for (x,y,w,h) in faces]
except Exception as e:
log.debug(f"Detect error: {e}")
return []