Seguimiento de objetos en video con OpenCV (MeanShift, CamShift)

En el campo de la visión por computadora, el seguimiento de objetos en video es una tarea muy importante.

El seguimiento de objetos en video se utiliza ampliamente en múltiples áreas como vigilancia, conducción autónoma e interacción persona-computadora.

OpenCV proporciona múltiples algoritmos de seguimiento de objetos, entre los cuales MeanShift y CamShift son dos algoritmos clásicos y de uso común. Este artículo explicará en detalle los principios, los pasos de implementación de estos dos algoritmos y cómo utilizarlos en OpenCV.

1. Algoritmo MeanShift

1.1 Principio del algoritmo

El algoritmo MeanShift (desplazamiento de la media) es un algoritmo de agrupamiento no paramétrico basado en densidad. Inicialmente se utilizó para la segmentación de imágenes y más tarde se introdujo en el campo del seguimiento de objetos. Su idea central es calcular de forma iterativa el centroide de la región objetivo y mover el centro de la ventana a la posición del centroide, logrando así el seguimiento del objeto.

Los pasos básicos del algoritmo MeanShift son los siguientes:

  1. Inicializar la ventana: En el primer fotograma del video, seleccione manual o automáticamente una región objetivo como ventana inicial.
  2. Calcular el centroide: En la ventana actual, calcule el centroide de la región objetivo (es decir, la media de los puntos de píxel).
  3. Mover la ventana: Mueva el centro de la ventana a la posición del centroide.
  4. Iterar: Repita los pasos 2 y 3 hasta que el centro de la ventana ya no cambie o se alcance el número máximo de iteraciones.

1.2 Implementación en OpenCV

En OpenCV, el algoritmo MeanShift se implementa a través de lacv2.meanShift()función. A continuación se muestra un ejemplo de código simple:

Ejemplo

import cv2
import numpy as np

# Leer el video
cap = cv2.VideoCapture('video.mp4')

# Leer el primer fotograma
ret, frame = cap.read()

# Establecer la ventana inicial (x, y, width, height)
x, y, w, h = 300, 200, 100, 50
track_window = (x, y, w, h)

# Establecer ROI (Region of Interest)
roi = frame[y:y+h, x:x+w]

# Convertir al espacio de color HSV
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)

# Crear la máscara y calcular el histograma
mask = cv2.inRange(hsv_roi, np.array((0., 60., 32.)), np.array((180., 255., 255.)))
roi_hist = cv2.calcHist([hsv_roi], [0], mask, [180], [0, 180])
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)

# Establecer la condición de terminación
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)

while True:
    ret, frame = cap.read()
    if not ret:
        break

    # Convertir al espacio de color HSV
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # Calcular la retroproyección
    dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)

    # Aplicar el algoritmo MeanShift
    ret, track_window = cv2.meanShift(dst, track_window, term_crit)

    # Dibujar el resultado del seguimiento
    x, y, w, h = track_window
    img2 = cv2.rectangle(frame, (x, y), (x+w, y+h), 255, 2)
    cv2.imshow('MeanShift Tracking', img2)

    if cv2.waitKey(30) & 0xFF == 27:
        break

cap.release()
cv2.destroyAllWindows()

1.3 Ventajas y desventajas

Ventajas:

  • Simple y fácil de implementar, con alta eficiencia computacional.
  • Es insensible a los cambios de forma y tamaño del objetivo.

Desventajas:

  • La capacidad para manejar el movimiento rápido o la oclusión del objetivo es deficiente.
  • El tamaño de la ventana es fijo y no puede adaptarse automáticamente a los cambios de tamaño del objetivo.

2. Algoritmo CamShift

2.1 Principio del algoritmo

El algoritmo CamShift (Continuously Adaptive MeanShift) es una versión mejorada de MeanShift. Ajusta el tamaño de la ventana de forma adaptativa para lograr un mejor seguimiento del objetivo. Sobre la base de MeanShift, el algoritmo CamShift añade el ajuste del tamaño y la orientación de la ventana, lo que le permite adaptarse a los cambios de tamaño y rotación del objetivo en el video.

Los pasos básicos del algoritmo CamShift son los siguientes:

  1. Inicializar la ventana: Igual que MeanShift, seleccione la ventana inicial en el primer fotograma del video.
  2. Calcular el centroide: En la ventana actual, calcule el centroide de la región objetivo.
  3. Mover la ventana: Mueva el centro de la ventana a la posición del centroide.
  4. Ajustar el tamaño y la orientación de la ventana: Ajuste la ventana según el tamaño y la orientación del objetivo.
  5. Iterar: Repita los pasos 2 a 4 hasta que el centro de la ventana ya no cambie o se alcance el número máximo de iteraciones.

2.2 Implementación en OpenCV

En OpenCV, el algoritmo CamShift se implementa a través de lacv2.CamShift()función. A continuación se muestra un ejemplo de código simple:

Ejemplo

import cv2
import numpy as np

# Leer el video
cap = cv2.VideoCapture('video.mp4')

# Leer el primer fotograma
ret, frame = cap.read()

# Establecer la ventana inicial (x, y, width, height)
x, y, w, h = 300, 200, 100, 50
track_window = (x, y, w, h)

# Establecer ROI (Region of Interest)
roi = frame[y:y+h, x:x+w]

# Convertir al espacio de color HSV
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)

# Crear la máscara y calcular el histograma
mask = cv2.inRange(hsv_roi, np.array((0., 60., 32.)), np.array((180., 255., 255.)))
roi_hist = cv2.calcHist([hsv_roi], [0], mask, [180], [0, 180])
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)

# Establecer la condición de terminación
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)

while True:
    ret, frame = cap.read()
    if not ret:
        break

    # Convertir al espacio de color HSV
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # Calcular la retroproyección
    dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)

    # Aplicar el algoritmo CamShift
    ret, track_window = cv2.CamShift(dst, track_window, term_crit)

    # Dibujar el resultado del seguimiento
    pts = cv2.boxPoints(ret)
    pts = np.int0(pts)
    img2 = cv2.polylines(frame, [pts], True, 255, 2)
    cv2.imshow('CamShift Tracking', img2)

    if cv2.waitKey(30) & 0xFF == 27:
        break

cap.release()
cv2.destroyAllWindows()

2.3 Ventajas y desventajas

Ventajas:

  • Puede adaptarse automáticamente a los cambios de tamaño y orientación del objetivo.
  • Posee una buena robustez ante los cambios de forma y rotación del objetivo.

Desventajas:

  • La capacidad para manejar el movimiento rápido o la oclusión del objetivo sigue siendo limitada.
  • La complejidad computacional es ligeramente superior a la de MeanShift.

Comparación entre MeanShift y CamShift

MeanShift y CamShift son dos algoritmos clásicos de seguimiento de objetos, y ambos tienen implementaciones listas en OpenCV.

El algoritmo MeanShift es simple y eficiente, adecuado para escenarios donde el tamaño y la orientación del objetivo no cambian mucho, mientras que el algoritmo CamShift, mediante el ajuste adaptativo del tamaño y la orientación de la ventana, puede manejar mejor los cambios de tamaño y orientación del objetivo. En aplicaciones prácticas, se puede elegir el algoritmo adecuado según las necesidades específicas.

CaracterísticaMeanShiftCamShift
Tamaño de la ventanaTamaño fijoAjuste adaptativo del tamaño y la orientación
Escenario aplicableEscenarios con tamaño de objetivo fijoEscenarios con cambios de tamaño y orientación del objetivo
Complejidad computacionalBajaAlta
Rendimiento en tiempo realBuenoLigeramente inferior
Otras extensiones