Распознавание номерных знаков с использованием YOLOV8
License plate recognition using YOLOV8
Введение:
YOLO V8 – последняя модель, разработанная командой Ultralytics. Это передовая модель YOLO, превосходящая своих предшественников как по точности, так и по эффективности.
![https://github.com/ultralytics/ultralytics](https://miro.medium.com/v2/resize:fit:640/format:webp/1*6Sn93qyovio0qn3Y3q7Vgw.png)
Он легко используется и доступен через командную строку или с помощью пакета Python. Он предлагает готовую поддержку задач обнаружения объектов, классификации и сегментации. Недавно была добавлена поддержка нативного отслеживания объектов, поэтому нам не придется иметь дело с клонированием репозиториев алгоритмов отслеживания.
В этой статье я расскажу о шагах, необходимых для использования YOLOV8 для создания инструмента автоматического распознавания номерных знаков (ANPR). Итак, приступим.
Отслеживание транспортных средств:
Как мы уже упоминали ранее, YOLOV8 имеет встроенное отслеживание, поэтому этот шаг довольно прост. Сначала установите пакет ultralytics
- Современная картина данных и руководства технологиями – Заменит ли главный AI-офицер главного офицера по цифровизации?
- Начало работы с структурами данных в Python в 5 шагах
- Основы Python Синтаксис, Типы данных и Управляющие структуры
pip install ultralytics
Затем нам нужно считывать видеофреймы с помощью open cv и применять метод отслеживания модели с аргументом persist, установленным в True, чтобы убедиться, что идентификаторы сохраняются на следующем фрейме. Модель возвращает координаты для рисования ограничительной рамки, а также идентификатор, метку и оценку
import cv2from ultralytics import YOLOmodel = YOLO('yolov8n.pt')cap = cv2.VideoCapture("test_vids/vid1.mp4")ret = Truewhile ret: # Читаем фрейм с камеры ret, frame = cap.read() if ret and frame_nbr % 10 == 0 : results = model.track(frame,persist=True) for result in results[0].boxes.data.tolist(): x1, y1, x2, y2, id, score,label = result # Проверяем, удовлетворяется ли порог и объект является ли автомобилем if score > 0.5 and label==2: cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 4) text_x = int(x1) text_y = int(y1) - 10 cv2.putText(frame, str(id), (text_x, text_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2) cropped_img = frame[int(y1):int(y2), int(x1):int(x2)]
вот результат на одном фрейме:
![изображение от автора](https://miro.medium.com/v2/resize:fit:640/format:webp/1*33SePe3LKq6iqn0TKu6Yyw.png)
Координаты ограничительных рамок затем используются для обрезки каждого автомобиля на фрейме в отдельное изображение
Распознавание номерных знаков:
Теперь, когда у нас есть наши автомобили, нам нужно обнаружить номерные знаки, для этого нам нужно обучить модель Yolo. Для этого я использовал следующий набор данных Kaggle.
Обнаружение номерных знаков автомобилей
433 изображения номерных знаков
www.kaggle.com
Однако метки в этом наборе данных представлены в формате PASCAL VOC XML:
<annotation> <folder>images</folder> <filename>Cars105.png</filename> <size> <width>400</width> <height>240</height> <depth>3</depth> </size> <segmented>0</segmented> <object> <name>licence</name> <pose>Unspecified</pose> <truncated>0</truncated> <occluded>0</occluded> <difficult>0</difficult> <bndbox> <xmin>152</xmin> <ymin>147</ymin> <xmax>206</xmax> <ymax>159</ymax> </bndbox> </object></annotation>
YOLO требует аннотаций каждого изображения в файле с следующим форматом: метка, центр по оси x, центр по оси y, ширина, высота
Этот код обрабатывает преобразование наших данных:
def xml_to_yolo(bbox, w, h): # xmin, ymin, xmax, ymax x_center = ((bbox[2] + bbox[0]) / 2) / w y_center = ((bbox[3] + bbox[1]) / 2) / h width = (bbox[2] - bbox[0]) / w height = (bbox[3] - bbox[1]) / h return [x_center, y_center, width, height]def convert_dataset(): for filename in os.listdir("annotations"): tree = ET.parse(f"annotations/{filename}") root = tree.getroot() name = root.find("filename").text.replace(".png", "") width = int(root.find("size").find("width").text) height = int(root.find("size").find("height").text) for obj in root.findall('object'): box = [] for x in obj.find("bndbox"): box.append(int(x.text)) yolo_box = xml_to_yolo(box, width, height) line = f"0 {yolo_box[0]} {yolo_box[1]} {yolo_box[2]} {yolo_box[3]}" with open(f"train/labels/{name}.txt", "a") as file: # Запись строки в файл file.write(f"{line}\n")
теперь все, что остается, это настроить нашу конфигурационную yaml с путями к папкам с данными для обучения и проверки, а затем обучить модель (обратите внимание, что имена папок внутри папок с данными для обучения и проверки должны быть labels и images). Затем мы передаем его в качестве аргумента в наш экземпляр модели и начинаем обучение
path: C:/Users/msi/PycharmProjects/ANPR_Yolov8train: trainval: val# Classesnames: 0: номерной знак
model = YOLO('yolov8n.yaml')result = model.train(data="config.yaml",device="0",epochs=100,verbose=True,plots=True,save=True)
![изображение от автора](https://miro.medium.com/v2/resize:fit:640/format:webp/1*DPWhZnGGI-mH0i36uQ4LoA.jpeg)
Теперь, когда у нас есть модель номерного знака, нам просто нужно загрузить ее и использовать на обрезанных изображениях автомобилей из видео, мы применяем градации серого к обрезке номерного знака и используем easy_ocr для чтения его содержимого
cropped_img = frame[int(y1):int(y2), int(x1):int(x2)]plates = lp_detector(cropped_img)for plate in plates[0].boxes.data.tolist(): if score > 0.6: x1, y1, x2, y2, score, _ = plate cv2.rectangle(cropped_img, (int(x1), int(y1)), (int(x2), int(y2)), (255, 0, 0), 2) lp_crop = cropped_img[int(y1):int(y2), int(x1):int(x2)] lp_crop_gray = cv2.cvtColor(lp_crop, cv2.COLOR_BGR2GRAY) ocr_res = reader.readtext(lp_crop_gray) if not ocr_res: print("Номерной знак не обнаружен") else: entry = {'id': id, 'number': ocr_res[0][1], 'score': ocr_res[0][2]} update_csv(entry) out.write(frame) cv2.imshow('frame', frame) frame_nbr += 1
функция update_csv будет записывать идентификатор автомобиля и номерной знак в CSV-файл. И вот пайплайн ANPR с помощью yolov8
![изображение от автора](https://miro.medium.com/v2/resize:fit:640/format:webp/1*30VOD5zplvEKRP3xlqWvNQ.png)
Вывод:
Как мы видели, YOLOV8 упрощает процесс построения пайплайна ANPR, так как он предлагает встроенное отслеживание и детектирование объектов.
этот репозиторий содержит полный проект, где я создал приложение ANPR с использованием streamlit:
GitHub – skandermenzli/ANPR_Yolov8
Внести вклад в развитие skandermenzli/ANPR_Yolov8, создав учетную запись на GitHub.
github.com