Wire detection pipeline: throttle YOLO, save crops, insert sightings, route person/vehicle
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c77f732ac7
commit
6771923585
@ -21,6 +21,7 @@ from vigilar.camera.recorder import AdaptiveRecorder
|
||||
from vigilar.camera.ring_buffer import RingBuffer
|
||||
from vigilar.config import CameraConfig, MQTTConfig, PetsConfig, RemoteConfig
|
||||
from vigilar.constants import Topics
|
||||
from vigilar.detection.crop_manager import CropManager
|
||||
from vigilar.detection.pet_id import PetIDClassifier
|
||||
from vigilar.detection.wildlife import classify_wildlife_threat
|
||||
from vigilar.detection.yolo import YOLODetector
|
||||
@ -113,6 +114,7 @@ def run_camera_worker(
|
||||
# Object detection (YOLOv8 unified detector)
|
||||
yolo_detector = None
|
||||
pet_classifier = None
|
||||
crop_manager = None
|
||||
if pets_cfg and pets_cfg.enabled:
|
||||
yolo_detector = YOLODetector(
|
||||
model_path=pets_cfg.model_path,
|
||||
@ -124,9 +126,14 @@ def run_camera_worker(
|
||||
high_threshold=pets_cfg.pet_id_threshold,
|
||||
low_threshold=pets_cfg.pet_id_low_confidence,
|
||||
)
|
||||
crop_manager = CropManager(
|
||||
staging_dir=pets_cfg.crop_staging_dir,
|
||||
training_dir=pets_cfg.training_dir,
|
||||
)
|
||||
|
||||
state = CameraState()
|
||||
shutdown = False
|
||||
last_detection_time: float = 0
|
||||
|
||||
def handle_signal(signum, frame):
|
||||
nonlocal shutdown
|
||||
@ -261,15 +268,24 @@ def run_camera_worker(
|
||||
if state.frame_count % idle_skip_factor == 0:
|
||||
recorder.write_frame(frame)
|
||||
|
||||
# Run object detection on motion frames
|
||||
if state.motion_active and yolo_detector and yolo_detector.is_loaded:
|
||||
# Run object detection on motion frames — throttled to 1 inference/second
|
||||
if (state.motion_active and yolo_detector and yolo_detector.is_loaded
|
||||
and now - last_detection_time >= 1.0):
|
||||
last_detection_time = now
|
||||
detections = yolo_detector.detect(frame)
|
||||
for det in detections:
|
||||
category = YOLODetector.classify(det)
|
||||
if category == "domestic_animal":
|
||||
# Crop for pet ID
|
||||
# Crop for pet ID and staging
|
||||
x, y, w, h = det.bbox
|
||||
crop = frame[max(0, y):y + h, max(0, x):x + w]
|
||||
|
||||
crop_path = None
|
||||
if crop_manager and crop.size > 0:
|
||||
crop_path = crop_manager.save_staging_crop(
|
||||
crop, species=det.class_name, camera_id=camera_id
|
||||
)
|
||||
|
||||
pet_result = None
|
||||
if pet_classifier and pet_classifier.is_loaded and crop.size > 0:
|
||||
pet_result = pet_classifier.identify(crop, species=det.class_name)
|
||||
@ -278,6 +294,7 @@ def run_camera_worker(
|
||||
"species": det.class_name,
|
||||
"confidence": round(det.confidence, 3),
|
||||
"camera_location": camera_cfg.location,
|
||||
"crop_path": crop_path,
|
||||
}
|
||||
if pet_result and pet_result.is_identified:
|
||||
payload["pet_id"] = pet_result.pet_id
|
||||
@ -302,6 +319,21 @@ def run_camera_worker(
|
||||
threat_level=threat_level,
|
||||
confidence=round(det.confidence, 3),
|
||||
camera_location=camera_cfg.location,
|
||||
crop_path=None,
|
||||
)
|
||||
|
||||
elif category == "person":
|
||||
bus.publish_event(
|
||||
Topics.camera_motion_start(camera_id),
|
||||
detection="person",
|
||||
confidence=round(det.confidence, 3),
|
||||
)
|
||||
|
||||
elif category == "vehicle":
|
||||
bus.publish_event(
|
||||
Topics.camera_motion_start(camera_id),
|
||||
detection="vehicle",
|
||||
confidence=round(det.confidence, 3),
|
||||
)
|
||||
|
||||
# Heartbeat every 10 seconds
|
||||
|
||||
@ -101,6 +101,34 @@ class EventProcessor:
|
||||
payload=payload,
|
||||
)
|
||||
|
||||
# Insert pet/wildlife sightings
|
||||
if event_type in (
|
||||
EventType.PET_DETECTED, EventType.PET_ESCAPE, EventType.UNKNOWN_ANIMAL
|
||||
):
|
||||
from vigilar.storage.queries import insert_pet_sighting
|
||||
insert_pet_sighting(
|
||||
engine,
|
||||
pet_id=payload.get("pet_id"),
|
||||
species=payload.get("species", "unknown"),
|
||||
camera_id=source_id or "",
|
||||
confidence=payload.get("confidence", 0.0),
|
||||
crop_path=payload.get("crop_path"),
|
||||
event_id=event_id,
|
||||
)
|
||||
elif event_type in (
|
||||
EventType.WILDLIFE_PREDATOR, EventType.WILDLIFE_NUISANCE, EventType.WILDLIFE_PASSIVE
|
||||
):
|
||||
from vigilar.storage.queries import insert_wildlife_sighting
|
||||
insert_wildlife_sighting(
|
||||
engine,
|
||||
species=payload.get("species", "unknown"),
|
||||
threat_level=payload.get("threat_level", "PASSIVE"),
|
||||
camera_id=source_id or "",
|
||||
confidence=payload.get("confidence", 0.0),
|
||||
crop_path=payload.get("crop_path"),
|
||||
event_id=event_id,
|
||||
)
|
||||
|
||||
# Evaluate rules
|
||||
actions = rule_engine.evaluate(topic, payload, fsm.state)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user