Ball tracking (Detección de balones opencv – python)

Standard

Detección de balones con opencv

Introducción

A continuación se muestra el primer programa para la detección de balones (ball tracking), cabe decir que esta versión presenta dos problemas principales, la primera es que falla en ocasiones cuando el ambiente no es controlado es decir que exista demasiada luz solar y la segunda es que el delay después de tiempo se incrementa considerablemente.

De las principales características de esta versión es que no es necesario un color o un tamaño en específico para el balón.

 Código en github (versión 1.4).

Desarrollo

En la primera parte del código importamos las librerías que necesitamos, también se puede observar que existe una variable llamada maxCirculos que se encarga de restringir el número de círculos que se muestren. Muy probablemente en un balón se encuentren más de 13 círculos para evitar tanto procesamiento podemos decir que solo se muestren seis, tres o dos círculos únicamente para comprobar coordenadas.

#Version 1.4
#CODIGO
#TUXTEAM
import cv2
import numpy as np

maxCirculos=6
maxCirculos=maxCirculos-1
video = cv2.VideoCapture(0)

Grabamos los frames en la variable ret, frame, en seguida se aplica una escala de grises a la imagen que estamos grabando y con  cv2.imshow(“Original”, framegrey1) mostramos lo que esta viendo la cámara en escala de grises.

Después se aplica un núcleo gaussiano se debe especificar el ancho y la altura del kernel que debe ser positivo e impar. También se debe especificar la desviación estándar en dirección X e Y, sigmaX y sigmaY respectivamente. Este método es muy eficaz en la eliminación de ruido de la imagen.

while True:
 ret, frame = video.read()
 framegrey1 = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
 cv2.imshow("Original", framegrey1)
 gray = cv2.GaussianBlur(framegrey1, (1,1), 2)

El resultado de aplicar este método es el que se muestra en la siguiente imagen:

La función cv2.medianBlur toma la mediana de todos los pixeles bajo el área del kernel y el elemento central se sustituye por este valor mediano. Esto es muy eficaz contra el ruido en las imágenes.
Lo interesante es que el elemento central es un valor recién calculado que puede ser un valor de píxel en la imagen o un nuevo valor. Pero en el desenfoque mediano, el elemento central siempre es reemplazado por algún valor de píxel en la imagen. Al final se puede observar que también reduce el ruido de manera efectiva.

gray = cv2.medianBlur(gray,5)

La función adaptiveThreshold transforma la imagen en escala de grises a una imagen binaria, es quizás el método más importante que se realiza ya que se dibujan solo los contornos de la figura que esta viendo la cámara.

gray = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
 cv2.THRESH_BINARY,19,3)

Finalmente para mejorar un poco esta salida se ocupan los métodos “erosion” que quita la estructura de pixeles de la capa mas externa y “dilation” que agrega pixeles a la estructura de la capa más externa, para estas funciones es necesario tener un kernel. Si se cambia el número de iteraciones mayor va hacer el efecto del método.

kernel = np.ones((3,3),np.uint8)
gray = cv2.erode(gray,kernel,iterations = 1) 
gray = cv2.dilate(gray,kernel,iterations = 1)

Finalmente se detectan los círculos con el método HoughCircles, y en seguida con un for se recorren los círculos encontrados y se dibuja un círculo sobre ellos, aquí es donde entra en juego la cantidad de círculos que queremos mostrar.

Cabe decir que para aumentar o disminuir la tolerancia para detectar círculos se deben cambiar los valores de los parámetros del método HoughCircles, para obtener más información se puede acceder a la siguiente página: “PyImageSearch” que en mi parecer es el mejor blog sobre contenido de opencv.

circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 2, 10, np.array([]), 40, 80, 5, 100)
circulos=0
if circles is not None:
  for c in circles[0]:
     cv2.circle(frame, (c[0],c[1]), c[2], (0,255,0),2)
     circulos=circulos+1
     print "Coordenada X: " + str(c[0])
     print "Coordenada Y: " + str(c[1])
     if(circulos>maxCirculos):
        break
 else:
 print("NO SE DETECTA EL BALON");

Por último se muestran las salidas, la imagen con filtros y donde se muestran los círculos que se están detectando.

cv2.imshow("video", frame)
cv2.imshow("filtros", gray)
key = cv2.waitKey(1)

El código explicado  es la versión 1.4 y se encuentra en github, con dos opciones:

 

Comments

comments

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *