OpenCV: Reconocimiento
Aprende a localizar y etiquetar objetos en tiempo real mediante las potentes herramientas de detección y seguimiento de OpenCV.
Aprende OpenCV GRATIS y certifícateEl reconocimiento de objetos en imágenes y vídeos con OpenCV representa un campo amplio que integra algoritmos tradicionales y técnicas basadas en aprendizaje profundo. En cada fotograma, se busca localizar y clasificar elementos para fines tan variados como vigilancia, automatización industrial o asistencia en conducción. Esta integración de métodos facilita la creación de sistemas capaces de detectar y etiquetar múltiples clases de objetos, con posibilidades de escalado y optimizaciones dependiendo de las necesidades del proyecto.
Para enfoques clásicos, las cascadas de Haar resultan un primer paso razonable cuando se requiere un procesamiento ligero. Mediante cv.CascadeClassifier
, se cargan modelos previamente entrenados que permiten localizar regiones candidatas y compararlas con patrones almacenados en la cascada correspondiente. Por ejemplo, para la detección de rostros en un flujo de vídeo, se procede a convertir cada fotograma a escala de grises y se aplica el clasificador:
import cv2 as cv
clasificador_rostros = cv.CascadeClassifier("haarcascade_frontalface_default.xml")
captura = cv.VideoCapture(0) # captura en tiempo real desde cámara
while True:
ret, frame = captura.read()
if not ret:
break
gris = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
rostros = clasificador_rostros.detectMultiScale(gris, scaleFactor=1.1, minNeighbors=5)
for (x, y, w, h) in rostros:
cv.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
cv.imshow("Detección de rostros", frame)
if cv.waitKey(1) & 0xFF == 27:
break
captura.release()
cv.destroyAllWindows()
Con este fragmento, se obtienen rectángulos en torno a cada rostro detectado. Si bien la detección mediante cascadas funciona en muchos casos, no siempre es la opción más robusta ante variaciones de luz o ángulos de visión, por lo que en escenarios más exigentes se recurre a modelos avanzados.
Los métodos basados en redes neuronales se integran gracias al módulo cv.dnn
. Estas redes, previamente entrenadas con grandes conjuntos de datos, permiten ubicar no solo rostros, sino también vehículos, peatones o cualquier otra categoría de interés. Para cargar una arquitectura como YOLO, es frecuente disponer de dos archivos: los pesos y la configuración. Un uso genérico podría ser:
import cv2 as cv
# Carga de la red YOLO v4 (ejemplo)
red = cv.dnn.readNet("yolov4.weights", "yolov4.cfg")
# Opcionalmente, se puede forzar la ejecución en GPU si hay soporte
# red.setPreferableBackend(cv.dnn.DNN_BACKEND_CUDA)
# red.setPreferableTarget(cv.dnn.DNN_TARGET_CUDA)
imagen = cv.imread("ejemplo.jpg")
blob = cv.dnn.blobFromImage(imagen, 1/255.0, (416, 416), swapRB=True, crop=False)
red.setInput(blob)
resultados = red.forward(red.getUnconnectedOutLayersNames())
La red devuelve bounding boxes, confidencias y etiquetas. Posteriormente, se aplica un proceso de non-maximum suppression (NMS) para unificar rectángulos solapados y filtrar aquellos con confianza baja:
import numpy as np
umbral_confianza = 0.5
umbral_nms = 0.4
cajas = []
confianzas = []
clases = []
for salida in resultados:
for deteccion in salida:
puntajes = deteccion[5:]
clase = np.argmax(puntajes)
confianza = puntajes[clase]
if confianza > umbral_confianza:
ancho, alto = imagen.shape[1], imagen.shape[0]
cx, cy, w, h = (deteccion[0:4] * [ancho, alto, ancho, alto]).astype('int')
x = int(cx - w / 2)
y = int(cy - h / 2)
cajas.append([x, y, int(w), int(h)])
confianzas.append(float(confianza))
clases.append(clase)
indices = cv.dnn.NMSBoxes(cajas, confianzas, umbral_confianza, umbral_nms)
for i in indices.flatten():
x, y, w, h = cajas[i]
cv.rectangle(imagen, (x, y), (x+w, y+h), (0, 255, 0), 2)
texto = f"Clase: {clases[i]}, Conf: {confianzas[i]:.2f}"
cv.putText(imagen, texto, (x, y - 5), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
cv.imshow("Detección con YOLO", imagen)
cv.waitKey(0)
cv.destroyAllWindows()
De esta forma, las coordenadas finales quedan dibujadas sobre la imagen con su etiqueta asociada, lo que facilita la interpretación de resultados. En casos de detección en vídeo, basta con encerrar este bloque en un bucle que lea cada fotograma, generando la misma salida en tiempo real.
Para la clasificación de objetos específicos, se puede combinar la detección de regiones de interés (ROI) con clasificadores entrenados. Por ejemplo, se detectan contornos o se segmentan áreas relevantes y, acto seguido, se aplica un SVM o red neuronal para decidir la clase de cada región. Este método evita procesar la imagen completa en cada pasada y se centra en pequeñas áreas de interés, optimizando recursos.
En el reconocimiento de objetos móviles, la incorporación de seguimiento resulta provechosa. Con cv2.TrackerMOSSE o cv2.TrackerCSRT, se puede iniciar un tracker tras la detección y mantener su seguimiento en fotogramas posteriores, reduciendo la carga de detección en cada iteración. El proceso consiste en:
- Detectar el objeto en el fotograma inicial.
- Extraer la ROI y crear una instancia del tracker deseado.
- En cada nuevo fotograma, emplear el método
update()
del tracker para obtener la posición actualizada.
Por ejemplo, una inicialización típica sería:
import cv2 as cv
tracker = cv.legacy.TrackerCSRT_create()
ok = tracker.init(frame_inicial, (x, y, w, h)) # ROI detectada
A continuación, en cada iteración se llama:
ok, caja = tracker.update(nuevo_frame)
if ok:
# Se dibuja la nueva caja sobre el frame
(x2, y2, w2, h2) = [int(v) for v in caja]
cv.rectangle(nuevo_frame, (x2, y2), (x2 + w2, y2 + h2), (255, 0, 0), 2)
Este sistema permite disminuir la carga computacional, ya que la detección completa no se repite en todos los fotogramas. Por otro lado, si el tracker pierde el rastro, puede reactivarse la fase de detección para reiniciar el proceso.
En proyectos que requieren entrenar su propio modelo, se recomienda contar con un conjunto de datos debidamente etiquetado y, a ser posible, realizar aumentos de datos (rotaciones, volteos, recortes aleatorios) para mejorar la generalización. Una vez finalizado el entrenamiento, el modelo resultante se integra en OpenCV con cv.dnn.readNetFromONNX()
, cv.dnn.readNetFromCaffe()
o cv.dnn.readNetFromTensorflow()
, según el formato. Esto simplifica la carga del modelo y su uso en aplicaciones de escritorio o sistemas empotrados.
Cuando se necesitan altas velocidades de procesamiento, puede establecerse la preferencia por la GPU mediante setPreferableBackend()
y setPreferableTarget()
. En entornos compatibles con CUDA, estas llamadas permiten que la red corra en paralelo sobre la tarjeta gráfica, disminuyendo la latencia de la detección de objetos en tiempo real.
La precisión y la velocidad no son los únicos factores a tener en cuenta. En ciertas aplicaciones, es relevante cómo se muestran los resultados al usuario o cómo se almacenan las detecciones para el análisis posterior. Se puede optar por guardar en disco cada fotograma con rectángulos, exportar anotaciones en formato JSON o incluso emitir eventos cuando se reconozcan objetos determinados.
Al combinar la detección de objetos, el uso de redes neuronales y la gestión de vídeo, OpenCV proporciona un entorno práctico para desarrollar aplicaciones. El bucle de captura, ya sea desde cámara o archivo, permite procesar cada fotograma con los pasos de preprocesamiento, inferencia y postprocesamiento, ofreciendo una visión completa del pipeline de reconocimiento en tiempo real. Con buena planificación, este enfoque puede adaptarse tanto a escenarios sencillos, como la detección de un solo tipo de objeto, como a contextos donde se requiera clasificar múltiples categorías, almacenar datos de seguimiento o distribuir resultados en sistemas de red.
Lecciones de este módulo de OpenCV
Lecciones de programación del módulo Reconocimiento del curso de OpenCV.
Ejercicios de programación en este módulo de OpenCV
Evalúa tus conocimientos en Reconocimiento con ejercicios de programación Reconocimiento de tipo Test, Puzzle, Código y Proyecto con VSCode.