Last active
November 19, 2020 00:16
-
-
Save jerivas/ff44a964f230ad403f01 to your computer and use it in GitHub Desktop.
Seguimiento de objetos por color. El script detecta objetos en base a colores y selecciona el más grande (por área). Se calcula la distancia del centroide del objeto al centro de la imagen.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
*.pyc | |
*.pyo | |
*.db | |
.DS_Store | |
.coverage | |
*.sublime-project | |
*.sublime-workspace | |
*~ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(lp1 | |
(lp2 | |
I30 | |
aI50 | |
aI60 | |
aa(lp3 | |
I45 | |
aI255 | |
aI255 | |
aa. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
numpy==1.15.2 | |
opencv-python==3.4.3.18 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# SCRIPT DE SEGUIMIENTO DE OBJETOS POR COLOR | |
# El script detecta objetos en base a colores y selecciona el más grande | |
# (por área). Se calcula la distancia del centroide del objeto al centro | |
# de la imagen. Se aplica acción controladora para mantener el objeto al | |
# centro de la imagen. Está acción se logra a través de servos conectados | |
# a un Arduino, el cual es controlado por el puerto serie de la PC. | |
# Por David Escobar, Ángel Moreno, Eduardo Rivas | |
# para la Universidad Don Bosco - Ciclo 2 - 2014 | |
# Desarrollado en Python 2.7, OpenCV 2.4.8, Ubuntu 14.04 | |
# Importar las librerías | |
import cv2 # OpenCV | |
import numpy as np # NumPy | |
# from serial import Serial # Puerto serie | |
import cPickle as pickle # Datos persistentes | |
def set_pallete_values(val): | |
""" | |
Callback que establece todos los valores de umbral HSV cada vez que cambia | |
uno en los sliders de control. También dibuja la paleta de colores. | |
""" | |
global colors, pallete | |
# Obtener los colores de los sliders iterando sobre ellos | |
for i, k in enumerate(["Low", "High"]): | |
for j, l in enumerate(["H", "S", "V"]): | |
colors[i][j] = cv2.getTrackbarPos(" ".join([k, l]), "Control") | |
# Actualizar la paleta de colores | |
cv2.rectangle(pallete, (0, 0), (149, 149), colors[0].tolist(), -1) | |
cv2.rectangle(pallete, (150, 0), (299, 149), colors[1].tolist(), -1) | |
pallete = cv2.cvtColor(pallete, cv2.COLOR_HSV2BGR) | |
cv2.imshow("Control", pallete) | |
# Nuevo puerto serie (para hablar con el Arduino) | |
# arduino = Serial("/dev/ttyACM0", 9600) | |
# Constantes relacionadas a los servos | |
servo_x = servo_y = 90 # Ángulo de inicio de los servos | |
step = 3 # Cantidad de ángulos que se ajustará en cada paso | |
threshold = 50 # Umbral de error (deadzone) | |
servo_max = 179 # Ángulo máximo | |
servo_min = 0 # Ángulo mínimo | |
# Establecer los servos a sus posiciones medias | |
# arduino.write("%s,%s\n" % (servo_x, servo_y)) | |
# Ancho y alto del video que se desea capturar | |
frame_w = 640 | |
frame_h = 480 | |
# Coordenadas del centro del video | |
center_x = int(frame_w/2) | |
center_y = int(frame_h/2) | |
# Indices de las propiedades de video (no editar) | |
FRAME_PROP_WIDTH = 3 | |
FRAME_PROP_HEIGHT = 4 | |
# Cargar los colores a partir del archivo "colors.pickle" | |
with open("colors.pickle", "rb") as f: | |
colors = pickle.load(f) | |
colors[0] = np.array(colors[0], dtype=np.uint8) # Umbral inferior | |
colors[1] = np.array(colors[1], dtype=np.uint8) # Umbral superior | |
# Crear ventana de control | |
cv2.namedWindow("Control", flags=cv2.WINDOW_NORMAL) | |
cv2.resizeWindow("Control", 300, 600) | |
cv2.moveWindow("Control", 0, 0) | |
# Crear sliders de control con los valores de colores precargados | |
cv2.createTrackbar("Low H", "Control", colors[0][0], 179, set_pallete_values) | |
cv2.createTrackbar("Low S", "Control", colors[0][1], 255, set_pallete_values) | |
cv2.createTrackbar("Low V", "Control", colors[0][2], 255, set_pallete_values) | |
cv2.createTrackbar("High H", "Control", colors[1][0], 179, set_pallete_values) | |
cv2.createTrackbar("High S", "Control", colors[1][1], 255, set_pallete_values) | |
cv2.createTrackbar("High V", "Control", colors[1][2], 255, set_pallete_values) | |
# Crear paleta de colores y mostrarla en la ventana de control | |
pallete = np.zeros([150, 300, 3], dtype=np.uint8) | |
cv2.imshow("Control", pallete) | |
# Actualizar la paleta con los colores actuales | |
set_pallete_values(None) | |
# Iniciar captura de video con el tamaño deseado | |
cap = cv2.VideoCapture(0) | |
cap.set(FRAME_PROP_WIDTH, frame_w) | |
cap.set(FRAME_PROP_HEIGHT, frame_h) | |
# Repetir mientras halla señal de video | |
while cap.isOpened(): | |
# Leer un frame | |
_, img = cap.read() | |
# Aplicar desenfoque para eliminar ruido | |
frame = cv2.blur(img, (15, 15)) | |
# Convertir frame de BRG a HSV | |
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) | |
# Aplicar threshold a la imagen y extraer los pixeles en el rango de color | |
thresh = cv2.inRange(hsv, colors[0], colors[1]) | |
# Encontrar los contornos en la imagen extraída | |
img2, cnts, h = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) | |
# Encontrar el contorno de mayor área y especificarlo como best_cnt | |
max_area = 0 | |
for cnt in cnts: | |
area = cv2.contourArea(cnt) | |
if area > max_area: | |
max_area = area | |
best_cnt = cnt | |
# Ejecutar este bloque solo si se encontró un área | |
if max_area > 0: | |
# Encontrar el centroide del mejor contorno y marcarlo | |
M = cv2.moments(best_cnt) | |
obj_x, obj_y = int(M["m10"]/M["m00"]), int(M["m01"]/M["m00"]) | |
cv2.circle(img, (obj_x, obj_y), 5, 255, -1) | |
# Dibujar un rectángulo alrdedor del objeto | |
x, y, w, h = cv2.boundingRect(best_cnt) | |
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2) | |
# Dibujar una línea del centro del frame al centroide | |
cv2.line(img, (obj_x, obj_y), (center_x, center_y), 255, 2) | |
# Calcular el error en X y Y | |
error_x = center_x - obj_x | |
error_y = center_y - obj_y | |
# Este bloque if/else corresponde a dos controladores ON/OFF | |
# Controlador para error_x | |
if error_x < -threshold: | |
if servo_x < servo_max: | |
servo_x += step | |
else: | |
servo_x = servo_max | |
elif error_x > threshold: | |
if servo_x > servo_min: | |
servo_x -= step | |
else: | |
servo_x = servo_min | |
# Controlador para error_y | |
if error_y < -threshold: | |
if servo_y < servo_max: | |
servo_y += step | |
else: | |
servo_y = servo_max | |
elif error_y > threshold: | |
if servo_y > servo_min: | |
servo_y -= step | |
else: | |
servo_y = servo_min | |
# Si hay error, se envía la corrección calculada por los controladores | |
# al Arduino a través del puerto serie | |
# if (abs(error_x) > threshold) or (abs(error_y) > threshold): | |
# arduino.write("%s,%s\n" % (servo_x, servo_y)) | |
# print(error_x, error_y, servo_x, servo_y) | |
# Se muestra el error en X y Y y la posición de los servos en pantalla | |
font = cv2.FONT_HERSHEY_SIMPLEX | |
cv2.putText(img, str(error_x), (30, 30), font, 0.8, 255, 2, 8) | |
cv2.putText(img, str(error_y), (120, 30), font, 0.8, 244, 2, 8) | |
cv2.putText(img, str(servo_x), (210, 30), font, 0.8, 244, 2, 8) | |
cv2.putText(img, str(servo_y), (280, 30), font, 0.8, 244, 2, 8) | |
# Mostrar la imagen original con todos los overlays | |
cv2.imshow("img", img) | |
# Mostrar la máscara con los pixeles extraídos | |
# cv2.imshow('thresh', thresh) | |
# Salir del bucle si se presiona ESC | |
k = cv2.waitKey(5) & 0xFF | |
if k == 27: | |
break | |
# Limpieza y fin de programa | |
# arduino.close() | |
cap.release() | |
# Se guardan los colores configurados por los slider para la siguiente vez | |
with open("colors.pickle", "wb") as f: | |
pickle.dump([colors[0].tolist(), colors[1].tolist()], f) | |
cv2.destroyAllWindows() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# SCRIPT DE SEGUIMIENTO DE OBJETOS POR COLOR | |
# El script detecta objetos en base a colores y selecciona el más grande | |
# (por área). Se calcula la distancia del centroide del objeto al centro | |
# de la imagen. | |
# Por David Escobar, Ángel Moreno, Eduardo Rivas | |
# para la Universidad Don Bosco - Ciclo 2 - 2014 | |
# Desarrollado en Python 2.7, OpenCV 2.4.8, Ubuntu 14.04 | |
# Importar las librerías OpenCV y Numpy | |
import cv2 | |
import numpy as np | |
from pwm import PWMPin | |
px = PWMPin(pin=10, freq=50, level=49) | |
py = PWMPin(pin=11, freq=50, level=49) | |
# Ancho y alto del video que se desea capturar | |
frame_w = 640 | |
frame_h = 480 | |
# Coordenadas del centro del video | |
fcx = int(frame_w/2) | |
fcy = int(frame_h/2) | |
# Indices de las propiedades de video (no editar) | |
FRAME_PROP_WIDTH = 3 | |
FRAME_PROP_HEIGHT = 4 | |
# Definir rango de color a identificar (HSV) | |
lower_color = np.array([90, 90, 90], dtype=np.uint8) | |
upper_color = np.array([120, 255, 255], dtype=np.uint8) | |
# Iniciar captura de video con el tamaño deseado | |
cap = cv2.VideoCapture(0) | |
cap.set(FRAME_PROP_WIDTH, frame_w) | |
cap.set(FRAME_PROP_HEIGHT, frame_h) | |
px.enable = py.enable = 1 | |
# Repetir mientras halla señal de video | |
while cap.isOpened(): | |
# Leer un frame | |
_, img = cap.read() | |
# Aplicar desenfoque para eliminar ruido | |
frame = cv2.blur(img, (15, 15)) | |
# Convertir frame de BRG a HSV | |
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) | |
# Aplicar umbral a la imagen y extraer los pixeles en el rango de colores | |
thresh = cv2.inRange(hsv, lower_color, upper_color) | |
# Encontrar los contornos en la imagen extraída | |
cnts, h = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) | |
# Encontrar el contorno de mayor área y especificarlo como best_cnt | |
max_area = 0 | |
for cnt in cnts: | |
area = cv2.contourArea(cnt) | |
if area > max_area: | |
max_area = area | |
best_cnt = cnt | |
# Ejecutar este bloque solo si se encontró un área | |
if max_area > 0: | |
# Encontrar el centroide del mejor contorno y marcarlo | |
M = cv2.moments(best_cnt) | |
cx, cy = int(M['m10']/M['m00']), int(M['m01']/M['m00']) | |
cv2.circle(img, (cx, cy), 5, 255, -1) | |
# Dibujar un rectángulo alrdedor del objeto | |
x, y, w, h = cv2.boundingRect(best_cnt) | |
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2) | |
# Dibujar una línea del centro del frame al centroide | |
cv2.line(img, (cx, cy), (fcx, fcy), 255, 2) | |
# Calcular el error en X y Y y mostrarlo como texto | |
errx = fcx - cx | |
erry = fcy - cy | |
if errx > 100: | |
if px.level < 79: | |
px.level += 1 | |
else: | |
px.level = 79 | |
elif errx < -100: | |
if px.level > 19: | |
px.level -= 1 | |
else: | |
px.level = 19 | |
if erry < -100: | |
if py.level < 79: | |
py.level += 1 | |
else: | |
py.level = 79 | |
elif erry > 100: | |
if py.level > 19: | |
py.level -= 1 | |
else: | |
py.level = 19 | |
# print(errx, erry, px.level, py.level) | |
font = cv2.FONT_HERSHEY_SIMPLEX | |
cv2.putText(img, str(errx), (30, 30), font, 0.8, 255, 2, 8) | |
cv2.putText(img, str(erry), (120, 30), font, 0.8, 244, 2, 8) | |
cv2.putText(img, str(px.level), (210, 30), font, 0.8, 244, 2, 8) | |
cv2.putText(img, str(py.level), (280, 30), font, 0.8, 244, 2, 8) | |
# Mostrar la imagen original con todos los overlays | |
cv2.imshow('img', img) | |
# Mostrar la máscara con los pixeles extraídos | |
cv2.imshow('thresh', thresh) | |
# Salir del bucle si se presiona ESC | |
k = cv2.waitKey(5) & 0xFF | |
if k == 27: | |
break | |
# Limpieza y fin de programa | |
px.level = py.level = 49 | |
px.enable = py.enable = 0 | |
cap.release() | |
cv2.destroyAllWindows() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
hola tienes el codigo en version actual de python