Uma etapa importante no processamento de imagens digitais para analisar o que está dentro dela é classificar seu conteúdo de pixeis em diferentes grupos. Esse processo é chamado de segmentação de imagem, cujo objetivo é transformar a representação de uma imagem em algo mais significativo e fácil de analisar. É muito comum o uso de algoritmos de agrupamento (“clusters”) para realizar esse procedimento. O post sobre Análise de clusters faz uma breve revisão dos métodos hierárquico e não-hierárquico de agrupamento, com aplicações em python.
O OpenCV (Open Source Computer Vision Library), originalmente desenvolvido e lançado pela Intel em 1999, é uma biblioteca livre e multiplataforma para o desenvolvimento de aplicativos na área de visão computacional. Desenvolvida em C/C++, pode ser usada no python instalando-se a biblioteca “opencv” (disponível no Conda). Possui módulos de processamento de imagens e centenas de algoritmos, como filtros de imagem, calibração de câmera, reconhecimento de objetos, análise estrutural e outros.
O OpenCV fornece a função cv2.kmeans(amostras, nclusters(K), critérios, numero_tentativas, sinalizadores) para agrupamento de cores. Os critérios são definidos como tipo, número máximo de iterações e epsilon (precisão). Os tipos podem ser cv.TERM_CRITERIA_EPS (interrompe a iteração do algoritmo se a precisão especificada, epsilon, for atingida), cv.TERM_CRITERIA_MAX_ITER (interrompe o algoritmo após o número especificado de iterações, max_iter) ou as duas juntas (interrompe a iteração quando alguma das condições for atendida). Os sinalizadores podem ser cv.KMEANS_PP_CENTERS ou cv.KMEANS_RANDOM_CENTERS.
Veja o exemplo a seguir:
#!/usr/bin/env python3.7.5 # -*- Coding: UTF-8 -*- # Read allsky image file and do segmentation import numpy as np import matplotlib.pyplot as plt import cv2 # Load image file and convert from color to RGB original_image = cv2.imread('20181206132000_11.jpg') img = cv2.cvtColor(original_image,cv2.COLOR_BGR2RGB, 0) # converts the MxNx3 image into a Kx3 matrix where K=MxN vectorized = img.reshape((-1,3)) # convert the unit8 values to float vectorized = np.float32(vectorized) # color clustering criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0) K = 3 attempts = 10 ret,label,center = cv2.kmeans(vectorized,K,None,criteria,attempts,cv2.KMEANS_PP_CENTERS) # Regenerate image center = np.uint8(center) res = center[label.flatten()] result_image = res.reshape((img.shape)) # Remove black (borders) #lower = np.array([50,50,1]) #-- Lower range -- #upper = np.array([255,255,255]) #-- Upper range -- #mask = cv2.inRange(img, lower, upper) #res = cv2.bitwise_and(img, img, mask= mask) #-- Contains pixels having the gray color-- #result_image = res.reshape((img.shape)) # Plot images figure_size = 15 plt.figure(figsize=(figure_size,figure_size)) plt.subplot(1,2,1),plt.imshow(img) plt.title('Original Image'), plt.xticks([]), plt.yticks([]) plt.subplot(1,2,2),plt.imshow(result_image) plt.title('Segmented Image when K = %i' % K), plt.xticks([]), plt.yticks([]) plt.show() # Canny Edge detection #edges = cv2.Canny(img,150,200) #plt.figure(figsize=(figure_size,figure_size)) #plt.subplot(1,2,1),plt.imshow(img) #plt.title('Original Image'), plt.xticks([]), plt.yticks([]) #plt.subplot(1,2,2),plt.imshow(edges,cmap = 'gray') #plt.title('Edge Image'), plt.xticks([]), plt.yticks([]) #plt.show()
Foi escolhido k = 3 para considerar os agrupamentos com as cores preta das bordas, azul do céu e branco/cinza das nuvens. Também foram incluídos blocos (comentados) para remover limiares de cores e para detecção de bordas. Fonte: KDnuggets – Introduction to Image Segmentation with K-Means clustering.
Existem outros algoritmos na separação entre céu e nuvem. Dentre os mais conhecidos, estão a definição de um limiar da imagem de acordo com a proporção de intensidades de vermelho e azul da imagem vermelho-verde-azul (thresholding RGB) ou de acordo com a componente de saturação da transformação matiz-saturação-intensidade (HSI) da imagem RGB original ou ainda um limiar de acordo com a escala de cinza.
A segmentação é a partição de uma imagem em várias partes “coerentes”, mas sem qualquer tentativa de compreender o que essas partes representam. Já a segmentação semântica tenta particionar a imagem em partes semanticamente significativas e classificar cada parte em uma das classes pré-determinadas.