mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-05-01 11:07:41 +03:00
Use ZMQ for signaling object detectoin is completed
This commit is contained in:
parent
225010c570
commit
301c01dbf2
@ -82,7 +82,6 @@ class FrigateApp:
|
|||||||
self.stop_event: MpEvent = mp.Event()
|
self.stop_event: MpEvent = mp.Event()
|
||||||
self.detection_queue: Queue = mp.Queue()
|
self.detection_queue: Queue = mp.Queue()
|
||||||
self.detectors: dict[str, ObjectDetectProcess] = {}
|
self.detectors: dict[str, ObjectDetectProcess] = {}
|
||||||
self.detection_out_events: dict[str, MpEvent] = {}
|
|
||||||
self.detection_shms: list[mp.shared_memory.SharedMemory] = []
|
self.detection_shms: list[mp.shared_memory.SharedMemory] = []
|
||||||
self.log_queue: Queue = mp.Queue()
|
self.log_queue: Queue = mp.Queue()
|
||||||
self.camera_metrics: dict[str, CameraMetrics] = {}
|
self.camera_metrics: dict[str, CameraMetrics] = {}
|
||||||
@ -363,8 +362,6 @@ class FrigateApp:
|
|||||||
|
|
||||||
def start_detectors(self) -> None:
|
def start_detectors(self) -> None:
|
||||||
for name in self.config.cameras.keys():
|
for name in self.config.cameras.keys():
|
||||||
self.detection_out_events[name] = mp.Event()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
largest_frame = max(
|
largest_frame = max(
|
||||||
[
|
[
|
||||||
@ -396,7 +393,7 @@ class FrigateApp:
|
|||||||
self.detectors[name] = ObjectDetectProcess(
|
self.detectors[name] = ObjectDetectProcess(
|
||||||
name,
|
name,
|
||||||
self.detection_queue,
|
self.detection_queue,
|
||||||
self.detection_out_events,
|
list(self.config.cameras.keys()),
|
||||||
detector_config,
|
detector_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -435,7 +432,6 @@ class FrigateApp:
|
|||||||
self.camera_maintainer = CameraMaintainer(
|
self.camera_maintainer = CameraMaintainer(
|
||||||
self.config,
|
self.config,
|
||||||
self.detection_queue,
|
self.detection_queue,
|
||||||
self.detection_out_events,
|
|
||||||
self.detected_frames_queue,
|
self.detected_frames_queue,
|
||||||
self.camera_metrics,
|
self.camera_metrics,
|
||||||
self.ptz_metrics,
|
self.ptz_metrics,
|
||||||
|
|||||||
@ -31,7 +31,6 @@ class CameraMaintainer(threading.Thread):
|
|||||||
self,
|
self,
|
||||||
config: FrigateConfig,
|
config: FrigateConfig,
|
||||||
detection_queue: Queue,
|
detection_queue: Queue,
|
||||||
detection_out_events: dict[str, MpEvent],
|
|
||||||
detected_frames_queue: Queue,
|
detected_frames_queue: Queue,
|
||||||
camera_metrics: dict[str, CameraMetrics],
|
camera_metrics: dict[str, CameraMetrics],
|
||||||
ptz_metrics: dict[str, PTZMetrics],
|
ptz_metrics: dict[str, PTZMetrics],
|
||||||
@ -40,7 +39,6 @@ class CameraMaintainer(threading.Thread):
|
|||||||
super().__init__(name="camera_processor")
|
super().__init__(name="camera_processor")
|
||||||
self.config = config
|
self.config = config
|
||||||
self.detection_queue = detection_queue
|
self.detection_queue = detection_queue
|
||||||
self.detection_out_events = detection_out_events
|
|
||||||
self.detected_frames_queue = detected_frames_queue
|
self.detected_frames_queue = detected_frames_queue
|
||||||
self.stop_event = stop_event
|
self.stop_event = stop_event
|
||||||
self.camera_metrics = camera_metrics
|
self.camera_metrics = camera_metrics
|
||||||
@ -54,7 +52,6 @@ class CameraMaintainer(threading.Thread):
|
|||||||
CameraConfigUpdateEnum.remove,
|
CameraConfigUpdateEnum.remove,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
self.detector_camera_publisher = DetectorCameraPublisher()
|
|
||||||
self.shm_count = self.__calculate_shm_frame_count()
|
self.shm_count = self.__calculate_shm_frame_count()
|
||||||
|
|
||||||
def __init_historical_regions(self) -> None:
|
def __init_historical_regions(self) -> None:
|
||||||
@ -151,7 +148,6 @@ class CameraMaintainer(threading.Thread):
|
|||||||
self.config.model,
|
self.config.model,
|
||||||
self.config.model.merged_labelmap,
|
self.config.model.merged_labelmap,
|
||||||
self.detection_queue,
|
self.detection_queue,
|
||||||
self.detection_out_events[name],
|
|
||||||
self.detected_frames_queue,
|
self.detected_frames_queue,
|
||||||
self.camera_metrics[name],
|
self.camera_metrics[name],
|
||||||
self.ptz_metrics[name],
|
self.ptz_metrics[name],
|
||||||
@ -234,6 +230,5 @@ class CameraMaintainer(threading.Thread):
|
|||||||
for camera in self.camera_metrics.keys():
|
for camera in self.camera_metrics.keys():
|
||||||
self.__stop_camera_process(camera)
|
self.__stop_camera_process(camera)
|
||||||
|
|
||||||
self.detector_camera_publisher.stop()
|
|
||||||
self.update_subscriber.stop()
|
self.update_subscriber.stop()
|
||||||
self.frame_manager.cleanup()
|
self.frame_manager.cleanup()
|
||||||
|
|||||||
21
frigate/comms/object_detector_signaler.py
Normal file
21
frigate/comms/object_detector_signaler.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
"""Facilitates communication between processes for object detection signals."""
|
||||||
|
|
||||||
|
from .zmq_proxy import Publisher, Subscriber
|
||||||
|
|
||||||
|
|
||||||
|
class ObjectDetectorPublisher(Publisher):
|
||||||
|
"""Publishes signal for object detection to different processes."""
|
||||||
|
|
||||||
|
topic_base = "object_detector/"
|
||||||
|
|
||||||
|
|
||||||
|
class ObjectDetectorSubscriber(Subscriber):
|
||||||
|
"""Simplifies receiving a signal for object detection."""
|
||||||
|
|
||||||
|
topic_base = "object_detector/"
|
||||||
|
|
||||||
|
def __init__(self, topic: str) -> None:
|
||||||
|
super().__init__(topic)
|
||||||
|
|
||||||
|
def check_for_update(self):
|
||||||
|
return super().check_for_update(timeout=5)
|
||||||
@ -13,6 +13,10 @@ import numpy as np
|
|||||||
from setproctitle import setproctitle
|
from setproctitle import setproctitle
|
||||||
|
|
||||||
import frigate.util as util
|
import frigate.util as util
|
||||||
|
from frigate.comms.object_detector_signaler import (
|
||||||
|
ObjectDetectorPublisher,
|
||||||
|
ObjectDetectorSubscriber,
|
||||||
|
)
|
||||||
from frigate.detectors import create_detector
|
from frigate.detectors import create_detector
|
||||||
from frigate.detectors.detector_config import (
|
from frigate.detectors.detector_config import (
|
||||||
BaseDetectorConfig,
|
BaseDetectorConfig,
|
||||||
@ -89,7 +93,7 @@ class LocalObjectDetector(ObjectDetector):
|
|||||||
def run_detector(
|
def run_detector(
|
||||||
name: str,
|
name: str,
|
||||||
detection_queue: Queue,
|
detection_queue: Queue,
|
||||||
out_events: dict[str, MpEvent],
|
cameras: list[str],
|
||||||
avg_speed: Value,
|
avg_speed: Value,
|
||||||
start: Value,
|
start: Value,
|
||||||
detector_config: BaseDetectorConfig,
|
detector_config: BaseDetectorConfig,
|
||||||
@ -110,9 +114,10 @@ def run_detector(
|
|||||||
|
|
||||||
frame_manager = SharedMemoryFrameManager()
|
frame_manager = SharedMemoryFrameManager()
|
||||||
object_detector = LocalObjectDetector(detector_config=detector_config)
|
object_detector = LocalObjectDetector(detector_config=detector_config)
|
||||||
|
detector_publisher = ObjectDetectorPublisher()
|
||||||
|
|
||||||
outputs = {}
|
outputs = {}
|
||||||
for name in out_events.keys():
|
for name in cameras:
|
||||||
out_shm = UntrackedSharedMemory(name=f"out-{name}", create=False)
|
out_shm = UntrackedSharedMemory(name=f"out-{name}", create=False)
|
||||||
out_np = np.ndarray((20, 6), dtype=np.float32, buffer=out_shm.buf)
|
out_np = np.ndarray((20, 6), dtype=np.float32, buffer=out_shm.buf)
|
||||||
outputs[name] = {"shm": out_shm, "np": out_np}
|
outputs[name] = {"shm": out_shm, "np": out_np}
|
||||||
@ -137,11 +142,12 @@ def run_detector(
|
|||||||
duration = datetime.datetime.now().timestamp() - start.value
|
duration = datetime.datetime.now().timestamp() - start.value
|
||||||
frame_manager.close(connection_id)
|
frame_manager.close(connection_id)
|
||||||
outputs[connection_id]["np"][:] = detections[:]
|
outputs[connection_id]["np"][:] = detections[:]
|
||||||
out_events[connection_id].set()
|
detector_publisher.publish(connection_id, connection_id)
|
||||||
start.value = 0.0
|
start.value = 0.0
|
||||||
|
|
||||||
avg_speed.value = (avg_speed.value * 9 + duration) / 10
|
avg_speed.value = (avg_speed.value * 9 + duration) / 10
|
||||||
|
|
||||||
|
detector_publisher.stop()
|
||||||
logger.info("Exited detection process...")
|
logger.info("Exited detection process...")
|
||||||
|
|
||||||
|
|
||||||
@ -150,11 +156,11 @@ class ObjectDetectProcess:
|
|||||||
self,
|
self,
|
||||||
name: str,
|
name: str,
|
||||||
detection_queue: Queue,
|
detection_queue: Queue,
|
||||||
out_events: dict[str, MpEvent],
|
cameras: list[str],
|
||||||
detector_config: BaseDetectorConfig,
|
detector_config: BaseDetectorConfig,
|
||||||
):
|
):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.out_events = out_events
|
self.cameras = cameras
|
||||||
self.detection_queue = detection_queue
|
self.detection_queue = detection_queue
|
||||||
self.avg_inference_speed = Value("d", 0.01)
|
self.avg_inference_speed = Value("d", 0.01)
|
||||||
self.detection_start = Value("d", 0.0)
|
self.detection_start = Value("d", 0.0)
|
||||||
@ -176,7 +182,6 @@ class ObjectDetectProcess:
|
|||||||
logging.info("Detection process has exited...")
|
logging.info("Detection process has exited...")
|
||||||
|
|
||||||
def start_or_restart(self):
|
def start_or_restart(self):
|
||||||
# TODO have to create a separate ZMQ listener for the MP.Events to be sent here
|
|
||||||
self.detection_start.value = 0.0
|
self.detection_start.value = 0.0
|
||||||
if (self.detect_process is not None) and self.detect_process.is_alive():
|
if (self.detect_process is not None) and self.detect_process.is_alive():
|
||||||
self.stop()
|
self.stop()
|
||||||
@ -186,7 +191,7 @@ class ObjectDetectProcess:
|
|||||||
args=(
|
args=(
|
||||||
self.name,
|
self.name,
|
||||||
self.detection_queue,
|
self.detection_queue,
|
||||||
self.out_events,
|
self.cameras,
|
||||||
self.avg_inference_speed,
|
self.avg_inference_speed,
|
||||||
self.detection_start,
|
self.detection_start,
|
||||||
self.detector_config,
|
self.detector_config,
|
||||||
@ -202,7 +207,6 @@ class RemoteObjectDetector:
|
|||||||
name: str,
|
name: str,
|
||||||
labels: dict[int, str],
|
labels: dict[int, str],
|
||||||
detection_queue: Queue,
|
detection_queue: Queue,
|
||||||
event: MpEvent,
|
|
||||||
model_config: ModelConfig,
|
model_config: ModelConfig,
|
||||||
stop_event: MpEvent,
|
stop_event: MpEvent,
|
||||||
):
|
):
|
||||||
@ -210,7 +214,6 @@ class RemoteObjectDetector:
|
|||||||
self.name = name
|
self.name = name
|
||||||
self.fps = EventsPerSecond()
|
self.fps = EventsPerSecond()
|
||||||
self.detection_queue = detection_queue
|
self.detection_queue = detection_queue
|
||||||
self.event = event
|
|
||||||
self.stop_event = stop_event
|
self.stop_event = stop_event
|
||||||
self.shm = UntrackedSharedMemory(name=self.name, create=False)
|
self.shm = UntrackedSharedMemory(name=self.name, create=False)
|
||||||
self.np_shm = np.ndarray(
|
self.np_shm = np.ndarray(
|
||||||
@ -220,6 +223,7 @@ class RemoteObjectDetector:
|
|||||||
)
|
)
|
||||||
self.out_shm = UntrackedSharedMemory(name=f"out-{self.name}", create=False)
|
self.out_shm = UntrackedSharedMemory(name=f"out-{self.name}", create=False)
|
||||||
self.out_np_shm = np.ndarray((20, 6), dtype=np.float32, buffer=self.out_shm.buf)
|
self.out_np_shm = np.ndarray((20, 6), dtype=np.float32, buffer=self.out_shm.buf)
|
||||||
|
self.detector_subscriber = ObjectDetectorSubscriber(name)
|
||||||
|
|
||||||
def detect(self, tensor_input, threshold=0.4):
|
def detect(self, tensor_input, threshold=0.4):
|
||||||
detections = []
|
detections = []
|
||||||
@ -229,9 +233,8 @@ class RemoteObjectDetector:
|
|||||||
|
|
||||||
# copy input to shared memory
|
# copy input to shared memory
|
||||||
self.np_shm[:] = tensor_input[:]
|
self.np_shm[:] = tensor_input[:]
|
||||||
self.event.clear()
|
|
||||||
self.detection_queue.put(self.name)
|
self.detection_queue.put(self.name)
|
||||||
result = self.event.wait(timeout=5.0)
|
result = self.detector_subscriber.check_for_update()
|
||||||
|
|
||||||
# if it timed out
|
# if it timed out
|
||||||
if result is None:
|
if result is None:
|
||||||
@ -247,5 +250,6 @@ class RemoteObjectDetector:
|
|||||||
return detections
|
return detections
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
|
self.detector_subscriber.stop()
|
||||||
self.shm.unlink()
|
self.shm.unlink()
|
||||||
self.out_shm.unlink()
|
self.out_shm.unlink()
|
||||||
|
|||||||
@ -473,7 +473,6 @@ def track_camera(
|
|||||||
model_config: ModelConfig,
|
model_config: ModelConfig,
|
||||||
labelmap: dict[int, str],
|
labelmap: dict[int, str],
|
||||||
detection_queue: Queue,
|
detection_queue: Queue,
|
||||||
result_connection: MpEvent,
|
|
||||||
detected_objects_queue,
|
detected_objects_queue,
|
||||||
camera_metrics: CameraMetrics,
|
camera_metrics: CameraMetrics,
|
||||||
ptz_metrics: PTZMetrics,
|
ptz_metrics: PTZMetrics,
|
||||||
@ -503,7 +502,7 @@ def track_camera(
|
|||||||
ptz_metrics=ptz_metrics,
|
ptz_metrics=ptz_metrics,
|
||||||
)
|
)
|
||||||
object_detector = RemoteObjectDetector(
|
object_detector = RemoteObjectDetector(
|
||||||
name, labelmap, detection_queue, result_connection, model_config, stop_event
|
name, labelmap, detection_queue, model_config, stop_event
|
||||||
)
|
)
|
||||||
|
|
||||||
object_tracker = NorfairTracker(config, ptz_metrics)
|
object_tracker = NorfairTracker(config, ptz_metrics)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user