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

Rotular e treinar modelos de pose

Cria rótulos de pontos-chave com visibilidade, define corretamente kpt_shape e flip_idx, treina com COCO8-pose e converte os pontos-chave em ângulos articulares sujeitos a um limiar de confiança.

A estimativa de pose converte cada pessoa em 17 pontos numerados, e desses pontos vêm os valores que os produtos vendem: ângulos dos cotovelos para ergonomia, ângulos dos joelhos para reabilitação, altura das ancas para deteção de quedas. Duas chaves do conjunto de dados determinam se esses pontos são fiáveis, e qualquer erro numa delas não gera erro algum — apenas um modelo que confunde esquerda e direita ou que treina silenciosamente sem a sua ampliação mais barata.

Resultado

Treina yolo26n-pose.pt com coco8-pose.yaml e calcula os ângulos dos cotovelos esquerdo e direito de cada pessoa a partir de result.keypoints, ignorando as articulações em que o modelo não tem confiança suficiente.

Via rápida
Se já sabes orientar-te, aqui está a versão resumida.
  1. Linha de rótulo: classe, caixa (4 valores), depois x y v por ponto-chave, todos normalizados; v é 0 (não rotulado), 1 (oculto) ou 2 (visível).

  2. Define kpt_shape: [K, 3] e um flip_idx que troque todos os pares esquerdo e direito.

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

  4. Lê result.keypoints.xy e .conf; ignora qualquer cálculo cujas articulações fiquem abaixo de um limiar mínimo de confiança.

Prático

A linha de rótulo dos pontos-chave#

Estimativa de pose Ultralytics YOLO de três corredores, cada um com uma caixa de pessoa e um esqueleto corporal de 17 pontos-chave

Uma linha de rótulo de pose é uma linha de deteção com pontos-chave acrescentados. Cada coordenada é normalizada para 0–1, e os pontos-chave aparecem sempre na mesma ordem fixa em todas as linhas. Uma linha real de COCO8-pose, truncada após quatro pontos-chave:

0 0.671279 0.617945 0.645759 0.726859 0.519751 0.381250 2.000000 0.550936 0.348438 2.000000 0.488565 0.367188 2.000000 0.642412 0.354687 2.000000 ...
ValoresSignificado
0índice da classe (pessoa)
0.671279 0.617945 0.645759 0.726859centro x da caixa, centro y, largura, altura
0.519751 0.381250 2ponto-chave 0 (nariz): x, y, visibilidade
…Mais 16 pontos-chave, com o mesmo padrão: 5 + 17 × 3 = 56 valores por linha

O indicador de visibilidade segue a convenção COCO: 2 visível, 1 rotulado, mas oculto, 0 não rotulado. O Ultralytics mascara os pontos-chave com v = 0 na função de perda, para que um pulso em falta não ensine o modelo a prever pulsos em (0, 0).

Editor de anotação da Ultralytics Platform numa imagem COCO8-pose, com esqueletos de 17 pontos-chave desenhados nas pessoas que estão a cortar um bolo

Etiqueta as articulações ocluídas cuja posição consegues determinar

Usa 1 para uma articulação ocluída cuja posição consigas determinar com confiança — uma anca atrás de uma mesa, um pulso atrás das costas; continua a ser útil para o treino. Reserva 0 para articulações que ninguém conseguiria localizar. Etiquetar todas as articulações ocultas com 0 elimina precisamente os casos difíceis de que o modelo precisa.

O guia de conjuntos de dados de pose também aborda a variante de dois valores (x y apenas, kpt_shape: [K, 2]) para conjuntos de dados sem visibilidade.

kpt_shape e flip_idx#

O YAML do conjunto de dados acrescenta duas chaves às habituais path, train, val e names:

kpt_shape: [17, 3] # 17 keypoints, each x, y, visibility
flip_idx: [0, 2, 1, 4, 3, 6, 5, 8, 7, 10, 9, 12, 11, 14, 13, 16, 15]

Ordem dos 17 pontos-chave COCO numa pessoa de pé, numerados de 0 no nariz a 16 no tornozelo direito

flip_idx indica à ampliação de inversão horizontal qual ponto-chave corresponde a cada um na imagem espelhada. Espelha uma pessoa e o seu pulso esquerdo (9) passa para onde estava o pulso direito (10), por isso a posição 9 de flip_idx contém 10 e a posição 10 contém 9; o nariz (0) corresponde a si próprio. Cada ampliação desloca o esqueleto juntamente com os pixels, e a inversão é a única que também precisa do mapa de índices:

Aumentos de pose de um corredor: original, inversão horizontal, rotação, escala, cor HSV e mosaico, com o esqueleto de pontos-chave acompanhando cada transformação

O que acontece quando flip_idx está errado, confirmado no código-fonte instalado:

  • Ausente: o treinamento registra um aviso e define fliplr e flipud como 0, então você perde seu aumento de dados mais barato.
  • Comprimento incorreto: o treinamento para com um ValueError que identifica a incompatibilidade — a única falha explícita.
  • Comprimento correto, pares errados: nenhum aviso é emitido. Metade das amostras invertidas ensina ao modelo que esquerda é direita, e as imagens de validação mostram trocas entre esquerda e direita em poses simétricas.

Treine com COCO8-pose#

Mosaico de treinamento COCO8-pose: pessoas em uma motocicleta, sob um guarda-chuva rosa, em um parque de skate e a cavalo, cada uma com uma caixa de pessoa e um esqueleto de pontos-chave colorido

from ultralytics import YOLO

model = YOLO("yolo26n-pose.pt")
model.train(data="coco8-pose.yaml", epochs=1, imgsz=320, device="cpu")
metrics = model.val()
print(f"box  mAP50-95: {metrics.box.map:.3f}")
print(f"pose mAP50-95: {metrics.pose.map:.3f}")
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Pose(P          R      mAP50  mAP50-95)
                   all          4         14          1      0.783      0.893      0.643      0.966      0.571      0.575      0.326
box  mAP50-95: 0.643
pose mAP50-95: 0.326

Assim como na segmentação, a tabela tem dois blocos. Box avalia as caixas de pessoas; Pose avalia o posicionamento dos pontos-chave com a Similaridade de Pontos-Chave de Objetos (OKS), dentro do mesmo mecanismo de mAP. O mAP50-95 de pose é o critério de aprovação para lançar um produto de pose — na próxima lição, você verá como o OKS decide se um ponto-chave está correto.

Dos pontos-chave aos ângulos das articulações#

result.keypoints contém xy (N × K × 2, pixels), xyn (normalizado) e conf (N × K), na ordem COCO mostrada acima. O ângulo de uma articulação é o ângulo entre os dois vetores dos membros que se encontram nela — um produto escalar:

import numpy as np

from ultralytics import YOLO

model = YOLO("yolo26n-pose.pt")
result = model("https://ultralytics.com/images/bus.jpg")[0]
kpts = result.keypoints.cpu().numpy()  # people x 17 x (x, y, conf)

SHOULDER, ELBOW, WRIST = 5, 7, 9  # left arm, COCO keypoint order
for person, (xy, conf) in enumerate(zip(kpts.xy, kpts.conf)):
    if conf[[SHOULDER, ELBOW, WRIST]].min() < 0.5:
        print(f"person {person}: left arm not visible enough")
        continue
    a, b, c = xy[SHOULDER], xy[ELBOW], xy[WRIST]
    cos = np.dot(a - b, c - b) / (np.linalg.norm(a - b) * np.linalg.norm(c - b))
    print(f"person {person}: left elbow angle {np.degrees(np.arccos(cos)):.0f} deg")
person 0: left elbow angle 71 deg
person 1: left elbow angle 96 deg
person 2: left elbow angle 59 deg
person 3: left arm not visible enough
person 4: left arm not visible enough

Linha por linha: kpts.xy[p] é os 17 pontos da pessoa p em pixels; a - b e c - b são o braço superior e o antebraço representados como vetores a partir do cotovelo; o produto escalar normalizado deles é o cosseno do ângulo entre eles. Um braço esticado indica aproximadamente 180°, e um totalmente dobrado, aproximadamente 30°. As pessoas 3 e 4 têm pelo menos uma articulação do braço esquerdo com confiança abaixo de 0.5, então o script não faz a medição.

Aplica um limiar de confiança a cada articulação

Sintoma: ângulos aparentemente fiáveis para pessoas com os braços fora do enquadramento. Causa: o modelo devolve uma coordenada para cada ponto-chave, esteja ou não ocluído. Solução: ignora qualquer cálculo cujas articulações fiquem abaixo de um limiar de confiança (0.5 neste caso) e regista a frequência com que o fazes — uma taxa crescente é um sinal precoce de uma alteração na câmara ou na iluminação.

Experimente

Treine por uma época com coco8-pose.yaml e registre o mAP50-95 de caixa e de pose. Em seguida, estenda pose.py para também informar o ângulo do cotovelo direito (pontos-chave 6, 8, 10) e liste quais pessoas na imagem do ônibus podem ter os dois braços medidos.

Concluído quando
Você concluiu a aula quando todos estes critérios forem atendidos.
  • O treinamento terminou e você registrou o mAP50-95 de caixa e de pose.

  • Seu script exibe os ângulos dos dois cotovelos de cada pessoa, ignorando qualquer braço abaixo do limite mínimo de confiança.

  • Você consegue explicar o que acontece quando flip_idx está ausente, tem comprimento incorreto ou contém pares errados.

Mostrar solução
import numpy as np

from ultralytics import YOLO

ARMS = {"left": (5, 7, 9), "right": (6, 8, 10)}  # shoulder, elbow, wrist
kpts = YOLO("yolo26n-pose.pt")("https://ultralytics.com/images/bus.jpg")[0].keypoints.cpu().numpy()

for person, (xy, conf) in enumerate(zip(kpts.xy, kpts.conf)):
    for side, (s, e, w) in ARMS.items():
        if conf[[s, e, w]].min() < 0.5:
            continue
        a, b, c = xy[s], xy[e], xy[w]
        cos = np.dot(a - b, c - b) / (np.linalg.norm(a - b) * np.linalg.norm(c - b))
        print(f"person {person}: {side} elbow {np.degrees(np.arccos(cos)):.0f} deg")
person 0: left elbow 71 deg
person 0: right elbow 94 deg
person 1: left elbow 96 deg
person 2: left elbow 59 deg
person 2: right elbow 135 deg

As pessoas 0 e 2 podem ter os dois braços medidos. O braço direito da pessoa 1 e os dois braços das pessoas 3 e 4 ficam abaixo do limite mínimo de confiança de 0.5, então o script os ignora em vez de tentar adivinhar.

A ausência de flip_idx desativa o aumento de dados por inversão e emite um aviso; um comprimento incorreto interrompe o treinamento com um ValueError; um flip_idx aparentemente válido, mas com pares errados, treina silenciosamente com rótulos espelhados e causa trocas entre esquerda e direita na validação.

Próximos passos

A seguir, projetaremos pontos-chave para objetos que não são pessoas e aprenderemos como o OKS decide se um ponto-chave está correto.

Entre para salvar seu progresso