Pet-Monitor/pet_speed.py
2026-09-27 23:09:00 +02:00

116 lines
4.2 KiB
Python

import math
import os
import sys
import time
from picamera2 import Picamera2
from picamera2.devices.hailo import Hailo, hailo_architecture
# Clases COCO: 15 = Cat (Gato), 16 = Dog (Perro)
TARGET_CLASSES = {15: "Gato", 16: "Perro"}
SPEED_THRESHOLD = 0.30 # Umbral de velocidad normalizada por segundo
def get_hailo_model_path():
arch = hailo_architecture()
candidates = []
if arch == "HAILO8":
candidates = [
"/usr/share/hailo-models/yolov8s_h8.hef",
"/usr/share/hailo-models/yolov8s_h8l.hef"
]
else:
candidates = [
"/usr/share/hailo-models/yolov8s_h8l.hef",
"/usr/share/hailo-models/yolov8s_h8.hef"
]
for path in candidates:
if os.path.exists(path):
return path
raise FileNotFoundError("No se encontró ningún modelo YOLOv8 HEF en /usr/share/hailo-models/")
def calculate_centroid(box):
"""
Hailo YOLOv8 NMS devuelve [ymin, xmin, ymax, xmax, confidence].
Calcula el centroide normalizado (x, y).
"""
ymin, xmin, ymax, xmax = box[:4]
cx = (xmin + xmax) / 2.0
cy = (ymin + ymax) / 2.0
return cx, cy
def main():
model_path = get_hailo_model_path()
print(f"[INFO] Cargando modelo Hailo: {model_path} ...")
hailo = Hailo(model_path)
model_h, model_w, _ = hailo.get_input_shape()
print(f"[INFO] Modelo cargado. Resolución de entrada: {model_w}x{model_h}")
picam2 = Picamera2()
# Usamos configuración dual:
# - main: 1280x720 para visualización / grabación / alertas nítidas
# - lores: 640x640 directo al tamaño del modelo Hailo sin sobrecarga de CPU (escalado por hardware PiSP)
config = picam2.create_video_configuration(
main={"size": (1280, 720), "format": "RGB888"},
lores={"size": (model_w, model_h), "format": "RGB888"},
controls={"FrameRate": 30}
)
picam2.configure(config)
picam2.start()
print("[INFO] Pipeline Picamera2 + Hailo activo a 30 FPS.")
print("[INFO] Monitorizando mascotas (Gatos y Perros)... Presiona Ctrl+C para salir.\n")
last_centroid = None
last_time = time.time()
try:
while True:
# Capturamos el frame 'lores' escalado por hardware por el ISP
lores_frame = picam2.capture_array("lores")
current_time = time.time()
dt = current_time - last_time
# Inferencia por hardware en la NPU Hailo
detections_by_class = hailo.run(lores_frame)
pet_found = False
for class_id, label in TARGET_CLASSES.items():
if class_id < len(detections_by_class):
class_detections = detections_by_class[class_id]
for det in class_detections:
# det: [ymin, xmin, ymax, xmax, confidence]
confidence = det[4]
if confidence > 0.45:
pet_found = True
centroid = calculate_centroid(det)
if last_centroid and dt > 0:
dx = centroid[0] - last_centroid[0]
dy = centroid[1] - last_centroid[1]
dist = math.hypot(dx, dy)
speed = dist / dt
if speed > SPEED_THRESHOLD:
print(f"⚠️ [ALERTA] ¡{label} corriendo! Vel: {speed:.2f} norm/s (Conf: {confidence:.2f})")
else:
print(f"🐾 [OK] {label} detectado (calmado). Vel: {speed:.2f} norm/s (Conf: {confidence:.2f})")
last_centroid = centroid
break # Evaluamos la mascota principal detectada
if pet_found:
break
if not pet_found:
last_centroid = None
last_time = current_time
except KeyboardInterrupt:
print("\n[INFO] Deteniendo monitor de mascotas...")
finally:
picam2.stop()
hailo.close()
print("[INFO] Cámara y acelerador Hailo liberados correctamente.")
if __name__ == "__main__":
main()