From c31cf16611e671ed83cf0b06a67dcc258b4ba4b2 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Fri, 28 Mar 2025 15:59:14 -0600 Subject: [PATCH] Add lpr fps --- .../common/license_plate/mixin.py | 17 +++++++++++++---- frigate/data_processing/real_time/face.py | 2 +- frigate/data_processing/types.py | 4 ++++ frigate/stats/util.py | 10 ++++++++-- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/frigate/data_processing/common/license_plate/mixin.py b/frigate/data_processing/common/license_plate/mixin.py index 84e432891..b59bbe19d 100644 --- a/frigate/data_processing/common/license_plate/mixin.py +++ b/frigate/data_processing/common/license_plate/mixin.py @@ -24,6 +24,7 @@ from frigate.comms.event_metadata_updater import ( from frigate.config.camera.camera import CameraTypeEnum from frigate.const import CLIPS_DIR from frigate.embeddings.onnx.lpr_embedding import LPR_EMBEDDING_SIZE +from frigate.util.builtin import EventsPerSecond from frigate.util.image import area logger = logging.getLogger(__name__) @@ -34,11 +35,12 @@ WRITE_DEBUG_IMAGES = False class LicensePlateProcessingMixin: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - + self.plates_rec_second = EventsPerSecond() + self.plates_rec_second.start() + self.plates_det_second = EventsPerSecond() + self.plates_det_second.start() self.event_metadata_publisher = EventMetadataPublisher() - self.ctc_decoder = CTCDecoder() - self.batch_size = 6 # Detection specific parameters @@ -955,7 +957,9 @@ class LicensePlateProcessingMixin: """ Update inference metrics. """ - self.metrics.alpr_speed.value = (self.metrics.alpr_speed.value * 9 + duration) / 10 + self.metrics.alpr_speed.value = ( + self.metrics.alpr_speed.value * 9 + duration + ) / 10 def _generate_plate_event(self, camera: str, plate: str, plate_score: float) -> str: """Generate a unique ID for a plate event based on camera and text.""" @@ -982,6 +986,8 @@ class LicensePlateProcessingMixin: self, obj_data: dict[str, any], frame: np.ndarray, dedicated_lpr: bool = False ): """Look for license plates in image.""" + self.metrics.alpr_pps.value = self.plates_rec_second.eps() + self.metrics.yolov9_pps.value = self.plates_det_second.eps() camera = obj_data if dedicated_lpr else obj_data["camera"] current_time = int(datetime.datetime.now().timestamp()) @@ -1011,6 +1017,7 @@ class LicensePlateProcessingMixin: logger.debug( f"{camera}: YOLOv9 LPD inference time: {(datetime.datetime.now().timestamp() - yolov9_start) * 1000:.2f} ms" ) + self.plates_det_second.update() self.__update_yolov9_metrics( datetime.datetime.now().timestamp() - yolov9_start ) @@ -1093,6 +1100,7 @@ class LicensePlateProcessingMixin: logger.debug( f"{camera}: YOLOv9 LPD inference time: {(datetime.datetime.now().timestamp() - yolov9_start) * 1000:.2f} ms" ) + self.plates_det_second.update() self.__update_yolov9_metrics( datetime.datetime.now().timestamp() - yolov9_start ) @@ -1197,6 +1205,7 @@ class LicensePlateProcessingMixin: license_plates, confidences, areas = self._process_license_plate( camera, id, license_plate_frame ) + self.plates_rec_second.update() self.__update_lpr_metrics(datetime.datetime.now().timestamp() - start) if license_plates: diff --git a/frigate/data_processing/real_time/face.py b/frigate/data_processing/real_time/face.py index 7fdad04be..5b20a6303 100644 --- a/frigate/data_processing/real_time/face.py +++ b/frigate/data_processing/real_time/face.py @@ -149,6 +149,7 @@ class FaceRealTimeProcessor(RealTimeProcessorApi): return face def __update_metrics(self, duration: float) -> None: + self.faces_per_second.update() self.metrics.face_rec_speed.value = ( self.metrics.face_rec_speed.value * 9 + duration ) / 10 @@ -256,7 +257,6 @@ class FaceRealTimeProcessor(RealTimeProcessorApi): max(0, face_box[0]) : min(frame.shape[1], face_box[2]), ] - self.faces_per_second.update() res = self.recognizer.classify(face_frame) if not res: diff --git a/frigate/data_processing/types.py b/frigate/data_processing/types.py index 9fd2e72ea..2f9c99b52 100644 --- a/frigate/data_processing/types.py +++ b/frigate/data_processing/types.py @@ -11,7 +11,9 @@ class DataProcessorMetrics: face_rec_speed: Synchronized face_rec_fps: Synchronized alpr_speed: Synchronized + alpr_pps: Synchronized yolov9_lpr_speed: Synchronized + yolov9_lpr_pps: Synchronized def __init__(self): self.image_embeddings_speed = mp.Value("d", 0.01) @@ -19,7 +21,9 @@ class DataProcessorMetrics: self.face_rec_speed = mp.Value("d", 0.01) self.face_rec_fps = mp.Value("d", 0.0) self.alpr_speed = mp.Value("d", 0.01) + self.alpr_pps = mp.Value("d", 0.0) self.yolov9_lpr_speed = mp.Value("d", 0.01) + self.yolov9_pps = mp.Value("d", 0.0) class DataProcessorModelRunner: diff --git a/frigate/stats/util.py b/frigate/stats/util.py index 72c84f0c0..cb7ed75fd 100644 --- a/frigate/stats/util.py +++ b/frigate/stats/util.py @@ -305,19 +305,25 @@ def stats_snapshot( stats["embeddings"]["face_recognition_speed"] = round( embeddings_metrics.face_rec_speed.value * 1000, 2 ) - stats["embeddings"]["face_recognition_fps"] = round( - embeddings_metrics.face_rec_speed.value, 2 + stats["embeddings"]["face_recognition"] = round( + embeddings_metrics.face_rec_fps.value, 2 ) if config.lpr.enabled: stats["embeddings"]["plate_recognition_speed"] = round( embeddings_metrics.alpr_speed.value * 1000, 2 ) + stats["embeddings"]["plate_recognition"] = round( + embeddings_metrics.alpr_pps.value, 2 + ) if "license_plate" not in config.objects.all_objects: stats["embeddings"]["yolov9_plate_detection_speed"] = round( embeddings_metrics.yolov9_lpr_speed.value * 1000, 2 ) + stats["embeddings"]["yolov9_plate_detection"] = round( + embeddings_metrics.yolov9_lpr_pps.value, 2 + ) get_processing_stats(config, stats, hwaccel_errors)