Compresión de imágenes usando agrupamiento de K-means

Requisito previo: agrupamiento de K-medias

Internet está repleto de enormes cantidades de datos en forma de imágenes. Las personas cargan millones de imágenes todos los días en sitios de redes sociales como Instagram, Facebook y plataformas de almacenamiento en la nube como Google Drive, etc. Con cantidades tan grandes de datos, las técnicas de compresión de imágenes se vuelven importantes para comprimir las imágenes y reducir el espacio de almacenamiento.

En este artículo, veremos la compresión de imágenes utilizando el algoritmo de agrupamiento K-means, que es un algoritmo de aprendizaje no supervisado.

Una imagen se compone de varios valores de intensidad conocidos como píxeles. En una imagen en color, cada píxel tiene 3 bytes que contienen valores RGB (Rojo-Azul-Verde) que tienen un valor de intensidad rojo, luego azul y luego un valor de intensidad verde para cada píxel.

Enfoque:
el agrupamiento de K-medias agrupará colores similares en grupos ‘k’ (digamos k=64) de diferentes colores (valores RGB). Por lo tanto, cada centroide de clúster es el representante del vector de color en el espacio de color RGB de su respectivo clúster. Ahora, estos centroides de clúster ‘k’ reemplazarán todos los vectores de color en sus respectivos clústeres. Por lo tanto, solo necesitamos almacenar la etiqueta para cada píxel que le dice al grupo al que pertenece este píxel. Adicionalmente, mantenemos el registro de vectores de color de cada centro de clúster.

Bibliotecas necesarias –

-> Biblioteca numpy: sudo pip3 install numpy.
-> Biblioteca Matplotlib: sudo pip3 install matplotlib.
-> biblioteca scipy:sudo pip3 install scipy

A continuación se muestra la implementación de Python:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as img
# from scipy.io import loadmat
from scipy import misc
  
def read_image():
      
    # loading the png image as a 3d matrix 
    img = misc.imread('bird_small.png') 
  
    # uncomment the below code to view the loaded image
    # plt.imshow(A) # plotting the image
    # plt.show() 
      
    # scaling it so that the values are small
    img = img / 255 
  
    return img
  
def initialize_means(img, clusters):
      
    # reshaping it or flattening it into a 2d matrix
    points = np.reshape(img, (img.shape[0] * img.shape[1],
                                             img.shape[2])) 
    m, n = points.shape
  
    # clusters is the number of clusters
    # or the number of colors that we choose.
      
    # means is the array of assumed means or centroids. 
    means = np.zeros((clusters, n)) 
  
    # random initialization of means. 
    for i in range(clusters):
        rand1 = int(np.random.random(1)*10)
        rand2 = int(np.random.random(1)*8)
        means[i, 0] = points[rand1, 0]
        means[i, 1] = points[rand2, 1]
  
    return points, means
  
  
# Function to measure the euclidean
# distance (distance formula)
def distance(x1, y1, x2, y2):
      
    dist = np.square(x1 - x2) + np.square(y1 - y2)
    dist = np.sqrt(dist)
  
    return dist
  
  
def k_means(points, means, clusters):
  
    iterations = 10 # the number of iterations 
    m, n = points.shape
      
    # these are the index values that
    # correspond to the cluster to
    # which each pixel belongs to.
    index = np.zeros(m) 
  
    # k-means algorithm.
    while(iterations > 0):
  
        for j in range(len(points)):
              
            # initialize minimum value to a large value
            minv = 1000
            temp = None
              
            for k in range(clusters):
                  
                x1 = points[j, 0]
                y1 = points[j, 1]
                x2 = means[k, 0]
                y2 = means[k, 1]
                  
                if(distance(x1, y1, x2, y2) < minv):         
                    minv = distance(x1, y1, x2, y2)
                    temp = k
                    index[j] = k 
          
        for k in range(clusters):
              
            sumx = 0
            sumy = 0
            count = 0
              
            for j in range(len(points)):
                  
                if(index[j] == k):
                    sumx += points[j, 0]
                    sumy += points[j, 1] 
                    count += 1
              
            if(count == 0):
                count = 1    
              
            means[k, 0] = float(sumx / count)
            means[k, 1] = float(sumy / count)     
              
        iterations -= 1
  
    return means, index
  
  
def compress_image(means, index, img):
  
    # recovering the compressed image by
    # assigning each pixel to its corresponding centroid.
    centroid = np.array(means)
    recovered = centroid[index.astype(int), :]
      
    # getting back the 3d matrix (row, col, rgb(3))
    recovered = np.reshape(recovered, (img.shape[0], img.shape[1],
                                                     img.shape[2]))
  
    # plotting the compressed image.
    plt.imshow(recovered)
    plt.show()
  
    # saving the compressed image.
    misc.imsave('compressed_' + str(clusters) +
                        '_colors.png', recovered)
  
  
# Driver Code
if __name__ == '__main__':
  
    img = read_image()
  
    clusters = 16
    clusters = int(input('Enter the number of colors in the compressed image. default = 16\n'))
  
    points, means = initialize_means(img, clusters)
    means, index = k_means(points, means, clusters)
    compress_image(means, index, img)

Imagen de entrada:

Producción :

Publicación traducida automáticamente

Artículo escrito por Adith Bharadwaj y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *