Resumen

¿Quieres comprimir y reconstruir rostros con alta fidelidad usando una fracción de los píxeles? Con eigenfaces y reducción de dimensionalidad mediante PCA en Python, es posible representar una cara como combinación de componentes principales y recuperar gran parte de los detalles con muy poca información. Ideal para reconocimiento facial y compresión de imágenes.

¿Qué son los eigenfaces y cómo reduce PCA un rostro?

Los componentes principales de PCA aplicados a imágenes de rostros no son ejes abstractos: son caras base o eigenfaces que capturan patrones de variación. El primer componente suele reflejar la iluminación general. Los siguientes concentran rasgos como nariz, mandíbula y ojos.

  • Un rostro se expresa como una combinación ponderada de eigenfaces.
  • Usando solo los componentes más importantes, se reconstruye la imagen con gran calidad.
  • Base de reconocimiento facial y compresión: menos datos, alta fidelidad.

¿Qué datos y dimensiones se manejan?

Se trabaja con las caras de Olivetti: 400 imágenes en escala de grises de 64×64 píxeles. Al vectorizar, cada imagen tiene 4096 características. La matriz de datos queda en forma (400, 4096).

  • Matriz de trabajo: X con forma (n_imágenes, n_pixeles).
  • Altura y ancho: h = 64, w = 64.
  • Configuración típica: 150 componentes para empezar; también se prueba con 300.

¿Cómo preparar los datos de Olivetti y configurar PCA en Python?

En Google Colab, se importan NumPy, Matplotlib y PCA de Scikit-learn, además del dataset de Olivetti con fetch_olivetti_faces y shuffle.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.datasets import fetch_olivetti_faces

faces_data = fetch_olivetti_faces(shuffle=True)
X = faces_data.data  # Matriz (400, 4096)
h, w = faces_data.images.shape[1], faces_data.images.shape[2]  # 64, 64

pca = PCA(n_components=150)
pca.fit(X)  # Ajuste sobre todo el conjunto

¿Qué significan fit, transform y fit_transform?

  • fit: encuentra los componentes principales del conjunto. Se usa para ajustar el modelo a todas las imágenes.
  • transform: proyecta nuevos datos en esos componentes ya aprendidos.
  • fit_transform: ajusta y proyecta en el mismo paso para todos los datos. Aquí se prefiere separar: fit sobre todas las caras y transform sobre una cara específica.

Ejemplo con una cara:

cara_original = X[0]
cara_comprimida = pca.transform([cara_original])  # Proyección en 150 componentes

¿Cómo reconstruir y visualizar con k componentes diferentes?

La idea es tomar los primeros k componentes, rellenar con ceros hasta 150 si hace falta y aplicar inverse_transform para volver al espacio de píxeles.

def reconstruir_con_k_componentes(k):
    cara_reducida = cara_comprimida[:, :k]
    if k < 150:  # Si luego usas 300, ajusta también aquí.
        padding = np.zeros((1, 150 - k))
        cara_reducida = np.c_[cara_reducida, padding]
    cara_k_reconstruida = pca.inverse_transform(cara_reducida)
    return cara_k_reconstruida.reshape(h, w)

Visualización con subplots, imshow, cmap='gray' y reshape para comparar original vs. reconstrucciones con k = 10, 50, 150:

fig, axes = plt.subplots(1, 4, figsize=(16, 5))
axes[0].imshow(cara_original.reshape(h, w), cmap='gray')
axes[0].set_title('Original')

axes[1].imshow(reconstruir_con_k_componentes(10), cmap='gray')
axes[1].set_title('Reconstrucción k=10')

axes[2].imshow(reconstruir_con_k_componentes(50), cmap='gray')
axes[2].set_title('Reconstrucción k=50')

axes[3].imshow(reconstruir_con_k_componentes(150), cmap='gray')
axes[3].set_title('Reconstrucción k=150')
plt.show()
  • Con k=10: se diferencian rasgos globales, pero se pierden detalles como barba, bigote y lentes.
  • Con k=50: mejora notable en contornos y textura.
  • Con k=150: la imagen es muy similar a la original usando solo una fracción de 4096 píxeles.
  • Al subir a k=300 (cambiando también la configuración y la función): la reconstrucción es prácticamente igual a la original.

¿Te animas a experimentar? Prueba con otro conjunto de rostros, incluso fotos de amistades o familia, y cuéntanos qué detalles se pierden o conservan con 10, 50, 100 o 150 componentes. ¿Con cuántos logras una reconstrucción satisfactoria? Deja tus resultados y observaciones en los comentarios. En la próxima sesión: interpretarás qué píxeles pesan más en cada eigenface con los componentes principales.