¡Hola, gente! En el tutorial de hoy, voy a enseñaros como trackear objetos con OpenCV+Python utilizando el método de Lucas Kanade.
Dado un frame de vídeo y un píxel inicial, el método de Lucas Kanade intentará encontrar este mismo píxel en frames posteriores. Por tanto, si el objeto que contenía este píxel se mueve, este método podrá seguir su desplazamiento.
Para trabajar, hoy os propongo escuchar El Canto de la Sibila, una pieza medieval que a mí me chifla :3
Ejemplo 1 – Seguir un único punto
Este primer código buscará un objeto de color verde en la imagen de vídeo y calculará su centro. Después, dentro del bucle principal, se pasarán sus coordenadas (x,y) a la función cv2.calcOpticalFlowPyrLK() para que siga su desplazamiento.
Nótese que para que el programa funcione, tiene que haber un objeto verde delante de la cámara en el momento en que se inicie. En caso contrario saltará un error, pues no se podrá calcular ningún centroide…
Como siempre, tenéis que empezar por llamar las librerías e inicializar la cámara:
import cv2 import numpy as np #Iniciar la camara captura = cv2.VideoCapture(0)
Después hay que construir un diccionario con los parámetros de la función de Lucas-Kanade.
# Parametros para la funcion de Lucas Kanade lk_params = dict( winSize = (15,15), maxLevel = 2, criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
Veamos, ¿qué hace cada parámetro?
- winSize es la “ventana” alrededor del píxel inicial sobre la que se aplicará el método de Lucas Kanade.
- maxLevel indica el número de pirámides que utilizará el método de Lucas Kanade. Para más información sobre el método de Lucas Kanade piramidal, visitad este enlace.
- criteria especifica la condición de parada del método de Lucas Kanade. En este caso le estamos diciendo que haga como máximo 10 iteraciones, o que pare cuando encuentre una región del nuevo frame cuya diferencia con la región próxima al píxel del frame anterior sea menor a 0.03. El Método de Lucas Kanade básicamente utiliza el método de Regresión por Mínimos Cuadrados para encontrar la nueva posición del píxel. Este 0.03 es el epsilon del método de RMC.
Para encontrar las coordenadas iniciales del objeto verde hay que capturar un primer frame de la cámara y aplicar detección de colores, encontrar contornos y calcular momentos. Como esto ya lo hemos hecho muchas veces, no voy a detallar cada paso. Pero si tenéis dudas escribidme un comentario, ¿de acuerdo?
#Capturamos una imagen y la convertimos de RGB -> HSV _, imagen = captura.read() hsv = cv2.cvtColor(imagen, cv2.COLOR_BGR2HSV) #Establecemos el rango de colores que vamos a detectar #En este caso de verde oscuro a verde-azulado claro verde_bajos = np.array([57,61,64], dtype=np.uint8) verde_altos = np.array([116, 255, 255], dtype=np.uint8) #Crear una mascara con solo los pixeles dentro del rango de verdes mask = cv2.inRange(hsv, verde_bajos, verde_altos) #Eliminamos ruido kernel = np.ones((10,10),np.uint8) mask = cv2.morphologyEx(mask,cv2.MORPH_OPEN,kernel) mask = cv2.morphologyEx(mask,cv2.MORPH_CLOSE,kernel) #Detectamos contornos, nos quedamos con el mayor y calculamos su centro contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) mayor_contorno = max(contours, key = cv2.contourArea) momentos = cv2.moments(mayor_contorno) cx = float(momentos['m10']/momentos['m00']) cy = float(momentos['m01']/momentos['m00'])
El frame capturado con la cámara se convierte a gris y se guarda para poder pasarlo como parámetro a la función de Lucas Kanade dentro del bucle principal. También se convierte el centro (cx, cy) a un array de numpy.
#Convertimos la imagen a gris para poder introducirla en el bucle principal frame_anterior = cv2.cvtColor(imagen, cv2.COLOR_BGR2GRAY) #Convertimos el punto elegido a un array de numpy que se pueda pasar como parametro #a la funcion cv2.calcOpticalFlowPyrLK() punto_elegido = np.array([[[cx,cy]]],np.float32)
Dentro del bucle principal se captura y se guarda un nuevo frame de la cámara y se convierte de BGR a escala de grises.
while(1): #Capturamos una imagen y la convertimos de RGB -> GRIS _, imagen = captura.read() frame_gray = cv2.cvtColor(imagen, cv2.COLOR_BGR2GRAY)
Ahora viene el punto clave… ¡aplicar el método de Lucas Kanade! Para ello se llama a la función cv2.calcOpticalFlowPyrLK(). Los argumentos de esta función son (en orden): el frame de la iteración anterior (en escala de grises), el nuevo frame dónde debe aplicarse el método para encontrar la nueva posición del píxel, las coordenadas (x,y) del píxel en el frame anterior (también puede ser un array con varios puntos, como se verá en el segundo ejemplo) y el diccionario con los parámetros que se han declarado al principio del script.
Después esta función devolverá un array con las nuevas coordenadas del punto, un vector de estado (que indica si se han encontrado los puntos o no) y una variable booleana que indica si se ha producido algún error.
#Se aplica el metodo de Lucas Kanade punto_elegido, st, err = cv2.calcOpticalFlowPyrLK(frame_anterior, frame_gray, punto_elegido, **lk_params)
Por último, se dibuja el centro del objeto verde sobre la imagen, se copia el frame (que pasará a ser el frame anterior) y se muestra la imagen antes de salir.
#Pintamos el centro (lo hacemos con un bucle por si, por alguna razon, decidimos pintar mas puntos) for i in punto_elegido: cv2.circle(imagen,tuple(i[0]), 3, (0,0,255), -1) #Se guarda el frame de la iteracion anterior del bucle frame_anterior = frame_gray.copy() #Mostramos la imagen original con la marca del centro cv2.imshow('Camara', imagen) tecla = cv2.waitKey(5) & 0xFF if tecla == 27: break cv2.destroyAllWindows()
Por tanto, ¿cómo quedará al final todo el código?
import cv2 import numpy as np #Iniciamos la camara captura = cv2.VideoCapture(0) # Parametros para la funcion de Lucas Kanade lk_params = dict( winSize = (15,15), maxLevel = 2, criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)) #Capturamos una imagen y la convertimos de RGB -> HSV _, imagen = captura.read() hsv = cv2.cvtColor(imagen, cv2.COLOR_BGR2HSV) #Establecemos el rango de colores que vamos a detectar #En este caso de verde oscuro a verde-azulado claro verde_bajos = np.array([57,61,64], dtype=np.uint8) verde_altos = np.array([116, 255, 255], dtype=np.uint8) #Crear una mascara con solo los pixeles dentro del rango de verdes mask = cv2.inRange(hsv, verde_bajos, verde_altos) #Eliminamos ruido kernel = np.ones((10,10),np.uint8) mask = cv2.morphologyEx(mask,cv2.MORPH_OPEN,kernel) mask = cv2.morphologyEx(mask,cv2.MORPH_CLOSE,kernel) #Detectamos contornos, nos quedamos con el mayor y calculamos su centro contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) mayor_contorno = max(contours, key = cv2.contourArea) momentos = cv2.moments(mayor_contorno) cx = float(momentos['m10']/momentos['m00']) cy = float(momentos['m01']/momentos['m00']) #Convertimos la imagen a gris para poder introducirla en el bucle principal frame_anterior = cv2.cvtColor(imagen, cv2.COLOR_BGR2GRAY) #Convertimos el punto elegido a un array de numpy que se pueda pasar como parametro #a la funcion cv2.calcOpticalFlowPyrLK() punto_elegido = np.array([[[cx,cy]]],np.float32) while(1): #Capturamos una imagen y la convertimos de RGB -> GRIS _, imagen = captura.read() frame_gray = cv2.cvtColor(imagen, cv2.COLOR_BGR2GRAY) #Se aplica el metodo de Lucas Kanade punto_elegido, st, err = cv2.calcOpticalFlowPyrLK(frame_anterior, frame_gray, punto_elegido, **lk_params) #Pintamos el centro (lo hacemos con un bucle por si, por alguna razon, decidimos pintar mas puntos) for i in punto_elegido: cv2.circle(imagen,tuple(i[0]), 3, (0,0,255), -1) #Se guarda el frame de la iteracion anterior del bucle frame_anterior = frame_gray.copy() #Mostramos la imagen original con la marca del centro cv2.imshow('Camara', imagen) tecla = cv2.waitKey(5) & 0xFF if tecla == 27: break cv2.destroyAllWindows()
Ejemplo 2 – Seguir múltiples puntos
En este segundo ejemplo le diremos al programa que nos busque él sólo 25 puntos idóneos para hacer tracking. Normalmente estos puntos son esquinas de objetos que tienen mucho contraste y son fáciles de reconocer al saltar de un frame a otro.
Las primeras líneas son iguales al ejemplo anterior:
import cv2 import numpy as np #Iniciamos la camara captura = cv2.VideoCapture(0) # Parametros para la funcion de Lucas Kanade lk_params = dict( winSize = (15,15), maxLevel = 2, criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)) #Capturamos una imagen y la convertimos de RGB -> HSV _, imagen = captura.read() hsv = cv2.cvtColor(imagen, cv2.COLOR_BGR2HSV) #Convertimos la imagen a gris para poder introducirla en el bucle principal frame_anterior = cv2.cvtColor(imagen, cv2.COLOR_BGR2GRAY)
Después se llama a la función cv2.goodFeaturesToTrack() para buscar 25 puntos ídoneos para trackear.
#El programa buscara automaticamente 25 puntos adecuados para trackear punto_elegido = cv2.goodFeaturesToTrack(frame_anterior,25,0.01,10)
El resto del código no cambia en nada:
while(1): #Capturamos una imagen y la convertimos de RGB -> GRIS _, imagen = captura.read() frame_gray = cv2.cvtColor(imagen, cv2.COLOR_BGR2GRAY) #Se aplica el metodo de Lucas Kanade punto_elegido, st, err = cv2.calcOpticalFlowPyrLK(frame_anterior, frame_gray, punto_elegido, **lk_params) #Pintamos el centro (lo hacemos con un bucle por si, por alguna razon, decidimos pintar mas puntos) for i in punto_elegido: cv2.circle(imagen,tuple(i[0]), 3, (0,0,255), -1) #Se guarda el frame de la iteracion anterior del bucle frame_anterior = frame_gray.copy() #Mostramos la imagen original con la marca del centro cv2.imshow('Camara', imagen) tecla = cv2.waitKey(5) & 0xFF if tecla == 27: break cv2.destroyAllWindows()
Por tanto, el código completo será este:
import cv2 import numpy as np #Iniciamos la camara captura = cv2.VideoCapture(0) # Parametros para la funcion de Lucas Kanade lk_params = dict( winSize = (15,15), maxLevel = 2, criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)) #Capturamos una imagen y la convertimos de RGB -> HSV _, imagen = captura.read() hsv = cv2.cvtColor(imagen, cv2.COLOR_BGR2HSV) #Convertimos la imagen a gris para poder introducirla en el bucle principal frame_anterior = cv2.cvtColor(imagen, cv2.COLOR_BGR2GRAY) #El programa buscara automaticamente 25 puntos adecuados para trackear punto_elegido = cv2.goodFeaturesToTrack(frame_anterior,25,0.01,10) while(1): #Capturamos una imagen y la convertimos de RGB -> GRIS _, imagen = captura.read() frame_gray = cv2.cvtColor(imagen, cv2.COLOR_BGR2GRAY) #Se aplica el metodo de Lucas Kanade punto_elegido, st, err = cv2.calcOpticalFlowPyrLK(frame_anterior, frame_gray, punto_elegido, **lk_params) #Pintamos el centro (lo hacemos con un bucle por si, por alguna razon, decidimos pintar mas puntos) for i in punto_elegido: cv2.circle(imagen,tuple(i[0]), 3, (0,0,255), -1) #Se guarda el frame de la iteracion anterior del bucle frame_anterior = frame_gray.copy() #Mostramos la imagen original con la marca del centro cv2.imshow('Camara', imagen) tecla = cv2.waitKey(5) & 0xFF if tecla == 27: break cv2.destroyAllWindows()
Con este ejemplo puede verse, pues, que es posible seguir varios puntos a la vez con la función de Lucas Kanade.
¡Y esto es todo por ahora! No dudéis en comentar todas las dudas que tengáis sobre este tutorial, y también si encontráis algún error o imprecisión en la explicación. ¡Un saludo!
-RESOLUCIÓN DE ERRORES-
(1) Si usáis algunas versiones recientes de OpenCV puede aparecer este error:
Traceback (most recent call last): File "mi_script.py", line 30, in <module> contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) ValueError: too many values to unpack (expected 2)
Esto se debe a que la función cv2.findContours() devuelve un tercer valor. Cambiad la línea
contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
por
_, contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
(2) Otro error que puede aparecer es:
Traceback (most recent call last): File “mi_script.py”, line 54, in punto_elegido, st, err = cv2.calcOpticalFlowPyrLK(frame_anterior, frame_gray, punto_elegido,**lk_params) TypeError: Required argument ‘nextPts’ (pos 4) not found
En este caso, hay que sustituir la línea
punto_elegido, st, err = cv2.calcOpticalFlowPyrLK(frame_anterior, frame_gray, punto_elegido, **lk_params)
por
punto_elegido, st, err = cv2.calcOpticalFlowPyrLK(frame_anterior, frame_gray, punto_elegido, None, **lk_params)
hola quiero hacer un programa en donde detecte peatones y que se marque un punto en los rectangulos de los peatones
¡Hola, Diego! Puedes empezar por seguir este tutorial sobre Haarcascades: https://robologs.net/2014/05/26/reconocimiento-facial-con-opencv-webcam/
Aunque este link explique sólo cómo detectar rostros, puedes buscar por internet un fichero .xml que detecte figuras humanas y reciclar el mismo código, o adaptarlo según necesites.
¡Un saludo!
Hola que tal! Me podrias orientar para detectar en el momento en que los puntos cambien de dirección, o de que forma se podría detectar?
Gracias, saludos!
¡Hola, Jesus! Se me ocurre que podrias calcular el vector que forma la posición actual de los puntos con la posición de los puntos en el frame anterior, e ir guardando estos vectores.
Después puedes calcular el ángulo que forma el vector actual con el último vector calculado, y si es superior a un cierto margen significa que el vector ha cambiado de dirección (y, por tanto, el punto también).
¡Un saludo!
hola!! es que tengo este error en el 2do codigo:
VIDEOIO ERROR: V4L: can’t open camera by index 0
Traceback (most recent call last):
File “gggg.py”, line 14, in
hsv = cv2.cvtColor (cv2.COLOR_BGR2HSV)
CV2.error: openCV(4.0.0) /home/pi/opencv/modules/imgproc/src/color.cpp:181:errror: (-215:Assertion failed) !_src.empty() in function “cvtColor”
si me pueden ayudar gracias!!!!
¡Buenas! En la línea captura = cv2.VideoCapture(0), intenta cambiar el índice 0 de la cámara por -1 ó 1.
Me olvidaba, uso el OpenCV – 4.1.0
Gracias
Hola, tengo este error al ejecutar el Ejemplo 1
mayor_contorno = max(contours, key = cv2.contourArea)
ValueError: max() arg is an empty sequence
Gracias
¡Hola, Juan! Lo más probable es que la cámara tarde en inicializarse, y la función max() esté intentando encontrar contornos en una lista vacía.
Puedes cambiar la línea que lee la cámara por:
Y justo después añadir:
Esto impedirá que el programa avance mientras la cámara no esté inicializada, y debería solucionar tu problema.
¡Un saludo!
Me sigue tirando este error… mayor_contorno = max(contours, key = cv2.contourArea) ValueError: max() arg is an empty sequence Te dejo parte del programa donde me tira la falla (que es el Ejemplo 1 tuyo…) ****************************************************************************************** #Detectamos contornos, nos quedamos con el mayor y calculamos su centro contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) mayor_contorno = max(contours, key = cv2.contourArea) momentos = cv2.moments(mayor_contorno) cx = float(momentos[‘m10’]/momentos[‘m00’]) cy = float(momentos[‘m01’]/momentos[‘m00’]) #Convertimos la imagen a gris para poder introducirla en el bucle principal frame_anterior = cv2.cvtColor(imagen, cv2.COLOR_BGR2GRAY) #Convertimos el punto elegido a un array de numpy que se pueda pasar como parametro #a la… Leer más »
Hola de nuevo.
El código que estás usando no es igual al del ejemplo 1 (dejando de lado las partes que has comentado). Fíjate que estás leyendo la cámara y comprobando que el frame sea válido DESPUÉS de calcular los contornos. Tienes que hacer la comprobación cada vez que intentes leer un frame de la cámara (líneas 14 y 51).
Otra cosa: también he visto que te dará este error si la máscara está vacía, es decir, si no se detecta ningún objeto verde. Intenta encontrar un objeto de este color y colócalo delante de la cámara.
Ok gracias
¿Conseguiste arreglar el problema?
Hola! Estoy trabajando en mi TFG de final de carrera, mi objetivo es buscar y guardar las coordenadas de fichas circulares de diferentes colores situadas en un tablero con fondo blanco, me podrias ayudar? Muchas Gracias
¡Hola, Sergio! Si sabes de qué color es cada ficha, puedes buscar cada color individualmente en la imagen, y luego juntarlas en una sola máscara. Este tutorial quizá te dé una idea: https://robologs.net/2016/05/18/detectar-multiples-colores-con-opencv-y-python/ (también podrías detectar el color blanco del fondo e invertir la máscara para extraer las fichas). Una vez tienes la máscara, tendrás que buscar los contornos con la función cv2.findContours(), y calcular el centro de cada contorno de la misma forma que hemos hecho en el tutorial de esta página. La única diferencia es que recorremos todo el vector de contornos en vez de quedarnos sólo con… Leer más »
Hola. Estoy realizando un trabajo para la universidad, donde encuentro contornos y obtengo el punto centro del mismo, pero necesito encerrarlo en un rectangulo y saber las dimensiones del rectangulo, como se podria hacer estto??
¡Hola, Richard! Si tienes extraidos los contornos, puedes usar la función cv2.boundingRect para encontrar el rectángulo mínimo que lo contiene: https://docs.opencv.org/3.4/da/d0c/tutorial_bounding_rects_circles.html
Hola, buenos días. Estoy trabajando en un proyecto sobre el seguimiento de objetos con infrarrojos, me ha servido de gran utilidad el código proporcionado por usted, pero tengo un problema, al hacer el seguimiento de varios objetos no me coge como objeto deseado el que realmente quiero. ¿Hay alguna forma para en lugar de usar “punto_elegido = cv2.goodFeaturesToTrack(frame_anterior,25,0.01,10)” y que coja los 25 mejores puntos estratégicamente, me coja los que yo quiero?
¡Hola! Puedes hacerlo de esta forma:
Hola. Estoy realizando un trabajo para la universidad y es la primera vez que utilizo opencv. El trabajo consiste en, dado un vídeo en el que se puede ver una jugada de billar desde arriba, detectar la posición de las bolas en el momento en que se encuentran quietas y el jugador no obstaculice la visión completa de la mesa. Me podría ayudar comentando una posible solución a este problema, no sé qué pasos debería seguir. Un saludo y gracias por adelantado.
¡Hola Mariam! Podrías aplicar detección de colores para eliminar el fondo verde y después aplicar Hough Circle Transform para encontrar todas las bolas.
Te paso algunos links:
Detectar colores:
https://robologs.net/2016/05/18/detectar-multiples-colores-con-opencv-y-python/
https://robologs.net/2014/07/02/deteccion-de-colores-con-opencv-y-python/
Hough Circle Transform:
https://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.html
y yo estoy haciendo un proyecto escolar. ¿Me podría ayudar?
es necesario hacer un programa para detectar un cuadrado y cuando se detecta se necesita que aparezca instrucciones en la pantalla indicando para qué lado debo mover la cámara para que este cuadrado quede en el centro de la imagen.
en el momento de detectar el cuadrado, pero no sé cómo hacer para encontrar las coordenadas del centro de la esquina y hacer que aparezcan las instrucciones
sigue el programa que estoy usando para identificar el cuadrado (él también habla si esta identificando un cuadrado o no) import argparse import imutils import cv2 cap = cv2.VideoCapture(1) while True: # Le el marco actual e indica el estado que él está (grabbed, frame) = cap.read() status = “SEM QUADRADO” # verifica si el video ya ha terminado if not grabbed: break # Convierte el marco a la escala de color gris, desencava y localiza los bordes gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (7, 7), 0) edged = cv2.Canny(blurred, 50, 150) # Encontrar contornos en el mapa de… Leer más »
¡Buenas! ¿Podrías pasarme el código por correo? (contacto@robologs.net)
Así veré mejor el tabulado y será más fácil ayudarte.
Hola mi nombre es José, en primer lugar gracias por difundir tus conocimientos para que podamos aprender. Mi cuentión es la siguiente, me devuelve el siguiente error el código de los puntos múltiples (Ya he añadido el None en la función de lucas-Kanade): Traceback (most recent call last): File “C:\Users\PRUEBA OPENCV\prueba_detector_v4.py”, line 32, in punto_elegido, st, err = cv2.calcOpticalFlowPyrLK(frame_anterior, frame_gray, punto_elegido, None, **lk_params) cv2.error: OpenCV(3.4.5) D:\Build\OpenCV\opencv-3.4.5\modules\video\src\lkpyramid.cpp:1231: error: (-215:Assertion failed) (npoints = prevPtsMat.checkVector(2, CV_32F, true)) >= 0 in function ‘cv::`anonymous-namespace’::SparsePyrLKOpticalFlowImpl::calc’ He estado leyendo bibliografía sobre la función pero no consigo dar con el problema.¿Tienes idea de qué puede ser? Gracias de… Leer más »
¡Hola, José!
Aunque el mensaje de error no sea exactamente el mismo, intenta hacer lo que pone en el punto (2) del apartado de “Resolución de errores” que hay al final del tutorial. Creo que esto debería resolver tu problema.
Si no te funciona dímelo y buscaremos otra solución 😉
Buen día, como podría solucionar este error?
Traceback (most recent call last):
File “LucasKanade.py”, line 31, in
mayor_contorno = max(contours, key = cv2.contourArea)
ValueError: max() arg is an empty sequence
¡Buenas! Esto puede deberse a que el frame que intenta leer la cámara está vacío y, por tanto, no puede leerse ningún contorno (algunas cámaras tardan en inicializarse). La solución sería comprobar que el frame sea válido antes de intentar detectar contornos y buscar el máximo. Puedes cambiar la línea 29 del código completo por: val, imagen = captura.read() La variable ‘val’ es un booleano que estará a True si el frame es válido. Después escribís un condicional que compruebe que el frame sea válido, y ponéis las líneas 30-43 dentro de este condicional. if val: frame_gray = cv2.cvtColor(imagen, cv2.COLOR_BGR2GRAY)… Leer más »
cordial saludo
excelente tutorial
pero como puedo solucionar este error
Traceback (most recent call last):
File “lineas.py”, line 31, in
mayor_contorno = max(contours, key = cv2.contourArea)
ValueError: max() arg is an empty sequence
lenovo@lenovo-Ideapad:~/Descargas/ejemplos_o
tengo el mismo problema
¡Buenas! Esto puede deberse a que el frame que intenta leer la cámara está vacío y, por tanto, no puede leerse ningún contorno (algunas cámaras tardan en inicializarse). La solución sería comprobar que el frame sea válido antes de intentar detectar contornos y buscar el máximo. Podéis cambiar la línea 29 del código completo por: val, imagen = captura.read() La variable ‘val’ es un booleano que estará a True si el frame es válido. Después escribís un condicional que compruebe que el frame sea válido, y ponéis las líneas 30-43 dentro de este condicional. if val: frame_gray = cv2.cvtColor(imagen, cv2.COLOR_BGR2GRAY)… Leer más »
Esto es similar a la deteccion de colores ¿cierto?. La deteccion de colores puede hacer el trabajo de tracking, es dicer, que en vez de llamarlo tracking de objeto, se le llmaria tracking color? He probado el codigo y tiene bastantes defectos. En sí, no trackea un objeto sino un pixel o pixeles especificamente, ¿o me equivoco?. Me gustaria saber como puedo detectar objetos completos u objetos complejos, un ejemplo podría ser un cubo o una esfera. Tambien Quisera saber si es posible detectar dos o mas objetos (por separado) de mismo color, forma y tamaño en cada frame. Sería… Leer más »
Aunque considerando mi falta de experiencia en ésto, creo que será mas adecuado no usar el metodo de Lucas Kanade ya que me pareció algo complejo XD. Asi que me gustaria empezar por detectar por ejemplo dos cuadrados del mismo color, pero por separado, en tal caso dibujar un rectangulo en cada uno. Yo supondría que deberia establecer un limite de acumulacion de pixeles a detectar por un lado, y si ese limite es exedido, pues separar la deteccion dibujando un rectangulo en la siguiente acumulacion de pixeles. Pero no sabria pasar ésto a codigo.
Agradeceria mucho la ayuda! Saludos!
¡Hola de nuevo!
A ver, antes de empezar a hacer cosas complicadas como Lucas Kanade te aconsejo que vayas por partes… especialmente si hace poco que has empezado a programar. Te recomiendo que sigas estos tutoriales por orden:
http://robologs.net/2014/07/02/deteccion-de-colores-con-opencv-y-python/
https://robologs.net/2016/05/18/detectar-multiples-colores-con-opencv-y-python/
http://robologs.net/2015/07/26/como-filtrar-el-ruido-de-una-mascara-con-opencv/
http://robologs.net/2015/01/25/deteccion-de-triangulos-con-opencv-y-python/
En el último tutorial, precisamete, buscamos el contorno de figuras geométricas (en este caso triángulos) y dibujamos sus bordes. No debería serte difícil adaptarlo para que detecte cuadrados en vez de triángulos 😉
¡Un saludo, Kelvin!
¡Saludos cordiales! es verdad! y solo me faltaba leer el ultimo tutorial, es excelente y ya se acerca a lo que busco XD, esto es bastante complejo debido a los diferentes métodos y funciones. Aun me quedan dudas del ultimo tutorial, primero no entiendo la linea 38: areas = [cv2.contourArea(c) for c in contours] cv2.contourArea es lo mismo que moments[‘m00’]? Luego está la i, significa que está recorriendo la lasta de contours[i] en cada vuelta de bucle? Ahora que metodo podria usar para detectar circulos u objetos con curbas.? Fuera de este tema me preguntaba se aceptas sugerencias para tutoriales!… Leer más »
¡Hola de nuevo Kelvin! Podrías usar tanto m00 como contourArea para calcular el área de un contorno. Y sí, la i es una variable auxiliar que sirve para recorrer el vector de contornos[] a cada vuelta del bucle. Para detectar circulos hay dos métodos para hacerlo: la forma “cutre” y la forma refinada. La forma “cutre” consiste en hacer un código como el del detector de triángulos, pero decirle que detecte figuras con muchos vértices. La forma interesante de hacerlo es con Hough Circle Transform (https://docs.opencv.org/3.1.0/da/d53/tutorial_py_houghcircles.html). En cuánto a tutoriales… no creo que aquí seamos ningún referente para dar consejos… Leer más »
Muchas gracias por info, Te agradezco mucho! Cualquier otra duda te comento!! =)
En el tema de los tutoriales, quizá no me entendiste bien, yo no me referia a dar consejos de ¿Como hacerlos? Sino a, aportar ideas nuevas para nuevos tutoriales valgame la redundancia XD.
Saludos! Se agradece la ayuda! ^^
Por cierto, te dejaré una imagen en facebook del resultado de un contorno en el que se supone que debió detectar un cuadrado.
Hola, tengo un problema, necesito hacer un código que me detecte la boca y una vez detectada haga el tracking. Tengo un código que hace la detección y otro que hace el trackin pero tengo problemas para vincularlos. Me podrían ayudar? Gracias. ***Detección*** import cv2 import numpy as np #Buscamos los archivos HAAR que permiten detectar el rostro y la boca en OpenCV face_cascade = cv2.CascadeClassifier(‘haarcascade_frontalface_default.xml’) mouth_cascade = cv2.CascadeClassifier(‘haarcascade_mouth.xml’) #Iniciamos la camara video = cv2.VideoCapture(0) while (True): #leemos un frame y lo guardamos ret, frame = video.read() if frame is not None: #convertimos la imagen a blanco y negro gray… Leer más »
Se que es una pregunta muy tonta, pero soy nuevo en esto y me gustaria saber si puedo obtener las coordenadas x,y del objeto que estos detectando.
¡Hola, José Carlos! Esto ya lo hacemos en el ejemplo cuándo pintamos el centro del objeto. Fíjate en las líneas 36 y 37 del código completo. La variable i[0] contiene las coordenadas [x,y] del objeto detectado, que es justo lo que necesitas 😉
¡Un saludo!
Hola, te felicito por el tutorial!!! al ejecutar el codigome tira este error…… yo uso el IDE de SPYDER.
Gracias
File “C:/Python27/Practicas/seguir_punto.py”, line 21, in
hsv = cv2.cvtColor(imagen, cv2.COLOR_BGR2HSV)
Hola para los que les sale este error:
File “C:\Users\Manu\Documents\Vision\TareaOpenCVTracking.py”, line 54, in
punto_elegido, st, err = cv2.calcOpticalFlowPyrLK(frame_anterior, frame_gray, punto_elegido, **lk_params)
TypeError: Required argument ‘nextPts’ (pos 4) not found
Searregla con lo que nos dejo en guia de soluciones:
Traceback (most recent call last):
File “mi_script.py”, line 34, in
punto_elegido, st, err = cv2.calcOpticalFlowPyrLK(frame_anterior, frame_gray, punto_elegido,**lk_params)
TypeError: Required argument ‘nextPts’ (pos 4) not found
En este caso, hay que sustituir la línea
punto_elegido, st, err = cv2.calcOpticalFlowPyrLK(frame_anterior, frame_gray, punto_elegido, **lk_params)
por
punto_elegido, st, err = cv2.calcOpticalFlowPyrLK(frame_anterior, frame_gray, punto_elegido, None, **lk_params)
¡¡##solo que obviamente lo cambian en su linea 54 y no en la linea 34##!!
Lo de la línea 34 en vez de 54 es porque hice la prueba con un fichero a parte, que sólo invocaba esta función para poder ver qué estaba fallaba
Hola a mi tambien me aparece un error, me podrias ayudar por favor
Traceback (most recent call last):
File “C:\Users\Manu\Documents\Vision\TareaOpenCVTracking.py”, line 54, in
punto_elegido, st, err = cv2.calcOpticalFlowPyrLK(frame_anterior, frame_gray, punto_elegido, **lk_params)
TypeError: Required argument ‘nextPts’ (pos 4) not found
>>>
¡Hola, Manuel! Mira el apartado final, dónde pone “Resolución de Errores”. Al final de todo explico cómo resolver tu error 🙂
Hola me aparece un error, me podrias ayudar, por favor,
Traceback (most recent call last):
File “C:\Users\the best\Documents\Vision\TareaOpenCVTracking.py”, line 32, in
punto_elegido,st,err = cv2.calcOpticalFlowPyrLK(frame_anterior, frame_gray, punto_elegido, **lk_params)
TypeError: Required argument ‘nextPts’ (pos 4) not found
>>>
saludos me gusta tu proyecto
¡Hola HHHH! Léete la parte del final del tutorial, dónde pone “Resolución de Errores”.
A qué se debe el siguiente error?
File “C:UsersGabrielDesktopseg.py”, line 30, in
contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
ValueError: too many values to unpack
¡Hola Lucia! He añadido un anexo al final del tutorial con la solución a tu problema 🙂
Tengo un error ->
Traceback (most recent call last):
File “mult-objects.py”, line 34, in
punto_elegido, st, err = cv2.calcOpticalFlowPyrLK(frame_anterior, frame_gray, punto_elegido,**lk_params)
TypeError: Required argument ‘nextPts’ (pos 4) not found
¡Hola! He puesto un pequeño anexo al final del tutorial con la solución a este problema.
Hola! Excelente tu blog. Queria hacer una consulta, a ver si me puedes orientar. Queria hacer un proyecto donde identificar en una tapa plastica cuadrada de una caja, el logo de una marca. El problema con el que me encuentro es que, el logo esta en sobrerrelieve, por lo tanto no tengo practicamente diferencia de color entre el fondo de la tapa y el logo. la finalidad del proyecto es detectar la orientacion del logo, si esta mal orientado descartar la tapa. Que metodo se te ocurre que podria utilizar?
Desde ya te agradezco tu tiempo.
Saludos
¡Hola, Diego! Lo que puedes hacer es aumentar el contraste de la imagen para intentar que el logo resalte más, seguido de una detección de contornos y finalmente aplicas Feature matching (https://docs.opencv.org/3.3.0/dc/dc3/tutorial_py_matcher.html) para encontrar el logo en la tapa. A partir de aquí debería serte sencillo encontrar su orientación.
¡Un saludo!
que tal, a que se debe el error en la linea 53 no me reconoce el “for”, me dice:
for i in punto elegido:
(no reconoce el for)
identation error: unexpected error
por cierto, que rola mas… medieval, me hizo recordar muchas peliculas… 🙂
¡Hola, Serato! Este problema se debe a que el for no está bien indentado. Tienes que asegurarte de que esté bien tabulado en relación al resto de líneas de código que están dentro del bucle while principal.
¡Un saludo! 🙂
Quisiera detectar solo el objeto que este en el centro de la camara , se podría hacer algo asi?
¡Hola Enzo! Tienes que guardar las coordenadas X,Y de todos los objetos de la escena, y quedarte únicamente con las del objeto que esté más cercano al centro (o descartarlas todas si están muy alejadas del centro).
Hola, estoy realizando un programa para detectar patrones específicos en una imagen pero hasta ahora no e encontrado nada parecido, (Solo e encontrado detección de esquinas y coincidencias en 2 imágenes). Mi pregunta es que método de investigación debo ocupar en opencv para lograr dicho programa?
¡Hola Manuel! Si necesitas encontrar patrones, lo mejor que podrías hacer es construir tus propies haarcascades del tipo de objeto/patrón que necesites buscar.
Hola Eduardo quisiera saber si es posible seguir la punta de un lápiz, y luego poder generar o determinar la dirección del trazo realizado. Tal vez podrías guiarme un poco. Gracias
Saludos… navegando encontré este blog.. .muy bueno.
Estoy empezando con esto de OpenCv y Python…. Es posible con este método de Lucas Kanade, lograr hacer reconocimiento de un espacio de aparcamiento… es decir … quiero por medio de una camara (webcam) que desde arriba apunte a un patio que tiene 30 espacio de para aparcar vehiculos y reconocer estos 30 espacios y avisar cuales estan disponibles o cuales no….
Es posible utilizar este método o existe otro mejor para estas condiciones?
Agradezco su aporte
¡Hola, Enrique! ¿Qué tal?
Pues no, el método de Lucas Kanade sólo sirve para hacer seguimiento de puntos, no tiene nada que ver con lo que necesitas.
Es un proyecto un poco ambicioso si acabas de empezar, pero podrías mirarte un poco como funcionan las HaarCascades (http://docs.opencv.org/trunk/d7/d8b/tutorial_py_face_detection.html) y como entrenarlas para reconocer otros objetos como coches (https://pythonprogramming.net/haar-cascade-object-detection-python-opencv-tutorial/)
¡Un saludo!
Buenas amigo, estoy realizando un proyecto bastante similar!!! lograste terminarlo?
me podria ayudar? le agradeceria muchisimo si logramos ponernos en contacto!
A qué se debe el siguiente error?
File “C:UsersGabrielDesktopseg.py”, line 30, in
contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
ValueError: too many values to unpack
Al parecer se corrige colocando _, antes de contours, aunque después aparece line 31, in
mayor_contorno = max(contours, key = cv2.contourArea)
ValueError: max() arg is an empty sequence