Usando Yolov4 para detectar classes personalizadas



Original Source Here

Usando Yolov4 para detectar classes personalizadas

Muitas vezes, em certos problemas, queremos que o nosso projeto detecte e faça reconhecimento de certos tipos de classes e para isso utilizamos de alguns algoritmos bastante famosos ou que já foram bastante comuns, como por exemplo: window sliding, EfficientDnet, R-CNN, Fast R-CNN e o mais recente Faster R-CNN. Entretanto ferramentas como o Windows Sliding se tornaram obsoletas por serem extremamente custosas, e o R-CNN apesar de ser bastante preciso não é tão rápido, e apenas o Faster R-CNN consegue oferecer uma boa rapidez na detecção de objetos.

Para resolver esse problema de custo e velocidade surgiu o algoritmo do Yolo. O Yolo se destaca pela sua grande velocidade em relação aos outros algoritmos, contudo ele perde um pouco da precisão. Para mais detalhes observar a Figura logo abaixo.

Para mais detalhes sobre o funcionamento e estruturação do Yolo é possível acessar o artigo dos criadores aqui.

Figura 1 — YOLOv4 performance.

Origem do Yolo

O Yolo foi inicialmente criado e desenvolvido por Joseph Redmon e Ali Farhadi, entretanto devido a algumas questões (Os autores originais viram que o Yolo estava sendo utilizado para fins militares) eles deixaram esse projeto de lado. Por causa disso as versões mais recentes (Yolov4 e o Yolov5) foram desenvolvidas por pessoas diferentes.

Mas como funciona o Yolo?

De forma resumida podemos dizer que o Yolo cria um grid na imagem (o tamanho dos quadrados do grid podem ser alterados), e após criar esse grid, o algoritmo irá chegar em cada um dos quadrados a probabilidade de ter uma classe (pessoa, cachorro…) ali, e assim colocar uma BoundingBoxes. Note que em mais de quadrado pode ter a mesma classe (o corpo de uma pessoa pode ocupar mais de um quadrado), então para isso foi feito uma IOU (intersection of union), ou seja, as BoundingBoxes que forem sendo criadas uma em cima da outra serão unificadas. E claro, como as boxes serão unificadas, a probabilidade da classe para cada uma das predições também serão somadas e depois feito a média.

Para mais detalhes acessar este outro artigo que fala sobre sua estrutura aqui.

Código desse tutorial

Todo código utilizado nesse tutorial foi feito em um Colab notebook que pode ser acessado aqui. Ou através do repositório do GitHub aqui.

Detectando e reconhecendo Objetos com as classes do COCO dataset

Primeiramente para entender melhor como funciona o YOLOv4 iremos primeiro detectar objetos com as classes do COCO dataset. E em seguida iremos fazer um modelo personalizado.

1. Baixando o arquivo do Yolov4

Agora iremos fazer o download do Yolov4 direto do repositório. Em seguida será feito um cd para o arquivo que acabamos de baixar o darknet, é nesse arquivo onde está todos os arquivos do yolov4, e logo em seguida iremos alterar o arquivo makefile para que yolov4 opere usando o OpenCV e a GPU.

  • É possível fazer o treinamento e a detecção do Yolov4 usando apenas a CPU, entretanto é bastante demorado e se recomendo utilizar a GPU.
  • O OpenCV é utilizado para gerar os boundingBoxes durante a detecção numa imagem ou vídeo.
# Git clone no repositorio!git clone https://github.com/AlexeyAB/darknet

Em seguida, como foi mencionado precisamos alterar o arquivo makefile para que o YOLOv4 entenda que queremos utilizar a GPU e o OpenCV no processo de treinamento.

# Alterando o makefile para habilitar a GPU e o OpenCV%cd darknet!sed -i 's/OPENCV=0/OPENCV=1/' Makefile!sed -i 's/GPU=0/GPU=1/' Makefile!sed -i 's/CUDNN=0/CUDNN=1/' Makefile!sed -i 's/CUDNN_HALF=0/CUDNN_HALF=1/' Makefile

