Maskenerkennung basierend auf Yolv5s

1. Yolov5-Algorithmusprinzip und Netzwerkstruktur

        YOLOv5 kann entsprechend der Netzwerktiefe und Netzwerkbreite in YO-LOv5s, YOLOv5m, YOLOv5l und YOLOv5x unterteilt werden. In diesem Artikel wird YOLOv5s verwendet, das die kleinste Netzwerkstruktur und die schnellste Bildinferenzgeschwindigkeit von 0,007 s aufweist. Die Netzwerkstruktur von YO-LOv5 besteht hauptsächlich aus vier Teilen, nämlich Input, Backbone, Neck und Head. Das Netzwerkstrukturdiagramm ist in der Abbildung dargestellt.

Yolov5-Netzwerkstrukturdiagramm

1.1Eingangsanschluss

        Die Eingabe nutzt die Mosaikdatenverbesserung, die adaptive Ankerrahmenberechnung und die Bildgrößenverarbeitung. Durch die Mosaikdatenverbesserung werden vier Bilder mithilfe zufälliger Skalierung, zufälligem Zuschneiden und zufälliger Anordnung zusammengefügt, wodurch der Erkennungsdatensatz erheblich bereichert wird, insbesondere durch das Hinzufügen vieler kleiner Ziele, wodurch die Netzwerkstruktur robuster wird. Im YOLOv5-Algorithmus werden in verschiedenen Datensätzen Ankerboxen mit unterschiedlichen Anfangslängen und -breiten festgelegt. Beim Training von Daten wird der vorhergesagte Rahmen auf der Grundlage des anfänglichen Ankerrahmens erhalten und der vorhergesagte Rahmen mit dem realen Rahmen verglichen, um die Differenz zwischen ihnen zu berechnen die beiden. Durch umgekehrte Aktualisierung, iterative Aktualisierung der Netzwerkstrukturparameter und adaptive Ankerboxberechnung kann der optimale Ankerboxwert ermittelt werden. Im Zielerkennungsalgorithmus sind die Größen der Trainingsbilder unterschiedlich, und die Originalbilder müssen einheitlich auf eine feste Größe skaliert und dann zum Training in das Netzwerk eingegeben werden. Die Größe der Bilder in diesem Artikel beträgt 608 × 608 × 3 .

1.2Backone

        ​ ​ ​ Backbone umfasst Focus, CSP und SPP. Focus ist in anderen YOLO-Algorithmen nicht vorhanden. Er wird hauptsächlich für Slicing-Vorgänge verwendet. Beispielsweise wird ein 608×608×3-Bild nach dem Slicing in der Focus-Struktur 304×304×12 groß und es werden 32 Volumenkerne verarbeitet Die Faltungsoperation wird zu einer 304 × 304 × 32-Feature-Map. In YOLOv4 gibt es nur eine CSP-Struktur, während es in YOLOv5 zwei gibt, CSP1_x und CSP2_x, die jeweils in Backbone und Neck verwendet werden. Die CSP-Struktur von YOLOv4 existiert nur in Backbone. Die CSP-Struktur ist in Abbildung 1 dargestellt x von CSP1_x stellt dar, dass es in CSP1 x Resunits (Restkomponenten) gibt. Das x von CSP2_x gibt an, dass es in CSP2 2x CBLs gibt. x beeinflusst die Tiefe der Netzwerkstruktur. In Backbone wird SPP (Space Vector Pyramid Pooling) verwendet, um das Pooling von Feature-Maps zu maximieren und Feature-Maps verschiedener Maßstäbe miteinander zu verbinden.

(1) Fokusstruktur

        Der Schlüssel zur Focus-Struktur ist die Slicing-Operation. Während des Demonstrationsprozesses der Slicing-Operation wird die 4×4×3-Feature-Map in eine 2×2×12-Feature-Map geschnitten. Geben Sie das 608 × 608 × 3-Dreikanalbild in die Focus-Struktur ein. Nach der Slicing-Operation wird es zunächst zu einer 304 × 304 × 12-Feature-Map. Nach einer Faltungsoperation mit 32 Faltungskernen wird es schließlich zu 304 × 304 × 32 Feature-Karte. Es ist zu beachten, dass die Focus-Struktur in der YOLOv5s-Netzwerkstruktur 32 Faltungskerne für Faltungsoperationen verwendet, während die anderen drei Netzwerkstrukturen eine erhöhte Anzahl von Faltungskernen verwenden.

