def getBoardGrid(boardSize, cnts): # initialize the reverse flag and sort index reverse = False # sorting against the y-coordinate i = 1 # construct the list of bounding boxes and sort them from top to # bottom boundingBoxes = [getRect(c) for c in cnts] # calculating the first square (the closest to (0,0) which is the upper left square) (cnts, boundingBoxes) = zip( *sorted(zip(cnts, boundingBoxes), key=lambda b: calcDistance((0, 0), (b[1][0], b[1][1])), reverse=reverse)) leftCellInLine = (cnts[0], boundingBoxes[0]) gridCells = [] for line in range(1, boardSize + 1): lineCells = [] lineCells.append(leftCellInLine) currCell = leftCellInLine for column in range(2, boardSize + 1): # current cell center (cX, cY) = getContourCenter(currCell[0]) cellWidth = currCell[1][2] nextCellPoint = (cX + cellWidth, cY) nextCell = findContourAndRectOfPoint(nextCellPoint, zip(cnts, boundingBoxes)) if nextCell == None: #print("can't find the next cell") return None lineCells.append(nextCell) currCell = nextCell gridCells.append(lineCells) # finding next line left cell if (line < boardSize): (cX, cY) = getContourCenter(leftCellInLine[0]) cellHeight = leftCellInLine[1][3] nextCellPoint = (cX, cY + cellHeight) leftCellInLine = findContourAndRectOfPoint( nextCellPoint, zip(cnts, boundingBoxes)) if leftCellInLine == None: #print("can't find the next line left cell") return None return gridCells
def getColorProps(image, contour): #mask = np.zeros(image.shape, np.uint8) #cv2.drawContours(mask, [square], 0, 255, -1) #mean = cv2.mean(squareImage, mask=mask) border = 5 x, y, w, h = getRect(contour) image = image[y + border:y + h - border, x + border:x + w - border] average_color_per_row = np.average(image, axis=0) avg = np.average(average_color_per_row, axis=0) min_per_row = np.amin(image, axis=0) min = np.amin(min_per_row, axis=0) max_per_row = np.amax(image, axis=0) max = np.amax(max_per_row, axis=0) return (min, max, avg)
def handleSquareCells(origCropedImage, squares, triangles): blockedCells, regularCells = [], [] image = convertToGray(origCropedImage.copy()) if (False): stam = convertToColor(image.copy()) stam = cv2.drawContours(stam, squares, -1, (255, 0, 0), 3) show(stam) # excluding all lines and other contours which are not cell square nativeSquares = list( filter(lambda x: not containedByOtherContour(x, squares), squares)) # getting all squares which doesn't contain triangles nativeSquares = list( filter(lambda x: not containsAnyContour(x, triangles), nativeSquares)) if (False): stam = convertToColor(image.copy()) stam = cv2.drawContours(stam, nativeSquares, -1, (255, 0, 0), 3) show(stam) # getting all square contours nativeSquares = list( filter( lambda x: not checkIfFarBiggerThanAreaSize( image.shape[0] * image.shape[1], x), nativeSquares)) ret, thresh = cv2.threshold(image, 170, 255, cv2.THRESH_BINARY) border = 5 for square in nativeSquares: if (False): stam = convertToColor(image.copy()) stam = cv2.drawContours(stam, [square], -1, (255, 0, 0), 3) show(stam) x, y, w, h = getRect(square) cell = thresh[y + border:y + h - border, x + border:x + w - border] if percentageOfWhitePixels(cell) > 30: regularCells.append(square) else: blockedCells.append(square) return blockedCells, regularCells
def crop(image): contours = getAllSquares(getAllContours(image.copy())) contour = max(contours, key=cv2.contourArea) board = cut_out_sudoku_puzzle(image.copy(), contour) rect = getRect(contour) return board, rect
def handleTriangleImage(origCroped, image, contour, minX, minY, alon): origGray = convertToGray(origCroped) if (True): # since we draw a square outside the triangle, we need to look for it's inner contours kernel = np.ones((3, 3), np.uint8) #image = cv2.erode(image, kernel, iterations=3) #image = cv2.GaussianBlur(image, (3, 3), 0) #show(image) stam = thresholdify(convertToGray(origCroped)) stam = cv2.GaussianBlur(stam, (3, 3), 0) if (alon[0] == 2 and alon[1] == 0): a = 5 #show(stam) digitContours = getAllContours(stam) # excluding all lines and other contours which are not cell square digitContours = list( filter(lambda x: not containedByOtherContour(x, digitContours), digitContours)) digits = [] for digitContour in digitContours: (x, y, w, h) = rect = getRect(digitContour) digitHeightInPercent, digitWidthInPercent = h / image.shape[ 0], w / image.shape[1] # not the crossing line of the triangle if ((digitWidthInPercent > 0.10 and digitWidthInPercent < 0.4) and (digitHeightInPercent > 0.10 and digitHeightInPercent < 0.7) and (x > 5 and y > 5)): # todo: debug if (alon[0] == 2 and alon[1] == 0): stam1 = convertToColor(stam) cv2.drawContours(stam1, [digitContour], -1, (255, 0, 0), 5) #show(stam1) digitCenter = getContourCenter(digitContour) # since we croped, we want to test the original image X,Y of the contour origDigitCenter = (digitCenter[0] + minX, digitCenter[1] + minY) # TODO: delete these 4 lines # cv2.drawContours(croped, [digitContour], -1, (0, 0, 0), 5) # show(croped) if (isPointInContour(origDigitCenter, contour)): global alonW global alonH alonW.append(digitWidthInPercent) alonH.append(digitHeightInPercent) digits.append({'contour': digitContour, 'rect': rect}) # sorting the digits from the left to the right (x axis) digits = sorted(digits, key=lambda x: x['rect'][0]) # todo: delete imageRect references #(imageX, imageY, w, h) = imageRect safeBorder = 3 digitsWithBorder = [] for digit in digits: (x, y, w, h) = digit['rect'] digitImage = image[y - safeBorder:y + h + safeBorder, x - safeBorder:x + w + safeBorder] if (False): p = cv2.GaussianBlur(digitImage, (7, 7), 0) thresh = cv2.adaptiveThreshold(p.astype(np.uint8), 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 10) # 3 #TODO: was 11,10 or 11,7 or 5,2 #show(digitImage) #p = putDigitInCenter(digitImage) #show(p) #value = getDigitsFromMNIST([p]) #show(p, str(value[0])) # show(digitImage) # since we croped the digit from the croped image (minY) # since we croped the board from the original image (imageY). same goes for X # digitImage = origImage[y + minY + imageY - safeBorder: y + h + minY + imageY + safeBorder, # x + minX + imageX - safeBorder: x + w + minX + imageX + safeBorder] # show(255 - digitImage) # digitImage = convertToGray(255 - digitImage) digitImage = putDigitInCenter(digitImage) digitImage = cv2.resize(digitImage, (sizeToMNIST, sizeToMNIST)) #show(digitImage) #thresh = cv2.adaptiveThreshold(digitImage.astype(np.uint8), 255, cv2.ADAPTIVE_THRESH_MEAN_C, #cv2.THRESH_BINARY, 3, 10) #digitImage = cv2.GaussianBlur(digitImage, (7, 7), 0) #digitImage = cv2.blur(digitImage, (3, 3)) digitImage = cv2.bilateralFilter(digitImage, 17, 75, 75) #show(digitImage) #show (thresh) #show(digitImage) digitsWithBorder.append(digitImage) if (len(digitsWithBorder) == 0): return {'hasValue': True, 'data': None} else: return {'hasValue': False, 'data': digitsWithBorder}