yolov5 de l'entrée à la maîtrise

Table des matières

introduction

organisation du réseau

augmentation des données

déployer

Générer des données pour la détection de cercles et de rectangles

introduction

Plusieurs versions ont été itérées depuis sa sortie le 18 mai 2020. La dernière version est la v7, qui ajoute des capacités de segmentation. Il y a eu de nombreux articles de blog expliquant le principe de yolov5 et comment utiliser les données marquées, telles que l' explication détaillée du réseau YOLOv5  et l'explication approfondie des connaissances de base de base de Yolov5 dans la série Yolo.  

Simple à installer et facile à utiliser, il est devenu de facto la référence des méthodes de détection 

// 克隆代码库即可
git clone https://github.com/ultralytics/yolov5  # clone
cd yolov5
pip install -r requirements.txt  # install

Il suffit d'une ligne de code pour terminer lors de l'utilisation

import torch
# 加载模型
model = torch.hub.load('ultralytics/yolov5', 'yolov5s')  # or yolov5n - yolov5x6, custom
# 图片路径
img = 'https://ultralytics.com/images/zidane.jpg'  # or file, Path, PIL, OpenCV, numpy, list
# 执行检测推理
results = model(img)
# 检测结果可视化
results.print()  # or .show(), .save(), .crop(), .pandas(), etc.

Quoi? Vous ne voulez pas écrire une seule ligne de code. Si vous souhaitez développer sans code et voir l'effet directement depuis la caméra, l'exécution de detect.py dans l'entrepôt peut également répondre à vos besoins.

python detect.py --weights yolov5s.pt --source 0

