DEV Community

Neuman F.
Neuman F.

Posted on

Introdução à Visão Computacional - Parte 2: Detecção de Objetos com YOLO 11

Introdução

Na primeira parte deste artigo, exploramos os princípios fundamentais da visão computacional e apresentamos bibliotecas e algoritmos utilizadas na área. Nessa segunda parte, iremos utilizar uma abordagem prática com o YOLOv11, algoritmo de detecção de objetos, desenvolvido pela Ultralytics. Mostraremos como configurar o ambiente, carregar um modelo YOLOv11 pré-treinado, detectar objetos em imagens e vídeos, e interpretar os resultados.

Detecção de objetos

Utilizaremos um notebook Python no ambiente Google Colab, como exemplo, porém o passo a passo pode ser seguido em qualquer outro ambiente.

Com sua conta Google, acesso o Google Colab: https://colab.research.google.com e crie um novo notebook, clicando em 'New notebook'.

Instalação de bibliotecas

Primeiramente, instalaremos a biblioteca da Ultralytics com o gerenciador de pacotes do Python, pip:

! pip install ultralytics
Enter fullscreen mode Exit fullscreen mode

Utilização

Em seguida, iremos carregar um modelo YOLO versão 11 pré-treinado. Ao executar o seguinte trecho de código, um modelo será baixado do GitHub da Ultralytics para o ambiente do notebook.

from ultralytics import YOLO

model = YOLO("yolo11n.pt") # ou YOLO("yolo11n.yaml") para criar um modelo do zero
Enter fullscreen mode Exit fullscreen mode

Treinamento

Treinaremos o modelo com o dataset de Common Objects in Context (ou COCO) versão 8, utilizando 5 epochs.

COCO é um conjunto de dados de detecção, segmentação e legendagem de objetos em larga escala. Em sua versão completa, ele possui mais de 200 mil imagens rotuladas, 80 categorias de objetos e 91 categorias de "coisas". Para fins de teste, utilizaremos um versão menor, composto das primeiras 128 imagens do COCO Train 2017.

Já epoch, se refere a uma passagem completa por todo o conjunto de dados de treinamento. Imagine que você tem um conjunto de imagens com rótulos, usado para treinar um modelo para detectar objetos. Durante uma epoch, o modelo "vê" todas essas imagens uma vez, ajustando seus pesos internos para aprender a fazer previsões mais precisas. Portanto, se você treinar um modelo com 50 epochs, isso significa que ele passará 50 vezes por todo o conjunto de dados. Escolher um número baixo de epochs pode causar o que chamamos de underfitting, onde o modelo aprende pouco. O oposto disso também pode ser prejudicial, pois o modelo aprende demais os dados de treino e perde capacidade de generalização, chamado de overfitting.

results = model.train(data="coco128.yaml", epochs=5)
Enter fullscreen mode Exit fullscreen mode

Depois de treinado, note que foram criados diretórios para o dataset e para o resultado dos treinamentos (métricas e pesos), em runs > detect > train. No diretório de weights, estão os pesos treinados do modelo. O arquivo best.pt representa o modelo com o melhor desempenho obtido durante o treinamento, medido com base em alguma métrica de validação, geralmente mAP (mean Average Precision). Já o last.pt, é o modelo salvo ao final do treinamento, independentemente de seu desempenho. De modo geral, podemos escolher o best.pt para detectar os objetos pós treinamento, e last.pt quando quisermos continuar o treinamento de onde parou.

Arquivos criados

Para sabermos se o modelo está desempenhando bem, podemos consultar as métricas disponíveis na imagem runs/detect/train/results.png. Nela, podemos ver a evolução do desempenho do modelo a cada epoch.

  • Precision é a proporção de previsões corretas entre todas as previsões positivas feitas. Alta precisão significa que o modelo não comete muitos falsos positivos
  • Recall é a proporção de objetos verdadeiros que o modelo conseguiu identificar corretamente. Alto recall significa que o modelo não deixa escapar muitos objetos reais.
  • mAP_0.5 e mAP_0.5:0.95 são métrica de mean Average Precision. mAP_0.5 é a média da precisão com IoU ≥ 0.5, idealmente deve ficar acima de 0.5 (ou 50%) para tarefas gerais. Enquanto mAP_0.5:0.95 é a média da precisão com múltiplos limiares de IoU (de 0.5 a 0.95, com passo 0.05), idealmente ficando acima de 0.75 (ou 75%) em contextos profissionais mais exigentes.

