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