Извлечение ящиков из судоку в opencv

Я преобразовал изображение судоку в сетку судоку с помощью opencv

теперь я хочу извлечь каждую коробку из изображения, как лучше всего это сделать?

согласно моим знаниям, я пытаюсь найти точки пересечения линий, чтобы найти угол каждого поля

class SudokuSolverPlay:
      def __init__(self, image):
         
      def __preProcess(self, img):
        """return grayscale image"""
      def __maskSudoku(self, img):
        """return masked image"""
      def __dectactEdge(self, img):
        """return sudoku grid"""
        def drawLines(src, dest, iteration=1):
            minLineLength = 100
            src = cv2.convertScaleAbs(src)
            for _ in range(iteration):
                lines = cv2.HoughLinesP(image=src, rho=1, theta=np.pi / 180,
                                    threshold=100, lines=np.array([]),
                                    minLineLength=minLineLength, maxLineGap=100)
                a, b, c = lines.shape
                for i in range(a):
                    x1, y1, x2, y2 = lines[i][0][0], lines[i][0][1], lines[i][0][2], lines[i][0][3]
                    cv2.line(dest, (x1, y1), (x2, y2),255, 1, cv2.LINE_AA)
                src = cv2.convertScaleAbs(dest)

        def findVerticalLines(img):
            imgX = cv2.GaussianBlur(img, (5, 5), 0)
            kernelx = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 10))
            imgY = cv2.Sobel(img, cv2.CV_64F, 1, 0)
            imgY = cv2.convertScaleAbs(imgY)
            cv2.normalize(imgY, imgY, 0, 255, cv2.NORM_MINMAX)
            imgY = cv2.morphologyEx(imgY, cv2.MORPH_CLOSE, kernelx, iterations=1)
            return imgY

        def findHorizontalLines(img):
            """same as above only args different"""

        img1 = np.zeros(img.shape)

        edges = cv2.Canny(img, 50, 150, apertureSize=3)
        laplacian = cv2.Laplacian(edges, cv2.CV_64F)
        drawLines(laplacian, img1, iteration=1)

        sby = findVerticalLines(img1)
        sbx = findHorizontalLines(img1)
        return img1
      def solveSudoku(self):
          gray = self.__preProcess(self.__originalImg)
          masked = self.__maskSudoku(gray)
          grid = self.__dectactGrid(masked)
                   

if __name__ == '__main__':
    colorImg = cv2.imread('sudoku1.jpg')
    solver = SudokuSolverPlay(colorImg)
    solver.solveSudoku()

здесь findVerticalLines() и findHorizontalLines() не могут правильно определять горизонтальные и вертикальные линии


person Janak Vaghasiya    schedule 14.01.2021    source источник
comment
Отвечает ли это на ваш вопрос? Как получить ячейки сетки судоку с помощью OpenCV?   -  person T A    schedule 15.01.2021
comment
да, у него та же цель, извините за ответ, нет, вы можете закрыть вопрос   -  person Janak Vaghasiya    schedule 15.01.2021


Ответы (1)


Один из способов решения - выполнить морфологическую операцию, чтобы найти вертикальные и горизонтальные линии на изображении четких краев, а затем выполнить анализ связанных компонентов, чтобы найти блоки. Я сделал образец версии ниже. Вы можете настроить его дальше, чтобы сделать его лучше. Я начал с замаскированного изображения в качестве ввода.

### reading input image
gray_scale=cv2.imread('masked_image.jpg',0)

Выполнение точного обнаружения краев и добавление слоя расширения

img_bin = cv2.Canny(gray_scale,50,110)
dil_kernel = np.ones((3,3), np.uint8)
img_bin=cv2.dilate(img_bin,dil_kernel,iterations=1)

Теперь расширенное двоичное изображение выглядит так. двоичное изображение после точного определения края

при условии, что минимальный размер коробки будет 20 * 20

line_min_width = 20

поиск горизонтальных линий

kernal_h = np.ones((1,line_min_width), np.uint8)
img_bin_h = cv2.morphologyEx(img_bin, cv2.MORPH_OPEN, kernal_h)

горизонтальные линии

поиск вертикальных линий

kernal_v = np.ones((line_min_width,1), np.uint8)
img_bin_v = cv2.morphologyEx(img_bin, cv2.MORPH_OPEN, kernal_v)

вертикальные линии

слияние и добавление слоя расширения, чтобы закрыть небольшие зазоры

img_bin_final=img_bin_h|img_bin_v
final_kernel = np.ones((3,3), np.uint8)
img_bin_final=cv2.dilate(img_bin_final,final_kernel,iterations=1)

объединенные блоки

применение анализа связанных компонентов

ret, labels, stats,centroids = cv2.connectedComponentsWithStats(~img_bin_final, connectivity=8, ltype=cv2.CV_32S)

визуализация изображения подключенного компонента

копия изображения

Как вы можете видеть, мы обнаружили некоторый текст также в виде полей, мы можем легко удалить их с помощью простых условий фильтрации. Здесь я выполняю фильтрацию с областью, которая должна быть минимум 1000 пикселей.

рисование прямоугольников на обнаруженных боксах.

### 1 and 0 and the background and residue connected components whihc we do not require
for x,y,w,h,area in stats[2:]:
#     cv2.putText(image,'box',(x-10,y-10),cv2.FONT_HERSHEY_SIMPLEX, 1.0,(0,255,0), 2)
    if area>1000:
        cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2)

окончательное выходное изображение

выходное изображение

Этот ответ основан на моем решении найти флажки / таблицы на изображении с использованием OpenCV. Вы можете найти подробное объяснение в моем блоге по адресу К науке о данных. Надеюсь, это приблизит вас к решению.

Удачного кодирования :)

- редактировать 1

код для визуализации связанных компонентов

def imshow_components(labels):
    ### creating a hsv image, with a unique hue value for each label
    label_hue = np.uint8(179*labels/np.max(labels))
    ### making saturation and volume to be 255
    empty_channel = 255*np.ones_like(label_hue)
    labeled_img = cv2.merge([label_hue, empty_channel, empty_channel])
    ### converting the hsv image to BGR image
    labeled_img = cv2.cvtColor(labeled_img, cv2.COLOR_HSV2BGR)
    labeled_img[label_hue==0] = 0
    ### returning the color image for visualising Connected Componenets
    return labeled_img
person Sreekiran    schedule 15.01.2021
comment
спасибо за краткий ответ, все работает! , я хочу спросить вас, можем ли мы принять разумное решение, например, когда применять эрозию, расширение или различные типы размытия в зависимости от изображения? - person Janak Vaghasiya; 15.01.2021
comment
как нарисовать изображение, как вы нарисовали в visualising Connected component image - person Janak Vaghasiya; 15.01.2021
comment
@JanakVaghasiya Добавлен код для визуализации связанных компонентов. Вы можете начать с изучения всех концепций обработки изображений. Затем, постепенно, после решения некоторых проблем с помощью этих методов, вы сможете самостоятельно принимать эти разумные решения. Это приходит с практикой. Продолжай учиться. Рад помочь. Пожалуйста, примите и ответ. :) - person Sreekiran; 15.01.2021