Detecção de bordas
A detecção de bordas prediz a probabilidade de cada pixel estar na borda de um objeto. O LibreYOLO expõe isso como a tarefa edge, que retorna um mapa denso de probabilidade no canvas da imagem original em vez de um conjunto de segmentos de reta.
Definição
A tarefa edge prediz uma probabilidade por pixel a partir de uma única imagem
RGB: 0 significa não-borda e 1 significa borda. O mapa permanece contínuo,
então escolher o limiar que o transforma em uma imagem binária de bordas fica a
cargo de quem chama, e o limiar certo depende do dataset e do uso posterior.
Uma predição preenche result.edges, um payload EdgeMap que guarda um array
float32 (H, W) em [0, 1] no canvas da imagem original. .array retorna esse
mapa como NumPy e .binary(threshold) retorna uma máscara booleana.
result.boxes fica vazio, então conf, iou e max_det não têm efeito.
Results.plot() cobre essa tarefa e desenha o mapa diretamente.
Modelos
Três famílias atendem edge.
O DexiNed, a Dense Extreme Inception Network, funde várias saídas laterais em um único mapa de probabilidade e roda em 352 px nativos.
O TEED, o Tiny and Efficient Edge Detector, é uma rede
pequena nos mesmos 352 px nativos, com stride de downsample de 4 contra os 16 do
DexiNed, então ele aceita mais valores de imgsz.
O LibreMODUS produz bordas no estilo Canny como um
dos alvos de um modelo any-to-any. Ele precisa do extra modus e da sua própria
conta autenticada no Hugging Face, e não oferece nem val() nem export(),
então não participa das seções de validação e exportação abaixo.
Predição
O LibreYOLO não publica nenhum checkpoint de bordas. Os pesos de DexiNed e TEED lançados oficialmente são treinados no BIPED, cujos termos publicados de dataset restringem o uso a fins não comerciais, então o LibreYOLO não os espelha. Converta um checkpoint que você tenha licença para usar e depois carregue o arquivo convertido pelo caminho:
python weights/convert_dexined_weights.py upstream.pth weights/LibreDexiNedb-edge.pt --verifyfrom libreyolo import LibreYOLO, SAMPLE_IMAGE # Nenhum checkpoint de bordas acompanha o LibreYOLO; converta um antes (abaixo).model = LibreYOLO("weights/LibreDexiNedb-edge.pt")result = model(SAMPLE_IMAGE, save=True) edges = result.edgesprint(edges.array.shape) # (H, W) float32 em [0, 1]print(edges.binary(0.5).sum()) # contagem de pixels de borda em 0.5from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("weights/LibreDexiNedb-edge.pt")result = model(SAMPLE_IMAGE) # O mapa contínuo é mantido para que o limiar continue sendo sua decisão.for t in (0.3, 0.5, 0.7): print(t, int(result.edges.binary(t).sum()))from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("weights/LibreDexiNedb-edge.pt")result = model(SAMPLE_IMAGE) # plot() desenha o mapa; ele é definido para resultados de borda e de normais.result.plot().save("edges.png")O nome do arquivo precisa carregar o sufixo de tarefa -edge para o loader
reconhecê-lo. imgsz precisa ser divisível pelo stride de downsample da rede, e
o LibreYOLO levanta um erro claro informando o divisor quando não for. Veja
predição para fontes, streaming e tratamento dos resultados.
Formato do dataset
A validação de bordas pareia cada imagem RGB com um mapa de canal único de mesmo nome-base e mesma resolução, mais uma máscara de validade opcional.
dataset/
data.yaml
images/
val/scene.jpg
edges/
val/scene.png
masks/
val/scene.pngpath: dataset
train: images/train
val: images/val
edges_dir: edges
masks_dir: masks
nc: 1
names: {0: edge}O alvo é um PNG ou TIF de canal único, não uma visualização RGB. Mapas inteiros
são divididos pelo máximo do seu dtype; mapas float já precisam ser finitos e
estar em [0, 1]. Pixels da máscara contam como válidos quando são diferentes de
zero, e pixels de padding nunca contribuem para uma métrica. edge_invert: true
cobre fontes que armazenam bordas pretas sobre branco. Veja
formatos de dataset para o contrato completo.
Treinamento
Nenhuma família de bordas no LibreYOLO tem implementação de treinamento:
train() levanta NotImplementedError nas três. Cada página de modelo indica o
script de conversão que transforma um checkpoint treinado em outro lugar em um
que o LibreYOLO consegue carregar.
Validação
val() reporta as F-measures no estilo BSDS. As predições contínuas são
primeiro afinadas com supressão de não-máximos de gradiente em quatro direções, e
depois os pixels de borda preditos e os do ground truth são pareados um a um
dentro de uma tolerância de distância.
from libreyolo import LibreYOLO model = LibreYOLO("weights/LibreDexiNedb-edge.pt")metrics = model.val(data="my-dataset.yaml", imgsz=352) print(metrics["metrics/ODS"]) # fitnessprint(metrics["metrics/OIS"])print(metrics["metrics/best_threshold"])from libreyolo import LibreYOLO model = LibreYOLO("weights/LibreDexiNedb-edge.pt")metrics = model.val( data="my-dataset.yaml", imgsz=352, edge_thresholds=(0.1, 0.2, 0.3, 0.4, 0.5), edge_max_dist=0.0075,) print(metrics["metrics/ODS"], metrics["metrics/best_threshold"])metrics/ODS é a F-measure na escala ótima do dataset: as contagens de
pareamento são agregadas em todo o dataset a cada limiar, e a melhor dessas
F-measures agregadas é reportada. Ela também é o fitness, o número lido pela
seleção do melhor checkpoint. metrics/OIS é a F-measure na escala ótima da
imagem, a média sobre as imagens da melhor F-measure de cada imagem, então ela
deixa cada imagem escolher o próprio limiar. metrics/best_threshold é o limiar
que produziu o ODS, e é ele que você deve reutilizar em edges.binary() na
inferência.
Dois argumentos moldam a varredura. edge_thresholds é o conjunto de limiares
testados, com padrão de 0.01 a 0.99 em centésimos. edge_max_dist é a
tolerância de pareamento como fração da diagonal da imagem, com padrão
0.0075; um par mais distante que isso não é um pareamento.
Exportação
Um modelo de bordas exportado é carregado de volta pelo LibreYOLO() a partir
do sufixo do arquivo, então um arquivo .onnx se comporta como um checkpoint e
retorna os mesmos Results.
from libreyolo import LibreYOLO model = LibreYOLO("weights/LibreDexiNedb-edge.pt")model.export(format="onnx", imgsz=352)from libreyolo import LibreYOLO, SAMPLE_IMAGE # A factory roteia pelo sufixo do arquivo, então um artefato exportado é# carregado como qualquer checkpoint e retorna o mesmo objeto Results.model = LibreYOLO("weights/LibreDexiNedb-edge.onnx")result = model(SAMPLE_IMAGE) print(result.edges.array.shape)A exportação de bordas usa um contrato de runtime de resolução fixa e batch 1:
dynamic e um batch diferente de 1 são rejeitados, e o grafo exportado gera um
único mapa de probabilidade fundido. A cobertura por formato está nas páginas do
DexiNed e do TEED e na
matriz completa de exportação.
Exportação lista os argumentos que cada formato aceita.