Home Filtro de densidade usando Machine Learning e Clusterização
Post
Cancel

Filtro de densidade usando Machine Learning e Clusterização

Filtro de densidade usando Machine Learning e Clusterização

Nesse capítulo você irá aprender uma maneira rápida e fácil de utilizar Machine learning para remover ruídos em uma captura de objeto utilizando range de cores. Na captura de imagens utilizando cores, um dos grandes problemas encontrados é a remoção do ruído indesejado por objetos menores ao fundo do cenário. Nesse contexto, iremos utilizar o método DBSCAN da Lib SKLEARN para reorganizar os pixels das cores selecionadas e identificar áreas de baixa densidade.

Obs. Os códigos contidos neste capítulo foram desenvolvidos para serem rodados no Google Colab e pode sofrer algumas alterações para rodar fora do Colab (exemplo: a utilização da lib google.colab.patches para visualizar imagens).

Preparando o ambiente

Para esse projeto é necessário que você tenha instalado os seguintes itens em sua máquina.

  1. Editor de textos de sua preferência.

  2. Python 3.8.5 .

  3. Bibliotecas (OpenCV, Collections, Sklearn, Numpy, urllib, matplotlib).

Caso queira, pode utilizar o Google Colab que tem o ambiente praticamente pronto.

Passos

Importar Libs

1
2
3
4
5
6
7
8
9
10
import numpy as np
import urllib
import cv2
from google.colab.patches import cv2_imshow
from collections import Counter
from sklearn.cluster import DBSCAN
from sklearn import metrics
from sklearn.datasets import make_blobs
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt

Download da imagem

Baixamos a imagem diretamente da internet utilizando a lib Urlib e após isso, utilizamos as libs Numpy e Opencv para converter a imagem para um formato aceito pela lib OpenCV.

Obs. Como estamos utilizando o Google Colab, estaremos realizando o download e conversão das imagens diretamente do Imgur.

1
2
3
4
5
6
7
8
9
10
def url_to_image(url):
    resp = urllib.request.urlopen(url)
    image = np.asarray(bytearray(resp.read()), dtype="uint8")
    image = cv2.imdecode(image, cv2.IMREAD_COLOR)
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    return hsv

url = f'https://i.imgur.com/PLGlnWj.png'

img = url_to_image(url)

image info

Seleção do range de cor

Este é um dos momentos mais demorados e manuais da aplicação, pois teremos que manualmente encontrar o range de cores utilizados no objeto que queremos selecionar. No nosso caso é o Azul.

1
2
3
4
img = url_to_image(url)
BLUE_MIN = (110,50,50)
BLUE_MAX = (130,255,255)

Separação de pixels

Nesta parte do código percorremos todos os pixels da imagem, verificamos quais encontram-se dentro do range de cores selecionados e guardamos as coordenadas dos azuis dentro do array data_cord

1
2
3
4
5
6
7
8
9
data_cord = []

height, width, channels = img.shape

for x in range(height): 
    for y in range(width):
        r, g, b = img[x,y]
        if (r,g,b) >= BLUE_MIN and (r,g,b) <= BLUE_MAX:
            data_cord.append([int(x),int(y)])

DBSCAN

Agora, com o data_cord já separado, iremos utilizar DBSCAN para clusterizar os dados. O DBSCAN é uma algoritmo de machine learning que clusteriza os dados com base em densidade e tamanho de cluster.

1
2
3
4
5
X = StandardScaler().fit_transform(data_cord)
db = DBSCAN(eps=0.1, min_samples=1).fit(X)
core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
core_samples_mask[db.core_sample_indices_] = True
labels = db.labels_

Apresentação de clusters (Opcional)

Este tópico não é obrigatório, mas caso queira visualizar os dados e verificar se está sendo separado corretamente. Utilizando Matplotlib, separamos os labels dos clusters e setamos uma cor para cada cluster.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
unique_labels = set(labels)
colors = [plt.cm.Spectral(each)
          for each in np.linspace(0, 1, len(unique_labels))]
for k, col in zip(unique_labels, colors):
    if k == -1:
        pass

    class_member_mask = (labels == k)

    xy = X[class_member_mask & core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
             markeredgecolor='k', markersize=14)
    
    xy = X[class_member_mask & ~core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
             markeredgecolor='k', markersize=6)

plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()

image info

Identificar maior cluster

Utilizando o código abaixo, separamos os clusters em dict, verificamos qual o maior e salvamos essa informação em template_max.

1
2
dict_data = dict(Counter(labels))
template_max = max(dict_data, key=dict_data.get)

Apresentação

No código abaixo, realizamos a varredura dentro de labels e para cada vez que identificamos o maior cluster, pegamos este index e buscamos a mesma posição no data_cord. Assim, conseguimos pegar as coordenadas que se encontram no maior cluster e podemos manipular as coordenadas do maior cluster, ignorando o ruído geral da imagem. No caso abaixo, estamos pintando de vermelho o maior cluster e pintando de azul os demais(ruídos) apenas para fins demonstrativos.

1
2
3
4
5
6
7
8
9
for i in range(len(labels)):
    if labels[i] == template_max:
      x,y = data_cord[i]
      img[x,y] = (0,0,255)
    else:
      x,y = data_cord[i]
      img[x,y] = (255,0,0)

cv2_imshow(img)

image info


Atenciosamente</br> Willian Jesus da Silva, Aluno do curso de Ciência da Computação no Instituto de ensino superior da Grande Florianópolis.

This post is licensed under CC BY 4.0 by the author.