Continuamos con el proyecto y ahora intentamos mejorar la detección de las fichas en el tablero. Este proceso es difícil y además depende de las condiciones de luz que haya en el ambiente. Básicamente consiste en detectar pixeles de color de las fichas y cuando veamos que hay una ficha nueva, colocarla en el tablero de juego. El problema es que el color no es único y el rango se amplía con la variación de la luz.
El programa que usamos consiste en mirar el color de la imagen en determinados pixeles y algunos a su alrededor. Cuando estos puntos tengan el color esperado, dentro de un margen aceptable, se toma como ficha correcta. El problema es que no conseguimos ajustar bien los puntos y los colores para distintas partidas.
Afortunadamente hemos encontrado unos tutoriales que nos han ayudado mucho para facilitar esta tarea, que recomendamos a cualquiera que quiera aprender a hacer visión por ordenador. El enlace es el siguiente:
https://www.computervision.zone/
Nos fijamos en el tutorial para filtrar imágenes por máscara HSV y lo aplicamos a nuestro tablero. Lo primero es seleccionar los valores correctos de H, S y V, que hacemos con el programa de ejemplo con deslizadores interactivos, que ajustamos hasta que sólo se vean las fichas rojas:
Después hacemos un pequeño programa de ejemplo para probar el código con el tablero sólo y la detección de las fichas:
El código es el siguiente:
############################ PRUEBA
# Prueba de vídeo con detección de fichas
# Convierte la imagen a HSV y aplica una máscara para detectar las fichas rojas
# Detecta los contornos y señala la posición de las fichas
import cv2
import numpy as np
def getContours(img):
print('----')
contours,hierarchy = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
for cnt in contours:
area = cv2.contourArea(cnt)
print(area)
if area>400:
# cv2.drawContours(imgContour, cnt, -1, (255, 0, 0), 3)
peri = cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,0.02*peri,True)
objCor = len(approx)
x, y, w, h = cv2.boundingRect(approx)
cv2.rectangle(imgContour,(x,y),(x+w,y+h),(0,255,0),2)
################################################################
frameWidth = 320
frameHeight = 240
cap = cv2.VideoCapture(1)
cap.set(3, frameWidth)
cap.set(4, frameHeight)
while True:
success, img = cap.read()
imgContour = img.copy()
imgHsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# Valores HSV para la cámara y fichas rojas
h_min=4
h_max=16
s_min=166
s_max=250
v_min=121
v_max=255
lower = np.array([h_min, s_min, v_min])
upper = np.array([h_max, s_max, v_max])
mask = cv2.inRange(imgHsv, lower, upper)
result = cv2.bitwise_and(img, img, mask=mask)
imgGray = cv2.cvtColor(result,cv2.COLOR_BGR2GRAY)
imgBlur = cv2.GaussianBlur(imgGray,(7,7),1)
imgCanny = cv2.Canny(imgBlur,50,50)
getContours(imgCanny)
mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
cv2.imshow('IMG', imgContour)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
El resultado funciona bien. Ahora queda integrarlo en el programa de juego.
Deja una respuesta