La signification des paramètres détaillés est la suivante, où --weights spécifie le poids de pré-entraînement que vous souhaitez utiliser, --source spécifie la source à détecter (image, liste de chemin d'image, caméra ou même flux push réseau) 

python detect.py --weights yolov5s.pt --source 0                               # webcam
                                               img.jpg                         # image
                                               vid.mp4                         # video
                                               screen                          # screenshot
                                               path/                           # directory
                                               list.txt                        # list of images
                                               list.streams                    # list of streams
                                               'path/*.jpg'                    # glob
                                               'https://youtu.be/Zgi9g1ksQHc'  # YouTube
                                               'rtsp://example.com/media.mp4'  # RTSP, RTMP, HTTP stream
yolov5 v7.0 comparaison de vitesse et de précision
Le mAP et la vitesse du modèle pré-entraîné sur coco

organisation du réseau

YOLOv5 a la même architecture réseau globale pour différentes tailles ( nsml,  ), mais il utilise différentes profondeurs et largeurs dans chaque sous-module pour traiter respectivement les paramètres du fichier . Il convient également de noter qu'en plus de la version officielle il existe également , la différence est que cette dernière est destinée aux images avec des résolutions plus grandes. Par exemple il existe bien sûr quelques différences de structure. 4 couches d'entités de prédiction, tandis que le premier ne sous-échantillonnera que 32 fois et utilisera 3 couches d'entités de prédiction.xyamldepth_multiplewidth_multiplensmlxn6s6m6l6x61280x1280

Par rapport à la version précédente, YOLOv5 v6.0a un petit changement après la version, remplaçant la première couche du réseau (à l'origine un Focusmodule) par une 6x6grande et une petite couche convolutive. Les deux sont équivalents en théorie , mais pour certains dispositifs GPU existants (et les algorithmes d'optimisation correspondants), il est plus efficace d'utiliser 6x6de grandes et petites couches convolutives que d'utiliser Focusdes modules. Pour plus de détails, veuillez consulter ce numéro #4825. La figure ci-dessous est le Focusmodule d'origine (similaire au précédent Swin Transformer) Patch Merging, 2x2divisez chaque pixel adjacent en un patch, puis patchassemblez les pixels de même position (même couleur) dans chacun pour obtenir 4 feature map, puis connectez Une 3x3couche convolutive de la taille précédente . Cela équivaut à utiliser directement 6x6une couche convolutive d' une taille.

Après YOLOv5 6.0, remplacez Focus par une couche convolutive 6x6 équivalente pour un déploiement facile

La partie Neck sera SPPremplacée par une SPPF( Glenn Jocherauto-conçue), la fonction des deux est la même, mais cette dernière est plus efficace. SPPLa structure consiste à faire passer l'entrée à travers plusieurs tailles différentes en parallèle MaxPool, puis à effectuer une fusion supplémentaire, ce qui peut résoudre le problème multi-échelle cible dans une certaine mesure. La SPPFstructure consiste à sérialiser l'entrée à travers des couches 5x5de plusieurs tailles MaxPool. Il convient de noter ici que le résultat du calcul de la sérialisation des couches 5x5de deux tailles est le même que celui des couches d' une taille, et le résultat du calcul de la sérialisation des couches de trois tailles est identique à celui des calques d'une même taille. Les résultats du calcul des calques sont les mêmes.MaxPool9x9MaxPool5x5MaxPool13x13MaxPool

Schéma de structure du réseau SPPF

augmentation des données

Mosaïque , combinez quatre images en une seule image

Augmentation des données en mosaïque

Copiez-collez , collez au hasard certaines cibles dans l'image, le principe est que les données doivent avoir segmentsdes données, c'est-à-dire les informations de segmentation d'instance de chaque cible

Copier coller, utilisé uniquement dans la formation fractionnée

Random affine (Rotation, Scale, Translation and Shear) effectue une transformation affine de manière aléatoire, mais selon les hyperparamètres du fichier de configuration, il s'avère que seules la somme Scaleet Translationla traduction sont utilisées.

Amélioration de la transformation radiale aléatoire

MixUp consiste à mélanger deux images ensemble avec une certaine transparence. On ne sait pas si c'est utile ou non. Après tout, il n'y a pas de papiers et pas d'expériences d'ablation. Seul le plus grand modèle est utilisé dans le code MixUp, et seulement 10 % du temps.

mélanger

Albumentations , principalement pour faire du filtrage, de l'égalisation de l'histogramme et changer la qualité de l'image, etc. Je vois que le code écrit dans le code ne sera activé que lorsque le package sera installé , mais le package est commenté albumentationsdans le requirements.txtfichier de projet , donc il n'est pas activé par défaut albumentations.

Augmenter HSV (Teinte, Saturation, Valeur) ajuste de manière aléatoire la teinte, la saturation et la luminosité.

changement de couleur aléatoire

Retournement horizontal aléatoire , retournement horizontal aléatoire 

Retournement horizontal aléatoire, ceci est plus couramment utilisé

De nombreuses stratégies de formation sont utilisées dans le code source YOLOv5

  • Formation multi-échelle (0,5 ~ 1,5x) , formation multi-échelle, en supposant que la taille de l'image d'entrée est définie sur 640 × 640, la taille utilisée pendant la formation est sélectionnée au hasard entre 0,5 × 640 ∼ 1,5 × 640, faites attention à la valeur obtenue lors de la sélection de la valeur Les deux sont des multiples entiers de 32 (car le réseau sous-échantillonnera au maximum 32 fois).
  • AutoAnchor (pour la formation de données personnalisées) , lors de la formation de votre propre ensemble de données, vous pouvez vous regrouper pour générer des modèles d'ancres en fonction des objectifs de votre propre ensemble de données.
  • Planificateur d'échauffement et de cosinus LR , échauffez-vous avant l'entraînement Warmup, puis utilisez Cosinela stratégie de baisse du taux d'apprentissage.
  • L'EMA (moyenne mobile exponentielle) peut être comprise comme l'ajout d'un élan aux paramètres d'entraînement pour rendre le processus de mise à jour plus fluide.
  • Précision mixte , formation de précision mixte, peut réduire l'utilisation de la mémoire vidéo et accélérer la formation, à condition que le support matériel GPU.
  • Faire évoluer les hyper-paramètres , l'optimisation des hyperparamètres, les personnes qui n'ont aucune expérience en alchimie ne doivent pas y toucher, juste garder la valeur par défaut.

La perte de YOLOv5 se compose principalement de trois parties :

  • La perte de classes , la perte de classification, est utilisée BCE loss, faites attention à ne calculer que la perte de classification des échantillons positifs.
  • Objectness loss , objla perte, est toujours utilisé BCE lossNotez que cela objfait référence à la boîte englobante cible prédite par le réseau et la GT Box CIoU. Ce qui est calculé ici est objla perte de tous les échantillons.
  • La perte de localisation , la perte de localisation, est utilisée CIoU loss, faites attention à ne calculer que la perte de localisation des échantillons positifs.

déployer

Les versions antérieures à yolov5 v6.0 (non incluses) utilisent la couche Focus, ce qui entraîne de nombreuses modifications du déploiement et nécessite de nombreuses opérations compliquées . les étapes sont les suivantes Détecter YOLOv5 vers le déploiement

// 1.导出onnx
python models/export.py --weights yolov5s.pt --img 320 --batch 1
// 2.简化模型
python -m onnxsim yolov5s.onnx yolov5s-sim.onnx
// 3. 模型转换到ncnn
./onnx2ncnn yolov5s-sim.onnx yolov5s.param yolov5s.bin
// 4. 编辑 yolov5s.param文件
第4行到13行删除(也就是Slice和Concat层),将第二行由172改成164(一共删除了10层,第二行的173更改为164,计算方法173-(10-1)=164)
增加自定义层
YoloV5Focus              focus                    1 1  images 159
其中159是刚才删除的Concat层的输出
// 5. 支持动态尺寸输入
将reshape中的960,240,60更改为-1,或者其他 0=后面的数
// 6. ncnnoptimize优化
./ncnnoptimize yolov5s.param yolov5s.bin yolov5s-opt.param yolov5s-opt.bin 1

Après la v6.0, il est beaucoup plus pratique d'utiliser la convolution 6x6 à la place.Vous pouvez directement utiliser le module dnn d'opencv pour le déploiement.Pour plus de détails, voir Détection d'objets avec YOLOv5, OpenCV, Python et C++ , code yolov5-opencv-cpp-python

Cependant, il convient de noter qu'il ne peut coopérer qu'avec opencv4.5.5 et supérieur.Il comprend principalement 6 étapes

// 1.加载模型
net = cv2.dnn.readNet('yolov5s.onnx')
// 2.加载图片
def format_yolov5(source):

    # put the image in square big enough
    col, row, _ = source.shape
    _max = max(col, row)
    resized = np.zeros((_max, _max, 3), np.uint8)
    resized[0:col, 0:row] = source
    
    # resize to 640x640, normalize to [0,1[ and swap Red and Blue channels
    result = cv2.dnn.blobFromImage(resized, 1/255.0, (640, 640), swapRB=True)
    
    return result
// 3.执行推理
predictions = net.forward()
output = predictions[0]
// 4.展开结果
def unwrap_detection(input_image, output_data):
    class_ids = []
    confidences = []
    boxes = []

    rows = output_data.shape[0]

    image_width, image_height, _ = input_image.shape

    x_factor = image_width / 640
    y_factor =  image_height / 640

    for r in range(rows):
        row = output_data[r]
        confidence = row[4]
        if confidence >= 0.4:

            classes_scores = row[5:]
            _, _, _, max_indx = cv2.minMaxLoc(classes_scores)
            class_id = max_indx[1]
            if (classes_scores[class_id] > .25):

                confidences.append(confidence)

                class_ids.append(class_id)

                x, y, w, h = row[0].item(), row[1].item(), row[2].item(), row[3].item() 
                left = int((x - 0.5 * w) * x_factor)
                top = int((y - 0.5 * h) * y_factor)
                width = int(w * x_factor)
                height = int(h * y_factor)
                box = np.array([left, top, width, height])
                boxes.append(box)

// 5.非极大值抑制
indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.25, 0.45) 

