Ultralytics YOLO27: Inscreve-te na lista de espera.
Get Started
Aulaintermediário

Rotular e treinar a segmentação de instâncias

Escreve rótulos poligonais, verifica-os em código, treina yolo26n-seg.pt em COCO8-seg e diagnostica um modelo com base na diferença entre as métricas de caixas e máscaras.

A segmentação de instâncias dá a cada objeto o seu próprio contorno, algo de que precisas quando a área, a sobreposição ou um limite determina a decisão. Os polígonos são os rótulos mais dispendiosos que a maioria das equipas compra, e uma linha malformada não interrompe o treino — treina silenciosamente com a forma errada. Nesta lição, vais acertar o formato da linha, verificar um conjunto de rótulos em código e treinar um primeiro modelo para veres o que a rotulagem extra proporciona: uma segunda métrica que avalia contornos, não apenas posições.

Resultado

Verifica um conjunto de rótulos poligonais à procura de linhas malformadas, treina yolo26n-seg.pt em coco8-seg.yaml e decide o que corrigir com base na diferença entre o mAP50-95 das caixas e o das máscaras.

Via rápida
Se já sabes orientar-te, aqui está a versão resumida.
  1. Escreve uma linha por objeto: índice da classe, seguido de pares de vértices normalizados x y, com pelo menos três vértices.

  2. Executa uma verificação dos rótulos à procura de quantidades ímpares de valores, coordenadas fora do intervalo e polígonos com área suspeitamente pequena.

  3. yolo segment train data=coco8-seg.yaml model=yolo26n-seg.pt epochs=1 imgsz=320.

  4. Usa o mAP50-95 das máscaras (metrics.seg.map) como critério e a diferença em relação ao mAP50-95 das caixas (metrics.box.map) como diagnóstico.

Prático

A linha de rótulo do polígono#

Segmentação de instâncias Ultralytics YOLO numa passadeira urbana, com uma máscara separada para cada carro, o autocarro e todos os peões

Um ficheiro de rótulos de segmentação tem uma linha por objeto, tal como um rótulo de deteção, mas, em vez de uma caixa, lista o contorno do objeto como pares de vértices normalizados. Uma linha real de COCO8-seg, abreviada:

45 0.782016 0.986521 0.937078 0.874167 0.957297 0.782021 0.950562 0.739333 0.825844 0.561792 ...
PosiçãoLinha de deteçãoLinha de segmentação
1índice da classe (45 é bowl)índice da classe
2–5x_center y_center width heightos dois primeiros vértices, x1 y1 x2 y2
6+—mais vértices, tantos quantos forem necessários para o contorno
Unidadesnormalizado de 0 a 1normalizado de 0 a 1 (x do píxel ÷ largura da imagem, y do píxel ÷ altura da imagem)

Três regras são fundamentais: pelo menos três vértices por objeto, coordenadas divididas pelo tamanho da imagem e uma linha por instância, mesmo quando dois objetos da mesma classe se tocam. O guia de conjuntos de dados de segmentação contém a especificação completa.

As etiquetas de polígonos também treinam caixas e mapas de classes

Os polígonos são um superconjunto de etiquetas de caixas. A mesma pasta de etiquetas treina yolo26n.pt (o Ultralytics calcula cada caixa a partir do respetivo polígono) e yolo26n-sem.pt (rasteriza os polígonos em mapas de classes) — treinámos ambos com coco8-seg.yaml. Se o plano mudar depois da etiquetagem, o orçamento não se perde.

Verifica os rótulos antes de treinar#

Uma linha com um número ímpar de valores, uma coordenada escrita em píxeis ou um contorno traçado em torno do objeto errado não interrompe o treino. Este verificador lê o conjunto de dados com o próprio carregador da Ultralytics, rejeita linhas malformadas e apresenta a área de cada polígono junto à caixa que a Ultralytics vai derivar dele:

from pathlib import Path

import numpy as np

from ultralytics.data.utils import check_det_dataset

data = check_det_dataset("coco8-seg.yaml")  # resolves paths, downloads if needed
for label in sorted(Path(data["path"], "labels", "train").glob("*.txt"))[:2]:
    for n, row in enumerate(label.read_text().splitlines(), 1):
        cls, *coords = row.split()
        if len(coords) % 2 or len(coords) < 6:
            print(f"{label.name}:{n} BAD: needs an even number of values and at least 3 vertices")
            continue
        xy = np.array(coords, dtype=float).reshape(-1, 2)
        if xy.min() < 0 or xy.max() > 1:
            print(f"{label.name}:{n} BAD: coordinates must be normalized to 0-1")
            continue
        x, y = xy[:, 0], xy[:, 1]
        area = 0.5 * abs(np.dot(x, np.roll(y, 1)) - np.dot(y, np.roll(x, 1)))  # shoelace formula
        w, h = xy.max(0) - xy.min(0)  # the box Ultralytics derives from the polygon
        name = data["names"][int(cls)]
        print(f"{label.stem} {name:9s} {len(xy):3d} vertices  polygon {area:.3f}  box {w * h:.3f}  fill {area / (w * h):.2f}")
000000000009 bowl       12 vertices  polygon 0.391  box 0.569  fill 0.69
000000000009 bowl       14 vertices  polygon 0.145  box 0.238  fill 0.61
000000000009 broccoli   50 vertices  polygon 0.161  box 0.252  fill 0.64
000000000009 bowl       55 vertices  polygon 0.079  box 0.531  fill 0.15
000000000009 orange     13 vertices  polygon 0.007  box 0.011  fill 0.64
000000000009 orange     13 vertices  polygon 0.005  box 0.009  fill 0.61
000000000009 orange     18 vertices  polygon 0.012  box 0.019  fill 0.61
000000000009 orange     12 vertices  polygon 0.010  box 0.022  fill 0.44
000000000025 giraffe    82 vertices  polygon 0.072  box 0.234  fill 0.31
000000000025 giraffe    19 vertices  polygon 0.010  box 0.027  fill 0.38

As áreas são frações da imagem, por isso a primeira taça ocupa 39% da fotografia. Preenchimento é a área do polígono dividida pela área da caixa, e é essa a coluna que deves analisar:

  • A maioria dos objetos compactos (taças, laranjas, brócolos) fica entre 0,6 e 0,7.
  • O valor 0,31 da girafa é genuíno: as pernas e o pescoço compridos deixam vazia a maior parte da caixa — é por isso que este objeto precisa de uma máscara.
  • O valor 0,15 da terceira taça é a linha que um revisor deve abrir. Só se vê uma borda fina da taça à volta da comida, por isso o contorno é uma faixa estreita dentro de uma caixa grande. Neste caso, está correto; nos teus dados, um preenchimento tão baixo pode muito bem indicar que o contorno foi traçado em torno do objeto errado.
Regra de decisão

Corrige todas as linhas BAD antes do treino. Depois, ordena por preenchimento e abre numa ferramenta de anotação as linhas com os valores mais baixos, correspondentes a alguns por cento de cada classe: um preenchimento baixo indica um objeto fino ou ocluído (mantém) ou um contorno incorreto (corrige).

Obtém polígonos sem traçar cada contorno#

Traçar contornos à mão é a parte dispendiosa da rotulagem de dados. Verifica que atalho se aplica antes de alguém começar:

Já tensFerramenta
JSON COCO com segmentaçãoconvert_coco(labels_dir, use_segments=True) de ultralytics.data.converter
Máscaras PNG (valor do píxel = índice da classe + 1, 0 = fundo)convert_segment_masks_to_yolo_seg(masks_dir, output_dir, classes) — objetos da mesma classe que se tocam são convertidos num único polígono, por isso separa-os durante a revisão
Apenas rótulos de caixasyolo_bbox2segment(im_dir) — fornece cada caixa como indicação ao SAM para gerar um polígono
Ainda nadaAnotação inteligente e rotulagem em lote — clica uma vez e revê o polígono

Na Ultralytics Platform, o modo Smart executa o SAM: um clique positivo no objeto e um clique negativo no que deve ser excluído geram uma máscara que depois revês.

Modo Smart da Ultralytics Platform com SAM 2.1 Tiny selecionado: um clique positivo e um negativo num robô de armazém geram a respetiva máscara

Revê todos os polígonos gerados por máquina

Uma máscara que se estende ao fundo treina o modelo a fazer o mesmo. Revê os polígonos gerados por máquina de acordo com os critérios de qualidade em Caixas vs. Máscaras e, depois, volta a executar a verificação de etiquetas acima.

Treina com COCO8-seg#

Mosaico de treino COCO8-seg: zebras, uma girafa, lancheiras com brócolos e laranjas e um vaso de flores, cada objeto com a sua própria máscara colorida e índice de classe

O treino segue o fluxo de trabalho de deteção, mas com um modelo -seg e um conjunto de dados de segmentação. Uma época em imgsz=320 num CPU de portátil demora segundos, o suficiente para comprovar todo o fluxo:

from ultralytics import YOLO

model = YOLO("yolo26n-seg.pt")
model.train(data="coco8-seg.yaml", epochs=1, imgsz=320, device="cpu")
metrics = model.val()
print(f"box  mAP50-95: {metrics.box.map:.3f}")
print(f"mask mAP50-95: {metrics.seg.map:.3f}")
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P          R      mAP50  mAP50-95)
                   all          4         17      0.909      0.449      0.661      0.482      0.685      0.409      0.557      0.377
                 horse          1          2          1      0.993      0.995      0.564      0.619      0.857      0.663      0.199
box  mAP50-95: 0.482
mask mAP50-95: 0.377

Quatro imagens de validação tornam estes números pouco fiáveis; o importante é a execução terminar e gravar weights/best.pt em runs/segment/. Para dados reais, segue o guia da tarefa Segment e treina com o plano completo numa GPU.

Analisa as métricas de caixas e máscaras lado a lado#

A tabela de validação tem dois blocos. Box avalia cada caixa prevista em relação à caixa implícita no rótulo; Mask avalia os píxeis previstos em relação ao polígono rotulado. Ambos usam o mesmo mecanismo de mAP; só muda o IoU.

O mAP50-95 das máscaras é quase sempre inferior ao das caixas, porque o IoU dos píxeis é mais rigoroso: uma caixa deslocada alguns píxeis continua a sobrepor-se bastante, enquanto uma máscara que não inclui um braço ou que se estende para a estrada perde IoU rapidamente nos limiares de 0,75–0,95. A linha horse mostra o caso mais extremo — mAP50-95 das caixas de 0,564 e das máscaras de 0,199. O modelo encontrou os dois cavalos e delimitou-os bem com caixas; não contornou as pernas nem as caudas. Usa a diferença para decidir o que corrigir:

  • Ambos baixos: o problema está em encontrar os objetos, não em contorná-los. Primeiro, acrescenta dados das condições que não foram detetadas.
  • Caixas boas, máscaras muito piores: o modelo encontra os objetos, mas não os contorna bem. Executa a verificação dos rótulos, experimenta um modelo maior ou treina e valida com um valor imgsz mais elevado.
  • As máscaras melhoram enquanto as caixas estagnam: não há problema — para um produto de segmentação, o mAP50-95 das máscaras é o critério de lançamento.
Dois parâmetros que não alteram a resolução das máscaras

overlap_mask=True combina máscaras de instâncias numa só imagem durante o treino, e mask_ratio=4 reduz a resolução das máscaras de treino. Nenhum dos dois altera a resolução das máscaras previstas — isso é controlado por retina_masks, na lição seguinte. Mantém ambos nos valores predefinidos, a menos que tenhas medido uma razão para os alterar.

Experimente

Executa check_seg_labels.py em todo o COCO8-seg (treino e validação) e lista as três linhas com o menor preenchimento. Depois, treina yolo26n-seg.pt em coco8-seg.yaml durante uma época com imgsz=320, regista o mAP50-95 das caixas, o mAP50-95 das máscaras e a classe com a maior diferença, e abre val_batch0_pred.jpg na pasta de validação para encontrares um objeto cuja máscara seja visivelmente pior do que a respetiva caixa.

Concluído quando
Você concluiu a aula quando todos estes critérios forem atendidos.
  • A verificação dos rótulos não apresenta nenhuma linha BAD e identificaste as três linhas com menor preenchimento, indicando se deves manter ou corrigir cada uma.

  • A execução do treino terminou, best.pt existe em runs/segment/ e registaste os dois valores de mAP50-95.

  • Identificaste a classe com a maior diferença entre caixas e máscaras e o passo seguinte indicado pelo gráfico de decisão.

Mostrar solução

Para verificar todas as divisões, substitui a pasta no ciclo por Path(data["path"], "labels").rglob("*.txt"). Depois, treina:

from ultralytics import YOLO

model = YOLO("yolo26n-seg.pt")
model.train(data="coco8-seg.yaml", epochs=1, imgsz=320, device="cpu")
metrics = model.val()
print(f"box  mAP50-95: {metrics.box.map:.3f}")   # 0.482 in our run
print(f"mask mAP50-95: {metrics.seg.map:.3f}")   # 0.377 in our run

A diferença de 0,1 é esperada: o IoU das máscaras penaliza cada píxel do contorno, enquanto o IoU das caixas penaliza apenas os quatro lados. Na nossa execução, a maior diferença é da classe horse (caixa 0,564, máscara 0,199). O mAP das caixas é bom e o das máscaras é muito inferior, por isso o gráfico aponta para a qualidade dos contornos: verifica primeiro esses polígonos e, depois, experimenta um modelo maior ou um valor imgsz mais elevado.

Próximos passos

A seguir, vamos transformar as máscaras previstas em valores: áreas, contornos, sobreposições e recortes com transparência.

Entre para salvar seu progresso