Saltar al contenido

¿Cómo obtener las celdas de una cuadrícula de sudoku con OpenCV?

Esta es la contestación más acertada que encomtrarás compartir, sin embargo obsérvala detenidamente y analiza si es compatible a tu proyecto.

Solución:

Aquí hay una posible solución:

  1. Obtener imagen binaria. Convertir imagen a escala de grises y umbral adaptativo

  2. Filtre todos los números y el ruido para aislar solo las cajas. Filtramos usando el área de contorno para eliminar los números ya que solo queremos cada celda individual

  3. Fijar líneas de cuadrícula. Realice un cierre morfológico con un kernel horizontal y vertical para reparar las líneas de la cuadrícula.
  4. Ordene cada celda en orden de arriba a abajo y de izquierda a derecha. Organizamos cada celda en un orden secuencial usando imutils.contours.sort_contours() con el top-to-bottom y left-to-right parámetro

Aquí está la imagen binaria inicial (izquierda) y los números filtrados + líneas de cuadrícula reparadas + imagen invertida (derecha)

Aquí hay una visualización de la iteración de cada celda.

Los números detectados en cada celda.

Código

import cv2
from imutils import contours
import numpy as np

# Load image, grayscale, and adaptive threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,57,5)

# Filter out all numbers and noise to isolate only boxes
cnts = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    if area < 1000:
        cv2.drawContours(thresh, [c], -1, (0,0,0), -1)

# Fix horizontal and vertical lines
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,5))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, vertical_kernel, iterations=9)
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,1))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, horizontal_kernel, iterations=4)

# Sort by top to bottom and each row by left to right
invert = 255 - thresh
cnts = cv2.findContours(invert, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
(cnts, _) = contours.sort_contours(cnts, method="top-to-bottom")

sudoku_rows = []
row = []
for (i, c) in enumerate(cnts, 1):
    area = cv2.contourArea(c)
    if area < 50000:
        row.append(c)
        if i % 9 == 0:  
            (cnts, _) = contours.sort_contours(row, method="left-to-right")
            sudoku_rows.append(cnts)
            row = []

# Iterate through each box
for row in sudoku_rows:
    for c in row:
        mask = np.zeros(image.shape, dtype=np.uint8)
        cv2.drawContours(mask, [c], -1, (255,255,255), -1)
        result = cv2.bitwise_and(image, mask)
        result[mask==0] = 255
        cv2.imshow('result', result)
        cv2.waitKey(175)

cv2.imshow('thresh', thresh)
cv2.imshow('invert', invert)
cv2.waitKey()

Nota: La idea de clasificación se adaptó de una respuesta anterior anterior en la extracción de color del solucionador de cubos de Rubrik.

Tienes la posibilidad difundir este enunciado si si solucionó tu problema.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

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