2025-02-21 07:51:37 -06:00
|
|
|
"""Handle processing images for face detection and recognition."""
|
|
|
|
|
|
|
|
|
|
import logging
|
2025-05-13 16:27:20 +02:00
|
|
|
from typing import Any
|
2025-02-21 07:51:37 -06:00
|
|
|
|
|
|
|
|
import numpy as np
|
|
|
|
|
|
2025-03-10 16:29:29 -06:00
|
|
|
from frigate.comms.event_metadata_updater import EventMetadataPublisher
|
2025-04-28 16:43:03 -06:00
|
|
|
from frigate.comms.inter_process import InterProcessRequestor
|
2025-02-21 07:51:37 -06:00
|
|
|
from frigate.config import FrigateConfig
|
|
|
|
|
from frigate.data_processing.common.license_plate.mixin import (
|
|
|
|
|
LicensePlateProcessingMixin,
|
|
|
|
|
)
|
|
|
|
|
from frigate.data_processing.common.license_plate.model import (
|
|
|
|
|
LicensePlateModelRunner,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
from ..types import DataProcessorMetrics
|
|
|
|
|
from .api import RealTimeProcessorApi
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class LicensePlateRealTimeProcessor(LicensePlateProcessingMixin, RealTimeProcessorApi):
|
|
|
|
|
def __init__(
|
|
|
|
|
self,
|
|
|
|
|
config: FrigateConfig,
|
2025-04-28 16:43:03 -06:00
|
|
|
requestor: InterProcessRequestor,
|
2025-03-10 16:29:29 -06:00
|
|
|
sub_label_publisher: EventMetadataPublisher,
|
2025-02-21 07:51:37 -06:00
|
|
|
metrics: DataProcessorMetrics,
|
|
|
|
|
model_runner: LicensePlateModelRunner,
|
2025-05-13 16:27:20 +02:00
|
|
|
detected_license_plates: dict[str, dict[str, Any]],
|
2025-02-21 07:51:37 -06:00
|
|
|
):
|
2025-04-28 16:43:03 -06:00
|
|
|
self.requestor = requestor
|
2025-02-21 07:51:37 -06:00
|
|
|
self.detected_license_plates = detected_license_plates
|
|
|
|
|
self.model_runner = model_runner
|
|
|
|
|
self.lpr_config = config.lpr
|
|
|
|
|
self.config = config
|
2025-03-10 16:29:29 -06:00
|
|
|
self.sub_label_publisher = sub_label_publisher
|
2025-05-11 13:03:53 -05:00
|
|
|
self.camera_current_cars: dict[str, list[str]] = {}
|
2025-02-21 14:26:03 -06:00
|
|
|
super().__init__(config, metrics)
|
2025-02-21 07:51:37 -06:00
|
|
|
|
2026-03-08 15:14:18 -05:00
|
|
|
CONFIG_UPDATE_TOPIC = "config/lpr"
|
|
|
|
|
|
|
|
|
|
def update_config(self, topic: str, payload: Any) -> None:
|
2026-03-06 14:45:39 -06:00
|
|
|
"""Update LPR config at runtime."""
|
2026-03-08 15:14:18 -05:00
|
|
|
if topic != self.CONFIG_UPDATE_TOPIC:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
previous_min_area = self.config.lpr.min_area
|
|
|
|
|
self.config.lpr = payload
|
|
|
|
|
self.lpr_config = payload
|
|
|
|
|
|
|
|
|
|
for camera_config in self.config.cameras.values():
|
|
|
|
|
if camera_config.lpr.min_area == previous_min_area:
|
|
|
|
|
camera_config.lpr.min_area = payload.min_area
|
|
|
|
|
|
2026-03-06 14:45:39 -06:00
|
|
|
logger.debug("LPR config updated dynamically")
|
|
|
|
|
|
2025-03-23 14:30:48 -05:00
|
|
|
def process_frame(
|
|
|
|
|
self,
|
2025-05-13 16:27:20 +02:00
|
|
|
obj_data: dict[str, Any],
|
2025-03-23 14:30:48 -05:00
|
|
|
frame: np.ndarray,
|
2026-03-26 12:54:12 -06:00
|
|
|
dedicated_lpr: bool = False,
|
|
|
|
|
) -> None:
|
2025-02-21 07:51:37 -06:00
|
|
|
"""Look for license plates in image."""
|
2025-03-23 14:30:48 -05:00
|
|
|
self.lpr_process(obj_data, frame, dedicated_lpr)
|
2025-02-21 07:51:37 -06:00
|
|
|
|
2026-03-26 12:54:12 -06:00
|
|
|
def handle_request(
|
|
|
|
|
self, topic: str, request_data: dict[str, Any]
|
|
|
|
|
) -> dict[str, Any] | None:
|
|
|
|
|
return None
|
2025-02-21 07:51:37 -06:00
|
|
|
|
2026-03-26 12:54:12 -06:00
|
|
|
def expire_object(self, object_id: str, camera: str) -> None:
|
2025-05-15 16:13:18 -06:00
|
|
|
"""Expire lpr objects."""
|
|
|
|
|
self.lpr_expire(object_id, camera)
|