Meet YOLO26: next-gen vision AI.

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

YOLOv7, lançado em julho de 2022, foi um avanço significativo em detecção de objetos em tempo real na época do seu lançamento. Ele alcançou 56,8% de AP em uma GPU V100, estabelecendo novos benchmarks quando foi introduzido. O YOLOv7 superou detectores de objetos contemporâneos como YOLOR, YOLOX, Scaled-YOLOv4 e YOLOv5 em velocidade e precisão. O modelo é treinado no conjunto de dados MS COCO do zero, sem usar quaisquer outros conjuntos de dados ou pesos pré-treinados. O código-fonte do YOLOv7 está disponível no GitHub. Observe que modelos mais novos como YOLO11 e YOLO26 alcançaram, desde então, maior precisão com eficiência aprimorada.

Comparação do YOLOv7 com detectores de objetos SOTA

Link to this sectionComparação de detectores de objetos SOTA#

A partir dos resultados na tabela de comparação do YOLO, sabemos que o método proposto possui o melhor equilíbrio entre velocidade e precisão de forma abrangente. Se compararmos o YOLOv7-tiny-SiLU com o YOLOv5-N (r6.1), nosso método é 127 fps mais rápido e 10,7% mais preciso em AP. Além disso, o YOLOv7 tem 51,4% de AP a uma taxa de quadros de 161 fps, enquanto o PPYOLOE-L com o mesmo AP tem apenas 78 fps de taxa de quadros. Em termos de uso de parâmetros, o YOLOv7 tem 41% a menos que o PPYOLOE-L.

Se compararmos o YOLOv7-X com 114 fps de velocidade de inferência com o YOLOv5-L (r6.1) com 99 fps de velocidade de inferência, o YOLOv7-X consegue melhorar o AP em 3,9%. Se o YOLOv7-X for comparado com o YOLOv5-X (r6.1) de escala similar, a velocidade de inferência do YOLOv7-X é 31 fps mais rápida. Além disso, em termos de quantidade de parâmetros e computação, o YOLOv7-X reduz 22% dos parâmetros e 8% da computação em comparação ao YOLOv5-X (r6.1), mas melhora o AP em 2,2% (Fonte).

Desempenho
ModeloParams
(M)
FLOPs
(G)
Tamanho
(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 sectionVisão geral#

A detecção de objetos em tempo real é um componente importante em muitos sistemas de visão computacional, incluindo rastreamento de objetos, direção autônoma, robótica e análise de imagens médicas. Nos últimos anos, o desenvolvimento da detecção de objetos em tempo real tem se concentrado na concepção de arquiteturas eficientes e na melhoria da velocidade de inferência de várias CPUs, GPUs e unidades de processamento neural (NPUs). O YOLOv7 suporta tanto dispositivos móveis com GPU quanto dispositivos com GPU, desde a borda até a nuvem.

Ao contrário dos detectores de objetos em tempo real tradicionais que se concentram na otimização da arquitetura, o YOLOv7 introduz um foco na otimização do processo de treinamento. Isso inclui módulos e métodos de otimização projetados para melhorar a precisão da detecção de objetos sem aumentar o custo de inferência, um conceito conhecido como "trainable bag-of-freebies".

Link to this sectionPrincipais recursos#

O YOLOv7 introduz várias funcionalidades principais:

  1. Reparametrização de Modelo: O YOLOv7 propõe um modelo reparametrizado planejado, que é uma estratégia aplicável a camadas em diferentes redes com o conceito de caminho de propagação de gradiente.

  2. Atribuição Dinâmica de Rótulos: O treinamento do modelo com múltiplas camadas de saída apresenta um novo problema: "Como atribuir alvos dinâmicos para as saídas de diferentes ramos?" Para resolver esse problema, o YOLOv7 introduz um novo método de atribuição de rótulos chamado atribuição de rótulos guiada por lead de grosso para fino.

  3. Escalonamento Estendido e Composto: O YOLOv7 propõe métodos de "escalonamento estendido" e "composto" para o detector de objetos em tempo real que podem utilizar efetivamente parâmetros e computação.

  4. Eficiência: O método proposto pelo YOLOv7 pode reduzir efetivamente cerca de 40% dos parâmetros e 50% da computação de detectores de objetos em tempo real de última geração, e possui uma velocidade de inferência mais rápida e maior precisão de detecção.

Link to this sectionExemplos de uso#

A Ultralytics não publica pesos pré-treinados yolov7.pt ou arquivos YAML ultralytics/cfg/models/v7/, e o treinamento e inferência nativos em PyTorch para YOLOv7 não são suportados pelo pacote Python da Ultralytics. No entanto, você pode trazer um checkpoint do YOLOv7 treinado no repositório upstream YOLOv7 para a Ultralytics exportando-o para ONNX ou TensorRT, conforme mostrado abaixo.

Link to this sectionExportação ONNX#

Para usar o modelo ONNX do YOLOv7 com a Ultralytics:

  1. (Opcional) Instale a Ultralytics e exporte um modelo ONNX para ter as dependências necessárias instaladas automaticamente:

    pip install ultralytics
    yolo export model=yolo26n.pt format=onnx
  2. Exporte o modelo YOLOv7 desejado usando o exportador no repositório 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. Modifique o grafo do modelo ONNX para ser compatível com a Ultralytics usando o seguinte script:

    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. Você pode então carregar o modelo ONNX modificado e executar a inferência com ele na Ultralytics normalmente:

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

Link to this sectionExportação TensorRT#

  1. Siga os passos 1-2 na seção Exportação ONNX.

  2. Instale o pacote Python TensorRT:

    pip install tensorrt
  3. Execute o seguinte script para converter o modelo ONNX modificado para o motor TensorRT:

    from ultralytics.utils.export import export_engine
    
    export_engine("yolov7-ultralytics.onnx", half=True)
  4. Carregue e execute o modelo na Ultralytics:

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

Link to this sectionCitações e Agradecimentos#

Gostaríamos de agradecer aos autores do YOLOv7 por suas contribuições significativas no campo da detecção de objetos em tempo real:

Citação
@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}
}

O artigo oficial do YOLOv7 foi publicado no CVF 2023 Open Access, com um preprint no arXiv. Os autores disponibilizaram seu trabalho publicamente, e a base de código pode ser acessada no GitHub. Agradecemos seus esforços em avançar o campo e tornar seu trabalho acessível à comunidade em geral.

Link to this sectionFAQ#

Link to this sectionO que é o YOLOv7 e por que ele é considerado um avanço na detecção de objetos em tempo real?#

O YOLOv7, lançado em julho de 2022, foi um modelo significativo de detecção de objetos em tempo real que alcançou excelente velocidade e precisão na época de seu lançamento. Ele superou modelos contemporâneos como YOLOX, YOLOv5 e PPYOLOE tanto no uso de parâmetros quanto na velocidade de inferência. As características distintivas do YOLOv7 incluem sua reparametrização de modelo e atribuição dinâmica de rótulos, que otimizam seu desempenho sem aumentar os custos de inferência. Para mais detalhes técnicos sobre sua arquitetura e métricas de comparação com outros detectores de objetos de última geração, consulte o artigo do YOLOv7.

Link to this sectionComo o YOLOv7 melhora em relação aos modelos YOLO anteriores, como o YOLOv4 e o YOLOv5?#

O YOLOv7 introduz várias inovações, incluindo a reparametrização de modelo e a atribuição dinâmica de rótulos, que aprimoram o processo de treinamento e melhoram a precisão da inferência. Comparado ao YOLOv5, o YOLOv7 aumenta significativamente a velocidade e a precisão. Por exemplo, o YOLOv7-X melhora a precisão em 2,2% e reduz os parâmetros em 22% em comparação com o YOLOv5-X. Comparações detalhadas podem ser encontradas na tabela de desempenho Comparação do YOLOv7 com detectores de objetos SOTA.

Link to this sectionPosso usar o YOLOv7 com ferramentas e plataformas da Ultralytics?#

Atualmente, a Ultralytics suporta apenas a inferência ONNX e TensorRT do YOLOv7. Para executar a versão exportada do YOLOv7 em ONNX e TensorRT com a Ultralytics, verifique a seção Exemplos de Uso.

Link to this sectionComo posso treinar um modelo YOLOv7 personalizado usando meu próprio conjunto de dados?#

Para instalar e treinar um modelo YOLOv7 personalizado, siga estes passos:

  1. Clone o repositório do YOLOv7:

    git clone https://github.com/WongKinYiu/yolov7
  2. Navegue até o diretório clonado e instale as dependências:

    cd yolov7
    pip install -r requirements.txt
  3. Prepare seu conjunto de dados e configure os parâmetros do modelo de acordo com as instruções de uso fornecidas no repositório. Para mais orientações, visite o repositório GitHub do YOLOv7 para obter as informações e atualizações mais recentes.

  4. Após o treinamento, você pode exportar o modelo para ONNX ou TensorRT para uso na Ultralytics, conforme mostrado em Exemplos de Uso.

Link to this sectionQuais são os principais recursos e otimizações introduzidos no YOLOv7?#

O YOLOv7 oferece várias funcionalidades principais que revolucionam a detecção de objetos em tempo real:

  • Reparametrização de Modelo: Aprimora o desempenho do modelo otimizando os caminhos de propagação de gradiente.
  • Atribuição Dinâmica de Rótulos: Usa um método guiado por lead de grosso para fino para atribuir alvos dinâmicos para saídas em diferentes ramos, melhorando a precisão.
  • Escalonamento Estendido e Composto: Utiliza eficientemente parâmetros e computação para escalar o modelo para várias aplicações em tempo real.
  • Eficiência: Reduz a contagem de parâmetros em 40% e a computação em 50% em comparação com outros modelos de última geração, alcançando velocidades de inferência mais rápidas.

Para mais detalhes sobre esses recursos, consulte a seção Visão Geral do YOLOv7.

Comentários