2. Baixando os pesos treinados do COCO + make do arquivo

Baixando os arquivos:

!wget https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.weights

Makefile:

!make

3. Fazendo a detecção de objetos

Para isso basta apenas rodar a seguinte linha de código.

!./darknet detector test cfg/coco.data cfg/yolov4.cfg yolov4.weights data/person.jpg

Reconhecendo e detectando Objetos com sua própria classe personalizada

Agora iremos fazer o passo a passo de como fazer um treinamento com classes personalizadas. Para isso é necessário fazer a criação/alteração de alguns arquivos importantes para o nosso treinamento, eles são:

  • Dados customizados com suas respectivas labels (as bounding boxes).
  • Arquivo .cfg onde irá conter a estrutura do modelo de treinamento.
  • Arquivos .data e .names, onde o .data irá conter as informações sobre os diretórios das imagens (tanto de validação como de treinamento), os pesos, e até mesmo o diretório do nosso arquivo .names, e o arquivo .names irá conter as classes existentes para esse treinamento.
  • Arquivos train.txt e o test.txt, que são os arquivos que indicam quais são os nomes das nossas imagens e os respectivos diretórios. Esses arquivos também são informados no arquivo .data.

Antes de tudo devemos baixar os arquivos do YOLOv4, fazer a alteração no arquivo makefile e por fim fazer o make do arquivo. Agora iremos mostrar passo a passo de como criar cada um dos arquivos necessários pra a criação do nosso modelo personalizado.

1. Baixando pesos pré-treinados

Diferente do passo anterior que baixamos pesos treinados para o dataset do COCO, iremos baixar pesos pré-treinados que serviram de base para treinar o nosso modelo personalizado. É possível não utilizar pesos pré-treinados e usar pesos randômicos.

# Baixando pesos pre-treinados do Yolo!wget https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.conv.137

2. Dataset e Labels

Agora que fizemos alguns pequenos preparativos vamos começar a trabalhar em cima do nosso dataset. Para esse projeto foi utilizado o dataset do MIT Indoor, como há varias imagens referentes a lugares fechados, iremos utilizar apenas as imagens referentes à banheiros, em especial serão criadas três classes: bath (banheira), sink (pia), e toilet (vazo sanitário), e para cada uma dessas classes será criada uma label na imagem.

Dentro da pasta darknet será criado uma pasta chamada dataset, onde irá conter todos os nosso arquivos e as imagens necessárias para o nosso treinamento. Na figura a seguir mostram como fica a arquitetura dos arquivos para melhor entendimentos:

Figura 2 — Estrutura dos arquivos

O dataset utilizado nesse tutorial pode ser encontrado aqui.

# Criando o nosso diretório dataset!mkdir dataset

Agora que criamos o nosso diretório dataset, será criado dois diretórios. Esses dois novos diretórios são para organizar as imagens e as labels, sendo que um diretório que será para as imagens de treino e outro diretório será para as imagens de validação. Ao criar esses dois diretórios, coloque as imagens dentro de cada um dos diretórios.

Para esse projeto será utilizado cerca de 100 imagens, então 90% das imagens serão para treino e os outros 10% para validação.

  • Total de imagens — 100 imagens.
  • Treino — 90 imagens.
  • Validação — 10 imagens.
!mkdir dataset/train!mkdir dataset/validation

2.1 Criando as Labels

Para gerar as labels de cada um dos objetos na imagem foi utilizado um programa chamado LabelImage. Para criar cada uma das BoudingBoxes bastar usar a opção de criar ‘RectBox’ do labelImg e em seguida colocar cada tag da classe. Ao fazer isso para cada uma as classes existentem na imagem basta salvar todo o processo no botão ‘Save’, lembrando que antes de salvar devemos por o arquivo no tipo ‘Yolo’.

Note que quando salvarmos o arquivo, será erado um arquivo de tipo .txt com o mesmo nome que a imagem.

