Limiares e filtragem
Quatro argumentos decidem quais predições sobrevivem: conf, iou, max_det e classes. Só dois deles se aplicam a todas as famílias, porque um preditor de conjuntos decodifica um conjunto fixo de queries e nunca roda NMS.
Os quatro argumentos
| Argumento | Padrão | Aplica-se a |
|---|---|---|
conf | 0.25 | Todas as famílias |
iou | 0.45 | Famílias que rodam supressão de não máximos |
max_det | 300 | Todas as famílias |
classes | None | Todas as famílias |
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreYOLO9s.pt") result = model( SAMPLE_IMAGE, conf=0.25, # mantém as predições com esta pontuação ou acima iou=0.45, # limiar de sobreposição do NMS, onde o NMS roda max_det=300, # teto por imagem classes=None, # ou uma lista de ids de classe)print(len(result.boxes))from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreYOLO9s.pt") for conf in (0.1, 0.25, 0.5, 0.75): result = model(SAMPLE_IMAGE, conf=conf) print(conf, len(result.boxes))libreyolo predict model=LibreYOLO9s.pt conf=0.4 iou=0.5 max_det=100 \ source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpgDois deles são universais e dois não são, e essa é a coisa mais útil de saber antes de ajustar qualquer outra.
A validação usa padrões diferentes de propósito: val() roda com conf=0.001 e
iou=0.6, porque a precisão média é calculada sobre uma curva de
precisão-recall completa e um corte em 0.25 a truncaria.
conf
conf é a pontuação abaixo da qual uma predição é descartada. Ela se aplica a
todas as famílias, inclusive as que nunca rodam NMS, e é o primeiro controle a
buscar quando há detecções demais ou de menos.
O padrão de 0.25 serve para olhar imagens. Alimentar um sistema a jusante
geralmente pede um valor mais alto; medir acurácia pede um valor bem mais baixo.
A validação de detecção expõe metrics/best_conf e limiares por classe obtidos de F1 em IoU 0.50. Use-os como pontos de partida medidos para os limiares de deploy; veja validação. A segmentação não expõe essas chaves.
iou
iou é a sobreposição acima da qual a supressão de não máximos remove, entre
duas caixas da mesma classe, a de menor pontuação. Só significa alguma coisa se
a família rodar supressão.
Um preditor de conjuntos decodifica um número fixo de queries e fica com as de
maior pontuação. As duplicatas são suprimidas dentro da arquitetura durante o
treinamento, não por uma etapa de pós-processamento, então não há limiar para
girar. Estas famílias aceitam iou por paridade de API e o ignoram:
CenterNet, DEIM, DETR, Deformable DETR, D-FINE, DINO-DETR, EdgeCrafter, Faster R-CNN, LW-DETR, Mask R-CNN, RF-DETR, RT-DETR e a cabeça end-to-end do YOLOv9. Variantes construídas sobre esses decodificadores herdam o comportamento.
from libreyolo import LibreYOLO, SAMPLE_IMAGE # O RF-DETR decodifica um conjunto fixo de queries, então iou não muda nada aqui.model = LibreYOLO("LibreRFDETRs.pt") loose = model(SAMPLE_IMAGE, iou=0.9)tight = model(SAMPLE_IMAGE, iou=0.1) # Mesma contagem nos dois casos. conf e max_det são os controles que funcionam.print(len(loose.boxes), len(tight.boxes))A maioria delas diz isso nas docstrings de pós-processamento, mas nenhum aviso é
emitido em tempo de execução, então uma varredura de iou no RF-DETR produz uma
linha reta em vez de um erro. Faster R-CNN e Mask R-CNN são um caso um pouco
diferente: os dois já rodaram NMS dentro do modelo, com um limiar fixo lá em
cima que iou não tem como mudar de forma suportada.
Estas famílias usam sim: YOLOv1 até YOLOv4, YOLOv7, YOLOv9, YOLOX, YOLO-NAS, RTMDet, PicoDet, EfficientDet, FCOS, RetinaNet e SSD.
Três opções de tempo de predição fazem iou importar até para um preditor de
conjuntos, porque as três agem sobre as caixas depois que o modelo terminou:
tiling=Truereconcilia tiles sobrepostos com NMS por classe emiouaugment=Truemescla visões espelhadas com NMS por classe emiouagnostic_nms=Truesuprime caixas sobrepostas entre classes emiou, descrito abaixo
As duas primeiras são cobertas em Desempenho de inferência.
Detectores de vocabulário aberto têm a própria regra. Uma família cujo
processador roda NMS declara o próprio limiar padrão e respeita iou, que é o
caso do OMDet-Turbo. Famílias que não suprimem nada, Grounding DINO, OWLv2 e
OV-DEIM, emitem um aviso quando iou é passado. Esse aviso é o único do gênero
na biblioteca.
max_det
max_det limita quantas predições voltam para uma imagem. Ele se aplica em
todo lugar, mas por mecanismos diferentes: uma família com NMS trunca depois da
supressão, um preditor de conjuntos usa o valor como o tamanho da sua seleção
top-k.
Algumas famílias limitam abaixo do que você pedir, porque a configuração de
referência original delas faz isso. O SSD limita em 200, e o FCOS no próprio limite de
detecções por imagem. Aumentar max_det acima desses valores não tem efeito.
max_det é aplicado de forma centralizada e não por família em dois casos: a
inferência por blocos (tiles), onde a lista mesclada é truncada depois que os
tiles são reconciliados, e as chamadas com classes ou agnostic_nms=True, em
que o corte vem depois do filtro ou da supressão.
Filtragem por classes
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreYOLO9s.pt") # Os ids de classe indexam model.names. No COCO, 0 é person.result = model(SAMPLE_IMAGE, classes=[0]) print({result.names[int(c)] for c in result.boxes.cls.tolist()})from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreYOLO9s.pt")result = model(SAMPLE_IMAGE) wanted = {"person", "backpack"}ids = [i for i, name in result.names.items() if name in wanted]print(ids) filtered = model(SAMPLE_IMAGE, classes=ids)print(len(filtered.boxes))classes recebe uma lista de ids de classe e mantém apenas as predições cuja
classe está nela. Os ids indexam result.names, e a forma mais segura de obter
um é ler names de um resultado em vez de supor a ordenação de um dataset.
A filtragem acontece de forma centralizada, depois do pós-processamento de cada família, no único funil pelo qual passa todo caminho de predição. Isso tem duas consequências que vale conhecer. Funciona em todas as famílias, inclusive nas que não têm NMS. E também filtra os payloads alinhados com as caixas, então máscaras, keypoints e caixas orientadas são cortados junto em vez de ficarem desalinhados.
Na linha de comando, classes aceita um inteiro solto, uma lista ou uma string
separada por vírgulas:
libreyolo predict model=LibreYOLO9s.pt classes=0 source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpglibreyolo predict model=LibreYOLO9s.pt classes="[0,2,5]" source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpgFiltrar não é acurácia de graça. O modelo continua gastando seu orçamento
prevendo classes que você depois descarta. Com classes definido, a família
mantém um orçamento de candidatos de 300 caixas, ou max_det quando ele é
maior, e o corte para max_det vem depois do filtro, então um max_det pequeno
não espreme a sua classe para fora. Os backends exportados usam o mesmo
orçamento, inclusive os engines TensorRT em batch. Uma imagem com mais de 300
caixas de maior score de classes indesejadas ainda pode encher o orçamento antes
de chegar na sua classe; aumente max_det acima de 300 se isso acontecer.
agnostic_nms
O NMS de toda família leva a classe em conta, então, por padrão, duas caixas
sobrepostas de classes diferentes sobrevivem as duas, em qualquer iou.
agnostic_nms=True acrescenta um passo agnóstico a classes: entre as caixas que
se sobrepõem acima de iou, só a de maior score sobrevive, quaisquer que sejam
as classes.
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreYOLO9s.pt") per_class = model(SAMPLE_IMAGE)agnostic = model(SAMPLE_IMAGE, agnostic_nms=True) # Caixas sobrepostas de classes diferentes colapsam na de maior score.print(len(per_class.boxes), len(agnostic.boxes))libreyolo predict model=LibreYOLO9s.pt agnostic_nms=true \ source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpgO passo roda sobre as detecções já prontas da família, depois do filtro de
classes e antes do corte para max_det. Por isso ele se comporta igual em
preditores de conjuntos que não rodam NMS próprio, em backends exportados, e com
augment=True e tiling=True. Máscaras e keypoints são descartados junto com a
sua caixa, e caixas orientadas são comparadas por IoU rotacionado. Ele cobre as
tarefas que retornam caixas: detect, segment, pose e obb.
A família mantém um orçamento de candidatos de 300 caixas, ou max_det quando
ele é maior, para o passo trabalhar. Com max_det abaixo de 300, candidatos de
menor score reabastecem as vagas que a supressão libera. Com 300 ou mais, o que
inclui o padrão, essas vagas ficam vazias.
Onde ele não se aplica:
- No caminho padrão do predict, uma tarefa sem caixas levanta
ValueError. LibreEnsemblee HRNet levantamNotImplementedError.- Os modelos
LibreSAMe os detectores 3D, WildDet3D, 3D-MOOD, FCOS3D e DetAny3D, não recebem esse argumento e levantamTypeError. - L2CS-Net, PP-OCRv5, SAM 3D Body e LibreFaceRec rodam o próprio caminho de predict e o ignoram.
val(agnostic_nms=True) aplica o mesmo passo à validação de detect e segment;
veja Validação e métricas.
O que o predict rejeita
Dois argumentos levantam erro em vez de avisar: visualize e embed levantam
NotImplementedError. Para embeddings, carregue o modelo com task="embed" e
chame predict ou embed normalmente. agnostic_nms=True levanta erro onde não
se aplica, como listado acima.
Qualquer coisa não reconhecida levanta TypeError nomeando as opções
suportadas, então um erro de digitação falha na hora em vez de ser ignorado em
silêncio.
Estes são aceitos, geram aviso e são descartados: boxes, dnn, half,
line_width, retina_masks, show_conf, show_labels e verbose.