Na imagem abaixo, podemos ver que a precisão está aumentando, porém o recall está instável. Além disso, pela baixa quantidade de epochs, os gráficos encontram-se muito instáveis.

Resultado para 5 epochs

Testando com 20 epochs, podemos notar que as curvas de loss de caem de forma consistente, o que indica que o modelo está conseguindo aprender com os dados. A precisão, apesar das oscilações, aparente estar aumentando. indicando que o modelo está acertando mais quando prevê a presença de objetos, e o recall está crescendo constantemente, o que indica que o modelo está detectando mais objetos verdadeiros ao longo do tempo.

Resultado para 20 epochs

Mas agora você pode estar se perguntando qual é o número ideal de epochs, e a resposta é: depende. Para datasets menores, como o COCO 128, de 50 e 100 epochs pode ser o suficiente, mas para grandes volumes de imagens, pode ser necessário mais de 300 epochs.

Para minimizar a tentativa e erro ao escolher o número de epochs, podemos utilizar o parâmetro patience, que serve para interromper automaticamente o treino quando não há melhora nas métricas por várias épocas consecutivas. Continuando nossa análise, agora podemos definir, por exemplo, epochs=100 e patience=15, que gera o resultado da figura a seguir.

Podemos notar que nos logs, foi mostrado que o treinamento parou mais cedo pois nenhuma melhora foi observada nas últimas 15 epochs, e os melhores resultados foram observados na epoch de número 73.

Output

Sobre as métricas, observamos que a precisão cresceu e se estabilizou por volta de 0.90, o recall atingiu aproximadamente 0.85 e mAP50 chegou a 0.91, o que são bons resultados para o dataset.

Resultado para 100 epochs com patient 15

Predição

Agora que temos o nosso modelo treinado, podemos utilizá-lo da seguinte forma:

model = YOLO("./runs/detect/train/weights/best.pt")
Enter fullscreen mode Exit fullscreen mode

Note que, nós fizemos diferentes treinamentos, portanto várias versões do diretório "train". Então, certifique-se que você ajustou o caminho do arquivo para o último treinamento.

Então, podemos utilizar o modelo para fazer uma predição com:

results = model("https://ultralytics.com/images/bus.jpg", save=True)
Enter fullscreen mode Exit fullscreen mode

O resultado da predição será salvo em 'runs/detect/predict'.

Resultado da predição com a imagem de teste

Detecção de objetos em vídeos

Para detectar objetos em vídeos, precisaremos primeiramente instalar a biblioteca OpenCV para Python, com:

! pip install opencv-python
Enter fullscreen mode Exit fullscreen mode

Então, com o trecho de código abaixo, recebemos um arquivo de vídeo no formato .mp4 (input.mp4), processamos cada frame, utilizando o modelo para predizer o resultado e escrevemos em um novo frame, que fará parte de um novo arquivo de vídeo, output.mp4.

import cv2

input_path = "input.mp4"
output_path = "output.mp4"

cap = cv2.VideoCapture(input_path)

width  = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps    = cap.get(cv2.CAP_PROP_FPS)
fourcc = cv2.VideoWriter_fourcc(*'mp4v')

out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))

while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break

    results = model(frame)

    annotated_frame = results[0].plot()

    out.write(annotated_frame)

cap.release()
out.release()
cv2.destroyAllWindows()
Enter fullscreen mode Exit fullscreen mode

O resultado pode ser visto abaixo.

Referências

  1. https://docs.ultralytics.com
  2. https://cocodataset.org

Top comments (1)

Collapse
 
jonatapaulino profile image
jonata

Muito bom seu tutorial. Parabéns. Onde posso encontrar a parte 1? Obrigado.