LPR improvements (#14641)

This commit is contained in:
Josh Hawkins 2024-10-28 11:49:12 -05:00 committed by Nicolas Mowen
parent 2aca66045a
commit 28d2281991
2 changed files with 29 additions and 5 deletions

View File

@ -13,6 +13,8 @@ from frigate.embeddings.embeddings import Embeddings
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
MIN_PLATE_LENGTH = 3
class LicensePlateRecognition: class LicensePlateRecognition:
def __init__( def __init__(
@ -197,7 +199,22 @@ class LicensePlateRecognition:
average_confidences[original_idx] = average_confidence average_confidences[original_idx] = average_confidence
areas[original_idx] = area areas[original_idx] = area
return license_plates, average_confidences, areas # Filter out plates that have a length of less than 3 characters
# Sort by area, then by plate length, then by confidence all desc
sorted_data = sorted(
[
(plate, conf, area)
for plate, conf, area in zip(
license_plates, average_confidences, areas
)
if len(plate) >= MIN_PLATE_LENGTH
],
key=lambda x: (x[2], len(x[0]), x[1]),
reverse=True,
)
if sorted_data:
return map(list, zip(*sorted_data))
return [], [], [] return [], [], []

View File

@ -598,7 +598,11 @@ class EmbeddingMaintainer(threading.Thread):
logger.debug("No text detected") logger.debug("No text detected")
return return
top_plate, top_char_confidences = license_plates[0], confidences[0] top_plate, top_char_confidences, top_area = (
license_plates[0],
confidences[0],
areas[0],
)
avg_confidence = ( avg_confidence = (
(sum(top_char_confidences) / len(top_char_confidences)) (sum(top_char_confidences) / len(top_char_confidences))
if top_char_confidences if top_char_confidences
@ -609,6 +613,7 @@ class EmbeddingMaintainer(threading.Thread):
if id in self.detected_license_plates: if id in self.detected_license_plates:
prev_plate = self.detected_license_plates[id]["plate"] prev_plate = self.detected_license_plates[id]["plate"]
prev_char_confidences = self.detected_license_plates[id]["char_confidences"] prev_char_confidences = self.detected_license_plates[id]["char_confidences"]
prev_area = self.detected_license_plates[id]["area"]
prev_avg_confidence = ( prev_avg_confidence = (
(sum(prev_char_confidences) / len(prev_char_confidences)) (sum(prev_char_confidences) / len(prev_char_confidences))
if prev_char_confidences if prev_char_confidences
@ -618,6 +623,7 @@ class EmbeddingMaintainer(threading.Thread):
# Define conditions for keeping the previous plate # Define conditions for keeping the previous plate
shorter_than_previous = len(top_plate) < len(prev_plate) shorter_than_previous = len(top_plate) < len(prev_plate)
lower_avg_confidence = avg_confidence <= prev_avg_confidence lower_avg_confidence = avg_confidence <= prev_avg_confidence
smaller_area = top_area < prev_area
# Compare character-by-character confidence where possible # Compare character-by-character confidence where possible
min_length = min(len(top_plate), len(prev_plate)) min_length = min(len(top_plate), len(prev_plate))
@ -628,13 +634,13 @@ class EmbeddingMaintainer(threading.Thread):
) )
worse_char_confidences = char_confidence_comparison >= min_length / 2 worse_char_confidences = char_confidence_comparison >= min_length / 2
if shorter_than_previous or ( if (shorter_than_previous or smaller_area) and (
lower_avg_confidence and worse_char_confidences lower_avg_confidence and worse_char_confidences
): ):
logger.debug( logger.debug(
f"Keeping previous plate. New plate stats: " f"Keeping previous plate. New plate stats: "
f"length={len(top_plate)}, avg_conf={avg_confidence:.2f} " f"length={len(top_plate)}, avg_conf={avg_confidence:.2f}, area={top_area} "
f"vs Previous: length={len(prev_plate)}, avg_conf={prev_avg_confidence:.2f}" f"vs Previous: length={len(prev_plate)}, avg_conf={prev_avg_confidence:.2f}, area={prev_area}"
) )
return return
@ -667,6 +673,7 @@ class EmbeddingMaintainer(threading.Thread):
self.detected_license_plates[id] = { self.detected_license_plates[id] = {
"plate": top_plate, "plate": top_plate,
"char_confidences": top_char_confidences, "char_confidences": top_char_confidences,
"area": top_area,
} }
def _create_thumbnail(self, yuv_frame, box, height=500) -> Optional[bytes]: def _create_thumbnail(self, yuv_frame, box, height=500) -> Optional[bytes]: