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.
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
.txtcom um arquivo por imagem, contendoclass x_center y_center width heightem 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.
| Funcionalidade | COCO JSON | YOLO TXT |
|---|---|---|
| Estrutura | Arquivo JSON único para todas as imagens | Um arquivo .txt por imagem |
| Formato de Bbox | [x_min, y_min, width, height] em pixels | class x_center y_center width height normalizado (0-1) |
| IDs de classe | category_id (pode começar a partir de qualquer número) | Indexado em zero (começa de 0) |
| Segmentação | Matrizes de polígonos no campo segmentation | Coordenadas 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.
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.jsonCada 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:
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
└── ...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.yaml4. 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: vestPara 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:
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}"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. Definecls91to80=Falsepara 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órioimages/, e depois cria um arquivodataset.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 desave_dir/labels/(por exemplo,save_dir/labels/train/) em vez de diretamente nolabels/train/do teu dataset junto aimages/train/. O YOLO espera que os rótulos fiquem em paralelo com as imagens — por exemplo,images/train/img.jpgprecisa delabels/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
cls91to80controla a forma como os valores decategory_iddo COCO são mapeados para os IDs de classe YOLO. QuandoTrue(padrão), ele aplica a tabela de consultacoco91_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 semprecls91to80=False— isto simplesmente subtrai 1 de cadacategory_idpara criar IDs de classe indexados a zero.Não com o pipeline de treinamento YOLO atual — as anotações devem estar no formato YOLO
.txtcom um arquivo por imagem. Usaconvert_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=Trueao chamarconvert_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=Truepara 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_segmentscomouse_keypointsestiverem definidos comoTrue, apenas os pontos-chave serão escritos nos arquivos de rótulo — os segmentos são ignorados silenciosamente.