Segmentar una imagen a través de umbrales es probablemente la forma más sencilla de identificar regiones de interés en una imagen. Esto hace que este método sea vulnerable a ruido, sombras y otros factores más a la hora de utilizarlo en la práctica. Sin embargo es una forma sencilla de introducir a las funciones de segmentación del módulo scikit-image. Primero, para este ejemplo tomaremos la siguiente pintura de Kazimir Malevich:
Separaremos la imagen en secciones para las cuales obtendremos un array con los índices de cada pixel para cada una de ellas. Para ello cargamos primero la imagen:
#Cargar imagen
im = skimage.io.imread("malevich-map-style.png")
imGS = skimage.color.rgb2gray(im) #Escala de grises
y creamos una imagen binarizada a partir de un umbral en la imagen en escala de grises:
#Umbral
thresh = 0.7
bw = binary_erosion(closing(imGS < thresh, np.ones((3,3))))
La variable bw es la imagen binarizada corregida y es obtenida aplicando la función closing seguida de binary_erosion (ambas contenidas en skimage.morphology). Closing() realiza una operación de dilatación seguida de una erosión, lo que permite cerrar "agujeros" oscuros en una imagen. El primer argumento que toma en este ejemplo es la imagen binarizada resultante de aplicar el umbral imGS < 0.7 y el segundo es una matriz que determina el tamaño de la dilatación/erosión. Binary_erosion es solo una operación de erosión que elimina las falsas regiones debidas a las zonas brillantes del fondo. Teniendo la imagen binarizada limpia, obtenermos los segmentos:
#Segmentación
labeled_im = skimage.measure.label(bw)
lab_img = label2rgb(labeled_im, image=imGS,bg_label=0)
dónde labeled_im es una nueva imagen obtenida con la función label()en dónde cada pixel de la imagen en escala de grises original esta clasificado con su número de región . Si esto no es muy claro, pueden visualizar este arreglo de datos con el explorador de variables de Spyder dando doble click en el nombre de la variable:
La imagen lab_img es una visualización gráfica de las etiquetas de región sobre la imagen original que al mostrarla con Matplotlib y utilizando la función plt.text() junto con los datos contenidos en labeled_im, el resultado final es el siguiente:
Código completo:
# -*- coding: utf-8 -*-
"""
Created on Tue Jun 27 13:27:53 2017
@author: rodolfo
"""
import numpy as np
from matplotlib import pyplot as plt
import skimage
from skimage.morphology import closing, binary_erosion
from skimage.color import label2rgb
#Cargar imagen
im = skimage.io.imread("malevich-map-style.png")
imR = im[:,:,0]
imG = im[:,:,1]
imB = im[:,:,2]
imGS = skimage.color.rgb2gray(im)
#Umbral
thresh = 0.7
bw = binary_erosion(closing(imGS < thresh, np.ones((3,3))))
#Segmentación
labeled_im = skimage.measure.label(bw)
lab_img = label2rgb(labeled_im, image=imGS,bg_label=0)
#Array de arrays de indices por segmento
reg_index = []
for i in range(0, np.max(labeled_im)):
u = np.where(labeled_im == i)
reg_index.append(zip(u[0],u[1]))
#Plots
R = []
cr = []
for i in range(0,np.max(labeled_im)):
R.append(np.where(labeled_im==i+1))
cr.append((np.mean(R[i][0]),np.mean(R[i][1])))
plt.figure(1)
plt.imshow(im)
plt.figure(2)
plt.imshow(lab_img)
for i in range(0,np.max(labeled_im)):
plt.text(cr[i][1],cr[i][0],str(i+1),color='w')