YOLO Vision 2026:

Como converter anotações COCO para o formato YOLO#

O treinamento de modelos Ultralytics YOLO requer anotações no formato YOLO, mas muitas ferramentas de anotação populares exportam no formato COCO JSON em vez disso. Este guia mostra como converter tuas anotações COCO para o formato YOLO e começar a treinar modelos de detecção de objetos, segmentação de instâncias e estimação de pose.

Prefere ignorar a conversão?

Para treinar diretamente no formato COCO JSON sem gerar arquivos .txt, consulta Train YOLO on COCO JSON Without Conversion.

Por que converter de COCO para YOLO?#

O formato COCO JSON armazena todas as anotações em um único arquivo, enquanto o YOLO usa um arquivo de texto por imagem com coordenadas normalizadas. A conversão é necessária porque:

  • Os modelos YOLO exigem arquivos de rótulo .txt com um arquivo por imagem, contendo class x_center y_center width height em coordenadas normalizadas.
  • O COCO JSON usa coordenadas de pixel no formato [x_min, y_min, width, height] com um único arquivo JSON para todas as imagens.
  • Os IDs de classe diferem — o COCO usa valores arbitrários de category_id, enquanto o YOLO exige IDs de classe indexados a zero.
FuncionalidadeCOCO JSONYOLO TXT
EstruturaArquivo JSON único para todas as imagensUm arquivo .txt por imagem
Formato de Bbox[x_min, y_min, width, height] em pixelsclass x_center y_center width height normalizado (0-1)
IDs de classecategory_id (pode começar a partir de qualquer número)Indexado em zero (começa de 0)
SegmentaçãoMatrizes de polígonos no campo segmentationCoordenadas de polígono após o ID da classe
Keypoints[x, y, visibility, ...] em pixels[x, y, visibility, ...] normalizado

Início Rápido#

A maneira mais rápida de converter anotações COCO e iniciar o treinamento:

from ultralytics.data.converter import convert_coco

convert_coco(
    labels_dir="my_dataset/annotations/",  # directory containing your JSON files
    save_dir="my_dataset/converted/",  # where to save converted labels
    cls91to80=False,  # set False for custom datasets (see warning below)
)

Após a conversão, organiza a tua estrutura de diretórios, cria um dataset.yaml e começa o treinamento. Consulta o guia passo a passo completo abaixo.

Datasets personalizados: sempre use `cls91to80=False`

O padrão de cls91to80=True foi projetado apenas para o dataset COCO padrão com 80 classes de objetos, que mapeia 91 IDs de categorias não contíguas para 80 IDs de classe contíguas. Para qualquer dataset personalizado, deves definir cls91to80=False — caso contrário, os teus IDs de classe serão mapeados incorretamente em segundo plano e o teu modelo aprenderá as classes erradas.

Guia de conversão passo a passo#

1. Prepare seu dataset COCO#

Um dataset típico em formato COCO exportado de ferramentas de anotação tem a seguinte estrutura:

my_dataset/
├── images/
│   ├── train/
│   │   ├── img_001.jpg
│   │   ├── img_002.jpg
│   │   └── ...
│   └── val/
│       ├── img_100.jpg
│       └── ...
└── annotations/
    ├── instances_train.json
    └── instances_val.json

Cada arquivo JSON segue a especificação do formato de dados COCO com três campos obrigatórios — images, annotations e categories:

{
    "images": [{ "id": 1, "file_name": "img_001.jpg", "width": 640, "height": 480 }],
    "annotations": [
        {
            "id": 1,
            "image_id": 1,
            "category_id": 1,
            "bbox": [100, 50, 200, 150],
            "area": 30000,
            "iscrowd": 0
        }
    ],
    "categories": [
        { "id": 1, "name": "helmet" },
        { "id": 2, "name": "vest" }
    ]
}

2. Converter anotações#

Usa a função convert_coco() para converter as tuas anotações COCO JSON para o formato YOLO .txt:

Converter COCO para o formato YOLO
from ultralytics.data.converter import convert_coco

convert_coco(
    labels_dir="my_dataset/annotations/",
    save_dir="my_dataset/converted/",
    cls91to80=False,
)

convert_coco() grava um arquivo .txt por imagem anotada em um subdiretório labels/ nomeado após cada arquivo JSON, com o prefixo instances_ removido (então instances_train.json produz labels/train/). Imagens sem anotações são ignoradas e não recebem arquivo de rótulo, portanto a árvore labels/ pode não espelhar todas as imagens:

my_dataset/converted/
└── labels/
    ├── train/   # from instances_train.json
    │   ├── img_001.txt
    │   └── ...
    └── val/     # from instances_val.json
        └── ...
Executar novamente cria uma nova pasta de saída

convert_coco() nunca sobrescreve um save_dir existente: se my_dataset/converted/ já existir, uma nova execução grava em my_dataset/converted-2/ em vez disso. Apaga a saída anterior (ou altera save_dir) antes de executar novamente, ou os próximos passos lerão rótulos desatualizados.

