mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-26 19:06:11 +01:00
Use regular expressions for plate matching (#14727)
This commit is contained in:
parent
6d6a07ff2c
commit
9d5d8ddbb2
@ -26,7 +26,7 @@ lpr:
|
|||||||
|
|
||||||
Several options are available to fine-tune the LPR feature. For example, you can adjust the `min_area` setting, which defines the minimum size in pixels a license plate must be before LPR runs. The default is 500 pixels.
|
Several options are available to fine-tune the LPR feature. For example, you can adjust the `min_area` setting, which defines the minimum size in pixels a license plate must be before LPR runs. The default is 500 pixels.
|
||||||
|
|
||||||
Additionally, you can define `known_plates`, allowing Frigate to label tracked vehicles with custom sub_labels when a recognized plate is detected. This information is then accessible in the UI, filters, and notifications.
|
Additionally, you can define `known_plates` as strings or regular expressions, allowing Frigate to label tracked vehicles with custom sub_labels when a recognized plate is detected. This information is then accessible in the UI, filters, and notifications.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
lpr:
|
lpr:
|
||||||
@ -37,12 +37,9 @@ lpr:
|
|||||||
- "ABC-1234"
|
- "ABC-1234"
|
||||||
- "ABC-I234"
|
- "ABC-I234"
|
||||||
Johnny:
|
Johnny:
|
||||||
- "JHN-1234"
|
- "J*N-*234" # Using wildcards for H/M and 1/I
|
||||||
- "JMN-1234"
|
|
||||||
- "JHN-I234"
|
|
||||||
Sally:
|
Sally:
|
||||||
- "SLL-1234"
|
- "[S5]LL-1234" # Matches SLL-1234 and 5LL-1234
|
||||||
- "5LL-1234"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
In this example, "Wife's Car" will appear as the label for any vehicle matching the plate "ABC-1234." The model might occasionally interpret the digit 1 as a capital I (e.g., "ABC-I234"), so both variations are listed. Similarly, multiple possible variations are specified for Johnny and Sally.
|
In this example, "Wife's Car" will appear as the label for any vehicle matching the plate "ABC-1234." The model might occasionally interpret the digit 1 as a capital I (e.g., "ABC-I234"), so both variations are listed. Similarly, multiple possible variations are specified for Johnny and Sally.
|
||||||
|
@ -154,7 +154,7 @@ class Embeddings:
|
|||||||
"detection.onnx": "https://github.com/hawkeye217/paddleocr-onnx/raw/refs/heads/master/models/detection.onnx"
|
"detection.onnx": "https://github.com/hawkeye217/paddleocr-onnx/raw/refs/heads/master/models/detection.onnx"
|
||||||
},
|
},
|
||||||
model_size="large",
|
model_size="large",
|
||||||
model_type=ModelTypeEnum.alpr_detect,
|
model_type=ModelTypeEnum.lpr_detect,
|
||||||
requestor=self.requestor,
|
requestor=self.requestor,
|
||||||
device="CPU",
|
device="CPU",
|
||||||
)
|
)
|
||||||
@ -166,7 +166,7 @@ class Embeddings:
|
|||||||
"classification.onnx": "https://github.com/hawkeye217/paddleocr-onnx/raw/refs/heads/master/models/classification.onnx"
|
"classification.onnx": "https://github.com/hawkeye217/paddleocr-onnx/raw/refs/heads/master/models/classification.onnx"
|
||||||
},
|
},
|
||||||
model_size="large",
|
model_size="large",
|
||||||
model_type=ModelTypeEnum.alpr_classify,
|
model_type=ModelTypeEnum.lpr_classify,
|
||||||
requestor=self.requestor,
|
requestor=self.requestor,
|
||||||
device="CPU",
|
device="CPU",
|
||||||
)
|
)
|
||||||
@ -178,7 +178,7 @@ class Embeddings:
|
|||||||
"recognition.onnx": "https://github.com/hawkeye217/paddleocr-onnx/raw/refs/heads/master/models/recognition.onnx"
|
"recognition.onnx": "https://github.com/hawkeye217/paddleocr-onnx/raw/refs/heads/master/models/recognition.onnx"
|
||||||
},
|
},
|
||||||
model_size="large",
|
model_size="large",
|
||||||
model_type=ModelTypeEnum.alpr_recognize,
|
model_type=ModelTypeEnum.lpr_recognize,
|
||||||
requestor=self.requestor,
|
requestor=self.requestor,
|
||||||
device="CPU",
|
device="CPU",
|
||||||
)
|
)
|
||||||
|
@ -38,9 +38,9 @@ class ModelTypeEnum(str, Enum):
|
|||||||
face = "face"
|
face = "face"
|
||||||
vision = "vision"
|
vision = "vision"
|
||||||
text = "text"
|
text = "text"
|
||||||
alpr_detect = "alpr_detect"
|
lpr_detect = "lpr_detect"
|
||||||
alpr_classify = "alpr_classify"
|
lpr_classify = "lpr_classify"
|
||||||
alpr_recognize = "alpr_recognize"
|
lpr_recognize = "lpr_recognize"
|
||||||
|
|
||||||
|
|
||||||
class GenericONNXEmbedding:
|
class GenericONNXEmbedding:
|
||||||
@ -142,11 +142,11 @@ class GenericONNXEmbedding:
|
|||||||
self.feature_extractor = self._load_feature_extractor()
|
self.feature_extractor = self._load_feature_extractor()
|
||||||
elif self.model_type == ModelTypeEnum.face:
|
elif self.model_type == ModelTypeEnum.face:
|
||||||
self.feature_extractor = []
|
self.feature_extractor = []
|
||||||
elif self.model_type == ModelTypeEnum.alpr_detect:
|
elif self.model_type == ModelTypeEnum.lpr_detect:
|
||||||
self.feature_extractor = []
|
self.feature_extractor = []
|
||||||
elif self.model_type == ModelTypeEnum.alpr_classify:
|
elif self.model_type == ModelTypeEnum.lpr_classify:
|
||||||
self.feature_extractor = []
|
self.feature_extractor = []
|
||||||
elif self.model_type == ModelTypeEnum.alpr_recognize:
|
elif self.model_type == ModelTypeEnum.lpr_recognize:
|
||||||
self.feature_extractor = []
|
self.feature_extractor = []
|
||||||
|
|
||||||
self.runner = ONNXModelRunner(
|
self.runner = ONNXModelRunner(
|
||||||
@ -223,17 +223,17 @@ class GenericONNXEmbedding:
|
|||||||
|
|
||||||
frame = np.expand_dims(frame, axis=0)
|
frame = np.expand_dims(frame, axis=0)
|
||||||
return [{"input_2": frame}]
|
return [{"input_2": frame}]
|
||||||
elif self.model_type == ModelTypeEnum.alpr_detect:
|
elif self.model_type == ModelTypeEnum.lpr_detect:
|
||||||
preprocessed = []
|
preprocessed = []
|
||||||
for x in raw_inputs:
|
for x in raw_inputs:
|
||||||
preprocessed.append(x)
|
preprocessed.append(x)
|
||||||
return [{"x": preprocessed[0]}]
|
return [{"x": preprocessed[0]}]
|
||||||
elif self.model_type == ModelTypeEnum.alpr_classify:
|
elif self.model_type == ModelTypeEnum.lpr_classify:
|
||||||
processed = []
|
processed = []
|
||||||
for img in raw_inputs:
|
for img in raw_inputs:
|
||||||
processed.append({"x": img})
|
processed.append({"x": img})
|
||||||
return processed
|
return processed
|
||||||
elif self.model_type == ModelTypeEnum.alpr_recognize:
|
elif self.model_type == ModelTypeEnum.lpr_recognize:
|
||||||
processed = []
|
processed = []
|
||||||
for img in raw_inputs:
|
for img in raw_inputs:
|
||||||
processed.append({"x": img})
|
processed.append({"x": img})
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
import base64
|
import base64
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import threading
|
import threading
|
||||||
from multiprocessing.synchronize import Event as MpEvent
|
from multiprocessing.synchronize import Event as MpEvent
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
@ -22,7 +23,7 @@ from frigate.comms.events_updater import EventEndSubscriber, EventUpdateSubscrib
|
|||||||
from frigate.comms.inter_process import InterProcessRequestor
|
from frigate.comms.inter_process import InterProcessRequestor
|
||||||
from frigate.config import FrigateConfig
|
from frigate.config import FrigateConfig
|
||||||
from frigate.const import CLIPS_DIR, FRIGATE_LOCALHOST, UPDATE_EVENT_DESCRIPTION
|
from frigate.const import CLIPS_DIR, FRIGATE_LOCALHOST, UPDATE_EVENT_DESCRIPTION
|
||||||
from frigate.embeddings.alpr.alpr import LicensePlateRecognition
|
from frigate.embeddings.lpr.lpr import LicensePlateRecognition
|
||||||
from frigate.events.types import EventTypeEnum
|
from frigate.events.types import EventTypeEnum
|
||||||
from frigate.genai import get_genai_client
|
from frigate.genai import get_genai_client
|
||||||
from frigate.models import Event
|
from frigate.models import Event
|
||||||
@ -651,13 +652,16 @@ class EmbeddingMaintainer(threading.Thread):
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Determine subLabel based on known plates
|
# Determine subLabel based on known plates, use regex matching
|
||||||
# Default to the detected plate, use label name if there's a match
|
# Default to the detected plate, use label name if there's a match
|
||||||
sub_label = top_plate
|
sub_label = next(
|
||||||
for label, plates in self.lpr_config.known_plates.items():
|
(
|
||||||
if top_plate in plates:
|
label
|
||||||
sub_label = label
|
for label, plates in self.lpr_config.known_plates.items()
|
||||||
break
|
if any(re.match(f"^{plate}$", top_plate) for plate in plates)
|
||||||
|
),
|
||||||
|
top_plate,
|
||||||
|
)
|
||||||
|
|
||||||
# Send the result to the API
|
# Send the result to the API
|
||||||
resp = requests.post(
|
resp = requests.post(
|
||||||
|
Loading…
Reference in New Issue
Block a user