Meet YOLO26: next-gen vision AI.

Link to this sectionYOLOv7 : Trainable Bag-of-Freebies#

YOLOv7, publié en juillet 2022, constituait une avancée significative en matière de détection d'objets en temps réel au moment de sa sortie. Il a atteint 56,8 % d'AP sur GPU V100, établissant de nouveaux points de référence lors de son introduction. YOLOv7 a surpassé les détecteurs d'objets contemporains tels que YOLOR, YOLOX, Scaled-YOLOv4 et YOLOv5 en termes de vitesse et de précision. Le modèle est entraîné sur le jeu de données MS COCO à partir de zéro, sans utiliser d'autres jeux de données ou de poids pré-entraînés. Le code source de YOLOv7 est disponible sur GitHub. Note que des modèles plus récents comme YOLO11 et YOLO26 ont depuis atteint une précision supérieure avec une efficacité améliorée.

Comparaison de YOLOv7 avec les détecteurs d'objets SOTA

Link to this sectionComparaison des détecteurs d'objets SOTA#

D'après les résultats du tableau de comparaison YOLO, nous savons que la méthode proposée offre le meilleur compromis vitesse-précision de manière exhaustive. Si l'on compare YOLOv7-tiny-SiLU avec YOLOv5-N (r6.1), notre méthode est 127 fps plus rapide et 10,7 % plus précise en AP. De plus, YOLOv7 affiche 51,4 % d'AP à un débit de 161 fps, tandis que PPYOLOE-L avec le même AP n'atteint qu'un débit de 78 fps. En termes d'utilisation des paramètres, YOLOv7 en utilise 41 % de moins que PPYOLOE-L.

Si l'on compare YOLOv7-X avec une vitesse d'inférence de 114 fps à YOLOv5-L (r6.1) avec une vitesse d'inférence de 99 fps, YOLOv7-X peut améliorer l'AP de 3,9 %. Si YOLOv7-X est comparé à YOLOv5-X (r6.1) à échelle similaire, la vitesse d'inférence de YOLOv7-X est 31 fps plus rapide. De plus, en termes de nombre de paramètres et de calcul, YOLOv7-X réduit de 22 % les paramètres et de 8 % les calculs par rapport à YOLOv5-X (r6.1), mais améliore l'AP de 2,2 % (Source).

Performance
ModèleParamètres
(M)
FLOPs
(G)
Taille
(pixels)
FPSAPtest / val
50-95
APtest
50
APtest
75
APtest
S
APtest
M
APtest
L
YOLOX-S9.026.864010240,5 % / 40,5 %-----
YOLOX-M25.373.86408147,2 % / 46,9 %-----
YOLOX-L54.2155.66406950,1 % / 49,7 %-----
YOLOX-X99.1281.96405851,5 % / 51,1 %-----
PPYOLOE-S7.917.464020843,1 % / 42,7 %60,5 %46,6 %23,2 %46,4 %56,9 %
PPYOLOE-M23,449.964012348,9 % / 48,6 %66,5 %53,0 %28,6 %52,9 %63,8 %
PPYOLOE-L52.2110,16407851,4 % / 50,9 %68,9 %55,6 %31,4 %55,3 %66,1 %
PPYOLOE-X98,4206,66404552,2 % / 51,9 %69,9 %56,5 %33,3 %56,3 %66,4 %
YOLOv5-N (r6.1)1.94.5640159- / 28,0 %-----
YOLOv5-S (r6.1)7.216,5640156- / 37,4 %-----
YOLOv5-M (r6.1)21.249.0640122- / 45,4 %-----
YOLOv5-L (r6.1)46,5109,164099- / 49,0 %-----
YOLOv5-X (r6.1)86,7205,764083- / 50,7 %-----
YOLOR-CSP52.9120,464010651,1 % / 50,8 %69,6 %55,7 %31,7 %55,3 %64,7 %
YOLOR-CSP-X96.9226,86408753,0 % / 52,7 %71,4 %57,9 %33,7 %57,1 %66,8 %
YOLOv7-tiny-SiLU6.213,864028638,7 % / 38,7 %56,7 %41,7 %18,8 %42,4 %51,9 %
YOLOv736.9104.764016151,4 % / 51,2 %69,7 %55,9 %31,8 %55,5 %65,0 %
YOLOv7-X71.3189.964011453,1 % / 52,9 %71,2 %57,8 %33,8 %57,1 %67,4 %
YOLOv5-N6 (r6.1)3.218,41280123/ 36,0 %-----
YOLOv5-S6 (r6.1)12.667,21280122/ 44,8 %-----
YOLOv5-M6 (r6.1)35,7200,0128090/ 51,3 %-----
YOLOv5-L6 (r6.1)76.8445,6128063/ 53,7 %-----
YOLOv5-X6 (r6.1)140,7839,2128038/ 55,0 %-----
YOLOR-P637,2325,612807653,9 % / 53,5 %71,4 %58,9 %36,1 %57,7 %65,6 %
YOLOR-W679,8453,212806655,2 % / 54,8 %72,7 %60,5 %37,7 %59,1 %67,1 %
YOLOR-E6115,8683,212804555,8 % / 55,7 %73,4 %61,1 %38,4 %59,7 %67,7 %
YOLOR-D6151.7935,612803456,5 % / 56,1 %74,1 %61,9 %38,9 %60,4 %68,7 %
YOLOv7-W670,4360,012808454,9 % / 54,6 %72,6 %60,1 %37,3 %58,7 %67,1 %
YOLOv7-E697.2515,212805656,0 % / 55,9 %73,5 %61,2 %38,0 %59,9 %68,4 %
YOLOv7-D6154,7806,812804456,6 % / 56,3 %74,0 %61,8 %38,8 %60,1 %69,5 %
YOLOv7-E6E151.7843,212803656,8 % / 56,8 %74,4 %62,1 %39,3 %60,5 %69,0 %

Link to this sectionPrésentation#

Real-time object detection is an important component in many computer vision systems, including multi-object tracking, autonomous driving, robotics, and medical image analysis. In recent years, real-time object detection development has focused on designing efficient architectures and improving the inference speed of various CPUs, GPUs, and neural processing units (NPUs). YOLOv7 supports both mobile GPU and GPU devices, from the edge to the cloud.

Contrairement aux détecteurs d'objets en temps réel traditionnels qui se concentrent sur l'optimisation de l'architecture, YOLOv7 met l'accent sur l'optimisation du processus d'entraînement. Cela inclut des modules et des méthodes d'optimisation conçus pour améliorer la précision de la détection d'objets sans augmenter le coût d'inférence, un concept connu sous le nom de "trainable bag-of-freebies" (sac d'astuces entraînables).

Link to this sectionFonctionnalités clés#

YOLOv7 introduit plusieurs fonctionnalités clés :

  1. Reparamétrage du modèle : YOLOv7 propose un modèle reparamétré planifié, une stratégie applicable aux couches dans différents réseaux avec le concept de chemin de propagation du gradient.

  2. Assignation dynamique d'étiquettes : L'entraînement d'un modèle avec plusieurs couches de sortie présente un nouveau problème : "Comment assigner des cibles dynamiques aux sorties de différentes branches ?" Pour résoudre ce problème, YOLOv7 introduit une nouvelle méthode d'assignation d'étiquettes appelée assignation guidée par leader de grossier à fin.

  3. Mise à l'échelle étendue et composée : YOLOv7 propose des méthodes de "mise à l'échelle étendue" et "composée" pour le détecteur d'objets en temps réel, capables d'utiliser efficacement les paramètres et le calcul.

  4. Efficacité : La méthode proposée par YOLOv7 peut réduire efficacement environ 40 % des paramètres et 50 % des calculs des détecteurs d'objets en temps réel à l'état de l'art, tout en offrant une vitesse d'inférence plus rapide et une précision de détection supérieure.

Link to this sectionExemples d'utilisation#

Ultralytics ne publie pas les poids pré-entraînés yolov7.pt ni les YAML ultralytics/cfg/models/v7/, et l'entraînement ainsi que l'inférence en PyTorch natif pour YOLOv7 ne sont pas pris en charge par le package Python Ultralytics. Cependant, tu peux importer un point de contrôle YOLOv7 entraîné dans le dépôt YOLOv7 officiel vers Ultralytics en l'exportant vers ONNX ou TensorRT, comme indiqué ci-dessous.

Link to this sectionExportation ONNX#

