Flask에서 난프레 해독 앱을 만들어 보았다.

소개



난프레의 문제 이미지를 읽으면 해독하여 문제를 풀어주는 앱을 만들어 보았습니다.
  • 문제 이미지를 업로드하면 1칸마다 숫자를 OCR한 결과가 화면 표시된다.
  • OCR한 난프레 문제를 1칸씩 손 입력으로 보정할 수 있다.
  • 난프레 문제의 해답을 취득해 화면 표시할 수 있다.

  • 개발 환경(일부)


  • Python : 3.7.6
  • Flask : 1.1.1
  • Flask-Cors : 3.0.8
  • Keras : 2.3.1
  • tensorflow : 1.13.1
  • opencv-python : 4.1.2.30

  • Nampre 이미지의 숫자 영역 추출



    난프레 문제의 1칸마다 수치 영역의 화상 취득은 OpenCV를 이용했습니다.

    우선, 사각형의 영역 취득 화상을 그레이 스케일 해, 2치화합니다.
    img_bgr = cv2.imread(image_path)
    img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)
    
    # 二値化
    _, img_2chi = cv2.threshold(img_gray, 200, 255, cv2.THRESH_BINARY)
    
    # 数独表の抽出
    t_x, t_y, t_w, t_h, img_bgr, img_2chi = get_rect_sudoku(img_bgr, img_2chi, image_path)
    

    그런 다음 난프 문제의 정사각형 영역을 감지합니다.
    def get_rect_sudoku(image_bgr, image_2chi, target_path):
        image_bgr = cv2.copyMakeBorder(image_bgr, 10, 10, 10, 10, cv2.BORDER_CONSTANT, value=255)
        image_2chi = cv2.copyMakeBorder(image_2chi, 10, 10, 10, 10, cv2.BORDER_CONSTANT, value=255)
    
        contours, hierarchy = cv2.findContours(image_2chi, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
        area_list = list(map(lambda x: cv2.contourArea(x), contours))
        target_index = np.array(area_list).argsort()[::-1][1]  # 面積が2番目に大きい矩形のindex
        target_cnt = contours[target_index]
        x, y, w, h = 0, 0, 0, 0
    
        if target_cnt is not None:
            x, y, w, h = cv2.boundingRect(target_cnt)
    
        return x, y, w, h, image_bgr, image_2chi
    

    나중에 사각형 영역을 9 × 9 등분하여 난프레 문제의 매스마다 이미지를 얻습니다.

    숫자 판정



    필기 숫자 인식으로 유명한 MNIST에서 학습한 모델을 이용하여 숫자 화상의 판정을 실시했습니다.
    CNN의 아키텍처는 기억나지 않지만 어디서나 데려온 것입니다.
    model.add(Conv2D(32, (3, 3), padding="same", input_shape=(28, 28, 1)))
    model.add(Activation("relu"))
    model.add(Conv2D(32, (3, 3), padding="same"))
    model.add(Activation("relu"))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.5))
    model.add(Conv2D(64, (3, 3), padding="same"))
    model.add(Activation("relu"))
    model.add(Conv2D(64, (3, 3), padding="same"))
    model.add(Activation("relu"))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.5))
    model.add(Conv2D(128, (3, 3), padding="same"))
    model.add(Activation("relu"))
    model.add(Conv2D(128, (3, 3), padding="same"))
    model.add(Activation("relu"))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.5))
    model.add(Flatten())
    model.add(Dense(100))
    model.add(Activation("relu"))
    model.add(Dropout(0.5))
    model.add(Dense(10))
    model.add(Activation('softmax'))
    
    model.compile(loss=categorical_crossentropy,
                  optimizer='Adam',
                  metrics=['accuracy'])
    

    난프레 문제의 해답 취득



    난프레 문제를 푸는 로직도 스스로 만드는 것은 힘들기 때문에 다음을 사용하셨습니다.
    고래 비행 책상 Python으로 난프를 풀어 보자.

    이하의 생각에 근거하고 있는 것 같습니다.
  • 왼쪽 위에서 오른쪽 아래로 순서대로 빈 매스를 조사해 간다
  • 빈 매스가 있으면 그 시점에서 배치 가능한 숫자를 확인하십시오.
  • 배치 가능한 숫자를 임시로 배치해, 다음 매스를 조사해 간다
  • 배치가 작동하지 않으면 (3)으로 돌아갑니다
  • 마지막 매스에 도달 할 때까지 (2) 이후의 처리를 반복한다
  • 마지막에 도달하면 결과를 출력합니다

  • 화면 이미지



    왼쪽이 업로드한 난프레 문제 이미지로 오른쪽이 1칸마다 숫자 판정한 결과입니다.
    저기 바르게, 거기에 실패합니다.



    소스 코드



    소스 코드는 여기에 있습니다.
    htps : // 기주 b. 코 m / 타케 9999 / 스도쿠 _ 오 cr

    이하를 참고로 했습니다.



    프론트 부분은 거의 둥글게 사용하고 있습니다.
    htps : // 코 m / 카즈야 _ 얼룩 / / ms / f5 에 f5 훗 d850b8b9 에 7 아 81

    Flask 이미지 업로드 부분
    htps : // 코 m / 케이 모리 야마 / ms / 7c935c91 95d857714fb

    좋은 웹페이지 즐겨찾기