Fokusstrukturdiagramm

(2) CSP-Struktur

        In YOLOv5 gibt es zwei CSP-Strukturen: Die CSP1_X-Struktur befindet sich im Backbone-Backbone-Netzwerk und die andere CSP2_X-Struktur befindet sich im Neck. Für die Backbone-Netzwerkstruktur von Backbone beträgt die Faltungskerngröße im CSP-Modul 3 * 3 und der Schrittwert 2. Wenn die Eingabebildgröße 608 * 608 beträgt, lautet die Änderungsregel für die Feature-Map: 608 * 608 -> 304*304->152*152->76*76->38*38->19*19, und schließlich wurde eine Feature-Map der Größe 19*19 erhalten.

        Vorteile der Verwendung des CSP-Moduls: 1. Verbessern Sie die Lernfähigkeit des Netzwerks, sodass das trainierte Modell leichtgewichtig bleiben und eine hohe Genauigkeit aufweisen kann. 2. Reduzieren Sie Datenengpässe. 3. Reduzieren Sie die Speicherkosten.

CSP-Strukturdiagramm

(3) SPP-Struktur

        Detaillierte Einführung in die SPP-Struktur: https://www.cnblogs.com/zongfa/p/9076311.html

SPP-Strukturdiagramm

1,3Hals

        Neck übernimmt die Struktur von FPN + PAN. FPN ist von oben nach unten und verwendet Upsampling, um Informationen zu übertragen und zu verschmelzen, um vorhergesagte Feature-Maps zu erhalten. PAN übernimmt eine Bottom-up-Feature-Pyramide. Die spezifische Struktur ist in der Abbildung dargestellt.

FPN+PAN-Strukturdiagramm 

1.4Vorhersage

        Die Vorhersage umfasst die Bounding-Box-Verlustfunktion und die nicht maximale Unterdrückung (NMS). YOLOv5 verwendet GIOU_Loss als Verlustfunktion, wodurch das Problem effektiv gelöst wird, wenn sich die Begrenzungsrahmen nicht überlappen. In der Verarbeitungsphase der Ergebnisse der Zielerkennungsvorhersage wird die gewichtete NMS-Operation verwendet, um die vielen scheinbaren Zielrahmen herauszufiltern, um den optimalen Zielrahmen zu erhalten.

  1. GIOU_Loss Verlustfunktion

        Die Verlustfunktion des Zielerkennungsalgorithmus besteht im Allgemeinen aus zwei Teilen: Klassifizierungsverlust (Klassifizierungsverlustfunktion) und Bounding-Box-Regressionsverlust (Regressionsverlustfunktion). Der Entwicklungsprozess der Regressionsverlustfunktion in den letzten Jahren ist: Smooth L1 Loss->IOU_Loss(2016)->GIOU_Loss(2019)->DIOU_Loss(2020)->CIOU_Loss(2020).

IOU_Loss-Bild

 Das Bild ist IOU_Loss. Es ist ersichtlich, dass das gelbe Kästchen das vorhergesagte Kästchen und das blaue Kästchen das reale Kästchen ist. Angenommen, der Schnittpunkt der vorhergesagten Box und der realen Box ist A und die Vereinigung ist B. IOU ist definiert als der Schnittpunkt A dividiert durch die Vereinigung B. Der Verlust von IOU ist:

        Der Verlust von IOUs ist relativ einfach, es gibt jedoch zwei Probleme.

        Frage 1: Wenn sich die vorhergesagte Box und die reale Box nicht schneiden, wie in Abbildung (a) Zustand 1 gezeigt, ist die IOU zu diesem Zeitpunkt 0, was den Abstand zwischen der vorhergesagten Box und der realen Box nicht widerspiegeln kann. Zu diesem Zeitpunkt , die Verlustfunktion kann nicht abgeleitet werden, IOU_Loss Die Verlustfunktion kann die Situation nicht optimieren, in der sich die vorhergesagte Box und die reale Box nicht schneiden

