Ultralytics YOLO27:
Get Started

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

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

Preferes ignorar a conversão?

Para treinar diretamente com COCO JSON sem gerar ficheiros .txt, consulta Treinar YOLO com COCO JSON sem conversão.

Porquê converter de COCO para YOLO?#

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

  • Os modelos YOLO requerem ficheiros de rótulos .txt, um ficheiro por imagem, que contêm class x_center y_center width height com coordenadas normalizadas.
  • O COCO JSON usa coordenadas em píxeis no formato [x_min, y_min, width, height], com um único ficheiro JSON para todas as imagens.
  • Os IDs de classe são diferentes — o COCO usa valores arbitrários de category_id, enquanto o YOLO requer IDs de classe indexados a partir de zero.
FuncionalidadeCOCO JSONYOLO TXT
EstruturaUm único ficheiro JSON para todas as imagensUm arquivo .txt por imagem
Formato BBox[x_min, y_min, width, height] em píxeisclass x_center y_center width height normalizado (0-1)
IDs de classecategory_id (pode começar com qualquer número)Indexado a partir de zero (começa em 0)
SegmentaçãoMatrizes de polígonos no campo segmentationCoordenadas dos polígonos após o ID da classe
Pontos-chave[x, y, visibility, ...] em píxeis[x, y, visibility, ...] normalizado

Início rápido#

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

from ultralytics.data.converter import convert_coco

convert_coco(
    labels_dir="my_dataset/annotations/",  # diretório que contém seus arquivos JSON
    save_dir="my_dataset/converted/",  # onde salvar os rótulos convertidos
    cls91to80=False,  # defina como False para conjuntos de dados personalizados (consulte o aviso abaixo)
)

Após a conversão, organize a estrutura do diretório, crie um dataset.yaml e comece o treinamento. Veja abaixo o guia passo a passo completo.

Conjuntos de dados personalizados: use sempre `cls91to80=False`

O valor padrão de cls91to80=True foi projetado somente para o conjunto de dados COCO padrão, com 80 classes de objetos, que mapeia 91 IDs de categoria não contíguos para 80 IDs de classe contíguos. Para qualquer conjunto de dados personalizado, você deve definir cls91to80=False — caso contrário, seus IDs de classe serão mapeados incorretamente sem aviso, e seu modelo aprenderá classes erradas.

Guia de conversão passo a passo#

1. Prepare seu conjunto de dados COCO#

Um conjunto de dados típico no 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. Converta as anotações#

Use a função convert_coco() para converter suas 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 para cada imagem anotada em um subdiretório labels/ com o nome de cada arquivo JSON e o prefixo instances_ removido (assim, instances_train.json gera labels/train/). Imagens sem anotações são ignoradas e não recebem um arquivo de rótulo, então a árvore labels/ pode não espelhar todas as imagens:

my_dataset/converted/
├── images/      # created but left empty
└── 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 substitui um save_dir existente: se my_dataset/converted/ já existir, uma nova execução gravará em my_dataset/converted-2/. Exclua a saída anterior (ou altere save_dir) antes de executar novamente; caso contrário, as próximas etapas lerão rótulos desatualizados.

3. Organize a estrutura do diretório#

Após a conversão, os arquivos de rótulo precisam ficar junto às 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 nomeia cada subdiretório com base no respectivo arquivo JSON (sem o prefixo "instances_"),
# então percorra os subdiretórios existentes em vez de presumir "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 estrutura final do conjunto de dados deve ter esta aparência:

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

4. Crie dataset.yaml#

Crie um arquivo de configuração dataset.yaml que mapeie suas categorias COCO para nomes de classes YOLO. Esse arquivo informa ao YOLO onde estão seus dados e quais classes detectar:

import json
from pathlib import Path

import yaml

# Leia as categorias do seu JSON COCO
with open("my_dataset/annotations/instances_train.json") as f:
    coco = json.load(f)

# Crie nomes de classes que correspondam à saída de convert_coco (category_id - 1)
categories = sorted(coco["categories"], key=lambda x: x["id"])
names = {cat["id"] - 1: cat["name"] for cat in categories}
# OBSERVAÇÃO: convert_coco mapeia os IDs das classes como category_id - 1, então category_id deve
# começar em 1. Se suas categorias começarem em 0, some 1 primeiro a cada ID.

# Crie 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 saber mais sobre o formato YAML do conjunto de dados, consulte o guia de configuração de conjuntos de dados.

5. Treine seu modelo YOLO#

Com o conjunto de dados convertido pronto, treine um modelo YOLO:

Treine com dados COCO convertidos
from ultralytics import YOLO

model = YOLO("yolo26n.pt")  # carrega um modelo pré-treinado
results = model.train(data="my_dataset/dataset.yaml", epochs=100, imgsz=640)

Para ver dicas de treinamento e práticas recomendadas, consulte o guia de treinamento de modelos.

6. Verifique sua conversão#