É possivel encontrar e baixar o labelImg no link: https://github.com/tzutalin/labelImg

Figura 3 — LabelImg

3. Gerando os arquivos train.txt e test.txt

Esses arquivos (train.txt e o test.txt) são usados para dizer ao YOLOv4 onde é o diretorio das nossas imagens e quais são os nomes das imagens. Aqui abaixo é possivel ver um exemplo de arquivo .txt para o train e test.

Figura 4 — train.txt
Figura 5 — test.txt

Código para a geração do arquivo train.txt

# Gerando o arquivo train.txtimport osos.getcwd()collection = 'dataset/teste'file = open('dataset/teste.txt', "w+")for filename in os.listdir(collection):  if(filename[-3:] != 'txt'):  file.write('dataset/teste/' + filename + '\n')file.close()

Código para a geração do arquivo test.txt

# Gerando os arquivos test.txtos.getcwd()collection = 'dataset/validation'file = open('dataset/test.txt', "w+")for filename in os.listdir(collection):  if(filename[-3:] != 'txt'):  file.write('dataset/test/' + filename + '\n')file.close()

4. Arquivos .data, .names

Agora que fizemos os ultimos arquivos .txt restante, vamos criar os arquivos .data e .names. O arquivo .data vai conter informaçõe sobre os diretorios para o Yolov4, enquanto o arquivo .names vai conter informaçõs sobre os nomes das classes.

Figura 6 — file .names
Figura 7 — file .data

5. Arquivo .cfg

Por fim, o ultimo arquivo que temos que criar o .cfg. Esse tipo de arquivo contém as informações referentes a rede, e as possíveis configurações que podem ser feitas nela. Para facilitar sugiro pegar o arquivo coco.cfg na pasta cfg do darknet, e em seguida será feita umas pequenas modificações simples para se adaptar a nossas classes.

Dentro do arquivo .cfg faça as seguintes mudanças:

  • max_batches = 2000 * (Número de classes)
  • steps = max_batches * 0.8, max_batches * 0.9
  • Em cada camada Yolo altere o valor classes = Número de classes
  • Antes de cada camada Yolo, altere o filtro da camada convolucional para filters = (Número de classes + 5) * 3

6. Observando nosso dataset

Para observamos melhor quais são as caracteristicas do nosso dataset fizemos um código para melhor visualiza-lo.

import osimport matplotlib.pyplot as pltimport matplotlib.gridspec as gridspecimport glob
def read_label(image_path): file_name = image_path.replace('.jpg', '.txt') with open(file_name, 'rt') as file: print(os.path.basename(file_name) + ': \n' + file.read())image_path = glob.glob("dataset/train/*.jpg")fig = plt.figure(figsize=(12,8))cols = 2rows = 2grid = gridspec.GridSpec(nrows=rows, ncols=cols, figure=fig)for i in range(cols*rows): fig.add_subplot(grid[i]) image=plt.imread(image_path[i]) plt.title(os.path.basename(image_path[i])) plt.axis(False) plt.imshow(image) read_label(image_path[i])plt.savefig("dataset_examples.jpg", dpi=300)
Figura 8— Exemplos

7. Treinando os nosso dados

Agora que temos tudo pronto, basta executar a linha de código a seguir para começar o treino.

./darknet detector train dataset/classes.data dataset/yolov4-custom.cfg yolov4.conv.137 -dont_show -map

8. Detectando nossa classe personalizada

img_path = "dataset/room30.jpg"./darknet detector test dataset/classes.data dataset/yolov4-custom.cfg dataset/yolov4-custom_best.weights {img_path} -dont-show
Figura 9 — Exemplo 1.
Figura 10 — Exemplo 2.

FIM

Espero que tenham gostado do tutorial e ele tenha sido de bastante ajuda :))

AI/ML

Trending AI/ML Article Identified & Digested via Granola by Ramsey Elbasheer; a Machine-Driven RSS Bot

%d bloggers like this: