Ultralytics YOLO27: Inscreve-te na lista de espera.
Get Started
Ultralytics YOLO em produção·Rastrear e criar pipelines·Aula 5/9
Aulaintermediário

Rastreia objetos com ByteTrack, BoT-SORT e TrackTrack

Atribui a cada objeto um ID estável entre fotogramas, escolhe um rastreador e ajusta os respetivos limites ao teu detetor.

Cada contagem, tempo de permanência e estimativa de velocidade depende de uma pergunta: o ID 17 neste fotograma é o mesmo objeto que o ID 17 no anterior? No mesmo clipe de 62 fotogramas, com cerca de 30 peões e o mesmo detetor, o ByteTrack encontrou 32 IDs e o TrackTrack predefinido encontrou 9. Escolher e ajustar o rastreador faz parte do modelo, e uma escolha errada compromete silenciosamente todos os números seguintes.

Resultado

Executa três rastreadores num vídeo, explica as respetivas contagens de IDs com base nas confianças do detetor, usa box.id num pipeline e corrige um rastreador incompatível com um YAML ajustado.

Via rápida
Se já sabes orientar-te, aqui está a versão resumida.
  1. model.track(source, stream=True, tracker="bytetrack.yaml"); cada caixa recebe um id estável.

  2. Estás a fornecer os fotogramas? Passa persist=True para que os IDs se mantenham entre chamadas; usa um rastreador por câmara.

  3. O valor predefinido é tracktrack.yaml; o ByteTrack é rápido e tolerante; o BoT-SORT adiciona compensação do movimento da câmara, com ReID opcional.

  4. Poucos IDs: mede as confianças do detetor e reduz new_track_thresh e track_high_thresh num YAML copiado.

Prático

O que um rastreador acrescenta#

Tráfego numa autoestrada rastreado pelo Ultralytics YOLO: cada carro, autocarro e camião mantém um ID numerado (carro #12, autocarro #21, camião #16) e deixa um rasto colorido ao longo do percurso recente

As etiquetas e os rastos neste fotograma são o resultado do rastreador. Cada ID é um rasto, uma hipótese sobre um objeto real, e o rasto visual mostra o histórico recente desse objeto. Em cada fotograma, o rastreador prevê onde cada rasto deverá estar usando um filtro de Kalman e, em seguida, associa as novas deteções a essas previsões com base na sobreposição das caixas (e, opcionalmente, na aparência):

Os rastos que não correspondem a uma deteção durante track_buffer fotogramas são eliminados. Esse é todo o mecanismo, e os respetivos limites determinam tudo o que se segue.

Escolhe um rastreador#

O modo de rastreamento inclui seis rastreadores: BoT-SORT, ByteTrack, OC-SORT, Deep OC-SORT, FastTracker e TrackTrack (o predefinido quando não passas tracker). Três cobrem a maioria das necessidades:

RastreadorCritérios de associação (configuração predefinida)Usa-o quando
ByteTrackMovimento e sobreposição das caixas, além de uma segunda passagem que recupera caixas com baixa confiançaCâmaras fixas, detetores pequenos ou incertos, quando o débito é importante
BoT-SORTAssociação ao estilo ByteTrack, mais compensação do movimento da câmara (gmc_method: sparseOptFlow)Câmaras em movimento ou com trepidação; define with_reid: True para multidões e oclusões prolongadas
TrackTrackCusto com vários critérios (forma da caixa, confiança, ângulo), inicialização consciente dos rastos e compensação do movimento da câmaraDeteções confiantes de um modelo robusto e bem treinado

A associação por aparência do BoT-SORT (reidentificação) está desativada por predefinição; com model: auto, reutiliza as próprias características do detetor, pelo que ativá-la acrescenta pouca sobrecarga.

Compara rastreadores num único clipe#

from ultralytics import YOLO

model = YOLO("yolo26n.pt")
video = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"

for tracker in ("bytetrack.yaml", "botsort.yaml", "tracktrack.yaml"):
    ids, frames = set(), 0
    for r in model.track(video, stream=True, tracker=tracker, classes=[0], verbose=False):
        frames += 1
        if r.boxes.is_track:
            ids.update(r.boxes.id.int().tolist())
    print(f"{tracker:16s} {frames} frames, {len(ids)} unique person IDs")
bytetrack.yaml   62 frames, 32 unique person IDs
botsort.yaml     62 frames, 33 unique person IDs
tracktrack.yaml  62 frames, 9 unique person IDs

O clipe mostra cerca de 30 pessoas a atravessar uma praça, filmada de cima, por isso o ByteTrack e o BoT-SORT aproximam-se da contagem real. O TrackTrack não está avariado: só inicia um rasto acima de new_track_thresh: 0.7 e só faz a primeira associação acima de track_high_thresh: 0.6, enquanto a confiança mediana de YOLO26n para pessoas neste clipe é 0,53 e apenas 17% das deteções chegam a 0,7. A maioria das pessoas nunca recebe um ID. Regra de decisão: compara os limites do rastreador com a distribuição de confiança do teu detetor antes de confiares em qualquer contagem.

Usa IDs num pipeline#

from collections import defaultdict

from ultralytics import YOLO

model = YOLO("yolo26n.pt")
video = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"

counts = defaultdict(set)
for r in model.track(video, stream=True, tracker="bytetrack.yaml", verbose=False):
    if not r.boxes.is_track:  # no confirmed tracks in this frame yet
        continue
    for cls, tid in zip(r.boxes.cls.int().tolist(), r.boxes.id.int().tolist()):
        counts[r.names[cls]].add(tid)

for cls, ids in counts.items():
    print(f"{cls}: {len(ids)} unique objects")
person: 32 unique objects

Um conjunto por classe conta cada ID uma única vez, independentemente do número de fotogramas em que aparece, pelo que o resultado corresponde a objetos e não a deteções. stream=True produz resultados fotograma a fotograma, em vez de manter o vídeo inteiro na memória. Contagem por região, mapas de calor e cálculo de distâncias são camadas simples sobre este ciclo.

Rastreia os fotogramas que lês diretamente#

Ao passar um caminho ou URL, o estado do rastreador é gerido automaticamente. Quando os fotogramas vêm do teu próprio descodificador, de uma webcam ou de uma câmara RTSP, passa persist=True para que cada chamada continue a mesma sequência (a documentação do modo de previsão enumera todos os tipos de origem):

import cv2

from ultralytics import YOLO
from ultralytics.utils.downloads import safe_download

model = YOLO("yolo26n.pt")
video = safe_download("https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4")
cap = cv2.VideoCapture(str(video))  # or 0 for a webcam, or an rtsp:// URL

seen = set()
while True:
    ok, frame = cap.read()
    if not ok:
        break
    r = model.track(frame, persist=True, tracker="bytetrack.yaml", classes=[0], verbose=False)[0]
    if r.boxes.is_track:
        seen.update(r.boxes.id.int().tolist())  # your logic: dwell time, trajectories, alerts
cap.release()
print(f"{len(seen)} unique IDs")
32 unique IDs

O resultado é o mesmo que ao passar o caminho, porque persist=True manteve um rastreador ativo ao longo das 62 chamadas.

Ajusta um rastreador ao teu detetor#

Copia uma configuração incluída no pacote, reduz os limites incompatíveis com o teu detetor e passa o novo ficheiro:

from pathlib import Path

from ultralytics import YOLO
from ultralytics.utils import ROOT

cfg = (ROOT / "cfg/trackers/tracktrack.yaml").read_text()  # packaged defaults
for old, new in (
    ("track_high_thresh: 0.6", "track_high_thresh: 0.3"),
    ("track_low_thresh: 0.25", "track_low_thresh: 0.1"),
    ("new_track_thresh: 0.7", "new_track_thresh: 0.35"),
):
    cfg = cfg.replace(old, new)
Path("tracktrack_tuned.yaml").write_text(cfg)

model = YOLO("yolo26n.pt")
video = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"
for tracker in ("tracktrack.yaml", "tracktrack_tuned.yaml"):
    ids = set()
    for r in model.track(video, stream=True, tracker=tracker, classes=[0], verbose=False):
        if r.boxes.is_track:
            ids.update(r.boxes.id.int().tolist())
    print(f"{tracker:22s} {len(ids)} unique person IDs")
tracktrack.yaml        9 unique person IDs
tracktrack_tuned.yaml  27 unique person IDs

Definir os limites ligeiramente abaixo da confiança mediana do detetor fez o TrackTrack passar de 9 para 27 IDs, aproximando-se da contagem manual. Os parâmetros comuns a todos os rastreadores:

ParâmetroPredefinição do ByteTrackAumenta paraReduz para
track_high_thresh0.25Ignorar deteções fracas na primeira associaçãoRastrear com um detetor de baixa confiança
new_track_thresh0.25Eliminar rastos falsos de curta duraçãoIniciar rastos para objetos pouco visíveis
track_buffer30 fotogramasManter os rastos durante oclusões prolongadasLibertar mais cedo os IDs de objetos que saíram de cena
match_thresh0.8Fazer associações mais permissivas (movimento rápido, caixas instáveis)Fazer associações mais rigorosas (multidões)

Armadilhas#

Limiares acima da confiança do detector

Sintoma: muito menos IDs do que objetos, principalmente com um modelo pequeno. Solução: mostre a confiança mediana das detecções (veja a solução) e defina new_track_thresh e track_high_thresh logo abaixo dela.

Esquecer persist ou compartilhá-lo

Sintoma: os IDs são redefinidos a cada quadro quando você chama model.track(frame) por conta própria, ou alternam entre objetos quando duas câmeras alimentam um modelo. Solução: passe persist=True para quadros consecutivos de um único fluxo e atribua uma instância própria do modelo a cada câmera (ou use uma origem .streams, que mantém um rastreador por fluxo).

Oscilação de ID em objetos lentos

Sintoma: o ID de um carro estacionado muda a cada poucos quadros. Solução: o rastreador está iniciando novas trajetórias em vez de corresponder às antigas. Primeiro, verifique a confiança do detector nesse objeto e, em seguida, aumente match_thresh e track_buffer.

Experimente

Grava um vídeo de 30–60 segundos do teu próprio domínio e conta manualmente os objetos de uma classe. Executa compare_trackers.py no vídeo, mede as confianças do detetor com o script da solução e ajusta um YAML do rastreador para que a contagem de IDs se aproxime da contagem manual. Apresenta uma tabela: rastreador, IDs únicos, contagem manual.

Concluído quando
Você concluiu a aula quando todos estes critérios forem atendidos.
  • Tens as contagens de IDs únicos do ByteTrack, BoT-SORT e TrackTrack no mesmo vídeo, juntamente com uma contagem manual.

  • Consegues explicar a contagem mais baixa com base nos limites do rastreador e na confiança mediana do detetor.

  • Um YAML de rastreador ajustado alterou a contagem na direção que previas antes de o executar.

Mostrar solução

Mede primeiro as confianças do detetor e, em seguida, define os limites ligeiramente abaixo delas:

import torch

from ultralytics import YOLO

model = YOLO("yolo26n.pt")
video = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"
conf = torch.cat([r.boxes.conf for r in model.predict(video, stream=True, classes=[0], verbose=False)])
print(f"median {conf.median():.2f}, share >= 0.7: {(conf >= 0.7).float().mean():.0%}")
median 0.53, share >= 0.7: 17%

Para o clipe da praça, a tabela indica: ByteTrack 32, BoT-SORT 33, TrackTrack 9, TrackTrack ajustado 27, contagem manual de cerca de 30. Apenas 17% das deteções ultrapassam new_track_thresh: 0.7 do TrackTrack, por isso reduzi-lo para 0,35 (com track_high_thresh: 0.3) é a solução certa; para esta câmara fixa, montada por cima, o ByteTrack simples é a opção mais direta.

Próximos passos

Com IDs estáveis, a próxima lição apresenta os pipelines de produção mais comuns construídos com base neles: contagens, zonas, mapas de calor e velocidades.

Entre para salvar seu progresso