Antes do treinamento, confira 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 encontrar IDs de classe negativos, seu JSON COCO provavelmente usa category_id começando em 0. Some 1 a todos os valores category_id no JSON antes de executar convert_coco(), pois ele mapeia os IDs de classe como category_id - 1.

Solução de problemas comuns#

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

Se o treinamento do seu modelo for concluído, mas ele detectar classes de objetos erradas, provavelmente você está usando cls91to80=True (padrão) em um conjunto de dados personalizado. Isso mapeia seus valores category_id usando a tabela de consulta COCO 91 para 80, que só é correta para o conjunto de dados COCO padrão. Um category_id sem correspondente no COCO-80 não é mapeado e gera TypeError: must be real number, not NoneType durante a conversão, em vez de produzir rótulos incorretos.

Solução: use sempre cls91to80=False para conjuntos de dados personalizados.

Nenhum rótulo encontrado durante o treinamento#

Se a verificação dos rótulos informar 0 images, N backgrounds e o treinamento for interrompido com ValueError: train: No labels found in .../labels/train.cache, seus arquivos de rótulo não estão no diretório esperado. convert_coco() salva os rótulos em um diretório de saída separado (por exemplo, save_dir/labels/train/), mas o YOLO espera labels/ em paralelo a images/ dentro do diretório do conjunto de dados.

Solução: mova os arquivos de rótulo para corresponder à estrutura de diretório esperada. Verifique se labels/train/ está no mesmo nível que images/train/.

KeyError durante a conversão#

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

Solução: coloque apenas arquivos JSON de anotação de instâncias (por exemplo, instances_train2017.json) em 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 ausentes, todas as anotações podem ter iscrowd: 1 (algo comum em máscaras geradas pelo SAM) ou as caixas delimitadoras podem ter largura ou altura zero. Executar com use_keypoints=True em uma exportação apenas de detecção produz o mesmo resultado, pois as anotações sem o campo keypoints são totalmente ignoradas.

Solução: inspecione os valores iscrowd nas anotações JSON. Se estiver usando máscaras SAM, pré-processe o JSON para definir iscrowd: 0. Se você passou use_keypoints=True, confirme se suas anotações realmente contêm keypoints.

Polígonos em forma de caixa provenientes de anotações de máscaras#

Se use_segments=True registrar annotations without a usable polygon, algumas anotações não têm um valor segmentation ou têm um valor que não é uma lista com pelo menos três pares de coordenadas. As causas mais comuns são exportações apenas de detecção, nas quais o campo está ausente ou vazio, e a codificação de comprimento variável COCO ({"counts": ..., "size": ...}), usada por exportadores de mapas de bits como o SAM; listas simples de coordenadas sem uma lista de polígonos que as envolva, contornos com um ou dois pontos e outros valores malformados são tratados da mesma maneira. Uma anotação mantém os polígonos restantes e, quando não há nenhum, recorre a uma linha de segmento com o formato da caixa delimitadora. Assim, os rótulos continuam válidos, mas essas linhas não contêm detalhes da máscara.

Solução: exporte novamente as anotações com segmentações poligonais, decodifique as máscaras RLE em polígonos antes de executar convert_coco() ou corrija os valores segmentation malformados.

Lacunas nos IDs de classe dos 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), sua ferramenta de anotação usa valores category_id não contíguos.

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

Para ver todos os detalhes da API e as descrições dos parâmetros, consulte a referência da API de convert_coco.

Perguntas frequentes#

  • Use a função convert_coco() da Ultralytics para converter anotações COCO JSON para o formato YOLO .txt. Defina cls91to80=False para conjuntos de dados 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, reorganize seus arquivos de rótulo para que labels/ espelhe o diretório images/ e, em seguida, crie um arquivo dataset.yaml. Consulte o guia passo a passo para ver o fluxo de trabalho completo.

  • Isso acontece porque convert_coco() salva os rótulos em um subdiretório de save_dir/labels/ (por exemplo, save_dir/labels/train/), em vez de diretamente em labels/train/ do conjunto de dados, junto a images/train/. O YOLO espera que os rótulos fiquem em paralelo às imagens — por exemplo, images/train/img.jpg precisa de labels/train/img.txt. Mova os rótulos convertidos para corresponder a essa estrutura. Consulte como corrigir a estrutura de diretórios.

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

  • Não sem código personalizado. O pipeline de treinamento padrão espera rótulos YOLO .txt, com um arquivo por imagem. Portanto, execute convert_coco() e siga este guia passo a passo, ou crie uma subclasse do conjunto de dados para analisar o COCO JSON em tempo real — consulte Treinar YOLO com COCO JSON sem conversão. Para saber mais sobre os formatos compatíveis, consulte formatos de conjuntos de dados.

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

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

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

    Observe que, se use_segments e use_keypoints forem definidos como True, somente os pontos-chave serão gravados nos arquivos de rótulo — os segmentos serão ignorados sem aviso.

Comentários