result_class_ids = []
result_confidences = []
result_boxes = []

for i in indexes:
    result_confidences.append(confidences[i])
    result_class_ids.append(class_ids[i])
    result_boxes.append(boxes[I])
// 6.可视化结果输出

class_list = []
with open("classes.txt", "r") as f:
    class_list = [cname.strip() for cname in f.readlines()]

colors = [(255, 255, 0), (0, 255, 0), (0, 255, 255), (255, 0, 0)]

for i in range(len(result_class_ids)):

    box = result_boxes[i]
    class_id = result_class_ids[i]

    color = colors[class_id % len(colors)]

    conf  = result_confidences[i]

    cv2.rectangle(image, box, color, 2)
    cv2.rectangle(image, (box[0], box[1] - 20), (box[0] + box[2], box[1]), color, -1)
    cv2.putText(image, class_list[class_id], (box[0] + 5, box[1] - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0))

Générer des données pour la détection de cercles et de rectangles

Ensuite, un projet de détection de cercles et de rectangles montre la génération de données d'entraînement et le processus d'entraînement de yolov5. Mais l'étiquetage des données est une tâche qui prend du temps et demande beaucoup de main-d'œuvre. Ne serait-il pas formidable que les données générées puissent être utilisées pour vérifier rapidement certaines expériences ?

