Seguimiento Automático de Objetos por Visión Artificial con Raspberry Pi y OpenCV
Un sistema pan/tilt de servos que rastrea automáticamente objetos de color usando visión por computador.
Historia
Introducción
En el tutorial previo aprendimos a controlar un servo pan/tilt para posicionar una cámara de Raspberry Pi. Hoy extenderemos esa configuración para que la cámara pueda rastrear autónomamente un objeto de color.
Esta es mi primera experiencia práctica con OpenCV, y ya estoy enamorado de esta librería open-source de visión por computador.
OpenCV es gratis para uso académico y comercial, ofrece interfaces C++, C, Python y Java, y corre en Windows, Linux, macOS, iOS y Android. En esta serie nos centramos en Raspberry Pi (Raspbian) y Python, porque OpenCV está construido para eficiencia computacional y aplicaciones en tiempo real —exactamente lo que necesitas para proyectos de computación física.
Paso 1: BOM – Lista de Materiales
Partes principales:
- Raspberry Pi V3 – 32,00 $
- Módulo de Vídeo Mini Cámara 5 MP 1080p OV5647 – 13,00 $
- Micro Servo TowerPro SG90 9G 180° (2 ×) – 4,00 $
- Plataforma Pan/Tilt Mini Anti-Vibración con 2 Servos (*) – 8,00 $
- LED Rojo
- Resistencia 220 Ω
- Resistencia 1 kΩ (2 ×) – Opcional
- Varios: piezas metálicas, bandas, etc. (si construyes tu propio mecanismo pan/tilt)
(*) Puedes comprar una plataforma pan/tilt completa con servos o construir la tuya.
Paso 2: Instalación de OpenCV 3
En una Raspberry Pi V3 con el último Raspbian Stretch, el método más fiable es seguir el tutorial de Adrian Rosebrock (Raspbian Stretch: Install OpenCV 3 + Python on your Raspberry Pi). Te guía compilando OpenCV desde fuente y configura un entorno virtual Python dedicado.
Tras completar el tutorial, activa el entorno virtual y confirma la instalación:
source ~/.profile
workon cv
python
import cv2
print(cv2.__version__)
Deberías ver versión 3.3.0 o superior. La salida confirma que OpenCV está listo para uso dentro del entorno virtual cv.
Paso 3: Probar tu Cámara
Con OpenCV instalado, verifica que la PiCamera transmite correctamente. Ejecuta el siguiente script (o descarga simpleCamTest.py):
import cv2
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
frame = cv2.flip(frame, -1) # Voltear verticalmente si necesario
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('frame', frame)
cv2.imshow('gray', gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Pulsa q o Ctrl+C para salir. Una ejecución exitosa muestra ambos feeds color y escala de grises.
Paso 4: Detección de Color en Python con OpenCV
OpenCV trabaja en espacio HSV (Hue, Saturation, Value), que se alinea mejor con la percepción humana del color. Para detectar un color específico, primero determinas sus valores BGR, luego conviertes a HSV y estableces límites inferior/superior.
Ejemplo: Rastrear un objeto amarillo. Usando un selector de color (ej. PowerPoint), encontraste valores BGR (71, 234, 213). Conviértelos a HSV con el script de abajo (o descarga bgr_hsv_converter.py):
import sys, numpy as np, cv2
blue, green, red = int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3])
color = np.uint8([[[blue, green, red]]])
hsv = cv2.cvtColor(color, cv2.COLOR_BGR2HSV)
hue = hsv[0][0][0]
print('Límite inferior:', [hue-10, 100, 100])
print('Límite superior:', [hue+10, 255, 255])
Ejecutando python bgr_hsv_converter.py 71 234 213 imprime:
Límite inferior: [24, 100, 100] Límite superior: [44, 255, 255]
Usa estos límites para enmascarar el color en una imagen:
import cv2, numpy as np
img = cv2.imread('yellow_object.JPG', 1)
img = cv2.resize(img, (0,0), fx=0.2, fy=0.2)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower = np.array([24, 100, 100], dtype=np.uint8)
upper = np.array([44, 255, 255], dtype=np.uint8)
mask = cv2.inRange(hsv, lower, upper)
cv2.imshow('mask', mask)
cv2.imshow('image', img)
while True:
k = cv2.waitKey(0)
if k == 27:
break
cv2.destroyAllWindows()
Guarda el script como colorDetection.py y ejecuta python colorDetection.py (asegúrate que la imagen está en el mismo directorio).
Paso 5: Seguimiento de Objetos en Tiempo Real
Basándonos en la máscara, podemos rastrear el centroide del objeto fotograma a fotograma. El código 아래 toma prestado del tutorial Ball Tracking de Adrian Rosebrock e incorpora los límites HSV definidos antes.
Primero, asegúrate que la librería imutils está instalada:
pip install imutils
Luego ejecuta ball_tracking.py:
python ball_tracking.py
El script voltea el frame verticalmente (si necesario) y aplica la máscara. Cuando se detecta el objeto, se dibuja un círculo y el centroide.
Paso 6: Probar los GPIOs
Ahora añadamos un LED rojo a la Pi y confirmemos que podemos controlarlo vía GPIO.
Cableado: Conecta el cátodo del LED a GPIO 21, el ánodo a tierra a través de resistencia 220 Ω.
Si RPi.GPIO no está instalado en el entorno cv, instálalo:
pip install RPi.GPIO
Script de prueba (LED_simple_test.py):
import sys, time, RPi.GPIO as GPIO
led = int(sys.argv[1])
freq = int(sys.argv[2])
GPIO.setmode(GPIO.BCM)
GPIO.setup(led, GPIO.OUT)
GPIO.setwarnings(False)
print(f'Parpadeando LED en GPIO {led} cada {freq}s, 5 veces.')
for _ in range(5):
GPIO.output(led, GPIO.LOW)
time.sleep(freq)
GPIO.output(led, GPIO.HIGH)
time.sleep(freq)
GPIO.cleanup()
Ejecuta con python LED_simple_test.py 21 1 para parpadear el LED cinco veces por segundo.
Paso 7: Reconocimiento de Color e Interacción GPIO
Combina la lógica de rastreo con control GPIO para que el LED se encienda cuando se detecta el color objetivo. Las adiciones clave son:
import RPi.GPIO as GPIO
led = 21
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(led, GPIO.OUT)
GPIO.output(led, GPIO.LOW)
ledOn = False
Dentro del bucle de detección, tras confirmar radio válido, añade:
if not ledOn:
GPIO.output(led, GPIO.HIGH)
ledOn = True
Script completo: object_detection_LED.py. Ejecuta con python object_detection_LED.py. El LED se enciende solo cuando el color del objeto cae dentro de los límites HSV.
Paso 8: El Mecanismo Pan/Tilt
Con OpenCV y GPIO funcionando, conecta los servos a una alimentación externa 5 V. Cablea los pines de datos así:
- GPIO 17 → Servo Tilt
- GPIO 27 → Servo Pan
Comparte la tierra entre la Pi, servos y fuente de alimentación. Opcionalmente coloca resistencia 1 kΩ en serie entre GPIO de la Pi y pin de datos del servo para proteger la Pi de picos de corriente.
Prueba control de servos con angleServoCtrl.py:
from time import sleep
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
def setServoAngle(servo, angle):
pwm = GPIO.PWM(servo, 50)
pwm.start(8)
duty = angle / 18. + 3.
pwm.ChangeDutyCycle(duty)
sleep(0.3)
pwm.stop()
if __name__ == '__main__':
import sys
servo = int(sys.argv[1])
GPIO.setup(servo, GPIO.OUT)
setServoAngle(servo, int(sys.argv[2]))
GPIO.cleanup()
Ejemplo: python angleServoCtrl.py 17 45 mueve el servo tilt a 45°.
Paso 9: Determinar la Posición del Objeto en Tiempo Real
Para centrar la cámara en el objetivo, primero necesitamos las coordenadas del centroide del objeto. Modifica objectDetect_LED.py para imprimir los valores x e y:
def mapObjectPosition(x, y):
print(f'[INFO] Centro del objeto en X={x}, Y={y}')
Las coordenadas van de 0–500 (izquierda-derecha) para x y 0–350 (arriba-abajo) para y. Mueve el objeto y observa la salida en vivo.
Paso 10: Sistema de Seguimiento de Posición del Objeto
Define una región "centrada" (ej. 220 < x < 280 y 160 < y < 210). Si el objeto cae fuera, ajusta los servos pan y tilt entsprechend:
def mapServoPosition(x, y):
global panAngle, tiltAngle
if x < 220:
panAngle = min(panAngle + 10, 140)
positionServo(panServo, panAngle)
if x > 280:
panAngle = max(panAngle - 10, 40)
positionServo(panServo, panAngle)
if y < 160:
tiltAngle = min(tiltAngle + 10, 140)
positionServo(tiltServo, tiltAngle)
if y > 210:
tiltAngle = max(tiltAngle - 10, 40)
positionServo(tiltServo, tiltAngle)
El helper positionServo(servo, angle) simplemente llama a angleServoCtrl.py:
import os
def positionServo(servo, angle):
os.system(f'python angleServoCtrl.py {servo} {angle}')
print(f'[INFO] Posicionando servo GPIO {servo} a {angle}°')
Todos los scripts están en el mismo directorio; descarga la implementación completa desde objectDetectTrack.py.
Paso 11: Conclusión
Este proyecto demuestra cómo combinar OpenCV, GPIO de Raspberry Pi y un montaje pan-tilt de servos para crear un sistema autónomo de rastreo de objetos por color. Siéntete libre de experimentar con diferentes colores, formas y velocidades de servo.
Código completo y recursos adicionales en GitHub y el blog MJRoBot.org.
¡Gracias por leer! Nos vemos en el próximo tutorial.
Proceso de manufactura
- Seguimiento Avanzado de Pelotas de Ping‑Pong con Raspberry Pi y OpenCV
- Speathe: comunicación impulsada por respiración para usuarios paralizados
- Reconocimiento Facial en Tiempo Real en Raspberry Pi – Guía Completa
- Máquinas de Prensa Automáticas: Funcionamiento, Beneficios y Aplicaciones
- Comprender las Prensas de Potencia Automáticas: Características, Beneficios y Aplicaciones
- Entendiendo las Curvadoras de Tubos Automáticas: Funciones, Beneficios y Aplicaciones
- Entendiendo las Mesas Rotativas Automáticas: Precisión y Eficiencia en Metalmecánica
- Medición de Precisión en Seguimiento de Objetos Dinámicos en Sistemas de Captura de Movimiento
- Nuevo filtro mejora visión robot para estimación precisa de pose 6-D
- Dominando la Programación Orientada a Objetos en Python: Clases, Herencia, Encapsulación y Polimorfismo
- Programación Orientada a Objetos en Python: Guía Completa y Práctica