Pour utiliser le modèle YOLOv7 ONNX avec Ultralytics :

  1. (Optionnel) Installe Ultralytics et exporte un modèle ONNX pour que les dépendances nécessaires soient installées automatiquement :

    pip install ultralytics
    yolo export model=yolo26n.pt format=onnx
  2. Exporte le modèle YOLOv7 souhaité en utilisant l'exportateur dans le dépôt YOLOv7 :

    git clone https://github.com/WongKinYiu/yolov7
    cd yolov7
    python export.py --weights yolov7-tiny.pt --grid --end2end --simplify --topk-all 100 --iou-thres 0.65 --conf-thres 0.35 --img-size 640 640 --max-wh 640
  3. Modifie le graphe du modèle ONNX pour le rendre compatible avec Ultralytics en utilisant le script suivant :

    import numpy as np
    import onnx
    from onnx import helper, numpy_helper
    
    # Load the ONNX model
    model_path = "yolov7/yolov7-tiny.onnx"  # Replace with your model path
    model = onnx.load(model_path)
    graph = model.graph
    
    # Fix input shape to batch size 1
    input_shape = graph.input[0].type.tensor_type.shape
    input_shape.dim[0].dim_value = 1
    
    # Define the output of the original model
    original_output_name = graph.output[0].name
    
    # Create slicing nodes
    sliced_output_name = f"{original_output_name}_sliced"
    
    # Define initializers for slicing (remove the first value)
    start = numpy_helper.from_array(np.array([1], dtype=np.int64), name="slice_start")
    end = numpy_helper.from_array(np.array([7], dtype=np.int64), name="slice_end")
    axes = numpy_helper.from_array(np.array([1], dtype=np.int64), name="slice_axes")
    steps = numpy_helper.from_array(np.array([1], dtype=np.int64), name="slice_steps")
    
    graph.initializer.extend([start, end, axes, steps])
    
    slice_node = helper.make_node(
        "Slice",
        inputs=[original_output_name, "slice_start", "slice_end", "slice_axes", "slice_steps"],
        outputs=[sliced_output_name],
        name="SliceNode",
    )
    graph.node.append(slice_node)
    
    # Define segment slicing
    seg1_start = numpy_helper.from_array(np.array([0], dtype=np.int64), name="seg1_start")
    seg1_end = numpy_helper.from_array(np.array([4], dtype=np.int64), name="seg1_end")
    seg2_start = numpy_helper.from_array(np.array([4], dtype=np.int64), name="seg2_start")
    seg2_end = numpy_helper.from_array(np.array([5], dtype=np.int64), name="seg2_end")
    seg3_start = numpy_helper.from_array(np.array([5], dtype=np.int64), name="seg3_start")
    seg3_end = numpy_helper.from_array(np.array([6], dtype=np.int64), name="seg3_end")
    
    graph.initializer.extend([seg1_start, seg1_end, seg2_start, seg2_end, seg3_start, seg3_end])
    
    # Create intermediate tensors for segments
    segment_1_name = f"{sliced_output_name}_segment1"
    segment_2_name = f"{sliced_output_name}_segment2"
    segment_3_name = f"{sliced_output_name}_segment3"
    
    # Add segment slicing nodes
    graph.node.extend(
        [
            helper.make_node(
                "Slice",
                inputs=[sliced_output_name, "seg1_start", "seg1_end", "slice_axes", "slice_steps"],
                outputs=[segment_1_name],
                name="SliceSegment1",
            ),
            helper.make_node(
                "Slice",
                inputs=[sliced_output_name, "seg2_start", "seg2_end", "slice_axes", "slice_steps"],
                outputs=[segment_2_name],
                name="SliceSegment2",
            ),
            helper.make_node(
                "Slice",
                inputs=[sliced_output_name, "seg3_start", "seg3_end", "slice_axes", "slice_steps"],
                outputs=[segment_3_name],
                name="SliceSegment3",
            ),
        ]
    )
    
    # Concatenate the segments
    concat_output_name = f"{sliced_output_name}_concat"
    concat_node = helper.make_node(
        "Concat",
        inputs=[segment_1_name, segment_3_name, segment_2_name],
        outputs=[concat_output_name],
        axis=1,
        name="ConcatSwapped",
    )
    graph.node.append(concat_node)
    
    # Reshape to [1, -1, 6]
    reshape_shape = numpy_helper.from_array(np.array([1, -1, 6], dtype=np.int64), name="reshape_shape")
    graph.initializer.append(reshape_shape)
    
    final_output_name = f"{concat_output_name}_batched"
    reshape_node = helper.make_node(
        "Reshape",
        inputs=[concat_output_name, "reshape_shape"],
        outputs=[final_output_name],
        name="AddBatchDimension",
    )
    graph.node.append(reshape_node)
    
    # Get the shape of the reshaped tensor
    shape_node_name = f"{final_output_name}_shape"
    shape_node = helper.make_node(
        "Shape",
        inputs=[final_output_name],
        outputs=[shape_node_name],
        name="GetShapeDim",
    )
    graph.node.append(shape_node)
    
    # Extract the second dimension
    dim_1_index = numpy_helper.from_array(np.array([1], dtype=np.int64), name="dim_1_index")
    graph.initializer.append(dim_1_index)
    
    second_dim_name = f"{final_output_name}_dim1"
    gather_node = helper.make_node(
        "Gather",
        inputs=[shape_node_name, "dim_1_index"],
        outputs=[second_dim_name],
        name="GatherSecondDim",
    )
    graph.node.append(gather_node)
    
    # Subtract from 100 to determine how many values to pad
    target_size = numpy_helper.from_array(np.array([100], dtype=np.int64), name="target_size")
    graph.initializer.append(target_size)
    
    pad_size_name = f"{second_dim_name}_padsize"
    sub_node = helper.make_node(
        "Sub",
        inputs=["target_size", second_dim_name],
        outputs=[pad_size_name],
        name="CalculatePadSize",
    )
    graph.node.append(sub_node)
    
    # Build the [2, 3] pad array:
    # 1st row -> [0, 0, 0] (no padding at the start of any dim)
    # 2nd row -> [0, pad_size, 0] (pad only at the end of the second dim)
    pad_starts = numpy_helper.from_array(np.array([0, 0, 0], dtype=np.int64), name="pad_starts")
    graph.initializer.append(pad_starts)
    
    zero_scalar = numpy_helper.from_array(np.array([0], dtype=np.int64), name="zero_scalar")
    graph.initializer.append(zero_scalar)
    
    pad_ends_name = "pad_ends"
    concat_pad_ends_node = helper.make_node(
        "Concat",
        inputs=["zero_scalar", pad_size_name, "zero_scalar"],
        outputs=[pad_ends_name],
        axis=0,
        name="ConcatPadEnds",
    )
    graph.node.append(concat_pad_ends_node)
    
    pad_values_name = "pad_values"
    concat_pad_node = helper.make_node(
        "Concat",
        inputs=["pad_starts", pad_ends_name],
        outputs=[pad_values_name],
        axis=0,
        name="ConcatPadStartsEnds",
    )
    graph.node.append(concat_pad_node)
    
    # Create Pad operator to pad with zeros
    pad_output_name = f"{final_output_name}_padded"
    pad_constant_value = numpy_helper.from_array(
        np.array([0.0], dtype=np.float32),
        name="pad_constant_value",
    )
    graph.initializer.append(pad_constant_value)
    
    pad_node = helper.make_node(
        "Pad",
        inputs=[final_output_name, pad_values_name, "pad_constant_value"],
        outputs=[pad_output_name],
        mode="constant",
        name="PadToFixedSize",
    )
    graph.node.append(pad_node)
    
    # Update the graph's final output to [1, 100, 6]
    new_output_type = onnx.helper.make_tensor_type_proto(
        elem_type=graph.output[0].type.tensor_type.elem_type, shape=[1, 100, 6]
    )
    new_output = onnx.helper.make_value_info(name=pad_output_name, type_proto=new_output_type)
    
    # Replace the old output with the new one
    graph.output.pop()
    graph.output.extend([new_output])
    
    # Save the modified model
    onnx.save(model, "yolov7-ultralytics.onnx")
  4. Tu peux ensuite charger le modèle ONNX modifié et exécuter l'inférence avec celui-ci dans Ultralytics normalement :

    from ultralytics import ASSETS, YOLO
    
    model = YOLO("yolov7-ultralytics.onnx", task="detect")
    
    results = model(ASSETS / "bus.jpg")