Basé sur Lable Studio [enregistrements de combat réels yoloV5] Xiaobai peut également former son propre ensemble de données ! Sur la base de labelimg, je vais vous apprendre à utiliser le deep learning pour faire de la détection d'objets (2) : étiquetage des données - Programmeur

Le format d'étiquetage de Yolov5 est très simple. Les images sont placées dans le dossier images. Sous le dossier étiquettes, chaque fichier image a un fichier txt correspondant avec le même nom, qui stocke la catégorie, les coordonnées normalisées et la largeur de chaque cible par ligne Élevé, de nombreux outils d'annotation prennent en charge l'exportation directe du format d'annotation yolo, et il existe également de nombreux scripts qui peuvent facilement convertir des formats VOC, coco et autres au format YOLO.

类别1 归一化中心点坐标x 归一化中心坐标y 归一化宽度 归一化高度
类别2 归一化中心点坐标x 归一化中心坐标y 归一化宽度 归一化高度
Exemple de fichier d'annotation

1. Ici, nous prenons le cercle de détection comme exemple pour introduire chaque étape en détail

Le premier est la génération et la visualisation des données d'entraînement, dessinez au hasard un cercle avec un point aléatoire comme centre et un rayon de 60-100 comme cible que nous voulons détecter, et générez un total de 100 000 données d'entraînement

import os
import cv2
import math
import random
import numpy as np
from tqdm import tqdm

def generate():
    img = np.zeros((640,640,3),np.uint8)
    x = 100+random.randint(0, 400)
    y = 100+random.randint(0, 400)
    radius = random.randint(60,100)
    r = random.randint(0,255)
    g = random.randint(0,255)
    b = random.randint(0,255)
    cv2.circle(img, (x,y), radius, (b,g,r),-1)
    return img, [x,y,radius]

def generate_batch(num=10000):
    images_dir = "data/circle/images"
    if not os.path.exists(images_dir):
        os.makedirs(images_dir)
    labels_dir = "data/circle/labels"
    if not os.path.exists(labels_dir):
            os.makedirs(labels_dir)
    for i in tqdm(range(num)):
        img, labels = generate()
        cv2.imwrite(images_dir+"/"+str(i)+".jpg", img)
        with open(labels_dir+"/"+str(i)+".txt", 'w') as f:
            x, y, radius = labels
            f.write("0 "+str(x/640)+" "+str(y/640)+" "+str(2*radius/640)+" "+str(2*radius/640)+"\n")

def show_gt(dir='data/circle'):
    files = os.listdir(dir+"/images")
    gtdir = dir+"/gt"
    if not os.path.exists(gtdir):
        os.makedirs(gtdir)
    for file in tqdm(files):
        imgpath = dir+"/images/"+file
        img = cv2.imread(imgpath)
        h,w,_ = img.shape
        labelpath = dir+"/labels/"+file[:-3]+"txt"
        with open(labelpath) as f:
            lines = f.readlines()
            for line in lines:
                items = line[:-1].split(" ")
                c = int(items[0])
                cx = float(items[1])
                cy = float(items[2])
                cw = float(items[3])
                ch = float(items[4])
                x1 = int((cx - cw/2)*w)
                y1 = int((cy - ch/2)*h)
                x2 = int((cx + cw/2)*w)
                y2 = int((cy + ch/2)*h)
                cv2.rectangle(img, (x1,y1),(x2,y2),(0,255,0),2)
            cv2.imwrite(gtdir+"/"+file, img)

if __name__=="__main__":
    generate_batch()
    show_gt()

Puis construisez circle.yaml

train: data/circle/images/
val: data/circle/images/
# number of classes
nc: 1

# class names
names: ['circle']

2. Si vous souhaitez détecter des cibles circulaires et rectangulaires, vous devez ajuster le script de génération et le fichier de configuration des données

import os
import cv2
import math
import random
import numpy as np
from tqdm import tqdm

def generate_circle():
    img = np.zeros((640,640,3),np.uint8)
    x = 100+random.randint(0, 400)
    y = 100+random.randint(0, 400)
    radius = random.randint(60,100)
    r = random.randint(0,255)
    g = random.randint(0,255)
    b = random.randint(0,255)
    cv2.circle(img, (x,y), radius, (b,g,r),-1)
    return img, [x,y,radius*2,radius*2]

def generate_rectangle():
    img = np.zeros((640,640,3),np.uint8)
    x1 = 100+random.randint(0, 400)
    y1 = 100+random.randint(0, 400)
    w = random.randint(80, 200)
    h = random.randint(80, 200)
    x2 = x1 + w
    y2 = y1 + h
    r = random.randint(0,255)
    g = random.randint(0,255)
    b = random.randint(0,255)
    cx = (x1+x2)//2
    cy = (y1+y2)//2
    cv2.rectangle(img, (x1,y1), (x2,y2), (b,g,r),-1)
    return img, [cx,cy,w,h]

def generate_batch(num=100000):
    images_dir = "data/shape/images"
    if not os.path.exists(images_dir):
        os.makedirs(images_dir)
    labels_dir = "data/shape/labels"
    if not os.path.exists(labels_dir):
            os.makedirs(labels_dir)
    for i in tqdm(range(num)):
        if i % 2 == 0:
            img, labels = generate_circle()
        else:
            img, labels = generate_rectangle()
        cv2.imwrite(images_dir+"/"+str(i)+".jpg", img)
        with open("data/shape/labels/"+str(i)+".txt", 'w') as f:
            cx,cy,w,h = labels
            f.write(str(i%2)+" "+str(cx/640)+" "+str(cy/640)+" "+str(w/640)+" "+str(h/640)+"\n")