IOU_Loss-Diagramm mit Sonderstatus

        Frage 2: Wenn die Größe der Vorhersagebox und der realen Box gleich ist, kann auch die IOU gleich sein, wie in Zustand 2 und Zustand 3 in (b) (c) oben gezeigt. Zu diesem Zeitpunkt ist der IOU_Loss-Verlust Funktion kann nicht zwischen den beiden Situationen unterscheiden. unterschiedlich. Verwenden Sie daher GIOU_Loss zur Verbesserung.

GIOU_Loss-Diagramm

         Die gelbe Box kann die vorhergesagte Box sein, und die blaue Box kann die reale Box sein. Das minimale umschließende Rechteck der vorhergesagten Box und der realen Box sei die Menge C, und die Differenzmenge ist als Differenz zwischen der Menge C definiert und der Vereinigungsmenge B, dann ist der GIOU_Loss:

        Die Verlustfunktion GIOU_Loss verbessert die Methode zur Messung der Schnittpunktskala und verringert die Mängel des einfachen IOU_Loss.

2. Experimente und Ergebnisse

2.1 Experimenteller Datensatz und experimentelle Umgebung

2.1.1 Datensatz

        Der Datensatz verwendet die Gesichtsmaskenerkennung auf Kaggle. Der Datensatz enthält insgesamt 853 Bilder, die in drei Kategorien unterteilt sind: Eines zeigt Menschen, die Masken tragen, eine trägt keine Masken und die andere zeigt Menschen, die keine Masken tragen . Datensatz-Link: https://www.kaggle.com/andrewmvd/face-mask-detection

        Datensatzanzeige:

        Nach dem Download sind diese Datensätze nicht direkt nutzbar. Weil yolov5 die XML-Dateiverarbeitung nicht unterstützt, aber TXT-Dateien unterstützt. Organisieren Sie also zunächst die Daten entsprechend dem Verzeichnisformat wie unten gezeigt:

        ​ ​ ​Führen Sie dann den folgenden Code aus, um den Datensatz in einen Datensatz umzuwandeln, den Yolov5 verwenden kann:

import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
import random
from shutil import copyfile

classes = ["with_mask", "without_mask","mask_weared_incorrect"]
# classes=["ball"]

TRAIN_RATIO = 80


def clear_hidden_files(path):
    dir_list = os.listdir(path)
    for i in dir_list:
        abspath = os.path.join(os.path.abspath(path), i)
        if os.path.isfile(abspath):
            if i.startswith("._"):
                os.remove(abspath)
        else:
            clear_hidden_files(abspath)


def convert(size, box):
    dw = 1. / size[0]
    dh = 1. / size[1]
    x = (box[0] + box[1]) / 2.0
    y = (box[2] + box[3]) / 2.0
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x * dw
    w = w * dw
    y = y * dh
    h = h * dh
    return (x, y, w, h)


def convert_annotation(image_id):
    in_file = open('VOCdevkit/VOC2007/Annotations/%s.xml' % image_id)
    out_file = open('VOCdevkit/VOC2007/YOLOLabels/%s.txt' % image_id, 'w')
    tree = ET.parse(in_file)
    root = tree.getroot()
    size = root.find('size')
    w = int(size.find('width').text)
    h = int(size.find('height').text)

    for obj in root.iter('object'):
        difficult = obj.find('difficult').text
        cls = obj.find('name').text
        if cls not in classes or int(difficult) == 1:
            continue
        cls_id = classes.index(cls)
        xmlbox = obj.find('bndbox')
        b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
             float(xmlbox.find('ymax').text))
        bb = convert((w, h), b)
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
    in_file.close()
    out_file.close()


wd = os.getcwd()
wd = os.getcwd()
data_base_dir = os.path.join(wd, "VOCdevkit/")
if not os.path.isdir(data_base_dir):
    os.mkdir(data_base_dir)
work_sapce_dir = os.path.join(data_base_dir, "VOC2007/")
if not os.path.isdir(work_sapce_dir):
    os.mkdir(work_sapce_dir)