3. Organizar a estrutura de diretórios#

Após a conversão, os arquivos de rótulo precisam ser colocados junto às tuas imagens. O YOLO espera um diretório labels/ que espelhe o diretório images/:

import shutil
from pathlib import Path

converted_dir = Path("my_dataset/converted/labels")
dataset_dir = Path("my_dataset")

# convert_coco names each subdirectory after its JSON file (minus the "instances_" prefix),
# so iterate the actual subdirectories instead of assuming "train"/"val".
for src in converted_dir.iterdir():
    if not src.is_dir():
        continue
    dst = dataset_dir / "labels" / src.name
    dst.mkdir(parents=True, exist_ok=True)
    for f in src.glob("*.txt"):
        shutil.move(str(f), str(dst / f.name))

A tua estrutura de dataset final deve ficar assim:

my_dataset/
├── images/
│   ├── train/
│   │   ├── img_001.jpg
│   │   └── ...
│   └── val/
│       └── ...
├── labels/
│   ├── train/
│   │   ├── img_001.txt
│   │   └── ...
│   └── val/
│       └── ...
└── dataset.yaml

4. Criar dataset.yaml#

Cria um arquivo de configuração dataset.yaml que mapeie as tuas categorias COCO para nomes de classes YOLO. Este arquivo diz ao YOLO onde estão os teus dados e quais classes detectar:

import json
from pathlib import Path

import yaml

# Read categories from your COCO JSON
with open("my_dataset/annotations/instances_train.json") as f:
    coco = json.load(f)

# Build class names matching convert_coco output (category_id - 1)
categories = sorted(coco["categories"], key=lambda x: x["id"])
names = {cat["id"] - 1: cat["name"] for cat in categories}
# NOTE: convert_coco maps class IDs as category_id - 1, so category_id must
# start from 1. If your categories start from 0, add 1 to each ID first.

# Create dataset.yaml
dataset = {
    "path": str(Path("my_dataset").resolve()),
    "train": "images/train",
    "val": "images/val",
    "names": names,
}

with open("my_dataset/dataset.yaml", "w") as f:
    yaml.dump(dataset, f, default_flow_style=False)

O arquivo YAML resultante:

path: /absolute/path/to/my_dataset
train: images/train
val: images/val
names:
    0: helmet
    1: vest

Para mais detalhes sobre o formato YAML de datasets, consulta o guia de configuração de datasets.

5. Treine seu modelo YOLO#

Com seu dataset convertido pronto, treine um modelo YOLO:

Treinar em dados COCO convertidos
from ultralytics import YOLO

model = YOLO("yolo26n.pt")  # load a pretrained model
results = model.train(data="my_dataset/dataset.yaml", epochs=100, imgsz=640)

Para dicas de treinamento e melhores práticas, consulta o guia de treinamento de modelos.

6. Verifique sua conversão#

Antes de treinar, verifique alguns arquivos de rótulo para confirmar se os IDs de classe e as coordenadas estão corretos:

from pathlib import Path

label_file = Path("my_dataset/labels/train/img_001.txt")
for line in label_file.read_text().strip().splitlines():
    parts = line.split()
    cls_id = int(parts[0])
    coords = [float(v) for v in parts[1:5]]
    assert cls_id >= 0, f"Negative class ID {cls_id} — category_id in your JSON may start from 0"
    assert all(0 <= v <= 1 for v in coords), f"Coordinates out of [0, 1] range: {coords}"
Dica

Se vires IDs de classe negativos, o teu COCO JSON provavelmente usa category_id começando em 0. Adiciona 1 a todos os valores de category_id no teu JSON antes de executar convert_coco(), já que ele mapeia os IDs de classe como category_id - 1.

Solução de problemas comuns#

IDs de classe errados após a conversão#

Se o teu modelo treinar mas detectar classes de objetos erradas, provavelmente estás a usar cls91to80=True (padrão) num dataset personalizado. Isto mapeia os teus valores de category_id através da tabela de consulta de 91 para 80 do COCO, o que só é correto para o dataset COCO padrão.

Solução: Usa sempre cls91to80=False para datasets personalizados.

Nenhum rótulo encontrado durante o treinamento#

Se o treinamento mostrar WARNING: No labels found ou 0 images, N backgrounds, os teus arquivos de rótulo não estão no diretório esperado. O convert_coco() guarda os rótulos num diretório de saída separado (por exemplo, save_dir/labels/train/), mas o YOLO espera que labels/ fique em paralelo com images/ dentro do diretório do teu dataset.

Solução: Move os arquivos de rótulo para corresponder à estrutura de diretórios esperada. Certifica-te de que labels/train/ é um irmão de images/train/.

KeyError durante a conversão#

Se obtiveres KeyError: 'bbox' ou erros semelhantes ao executar convert_coco(), o teu labels_dir provavelmente contém arquivos JSON que não são de instâncias (por exemplo, captions_train2017.json) que possuem uma estrutura de anotação diferente.

