Create util.py
Browse files
util.py
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import string
|
| 2 |
+
import easyocr
|
| 3 |
+
|
| 4 |
+
# Initialize the OCR reader
|
| 5 |
+
reader = easyocr.Reader(['en'], gpu=False)
|
| 6 |
+
|
| 7 |
+
# Mapping dictionaries for character conversion
|
| 8 |
+
dict_char_to_int = {'O': '0',
|
| 9 |
+
'I': '1',
|
| 10 |
+
'J': '3',
|
| 11 |
+
'A': '4',
|
| 12 |
+
'G': '6',
|
| 13 |
+
'S': '5'}
|
| 14 |
+
|
| 15 |
+
dict_int_to_char = {'0': 'O',
|
| 16 |
+
'1': 'I',
|
| 17 |
+
'3': 'J',
|
| 18 |
+
'4': 'A',
|
| 19 |
+
'6': 'G',
|
| 20 |
+
'5': 'S'}
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def write_csv(results, output_path):
|
| 24 |
+
"""
|
| 25 |
+
Write the results to a CSV file.
|
| 26 |
+
|
| 27 |
+
Args:
|
| 28 |
+
results (dict): Dictionary containing the results.
|
| 29 |
+
output_path (str): Path to the output CSV file.
|
| 30 |
+
"""
|
| 31 |
+
with open(output_path, 'w') as f:
|
| 32 |
+
f.write('{},{},{},{},{},{},{}\n'.format('frame_nmr', 'car_id', 'car_bbox',
|
| 33 |
+
'license_plate_bbox', 'license_plate_bbox_score', 'license_number',
|
| 34 |
+
'license_number_score'))
|
| 35 |
+
|
| 36 |
+
for frame_nmr in results.keys():
|
| 37 |
+
for car_id in results[frame_nmr].keys():
|
| 38 |
+
print(results[frame_nmr][car_id])
|
| 39 |
+
if 'car' in results[frame_nmr][car_id].keys() and \
|
| 40 |
+
'license_plate' in results[frame_nmr][car_id].keys() and \
|
| 41 |
+
'text' in results[frame_nmr][car_id]['license_plate'].keys():
|
| 42 |
+
f.write('{},{},{},{},{},{},{}\n'.format(frame_nmr,
|
| 43 |
+
car_id,
|
| 44 |
+
'[{} {} {} {}]'.format(
|
| 45 |
+
results[frame_nmr][car_id]['car']['bbox'][0],
|
| 46 |
+
results[frame_nmr][car_id]['car']['bbox'][1],
|
| 47 |
+
results[frame_nmr][car_id]['car']['bbox'][2],
|
| 48 |
+
results[frame_nmr][car_id]['car']['bbox'][3]),
|
| 49 |
+
'[{} {} {} {}]'.format(
|
| 50 |
+
results[frame_nmr][car_id]['license_plate']['bbox'][0],
|
| 51 |
+
results[frame_nmr][car_id]['license_plate']['bbox'][1],
|
| 52 |
+
results[frame_nmr][car_id]['license_plate']['bbox'][2],
|
| 53 |
+
results[frame_nmr][car_id]['license_plate']['bbox'][3]),
|
| 54 |
+
results[frame_nmr][car_id]['license_plate']['bbox_score'],
|
| 55 |
+
results[frame_nmr][car_id]['license_plate']['text'],
|
| 56 |
+
results[frame_nmr][car_id]['license_plate']['text_score'])
|
| 57 |
+
)
|
| 58 |
+
f.close()
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
def license_complies_format(text):
|
| 62 |
+
"""
|
| 63 |
+
Check if the license plate text complies with the required format.
|
| 64 |
+
|
| 65 |
+
Args:
|
| 66 |
+
text (str): License plate text.
|
| 67 |
+
|
| 68 |
+
Returns:
|
| 69 |
+
bool: True if the license plate complies with the format, False otherwise.
|
| 70 |
+
"""
|
| 71 |
+
if len(text) != 7:
|
| 72 |
+
return False
|
| 73 |
+
|
| 74 |
+
if (text[0] in string.ascii_uppercase or text[0] in dict_int_to_char.keys()) and \
|
| 75 |
+
(text[1] in string.ascii_uppercase or text[1] in dict_int_to_char.keys()) and \
|
| 76 |
+
(text[2] in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] or text[2] in dict_char_to_int.keys()) and \
|
| 77 |
+
(text[3] in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] or text[3] in dict_char_to_int.keys()) and \
|
| 78 |
+
(text[4] in string.ascii_uppercase or text[4] in dict_int_to_char.keys()) and \
|
| 79 |
+
(text[5] in string.ascii_uppercase or text[5] in dict_int_to_char.keys()) and \
|
| 80 |
+
(text[6] in string.ascii_uppercase or text[6] in dict_int_to_char.keys()):
|
| 81 |
+
return True
|
| 82 |
+
else:
|
| 83 |
+
return False
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
def format_license(text):
|
| 87 |
+
"""
|
| 88 |
+
Format the license plate text by converting characters using the mapping dictionaries.
|
| 89 |
+
|
| 90 |
+
Args:
|
| 91 |
+
text (str): License plate text.
|
| 92 |
+
|
| 93 |
+
Returns:
|
| 94 |
+
str: Formatted license plate text.
|
| 95 |
+
"""
|
| 96 |
+
license_plate_ = ''
|
| 97 |
+
mapping = {0: dict_int_to_char, 1: dict_int_to_char, 4: dict_int_to_char, 5: dict_int_to_char, 6: dict_int_to_char,
|
| 98 |
+
2: dict_char_to_int, 3: dict_char_to_int}
|
| 99 |
+
for j in [0, 1, 2, 3, 4, 5, 6]:
|
| 100 |
+
if text[j] in mapping[j].keys():
|
| 101 |
+
license_plate_ += mapping[j][text[j]]
|
| 102 |
+
else:
|
| 103 |
+
license_plate_ += text[j]
|
| 104 |
+
|
| 105 |
+
return license_plate_
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
def read_license_plate(license_plate_crop):
|
| 109 |
+
"""
|
| 110 |
+
Read the license plate text from the given cropped image.
|
| 111 |
+
|
| 112 |
+
Args:
|
| 113 |
+
license_plate_crop (PIL.Image.Image): Cropped image containing the license plate.
|
| 114 |
+
|
| 115 |
+
Returns:
|
| 116 |
+
tuple: Tuple containing the formatted license plate text and its confidence score.
|
| 117 |
+
"""
|
| 118 |
+
|
| 119 |
+
detections = reader.readtext(license_plate_crop)
|
| 120 |
+
|
| 121 |
+
for detection in detections:
|
| 122 |
+
bbox, text, score = detection
|
| 123 |
+
|
| 124 |
+
text = text.upper().replace(' ', '')
|
| 125 |
+
|
| 126 |
+
if license_complies_format(text):
|
| 127 |
+
return format_license(text), score
|
| 128 |
+
|
| 129 |
+
return None, None
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
def get_car(license_plate, vehicle_track_ids):
|
| 133 |
+
"""
|
| 134 |
+
Retrieve the vehicle coordinates and ID based on the license plate coordinates.
|
| 135 |
+
|
| 136 |
+
Args:
|
| 137 |
+
license_plate (tuple): Tuple containing the coordinates of the license plate (x1, y1, x2, y2, score, class_id).
|
| 138 |
+
vehicle_track_ids (list): List of vehicle track IDs and their corresponding coordinates.
|
| 139 |
+
|
| 140 |
+
Returns:
|
| 141 |
+
tuple: Tuple containing the vehicle coordinates (x1, y1, x2, y2) and ID.
|
| 142 |
+
"""
|
| 143 |
+
x1, y1, x2, y2, score, class_id = license_plate
|
| 144 |
+
|
| 145 |
+
foundIt = False
|
| 146 |
+
for j in range(len(vehicle_track_ids)):
|
| 147 |
+
xcar1, ycar1, xcar2, ycar2, car_id = vehicle_track_ids[j]
|
| 148 |
+
|
| 149 |
+
if x1 > xcar1 and y1 > ycar1 and x2 < xcar2 and y2 < ycar2:
|
| 150 |
+
car_indx = j
|
| 151 |
+
foundIt = True
|
| 152 |
+
break
|
| 153 |
+
|
| 154 |
+
if foundIt:
|
| 155 |
+
return vehicle_track_ids[car_indx]
|
| 156 |
+
|
| 157 |
+
return -1, -1, -1, -1, -1
|