def show_gt(dir='data/shape'):
    files = os.listdir(dir+"/images")
    gtdir = dir+"/gt"
    if not os.path.exists(gtdir):
        os.makedirs(gtdir)
    for file in tqdm(files):
        imgpath = dir+"/images/"+file
        img = cv2.imread(imgpath)
        h, w, _ = img.shape
        labelpath = dir+"/labels/"+file[:-3]+"txt"
        with open(labelpath) as f:
            lines = f.readlines()
            for line in lines:
                items = line[:-1].split(" ")
                c = int(items[0])
                cx = float(items[1])
                cy = float(items[2])
                cw = float(items[3])
                ch = float(items[4])
                x1 = int((cx - cw/2)*w)
                y1 = int((cy - ch/2)*h)
                x2 = int((cx + cw/2)*w)
                y2 = int((cy + ch/2)*h)
                cv2.rectangle(img, (x1,y1),(x2,y2),(0,255,0),2)
                cv2.putText(img, str(c), (x1,y1), 3,1,(0,0,255))
            cv2.imwrite(gtdir+"/"+file, img)

if __name__=="__main__":
    generate_batch()
    show_gt()

 Shape.yaml correspondant, notez que le nombre de catégories est de 2

train: data/shape/images/
val: data/shape/images/
# number of classes
nc: 2

# class names
names: ['circle', 'rectangle']

former

Commencez l'entraînement avec la commande suivante

python train.py --data circle.yaml --cfg yolov5s.yaml --weights '' --batch-size 64

S'il y a deux types de cibles, circulaire et rectangulaire, la commande est

python train.py --data shape.yaml --cfg yolov5s.yaml --weights '' --batch-size 64

​​​​​​​  

Regardez les statistiques, les catégories et les distributions imprimées pendant la formation

 

Entraînez quelques époques pour voir les résultats

               epoch,      train/box_loss,      train/obj_loss,      train/cls_loss,   metrics/precision,      metrics/recall,     metrics/mAP_0.5,metrics/mAP_0.5:0.95,        val/box_loss,        val/obj_loss,        val/cls_loss,               x/lr0,               x/lr1,               x/lr2
                   0,             0.03892,            0.011817,                   0,             0.99998,             0.99978,               0.995,             0.92987,           0.0077891,           0.0030948,                   0,           0.0033312,           0.0033312,            0.070019
                   1,            0.017302,           0.0049876,                   0,                   1,              0.9999,               0.995,             0.99105,           0.0031843,           0.0015662,                   0,           0.0066644,           0.0066644,            0.040019
                   2,            0.011272,           0.0034826,                   0,                   1,             0.99994,               0.995,             0.99499,           0.0020194,           0.0010969,                   0,           0.0099969,           0.0099969,            0.010018
                   3,           0.0080153,           0.0027186,                   0,                   1,             0.99994,               0.995,               0.995,           0.0013095,          0.00083033,                   0,           0.0099978,           0.0099978,           0.0099978
                   4,           0.0067639,           0.0023831,                   0,                   1,             0.99996,               0.995,               0.995,          0.00099513,          0.00068878,                   0,           0.0099978,           0.0099978,           0.0099978
                   5,           0.0061637,           0.0022279,                   0,                   1,             0.99996,               0.995,               0.995,          0.00090497,          0.00064193,                   0,           0.0099961,           0.0099961,           0.0099961
                   6,           0.0058844,            0.002144,                   0,             0.99999,             0.99998,               0.995,               0.995,           0.0009117,          0.00063328,                   0,           0.0099938,           0.0099938,           0.0099938
                   7,           0.0056247,             0.00208,                   0,             0.99999,             0.99999,               0.995,               0.995,          0.00086355,          0.00061343,                   0,           0.0099911,           0.0099911,           0.0099911
                   8,           0.0054567,           0.0020223,                   0,                   1,             0.99999,               0.995,               0.995,          0.00081632,          0.00059592,                   0,           0.0099879,           0.0099879,           0.0099879
                   9,           0.0053597,           0.0019864,                   0,                   1,                   1,               0.995,               0.995,          0.00081379,          0.00058942,                   0,           0.0099842,           0.0099842,           0.0099842
                  10,           0.0053103,           0.0019559,                   0,                   1,                   1,               0.995,               0.995,           0.0008175,          0.00058669,                   0,             0.00998,             0.00998,             0.00998
                  11,           0.0052146,           0.0019445,                   0,                   1,                   1,               0.995,               0.995,          0.00083248,          0.00058731,                   0,           0.0099753,           0.0099753,           0.0099753
                  12,           0.0050852,           0.0019065,                   0,                   1,                   1,               0.995,               0.995,          0.00085092,          0.00058853,                   0,           0.0099702,           0.0099702,           0.0099702
                  13,           0.0050589,           0.0019031,                   0,                   1,                   1,               0.995,               0.995,          0.00086915,          0.00059267,                   0,           0.0099645,           0.0099645,           0.0099645
                  14,           0.0049664,           0.0018693,                   0,                   1,                   1,               0.995,               0.995,          0.00090856,          0.00059815,                   0,           0.0099584,           0.0099584,           0.0099584
                  15,           0.0049839,           0.0018568,                   0,                   1,                   1,               0.995,               0.995,          0.00093147,          0.00060425,                   0,           0.0099517,           0.0099517,           0.0099517
                  16,           0.0049079,           0.0018459,                   0,                   1,                   1,               0.995,               0.995,           0.0009656,          0.00061124,                   0,           0.0099446,           0.0099446,           0.0099446
                  17,           0.0048693,           0.0018277,                   0,                   1,                   1,               0.995,               0.995,          0.00099703,          0.00061948,                   0,            0.009937,            0.009937,            0.009937
                  18,           0.0048052,           0.0018103,                   0,                   1,                   1,               0.995,               0.995,           0.0010246,          0.00062618,                   0,           0.0099289,           0.0099289,           0.0099289
                  19,           0.0047608,           0.0017947,                   0,                   1,                   1,               0.995,               0.995,           0.0010439,          0.00063123,                   0,           0.0099203,           0.0099203,           0.0099203

Le mAP a atteint 99,5+, ce qui est vraiment bien, regardez les résultats de la prédiction

  

courbe PR

objets ronds et rectangulaires

  

déployer

Enfin, utilisez la commande suivante pour détecter, n'oubliez pas de remplacer le chemin par le chemin local

python detect.py --weights exps/yolov5s_circle/weights/best.pt --source data/circle/images

 

La démo intégrée est trop longue pour être compatible avec différents formats, et le code de déploiement onnx est beaucoup plus simple

import cv2
import numpy as np
import torch
from torchvision import transforms
import onnxruntime
from utils.general import non_max_suppression

def detect(img, ort_session):
    img = img.astype(np.float32)
    img = img / 255
    img_tensor = img.transpose(2,0,1)[None]
    ort_inputs = {ort_session.get_inputs()[0].name: img_tensor}
    pred = torch.tensor(ort_session.run(None, ort_inputs)[0])
    dets = non_max_suppression(pred, 0.25, 0.45)
    return dets[0]

def demo():
    ort_session = onnxruntime.InferenceSession("yolov5s.onnx",  providers=['TensorrtExecutionProvider'])
    img = cv2.imread("data/images/bus.jpg")
    img = cv2.resize(img,(640,640))
    dets = detect(img, ort_session)
    for det in dets:
        x1 = int(det[0])
        y1 = int(det[1])
        x2 = int(det[2])
        y2 = int(det[3])
        score = float(det[4])
        cls = int(det[5])
        info = "{}_{:.2f}".format(cls, score*100)
        cv2.rectangle(img, (x1,y1),(x2,y2),(255,255,0))
        cv2.putText(img, info, (x1,y1), 1, 1, (0,0,255))
    cv2.imwrite("runs/detect/bus.jpg", img)
if __name__=="__main__":
    demo()

Résumer

Cet article explique en détail comment générer les étiquettes requises pour les données d'entraînement à travers deux exemples de détection de cercle et de détection de rectangle, et donne l'implémentation du code de l'ensemble du processus d'entraînement, de test et de déploiement

Je suppose que tu aimes

Origine blog.csdn.net/minstyrain/article/details/123486914
conseillé
Classement