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.
Editor de textos de sua preferência.
Python 3.8.5 .
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)
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()
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)
Atenciosamente</br> Willian Jesus da Silva, Aluno do curso de Ciência da Computação no Instituto de ensino superior da Grande Florianópolis.