Solução: Coloca apenas arquivos JSON de anotação de instâncias (por exemplo, instances_train2017.json) no labels_dir.

Arquivos de rótulo vazios após a conversão#

Se a conversão for concluída, mas os arquivos .txt estiverem vazios ou em falta, todas as anotações podem ter iscrowd: 1 (comum com máscaras geradas pelo SAM), ou as caixas delimitadoras têm largura ou altura zero.

Solução: Inspeciona as tuas anotações JSON em busca de valores de iscrowd. Se estiveres a usar máscaras do SAM, pré-processa o JSON para definir iscrowd: 0.

Polígonos em Formato de Caixa de Anotações de Máscara#

Se use_segments=True registar annotations without a usable polygon, algumas anotações não transportam nenhum valor segmentation, ou contêm um que não é uma lista de pelo menos três pares de coordenadas. As causas habituais são exportações focadas apenas em deteção, que deixam o campo em falta ou vazio, e a codificação de comprimento de execução do COCO ({"counts": ..., "size": ...}), que exportadores de máscaras de bits como o SAM escrevem; uma lista de coordenadas plana sem uma lista de polígonos envolvente, contornos de um e dois pontos, e outros valores malformados são tratados da mesma forma. Uma anotação mantém os polígonos que restarem e recorre a uma linha de segmento moldada como a sua caixa delimitadora quando nenhum restar, para que os rótulos permaneçam válidos, mas essas linhas não transportam detalhes de máscara.

Solução: Reexporta as anotações com segmentações de polígonos, descodifica as máscaras RLE em polígonos antes de executar convert_coco(), ou corrige quaisquer valores malformados de segmentation.

Lacunas nos IDs de classe nos rótulos convertidos#

Se os IDs de classe nos arquivos de rótulo não forem contíguos (por exemplo, 0, 4, 9 em vez de 0, 1, 2), a tua ferramenta de anotação usa valores de category_id não contíguos.

Solução: Verifica se os IDs de classe nos teus arquivos .txt correspondem ao dicionário names em dataset.yaml. Remapeia os IDs para valores contíguos, se necessário.

Para detalhes completos da API e descrições de parâmetros, consulta a referência da API de convert_coco.

FAQ#

  • Usa a função convert_coco() do Ultralytics para converter anotações COCO JSON para o formato YOLO .txt. Define cls91to80=False para datasets personalizados:

    from ultralytics.data.converter import convert_coco
    
    convert_coco(labels_dir="path/to/annotations/", save_dir="output/", cls91to80=False)

    Após a conversão, reorganiza os teus arquivos de rótulo para que labels/ espelhe o diretório images/, e depois cria um arquivo dataset.yaml. Consulta o guia passo a passo para o fluxo de trabalho completo.

  • Isto acontece porque convert_coco() guarda os rótulos num subdiretório dentro de save_dir/labels/ (por exemplo, save_dir/labels/train/) em vez de diretamente no labels/train/ do teu dataset junto a images/train/. O YOLO espera que os rótulos fiquem em paralelo com as imagens — por exemplo, images/train/img.jpg precisa de labels/train/img.txt. Move os teus rótulos convertidos para corresponder a esta estrutura. Consulta como corrigir a estrutura de diretórios.

  • O parâmetro cls91to80 controla a forma como os valores de category_id do COCO são mapeados para os IDs de classe YOLO. Quando True (padrão), ele aplica a tabela de consulta coco91_to_coco80_class() projetada para o dataset COCO padrão, que possui 80 classes com IDs não contíguos (1-90). Para datasets personalizados, define sempre cls91to80=False — isto simplesmente subtrai 1 de cada category_id para criar IDs de classe indexados a zero.

  • Não com o pipeline de treinamento YOLO atual — as anotações devem estar no formato YOLO .txt com um arquivo por imagem. Usa convert_coco() para converter o teu COCO JSON primeiro, e depois segue este guia para organizar e treinar. Para saberes mais sobre os formatos suportados, consulta formatos de dataset.

  • Sim, usa use_segments=True ao chamar convert_coco() para incluir máscaras de segmentação de polígonos nos rótulos YOLO convertidos. Isto produz arquivos de rótulo compatíveis com modelos de segmentação YOLO:

    from ultralytics.data.converter import convert_coco
    
    convert_coco(labels_dir="annotations/", save_dir="output/", use_segments=True, cls91to80=False)
  • Usa use_keypoints=True para converter anotações de pontos-chave COCO para o treinamento de estimação de pose:

    from ultralytics.data.converter import convert_coco
    
    convert_coco(labels_dir="annotations/", save_dir="output/", use_keypoints=True, cls91to80=False)

    Nota que se tanto use_segments como use_keypoints estiverem definidos como True, apenas os pontos-chave serão escritos nos arquivos de rótulo — os segmentos são ignorados silenciosamente.

Comentários