ANPR con YOLOV8

ANPR con YOLOV8

Foto di Semyon Borisov su Unsplash

Introduzione:

YOLO V8 è l’ultimo modello sviluppato dal team di Ultralytics. È un modello YOLO all’avanguardia che supera i suoi predecessori sia in termini di precisione che di efficienza.

https://github.com/ultralytics/ultralytics

È facile da usare e accessibile dalla riga di comando o tramite il pacchetto Python. Offre un supporto immediato per le attività di rilevamento oggetti, classificazione e segmentazione. Di recente ha aggiunto il supporto nativo per il tracciamento degli oggetti, quindi non dovremo occuparci di clonare repository di algoritmi di tracciamento.

In questo articolo, tratterò i passaggi per utilizzare YOLOV8 per costruire uno strumento di riconoscimento automatico delle targhe dei veicoli (ANPR). Quindi cominciamo.

Tracciamento dei veicoli:

Come abbiamo accennato in precedenza, YOLOV8 ha il tracciamento nativo, quindi questa fase è piuttosto semplice. Prima, installa il pacchetto ultralytics

pip install ultralytics

Poi, dobbiamo leggere i frame del video con OpenCV e applicare il metodo di tracciamento del modello con l’argomento persist impostato su True per garantire che gli ID persistano nel frame successivo. Il modello restituisce le coordinate per disegnare un rettangolo di delimitazione più l’ID, l’etichetta e il punteggio

import cv2from ultralytics import YOLOmodel = YOLO('yolov8n.pt')cap = cv2.VideoCapture("test_vids/vid1.mp4")ret = Truewhile ret:    # Leggi un frame dalla telecamera    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            # verifica se la soglia è soddisfatta e l'oggetto è un'auto            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)]

ecco il risultato su un frame:

immagine fornita dall'autore

Le coordinate dei rettangoli di delimitazione vengono quindi utilizzate per ritagliare ogni auto nel frame in un’immagine

Riconoscimento delle targhe:

Ora che abbiamo le nostre auto, dobbiamo rilevare le targhe, per questo, dobbiamo addestrare il modello Yolo. A tal fine, ho utilizzato il seguente dataset di Kaggle.

Rilevamento delle targhe dei veicoli

433 immagini di targhe

www.kaggle.com

Tuttavia le etichette in questo dataset sono in formato 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 ha bisogno delle annotazioni di ogni immagine in un file con il seguente formato: etichetta, centro x, centro y, larghezza, altezza

Questo codice gestisce la trasformazione dei nostri dati:

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:                # Scrivi una riga nel file                file.write(f"{line}\n")

ora, l’unica cosa che rimane è configurare il nostro file yaml di configurazione con i percorsi alle cartelle dei dati di train e di validazione, quindi allenare il modello nota (i nomi delle cartelle all’interno delle cartelle di train e di validazione dovrebbero essere labels e images). Quindi, lo passiamo come argomento all’istanza del nostro modello e iniziamo l’allenamento

path: C:/Users/msi/PycharmProjects/ANPR_Yolov8train: trainval: val# Classesnames:  0: targa

model = YOLO('yolov8n.yaml')result = model.train(data="config.yaml",device="0",epochs=100,verbose=True,plots=True,save=True)
immagine di autore

Ora che abbiamo il nostro modello di targa, dobbiamo semplicemente caricarlo e usarlo sulle immagini di auto ritagliate dal video, applichiamo la scala di grigi sul ritaglio della targa e usiamo easy_ocr per leggerne il contenuto

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("Nessuna targa rilevata")           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

la funzione update_csv scriverà l’id dell’auto e il numero di targa in un file CSV. E questo è il flusso di lavoro ANPR con yolov8

immagine di autore

Conclusioni:

Come abbiamo visto, YOLOV8 semplifica il processo di costruzione di un flusso di lavoro ANPR in quanto offre il tracciamento nativo e la rilevazione degli oggetti.

questo repository contiene il progetto completo in cui ho creato un’app ANPR con streamlit:

GitHub – skandermenzli/ANPR_Yolov8

Contribuisci allo sviluppo di skandermenzli/ANPR_Yolov8 creando un account su GitHub.

github.com