📍 Introducción
En esta práctica, trabajamos por primera vez con imágenes como datos de entrada para entrenar clasificadores. Nos centramos en desarrollar un modelo SVM capaz de distinguir entre imágenes que contienen personas y las que no.
A lo largo de esta entrada, te mostraré cómo preparé los datos, cómo entrené el modelo y qué dificultades encontré antes de aplicar técnicas de extracción de características como HOG.
🎯 Objetivo
El objetivo final es implementar un algoritmo de detección de personas. Sin embargo, antes de llegar a esa etapa, comenzamos abordando el problema más simple: clasificar imágenes completas como positivas (contienen personas) o negativas (no contienen personas).
🗂️ Dataset: INRIA Person Dataset (Toy Version)
Para simplificar el proceso inicial, trabajamos con un subconjunto reducido del famoso INRIA Person Dataset. Los conjuntos se dividen de la siguiente forma:
- Train_toy
train_pos/: 5 imágenes positivas de 134×70 píxelestrain_neg/: 2 imágenes grandes (320×240) sin personas
- Test_toy
pos/: 5 imágenes positivasneg/: 3 imágenes negativas
Todas las imágenes se convirtieron a escala de grises (matrices de enteros de 0 a 255).
Puedes acceder al conjunto de datos INRIA Person Dataset, utilizado comúnmente para tareas de detección de peatones, a través de los siguientes enlaces:
- Sitio oficial de INRIA: pascal.inrialpes.fr
- Repositorio en GitHub: github.com/rupy/HumanDetection
- Hugging Face: huggingface.co/datasets/marcelarosalesj/inria-person
- Kaggle: kaggle.com/datasets/jcoral02/inriapersonthoth.inrialpes.fr+3cs.ucf.edu+3GitHub+3GitHubHugging FaceKaggle
🧾 Paso 1: Carga y visualización de imágenes
Primero, leemos las imágenes usando PIL y las convertimos a arrays NumPy:
pythonCopiarEditarfrom PIL import Image
import numpy as np
def leer_imagenes(ruta):
imagenes = []
for archivo in os.listdir(ruta):
if archivo.endswith(('.jpg', '.png', '.jpeg')):
img = Image.open(os.path.join(ruta, archivo)).convert('L')
imagenes.append(np.array(img))
return imagenes
Visualizamos las imágenes positivas y negativas para confirmar su estructura.
🧪 Paso 2: Aplanar imágenes y crear los vectores de entrenamiento
Como primer enfoque (sin extracción de características), tratamos cada píxel como una característica. Aplanamos las imágenes con .reshape para que cada imagen sea un vector de 9380 elementos (134×70):
pythonCopiarEditarimagenes_pos = np.array(imagenes_pos)
Xtraintoy_pos = imagenes_pos.reshape(imagenes_pos.shape[0], -1)
ytraintoy_pos = np.ones(Xtraintoy_pos.shape[0])
Para las imágenes negativas, como no tenían el tamaño adecuado, extraemos varios fragmentos 134×70:
pythonCopiarEditardef sacar_fragmentos(imagenes, dimension):
nuevas = []
for im in imagenes:
for i in range(im.shape[0] - dimension[0], 0, -dimension[0]):
for j in range(im.shape[1] - dimension[1], 0, -dimension[1]):
ventana = im[i:i+dimension[0], j:j+dimension[1]]
nuevas.append(ventana)
return np.array(nuevas)
🧠 Paso 3: Entrenamiento de un modelo SVM
Entrenamos un modelo SVM lineal básico con scikit-learn:
pythonCopiarEditarfrom sklearn.svm import SVC
svc = SVC(kernel='linear')
svc.fit(Xtraintoy, ytraintoy)
Resultados:
yamlCopiarEditarAccuracy train: 1.0
Accuracy test : 0.41
Claramente, el modelo está sobreajustado: aprende perfectamente los datos de entrenamiento, pero no generaliza a nuevos ejemplos.
🔧 Paso 4: Búsqueda de mejores hiperparámetros y kernels
Probamos diferentes kernels (poly, rbf, sigmoid) y ajustamos los parámetros con GridSearchCV:
pythonCopiarEditarfrom sklearn.model_selection import GridSearchCV
param_grid = {
'C': [0.1, 1, 10],
'gamma': [0.01, 0.1, 1]
}
grid = GridSearchCV(SVC(kernel='rbf'), param_grid, cv=5)
grid.fit(Xtraintoy, ytraintoy)
Mejor configuración obtenida:
mathematicaCopiarEditarC=0.1, gamma='scale'
Accuracy train: 0.61
Accuracy test : 0.71
Aunque no es perfecto, el modelo mejora su capacidad de generalización, mostrando una menor diferencia entre train y test.
⚠️ Limitaciones del enfoque actual
- Tenemos muchas características (9380) y muy pocos ejemplos (13 imágenes en train).
- La intensidad de píxeles por sí sola no aporta suficiente información semántica.
- Por ello, este enfoque no es recomendable a gran escala.
🧭 Próximos pasos: extracción de características con HOG
La solución pasa por aplicar Histogramas de Gradientes Orientados (HOG), una técnica clásica de visión por computador que extrae información estructural de las imágenes.
✅ Conclusión
En esta primera parte de la práctica:
- Aprendimos cómo preparar datos de imagen para un clasificador tradicional.
- Exploramos diferentes configuraciones de SVMs.
- Observamos los límites de usar imágenes crudas como vectores de píxeles.
- Preparamos el terreno para aplicar técnicas más avanzadas como HOG.
En la próxima entrada, implementaremos HOG + SVM para abordar el problema de detección de personas de forma más eficaz.
De momento puedes ver nuestros avances en este GIST:








Deja un comentario