mirror of
				https://github.com/blakeblackshear/frigate.git
				synced 2025-10-27 10:52:11 +01:00 
			
		
		
		
	Fix lpr metrics and add yolov9 plate detection metric (#16827)
This commit is contained in:
		
							parent
							
								
									7eb3c87fa0
								
							
						
					
					
						commit
						447f26e1b9
					
				@ -816,6 +816,20 @@ class LicensePlateProcessingMixin:
 | 
			
		||||
        # 5. Return True if we should keep the previous plate (i.e., if it scores higher)
 | 
			
		||||
        return prev_score > curr_score
 | 
			
		||||
 | 
			
		||||
    def __update_yolov9_metrics(self, duration: float) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Update inference metrics.
 | 
			
		||||
        """
 | 
			
		||||
        self.metrics.yolov9_lpr_fps.value = (
 | 
			
		||||
            self.metrics.yolov9_lpr_fps.value * 9 + duration
 | 
			
		||||
        ) / 10
 | 
			
		||||
 | 
			
		||||
    def __update_lpr_metrics(self, duration: float) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Update inference metrics.
 | 
			
		||||
        """
 | 
			
		||||
        self.metrics.alpr_pps.value = (self.metrics.alpr_pps.value * 9 + duration) / 10
 | 
			
		||||
 | 
			
		||||
    def lpr_process(self, obj_data: dict[str, any], frame: np.ndarray):
 | 
			
		||||
        """Look for license plates in image."""
 | 
			
		||||
 | 
			
		||||
@ -843,6 +857,7 @@ class LicensePlateProcessingMixin:
 | 
			
		||||
 | 
			
		||||
        if self.requires_license_plate_detection:
 | 
			
		||||
            logger.debug("Running manual license_plate detection.")
 | 
			
		||||
 | 
			
		||||
            car_box = obj_data.get("box")
 | 
			
		||||
 | 
			
		||||
            if not car_box:
 | 
			
		||||
@ -867,6 +882,9 @@ class LicensePlateProcessingMixin:
 | 
			
		||||
            logger.debug(
 | 
			
		||||
                f"YOLOv9 LPD inference time: {(datetime.datetime.now().timestamp() - yolov9_start) * 1000:.2f} ms"
 | 
			
		||||
            )
 | 
			
		||||
            self.__update_yolov9_metrics(
 | 
			
		||||
                datetime.datetime.now().timestamp() - yolov9_start
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            if not license_plate:
 | 
			
		||||
                logger.debug("Detected no license plates for car object.")
 | 
			
		||||
@ -945,11 +963,15 @@ class LicensePlateProcessingMixin:
 | 
			
		||||
                license_plate_frame,
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        start = datetime.datetime.now().timestamp()
 | 
			
		||||
 | 
			
		||||
        # run detection, returns results sorted by confidence, best first
 | 
			
		||||
        license_plates, confidences, areas = self._process_license_plate(
 | 
			
		||||
            license_plate_frame
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        self.__update_lpr_metrics(datetime.datetime.now().timestamp() - start)
 | 
			
		||||
 | 
			
		||||
        logger.debug(f"Text boxes: {license_plates}")
 | 
			
		||||
        logger.debug(f"Confidences: {confidences}")
 | 
			
		||||
        logger.debug(f"Areas: {areas}")
 | 
			
		||||
 | 
			
		||||
@ -40,12 +40,6 @@ class LicensePlatePostProcessor(LicensePlateProcessingMixin, PostProcessorApi):
 | 
			
		||||
        self.config = config
 | 
			
		||||
        super().__init__(config, metrics, model_runner)
 | 
			
		||||
 | 
			
		||||
    def __update_metrics(self, duration: float) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Update inference metrics.
 | 
			
		||||
        """
 | 
			
		||||
        self.metrics.alpr_pps.value = (self.metrics.alpr_pps.value * 9 + duration) / 10
 | 
			
		||||
 | 
			
		||||
    def process_data(
 | 
			
		||||
        self, data: dict[str, any], data_type: PostProcessDataEnum
 | 
			
		||||
    ) -> None:
 | 
			
		||||
@ -57,8 +51,6 @@ class LicensePlatePostProcessor(LicensePlateProcessingMixin, PostProcessorApi):
 | 
			
		||||
        Returns:
 | 
			
		||||
            None.
 | 
			
		||||
        """
 | 
			
		||||
        start = datetime.datetime.now().timestamp()
 | 
			
		||||
 | 
			
		||||
        event_id = data["event_id"]
 | 
			
		||||
        camera_name = data["camera"]
 | 
			
		||||
 | 
			
		||||
@ -128,7 +120,10 @@ class LicensePlatePostProcessor(LicensePlateProcessingMixin, PostProcessorApi):
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        if WRITE_DEBUG_IMAGES:
 | 
			
		||||
            cv2.imwrite(f"debug/frames/lpr_post_{start}.jpg", image)
 | 
			
		||||
            cv2.imwrite(
 | 
			
		||||
                f"debug/frames/lpr_post_{datetime.datetime.now().timestamp()}.jpg",
 | 
			
		||||
                image,
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        # convert to yuv for processing
 | 
			
		||||
        frame = cv2.cvtColor(image, cv2.COLOR_BGR2YUV_I420)
 | 
			
		||||
@ -210,8 +205,6 @@ class LicensePlatePostProcessor(LicensePlateProcessingMixin, PostProcessorApi):
 | 
			
		||||
        logger.debug(f"Post processing plate: {event_id}, {frame_time}")
 | 
			
		||||
        self.lpr_process(keyframe_obj_data, frame)
 | 
			
		||||
 | 
			
		||||
        self.__update_metrics(datetime.datetime.now().timestamp() - start)
 | 
			
		||||
 | 
			
		||||
    def handle_request(self, topic, request_data) -> dict[str, any] | None:
 | 
			
		||||
        if topic == EmbeddingsRequestEnum.reprocess_plate.value:
 | 
			
		||||
            event = request_data["event"]
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,5 @@
 | 
			
		||||
"""Handle processing images for face detection and recognition."""
 | 
			
		||||
 | 
			
		||||
import datetime
 | 
			
		||||
import logging
 | 
			
		||||
 | 
			
		||||
import numpy as np
 | 
			
		||||
@ -33,17 +32,9 @@ class LicensePlateRealTimeProcessor(LicensePlateProcessingMixin, RealTimeProcess
 | 
			
		||||
        self.config = config
 | 
			
		||||
        super().__init__(config, metrics)
 | 
			
		||||
 | 
			
		||||
    def __update_metrics(self, duration: float) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Update inference metrics.
 | 
			
		||||
        """
 | 
			
		||||
        self.metrics.alpr_pps.value = (self.metrics.alpr_pps.value * 9 + duration) / 10
 | 
			
		||||
 | 
			
		||||
    def process_frame(self, obj_data: dict[str, any], frame: np.ndarray):
 | 
			
		||||
        """Look for license plates in image."""
 | 
			
		||||
        start = datetime.datetime.now().timestamp()
 | 
			
		||||
        self.lpr_process(obj_data, frame)
 | 
			
		||||
        self.__update_metrics(datetime.datetime.now().timestamp() - start)
 | 
			
		||||
 | 
			
		||||
    def handle_request(self, topic, request_data) -> dict[str, any] | None:
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
@ -10,12 +10,14 @@ class DataProcessorMetrics:
 | 
			
		||||
    text_embeddings_sps: Synchronized
 | 
			
		||||
    face_rec_fps: Synchronized
 | 
			
		||||
    alpr_pps: Synchronized
 | 
			
		||||
    yolov9_lpr_fps: Synchronized
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.image_embeddings_fps = mp.Value("d", 0.01)
 | 
			
		||||
        self.text_embeddings_sps = mp.Value("d", 0.01)
 | 
			
		||||
        self.face_rec_fps = mp.Value("d", 0.01)
 | 
			
		||||
        self.alpr_pps = mp.Value("d", 0.01)
 | 
			
		||||
        self.yolov9_lpr_fps = mp.Value("d", 0.01)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DataProcessorModelRunner:
 | 
			
		||||
 | 
			
		||||
@ -302,6 +302,10 @@ def stats_snapshot(
 | 
			
		||||
            stats["embeddings"]["plate_recognition_speed"] = round(
 | 
			
		||||
                embeddings_metrics.alpr_pps.value * 1000, 2
 | 
			
		||||
            )
 | 
			
		||||
            if "license_plate" not in config.objects.all_objects:
 | 
			
		||||
                stats["embeddings"]["yolov9_plate_detection_speed"] = round(
 | 
			
		||||
                    embeddings_metrics.yolov9_lpr_fps.value * 1000, 2
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
    get_processing_stats(config, stats, hwaccel_errors)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user