El reconocimiento facial es uno de los campos que emplea el aprendizaje automático y se utiliza ampliamente en muchos ámbitos, desde el etiquetado de fotos en las redes sociales y el emparejamiento de personas con los mismos rasgos faciales en los sitios de citas, hasta la localización de delincuentes y la seguridad de las fronteras, pasando por el mantenimiento a raya de los grandes jugadores en los casinos.

Me parece fascinante que podamos simular el proceso de reconocimiento facial con un grado significativo de precisión, mientras que al mismo tiempo hay personas que sufren de prosopagnosia, o «ceguera facial», que no tienen tanta suerte. Un autor de un artículo de Cracked con el que me topé hace un tiempo describe esta experiencia como la de ver una pila de LEGOs en la que, en cuanto apartas la vista, ya no puedes describir con ningún detalle sustancial de qué color y forma era cada pieza o cómo estaban colocadas. Me he preguntado si este trastorno cognitivo tiene algo que ver con la asignación de memoria. Por suerte, la memoria es algo de lo que los ordenadores disponen en abundancia y ni siquiera hemos empezado a arañar la superficie del conjunto completo de capacidades que presentará la computación cuántica.

Pero volvamos a las eigenfaces.

Los datos visuales de una imagen se pueden mapear en un vector en el que cada entrada representa el brillo del píxel correspondiente. Tomando un conjunto de imágenes, se puede construir una matriz en la que cada fila corresponde a un vector de imagen específico. Lo ideal es que las imágenes se normalicen primero de forma que se alineen los rasgos básicos, como los ojos, la nariz y la boca, para aumentar la precisión y reducir el ruido. Los rostros propios son entonces los vectores propios que se derivan de la matriz de covarianza de esta matriz de datos faciales analizados.

El conjunto de datos de rostros que utilizamos fue proporcionado amablemente por los Laboratorios AT&T de Cambridge y consistía en 40 rostros individuales, 10 imágenes de cada uno con diferentes expresiones faciales y posiciones de la cabeza.

En este ejercicio se utilizaron las siguientes bibliotecas y módulos de Python:

from sklearn.preprocessing import normalize
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
from scipy.misc import imread
from itertools import chain
import numpy as np
import scipy as sp
import glob
  • normalize la función escala cada vector individual de la muestra para que tenga norma unitaria.
  • PCA o Análisis de Componentes Principales, es un proceso de reducción de la dimensionalidad lineal que utiliza la Descomposición del Valor Singular de los datos para proyectarlos a un espacio de menor dimensión. En otras palabras, es el proceso de encontrar la estructura subyacente de los datos o las direcciones en las que hay más varianza.
  • matplotlib.pyplot es la conocida función de trazado.
  • imread se utiliza para leer en una imagen de un archivo como una matriz.
  • chain es un iterador que recorre la lista devolviendo elementos individuales de cada iterable.
  • numpy es el paquete fundamental de Python para la computación científica.
  • scipy es otro paquete para la computación científica y técnica, similar a numpy pero que contiene versiones más completas de los módulos de álgebra lineal, así como muchos otros algoritmos numéricos.
  • glob módulo encuentra todos los nombres de ruta que coinciden con un patrón especificado.

El primer paso es extraer todos los nombres de archivo del archivo comprimido. A continuación, se crea una matriz deshaciendo las matrices de imágenes en vectores mediante el comando chain y apilándolas. Esto crea una matriz de 400×10304 con cada fila que contiene toda la información sobre una imagen específica de 112×92.

filenames = m = for i in range(400)]for i in range(400):
m = list(chain.from_iterable(imread(filenames)))
m = np.matrix(m)

A continuación, se normaliza la matriz y se aplica el PCA. Aquí hemos reducido nuestro espacio vectorial a sólo 40 de 10304 dimensiones:

model = PCA(n_components=40)
pts = normalize(m)
model.fit(pts)
pts2 = model.transform(pts)

Por último, las caras propias, contenidas en model.components_, pueden mostrarse:

fig, ax = plt.subplots(1,40)for i in range(40):
ord = model.components_
img = ord.reshape(112,92)
ax.imshow(img,cmap='gray')

Y ahí lo tenemos. Un montón de caras espeluznantes.

Lo que esencialmente hemos hecho es crear un conjunto de bases ortogonales en el que cada eigenfaz destaca un determinado tipo de rasgo, y a partir del cual se pueden reconstruir las caras que hemos utilizado mediante diferentes combinaciones y proporciones de eigenvectores.

faces_pca = PCA(n_components=40)
faces_pca.fit(m)
components = faces_pca.transform(m)
projected = faces_pca.inverse_transform(components)fig, axes = plt.subplots(40,10,figsize=(20,80))
for i, ax in enumerate(axes.flat):
ax.imshow(projected.reshape(112,92),cmap="gray")

Debido a que comprimimos tanto nuestro espacio vectorial (y no alineamos las caras para empezar), se perdieron muchos detalles, pero las caras seguían siendo algo reconocibles.

Así pues, el objetivo del problema de visión por ordenador del reconocimiento de rostros humanos es crear el mínimo número de caras propias que puedan representar adecuadamente todo el conjunto de entrenamiento. Si el conjunto de entrenamiento es lo suficientemente diverso, el conjunto resultante de caras propias debería ser capaz de representar todas las caras. Y, aunque en los últimos años se han realizado importantes avances en los algoritmos de reconocimiento facial, aún queda mucho camino por recorrer y muchas mejoras por hacer.

Por otra parte, y como siempre, hay algunos peligros asociados a las capacidades cada vez mayores de un software que es capaz de reconocer, simular y, por lo tanto, potencialmente engañar y manipular a un individuo desprevenido, y debemos tomar las precauciones adecuadas para asegurarnos de que se utiliza de manera apropiada.

Y sólo voy a dejar esto aquí como un caso en cuestión y para su entretenimiento.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.