Link to this sectionExportation TensorRT#

  1. Suis les étapes 1 à 2 de la section Exportation ONNX.

  2. Installe le package Python TensorRT :

    pip install tensorrt
  3. Exécute le script suivant pour convertir le modèle ONNX modifié en moteur TensorRT :

    from ultralytics.utils.export import export_engine
    
    export_engine("yolov7-ultralytics.onnx", half=True)
  4. Charge et exécute le modèle dans Ultralytics :

    from ultralytics import ASSETS, YOLO
    
    model = YOLO("yolov7-ultralytics.engine", task="detect")
    
    results = model(ASSETS / "bus.jpg")

Link to this sectionCitations et remerciements#

Nous tenons à remercier les auteurs de YOLOv7 pour leurs contributions significatives dans le domaine de la détection d'objets en temps réel :

Citation
@inproceedings{wang2023yolov7,
  title={YOLOv7: Trainable Bag-of-Freebies Sets New State-of-the-Art for Real-Time Object Detectors},
  author={Wang, Chien-Yao and Bochkovskiy, Alexey and Liao, Hong-Yuan Mark},
  booktitle={Proceedings of the IEEE/CVF conference on Computer Vision and Pattern Recognition (CVPR)},
  pages={7464--7475},
  year={2023}
}

L'article officiel YOLOv7 a été publié dans le CVF 2023 Open Access, avec une prépublication sur arXiv. Les auteurs ont rendu leur travail publiquement disponible, et le code peut être consulté sur GitHub. Nous apprécions leurs efforts pour faire avancer le domaine et rendre leur travail accessible à la communauté au sens large.

Link to this sectionFAQ#

Link to this sectionQu'est-ce que YOLOv7 et pourquoi est-il considéré comme une avancée dans la détection d'objets en temps réel ?#

YOLOv7, sorti en juillet 2022, était un modèle de détection d'objets en temps réel significatif qui a atteint une vitesse et une précision excellentes au moment de sa sortie. Il a surpassé les modèles contemporains tels que YOLOX, YOLOv5 et PPYOLOE, tant en termes d'utilisation des paramètres que de vitesse d'inférence. Les caractéristiques distinctives de YOLOv7 incluent son reparamétrage du modèle et son assignation dynamique d'étiquettes, qui optimisent ses performances sans augmenter les coûts d'inférence. Pour plus de détails techniques sur son architecture et ses métriques de comparaison avec d'autres détecteurs d'objets à l'état de l'art, reporte-toi à l'article YOLOv7.

Link to this sectionComment YOLOv7 améliore-t-il les modèles YOLO précédents comme YOLOv4 et YOLOv5 ?#

YOLOv7 introduit plusieurs innovations, notamment le reparamétrage du modèle et l'assignation dynamique d'étiquettes, qui améliorent le processus d'entraînement et la précision de l'inférence. Par rapport à YOLOv5, YOLOv7 augmente considérablement la vitesse et la précision. Par exemple, YOLOv7-X améliore la précision de 2,2 % et réduit les paramètres de 22 % par rapport à YOLOv5-X. Des comparaisons détaillées se trouvent dans le tableau de performance Comparaison de YOLOv7 avec les détecteurs d'objets SOTA.

Link to this sectionPuis-je utiliser YOLOv7 avec les outils et plateformes Ultralytics ?#

À ce jour, Ultralytics ne prend en charge que l'inférence YOLOv7 via ONNX et TensorRT. Pour exécuter la version exportée de YOLOv7 en ONNX et TensorRT avec Ultralytics, consulte la section Exemples d'utilisation.

Link to this sectionComment entraîner un modèle YOLOv7 personnalisé en utilisant mon jeu de données ?#

Pour installer et entraîner un modèle YOLOv7 personnalisé, suis ces étapes :

  1. Clone le dépôt YOLOv7 :

    git clone https://github.com/WongKinYiu/yolov7
  2. Accède au répertoire cloné et installe les dépendances :

    cd yolov7
    pip install -r requirements.txt
  3. Prépare ton jeu de données et configure les paramètres du modèle selon les instructions d'utilisation fournies dans le dépôt. Pour obtenir des conseils supplémentaires, visite le dépôt GitHub de YOLOv7 pour les dernières informations et mises à jour.

  4. Après l'entraînement, tu peux exporter le modèle vers ONNX ou TensorRT pour l'utiliser dans Ultralytics comme indiqué dans Exemples d'utilisation.

Link to this sectionQuelles sont les principales fonctionnalités et optimisations introduites dans YOLOv7 ?#

YOLOv7 offre plusieurs fonctionnalités clés qui révolutionnent la détection d'objets en temps réel :

  • Reparamétrage du modèle : Améliore les performances du modèle en optimisant les chemins de propagation du gradient.
  • Assignation dynamique d'étiquettes : Utilise une méthode guidée par leader de grossier à fin pour assigner des cibles dynamiques aux sorties sur différentes branches, améliorant ainsi la précision.
  • Mise à l'échelle étendue et composée : Utilise efficacement les paramètres et le calcul pour mettre à l'échelle le modèle pour diverses applications en temps réel.
  • Efficacité : Réduit le nombre de paramètres de 40 % et les calculs de 50 % par rapport à d'autres modèles à l'état de l'art tout en atteignant des vitesses d'inférence plus rapides.

Pour plus de détails sur ces fonctionnalités, voir la section Présentation de YOLOv7.

Commentaires