From 1233bc3a422b6b31f46e194d1fa1b67d3293ea54 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Thu, 27 Mar 2025 06:49:14 -0500 Subject: [PATCH] Miscellaneous fixes (#17406) * add config validator for face and lpr * more lpr docs tweaks * fix object lifecycle point clicking for aspect ratios less than 16/9 * fix semantic search indexing i18n keys * remove ability to set system language * clarify debug output --- .../license_plate_recognition.md | 20 ++++++++++++++---- frigate/config/config.py | 20 +++++++++++++++++- .../common/license_plate/mixin.py | 4 +++- web/src/components/menu/GeneralSettings.tsx | 21 +------------------ .../overlay/detail/ObjectLifecycle.tsx | 1 - web/src/pages/Explore.tsx | 12 ++++++++--- 6 files changed, 48 insertions(+), 30 deletions(-) diff --git a/docs/docs/configuration/license_plate_recognition.md b/docs/docs/configuration/license_plate_recognition.md index e4c8c1167..13d45310e 100644 --- a/docs/docs/configuration/license_plate_recognition.md +++ b/docs/docs/configuration/license_plate_recognition.md @@ -40,14 +40,14 @@ lpr: enabled: True ``` -You can also enable it for specific cameras only at the camera level: +Like other enrichments in Frigate, LPR **must be enabled globally** to use the feature. You can disable it for specific cameras at the camera level: ```yaml cameras: driveway: ... lpr: - enabled: True + enabled: False ``` For non-dedicated LPR cameras, ensure that your camera is configured to detect objects of type `car`, and that a car is actually being detected by Frigate. Otherwise, LPR will not run. @@ -195,12 +195,16 @@ When using `type: "lpr"` for a camera, a non-standard object detection pipeline Ensure that: -- Your camera has a clear, human-readable, well-lit view of the plate. If you can't read the plate, Frigate certainly won't be able to. This may require changing video size, quality, or frame rate settings on your camera, depending on your scene and how fast the vehicles are traveling. +- Your camera has a clear, human-readable, well-lit view of the plate. If you can't read the plate's characters, Frigate certainly won't be able to, even if the model is recognizing a `license_plate`. This may require changing video size, quality, or frame rate settings on your camera, depending on your scene and how fast the vehicles are traveling. - The plate is large enough in the image (try adjusting `min_area`) or increasing the resolution of your camera's stream. If you are using a Frigate+ model or a custom model that detects license plates, ensure that `license_plate` is added to your list of objects to track. If you are using the free model that ships with Frigate, you should _not_ add `license_plate` to the list of objects to track. +Recognized plates will show as object labels in the debug view and will appear in the "Recognized License Plates" select box in the More Filters popout in Explore. + +If you are still having issues detecting plates, start with a basic configuration and see the debugging tips below. + ### Can I run LPR without detecting `car` objects? In normal LPR mode, Frigate requires a `car` to be detected first before recognizing a license plate. If you have a dedicated LPR camera, you can change the camera `type` to `"lpr"` to use the Dedicated LPR Camera algorithm. This comes with important caveats, though. See the [Dedicated LPR Cameras](#dedicated-lpr-cameras) section above. @@ -222,10 +226,18 @@ Use `match_distance` to allow small character mismatches. Alternatively, define ### How do I debug LPR issues? - View MQTT messages for `frigate/events` to verify detected plates. -- Adjust `detection_threshold` and `recognition_threshold` settings. - If you are using a Frigate+ model or a model that detects license plates, watch the debug view (Settings --> Debug) to ensure that `license_plate` is being detected with a `car`. +- Watch the debug view to see plates recognized in real-time. For non-dedicated LPR cameras, the `car` label will change to the recognized plate when LPR is enabled and working. +- Adjust `detection_threshold` and `recognition_threshold` settings per the suggestions [above](#advanced-configuration). - Enable debug logs for LPR by adding `frigate.data_processing.common.license_plate: debug` to your `logger` configuration. These logs are _very_ verbose, so only enable this when necessary. + ```yaml + logger: + default: info + logs: + frigate.data_processing.common.license_plate: debug + ``` + ### Will LPR slow down my system? LPR runs on the CPU, so performance impact depends on your hardware. Ensure you have at least 4GB RAM and a capable CPU for optimal results. If you are running the Dedicated LPR Camera mode, resource usage will be higher compared to users who run a model that natively detects license plates. Tune your motion detection settings for your dedicated LPR camera so that the license plate detection model runs only when necessary. diff --git a/frigate/config/config.py b/frigate/config/config.py index c27cd365d..7c0b669c8 100644 --- a/frigate/config/config.py +++ b/frigate/config/config.py @@ -292,13 +292,30 @@ def verify_autotrack_zones(camera_config: CameraConfig) -> ValueError | None: def verify_motion_and_detect(camera_config: CameraConfig) -> ValueError | None: - """Verify that required_zones are specified when autotracking is enabled.""" + """Verify that motion detection is not disabled and object detection is enabled.""" if camera_config.detect.enabled and not camera_config.motion.enabled: raise ValueError( f"Camera {camera_config.name} has motion detection disabled and object detection enabled but object detection requires motion detection." ) +def verify_lpr_and_face( + frigate_config: FrigateConfig, camera_config: CameraConfig +) -> ValueError | None: + """Verify that lpr and face are enabled at the global level if enabled at the camera level.""" + if camera_config.lpr.enabled and not frigate_config.lpr.enabled: + raise ValueError( + f"Camera {camera_config.name} has lpr enabled but lpr is disabled at the global level of the config. You must enable lpr at the global level." + ) + if ( + camera_config.face_recognition.enabled + and not frigate_config.face_recognition.enabled + ): + raise ValueError( + f"Camera {camera_config.name} has face_recognition enabled but face_recognition is disabled at the global level of the config. You must enable face_recognition at the global level." + ) + + class FrigateConfig(FrigateBaseModel): version: Optional[str] = Field(default=None, title="Current config version.") @@ -607,6 +624,7 @@ class FrigateConfig(FrigateBaseModel): verify_required_zones_exist(camera_config) verify_autotrack_zones(camera_config) verify_motion_and_detect(camera_config) + verify_lpr_and_face(self, camera_config) self.objects.parse_all_objects(self.cameras) self.model.create_colormap(sorted(self.objects.all_objects)) diff --git a/frigate/data_processing/common/license_plate/mixin.py b/frigate/data_processing/common/license_plate/mixin.py index 9cc988267..48c191876 100644 --- a/frigate/data_processing/common/license_plate/mixin.py +++ b/frigate/data_processing/common/license_plate/mixin.py @@ -814,7 +814,9 @@ class LicensePlateProcessingMixin: ] ).clip(0, [input.shape[1], input.shape[0]] * 2) - logger.debug(f"Found license plate: {expanded_box.astype(int)}") + logger.debug( + f"Found license plate. Bounding box: {expanded_box.astype(int)}" + ) return tuple(expanded_box.astype(int)) else: return None # No detection above the threshold diff --git a/web/src/components/menu/GeneralSettings.tsx b/web/src/components/menu/GeneralSettings.tsx index eac5f6384..f844b74ef 100644 --- a/web/src/components/menu/GeneralSettings.tsx +++ b/web/src/components/menu/GeneralSettings.tsx @@ -12,7 +12,6 @@ import { LuSettings, LuSun, LuSunMoon, - LuEarth, } from "react-icons/lu"; import { DropdownMenu, @@ -76,7 +75,7 @@ export default function GeneralSettings({ className }: GeneralSettingsProps) { // settings - const { language, setLanguage, systemLanguage } = useLanguage(); + const { language, setLanguage } = useLanguage(); const { theme, colorScheme, setTheme, setColorScheme } = useTheme(); const [restartDialogOpen, setRestartDialogOpen] = useState(false); const [passwordDialogOpen, setPasswordDialogOpen] = useState(false); @@ -352,24 +351,6 @@ export default function GeneralSettings({ className }: GeneralSettingsProps) { )} - diff --git a/web/src/components/overlay/detail/ObjectLifecycle.tsx b/web/src/components/overlay/detail/ObjectLifecycle.tsx index 0f77ecfbf..6dca83362 100644 --- a/web/src/components/overlay/detail/ObjectLifecycle.tsx +++ b/web/src/components/overlay/detail/ObjectLifecycle.tsx @@ -365,7 +365,6 @@ export default function ObjectLifecycle({