annotation_dir = os.path.join(work_sapce_dir, "Annotations/")
if not os.path.isdir(annotation_dir):
    os.mkdir(annotation_dir)
clear_hidden_files(annotation_dir)
image_dir = os.path.join(work_sapce_dir, "JPEGImages/")
if not os.path.isdir(image_dir):
    os.mkdir(image_dir)
clear_hidden_files(image_dir)
yolo_labels_dir = os.path.join(work_sapce_dir, "YOLOLabels/")
if not os.path.isdir(yolo_labels_dir):
    os.mkdir(yolo_labels_dir)
clear_hidden_files(yolo_labels_dir)
yolov5_images_dir = os.path.join(data_base_dir, "images/")
if not os.path.isdir(yolov5_images_dir):
    os.mkdir(yolov5_images_dir)
    clear_hidden_files(yolov5_images_dir)
    yolov5_labels_dir = os.path.join(data_base_dir, "labels/")
    if not os.path.isdir(yolov5_labels_dir):
        os.mkdir(yolov5_labels_dir)
    clear_hidden_files(yolov5_labels_dir)
    yolov5_images_train_dir = os.path.join(yolov5_images_dir, "train/")
    if not os.path.isdir(yolov5_images_train_dir):
        os.mkdir(yolov5_images_train_dir)
    clear_hidden_files(yolov5_images_train_dir)
    yolov5_images_test_dir = os.path.join(yolov5_images_dir, "val/")
    if not os.path.isdir(yolov5_images_test_dir):
        os.mkdir(yolov5_images_test_dir)
    clear_hidden_files(yolov5_images_test_dir)
    yolov5_labels_train_dir = os.path.join(yolov5_labels_dir, "train/")
    if not os.path.isdir(yolov5_labels_train_dir):
        os.mkdir(yolov5_labels_train_dir)
    clear_hidden_files(yolov5_labels_train_dir)
    yolov5_labels_test_dir = os.path.join(yolov5_labels_dir, "val/")
    if not os.path.isdir(yolov5_labels_test_dir):
        os.mkdir(yolov5_labels_test_dir)
    clear_hidden_files(yolov5_labels_test_dir)

    train_file = open(os.path.join(wd, "yolov5_train.txt"), 'w')
    test_file = open(os.path.join(wd, "yolov5_val.txt"), 'w')
    train_file.close()
    test_file.close()
    train_file = open(os.path.join(wd, "yolov5_train.txt"), 'a')
    test_file = open(os.path.join(wd, "yolov5_val.txt"), 'a')
    list_imgs = os.listdir(image_dir)  # list image files
    prob = random.randint(1, 100)
    print("Probability: %d" % prob)
    for i in range(0, len(list_imgs)):
        path = os.path.join(image_dir, list_imgs[i])
        if os.path.isfile(path):
            image_path = image_dir + list_imgs[i]
            voc_path = list_imgs[i]
            (nameWithoutExtention, extention) = os.path.splitext(os.path.basename(image_path))
            (voc_nameWithoutExtention, voc_extention) = os.path.splitext(os.path.basename(voc_path))
            annotation_name = nameWithoutExtention + '.xml'
            annotation_path = os.path.join(annotation_dir, annotation_name)
            label_name = nameWithoutExtention + '.txt'
    label_path = os.path.join(yolo_labels_dir, label_name)
    prob = random.randint(1, 100)
    print("Probability: %d" % prob)
    if (prob < TRAIN_RATIO):  # train dataset
        if os.path.exists(annotation_path):
            train_file.write(image_path + '\n')
            convert_annotation(nameWithoutExtention)  # convert label
            copyfile(image_path, yolov5_images_train_dir + voc_path)
            copyfile(label_path, yolov5_labels_train_dir + label_name)
    else:  # test dataset
        if os.path.exists(annotation_path):
            test_file.write(image_path + '\n')
            convert_annotation(nameWithoutExtention)  # convert label
            copyfile(image_path, yolov5_images_test_dir + voc_path)
            copyfile(label_path, yolov5_labels_test_dir + label_name)
train_file.close()
test_file.close()

         Nach dem Ausführen des obigen Codes wird das folgende Verzeichnisformat generiert:

        Sie können sehen, dass durch Ausführen des obigen Codes die Ordner „images“ und „labels“ im VOCdevkit-Verzeichnis generiert werden. Unter diesen beiden Ordnern befinden sich auch die Ordner „train“ und „val“. Dies ist der erforderliche Datensatz. Unter diesen entspricht train dem Trainingssatz und val dem Testsatz.

2.2.2 Datensatzanmerkung

        Da die annotierten XML-Dateien im Datensatz angegeben wurden, erfolgt hier keine weitere Annotation. Die Annotation von Datensätzen erfolgt hauptsächlich über labelimg.

2.2.3 Experimentelle Umgebung

       Die experimentelle Umgebung verwendet Ubuntu 20.04.2+ Dual-Channel Intel 4110CPU + 64G Speicher + RTX2080Ti-Grafikkarte + Anaconda3 für Experimente.

2.2Yolov5-Netzwerkschulung

       Um die Trainingszeit des Netzwerks zu verkürzen und eine bessere Genauigkeit zu erreichen, laden wir im Allgemeinen Vortrainingsgewichte für das Netzwerktraining. Die 5.0-Version von yolov5 stellt uns mehrere Vortrainingsgewichte zur Verfügung. Wir können je nach unseren unterschiedlichen Anforderungen verschiedene Versionen von Vortrainingsgewichten auswählen. Die Namens- und Größeninformationen des Gewichts können der folgenden Abbildung entnommen werden. Es ist zu erwarten, dass die Trainingsgenauigkeit umso höher ist, je größer das Gewicht vor dem Training ist, die Erkennungsgeschwindigkeit jedoch umso langsamer ist. Die Gewichte vor dem Training können über diese URL heruntergeladen werden. Die Gewichte vor dem Training, die dieses Mal zum Trainieren Ihres eigenen Datensatzes verwendet werden, sind yolov5s.pt.

        Wir ziehen zuerst den Yolov5-Code über Git auf den lokalen Code, und Sie können das folgende Verzeichnisformat sehen:

        ​ ​ ​ Anschließend legen wir die heruntergeladene Yolov5.pt-Modelldatei im Stammverzeichnis von Yolov5 ab. Platzieren Sie die Datensatzdatei außerdem im Yolov5-Stammverzeichnis:

        Lassen Sie uns nun eine Einführung in das Gesamtverzeichnis des Codes geben:

├── Daten: Speichert hauptsächlich einige Hyperparameter-Konfigurationsdateien (diese Dateien (YAML-Dateien) werden zum Konfigurieren der Pfade des Trainingssatzes, des Testsatzes und des Validierungssatzes verwendet, einschließlich der Anzahl der Zielerkennungstypen und des Namens des Typ) ); Es stehen auch einige offizielle Bilder zum Testen zur Verfügung. Wenn Sie Ihren eigenen Datensatz trainieren, müssen Sie die Yaml-Datei ändern. Es wird jedoch nicht empfohlen, Ihren eigenen Datensatz unter diesem Pfad zu platzieren. Stattdessen wird empfohlen, den Datensatz unter demselben Ebenenverzeichnis des yolov5-Projekts zu platzieren.

├── Modelle: Es enthält hauptsächlich einige Konfigurationsdateien und Funktionen für den Netzwerkaufbau, die vier verschiedene Versionen des Projekts enthalten, nämlich s, m, l und x. Wie Sie am Namen und der Größe dieser Versionen erkennen können. Ihre Erkennungsmaßnahmen reichen von schnell bis langsam, aber ihre Genauigkeit reicht von niedrig bis hoch. Dies ist die sogenannte Unfähigkeit, Ihren Kuchen zu haben und ihn auch zu essen. Wenn Sie Ihren eigenen Datensatz trainieren, müssen Sie die entsprechende Yaml-Datei ändern, um Ihr eigenes Modell zu trainieren.

├── Dienstprogramme: Es speichert Werkzeugfunktionen, einschließlich Verlustfunktion, Metrikfunktion, Plotfunktion usw.

├── Gewichte: Platzieren Sie die trainierten Gewichtsparameter.

├── discover.py: Verwenden Sie die trainierten Gewichtsparameter zur Zielerkennung, die Bilder, Videos und Kameras erkennen können.

├── train.py: Funktion zum Trainieren Ihres eigenen Datensatzes.

├── test.py: Funktion zum Testen der Trainingsergebnisse.

├──requirements.txt: Dies ist eine Textdatei, die einige Versionen der Umgebungsabhängigkeitspakete enthält, die das yolov5-Projekt verwenden. Sie können diesen Text verwenden, um die entsprechende Version des Pakets zu importieren.

        ​ ​ ​ Dann ändern wir die Datei models/yolov5s.yaml, um nc auf 3 zu ändern, da wir ein 3-Klassifizierungsproblem haben. Und erstellen Sie eine Datei biaoqing.yaml im Datenverzeichnis. Ihr Inhalt lautet:

train: Mask_Datas/images/train  # train images (relative to 'path') 128 images
val: Mask_Datas/images/val  # val images (relative to 'path') 128 images


# Classes
nc: 3  # number of classes
names: ['with_mask', 'without_mask', 'mask_weared_incorrect']  # class names

        Es gibt die Pfade des Trainingssatzes und des Testsatzes sowie den Klassifizierungsinhalt an.

        ​ ​ ​ Anschließend ändern wir die Datei train.py im Stammverzeichnis von Yolov5 und ändern die Hyperparameter wie unten gezeigt. Unter diesen gibt --weights die Gewichte vor dem Training an, --cfg gibt die Konfigurationsdatei der Gewichte vor dem Training an und --data gibt die Konfigurationsdatei des Datensatzes an. Es gibt auch einige Parameter wie -epochs, die die Anzahl der Trainingsrunden angeben. Der Standardwert beträgt 300 Runden und kann nach Bedarf geändert werden. Es gibt auch --batch-size, um anzugeben, wie viele Fotos gleichzeitig gelesen werden sollen, normalerweise ein Vielfaches von 8. Passen Sie es entsprechend Ihrer Computerleistung an.

        Nachdem wir die oben genannten Parameter geändert hatten, haben wir den Code wie folgt in die laufende Umgebung hochgeladen:

        ​ ​ ​ Die erforderlichen Bibliotheken wurden über „requirements.txt“ installiert. Führen Sie python train.py direkt aus, um mit dem Training zu beginnen. Das Folgende ist das Trainingsdiagramm.

        Nach 200 Trainingsrunden haben wir eine best.pt generiert, die die endgültige Gewichtsdatei darstellt, die während dieser 200 Trainingsrunden erhalten wurde.

2.3 Experimentelle Ergebnisse und Analyse 

 

        Wir betrachten die Datei results.png wie folgt:

Wenn die Anzahl der Iterationen während des Trainingsprozesses zunimmt, ändern sich verschiedene Werte, wie in der Abbildung oben dargestellt. Die Bedeutung jedes Werts in der Abbildung ist wie folgt:

GIo U: Je näher der Wert an 0 liegt, desto genauer wird der Zielrahmen gezeichnet.

Objektivität: Je näher der Wert bei 0 liegt, desto genauer ist die Zielerkennung.

Klassifizierung: Je näher der Wert bei 0 liegt, desto genauer ist die Zielklassifizierung.

Präzision: Genauigkeit, d. h. die Anzahl der korrekt markierten Ziele dividiert durch die Gesamtzahl der markierten Ziele. Je näher an 1, desto höher die Genauigkeit.

Rückruf: Rückrufrate, d. h. die Anzahl der korrekt markierten Ziele dividiert durch die Gesamtzahl der zu markierenden Ziele. Je näher an 1, desto höher die Genauigkeit.

m AP@0,5 und m AP@0,5:0,95: AP ist der Bereich, der durch die Verwendung von Präzision und Rückruf als zwei Koordinatenachsen eingeschlossen wird. Je näher an 1, desto höher die Genauigkeit.

Vertrauenskarte

                     P-R-Diagramm

 

Verwirrung Matrix 

 Experimentelle Ergebnisse:

Supongo que te gusta

Origin blog.csdn.net/weixin_41477928/article/details/129484881
Recomendado
Clasificación