Spaces:
Sleeping
Sleeping
File size: 6,519 Bytes
1a5455d 2b4a005 1a5455d 0f53078 1a5455d 484d173 b75b567 1b4dd95 cfd19ee ac11265 747ff01 d6f1324 cfd19ee b7b5aa9 cfd19ee b7b5aa9 cfd19ee b7b5aa9 cfd19ee b7b5aa9 cfd19ee b7b5aa9 cfd19ee 87b01f5 cfd19ee 87b01f5 cfd19ee 87b01f5 cfd19ee 87b01f5 cfd19ee 87b01f5 cfd19ee 87b01f5 4360d4c cfd19ee 2b4a005 1a5455d 2b4a005 1a5455d 2b4a005 05bfa3c 8a83802 ac11265 05bfa3c ac11265 747ff01 2b4a005 b7b5aa9 2b4a005 b7b5aa9 2b4a005 b7b5aa9 2b4a005 ac11265 11355bf 1a5455d 2b4a005 1a5455d 2b4a005 b7b5aa9 2b4a005 6ba792b 143b687 6ba792b 8a83802 81a35ba 2b4a005 81a35ba |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
import streamlit as st
import cv2
from tensorflow.keras.models import load_model
from PIL import Image
import numpy as np
model = load_model('sudoku_net.h5')
def preprocess(image):
if len(image.shape) == 2:
gray = image # No need to convert, it's already grayscale
else:
# Convert RGB image to grayscale using OpenCV
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
# blur = cv2.GaussianBlur(gray, (3,3),6)
blur = cv2.bilateralFilter(gray,6,3,3)
threshold_img = cv2.adaptiveThreshold(blur,255,1,1,11,2)
return threshold_img
def main_outline(contour):
biggest = np.array([])
max_area = 0
for i in contour:
area = cv2.contourArea(i)
if area >50:
peri = cv2.arcLength(i, True)
approx = cv2.approxPolyDP(i , 0.02* peri, True)
if area > max_area and len(approx) ==4:
biggest = approx
max_area = area
return biggest ,max_area
def reframe(points):
points = points.reshape((4, 2))
points_new = np.zeros((4,1,2),dtype = np.int32)
add = points.sum(1)
points_new[0] = points[np.argmin(add)]
points_new[3] = points[np.argmax(add)]
diff = np.diff(points, axis =1)
points_new[1] = points[np.argmin(diff)]
points_new[2] = points[np.argmax(diff)]
return points_new
def splitcells(img):
rows = np.vsplit(img,9)
boxes = []
for r in rows:
cols = np.hsplit(r,9)
for box in cols:
boxes.append(box)
return boxes
def CropCell(cells):
Cells_croped = []
for image in cells:
img = np.array(image)
img = img[4:46, 6:46]
img = Image.fromarray(img)
Cells_croped.append(img)
return Cells_croped
def read_cells(cell,model):
result = []
for image in cell:
# preprocess the image as it was in the model
img = np.asarray(image)
img = img[4:img.shape[0] - 4, 4:img.shape[1] -4]
img = cv2.resize(img, (32, 32))
img = img / 255
img = img.reshape(1, 32, 32, 1)
# getting predictions and setting the values if probabilities are above 65%
predictions = model.predict(img)
classIndex = np.argmax(predictions, axis=1)
probabilityValue = np.amax(predictions)
if probabilityValue > 0.65:
result.append(classIndex[0])
else:
result.append(0)
return result
#This function finds the next box to solve
def find_empty(board):
for i in range(len(board)):
for j in range(len(board)):
if board[i][j] == 0:
return i,j
return None
#Function to fill in the possible values by evaluating rows collumns and smaller cells
def valid(board, num, pos):
# check row
for i in range(len(board)):
if board[pos[0]][i]==num and pos[1]!=i:
return False
# check column
for i in range(len(board)):
if board[i][pos[1]]==num and pos[0]!=i:
return False
# check 3X3 cube
box_x=pos[0]//3
box_y=pos[1]//3
for i in range(box_x*3,box_x+3):
for j in range(box_y*3,box_y+3):
if board[i][j]==num and [i,j]!=pos:
return False
return True
#function to loop over untill a valid answer is found.
def solve(board):
find=find_empty(board)
if not find:
return True
else:
row,col=find
for i in range(1,10):
if valid(board,i,[row,col]):
board[row][col]=i
if solve(board):
return True
board[row][col]=0
return False
def display(quiz):
for row in range(9):
if row % 3 == 0 and row != 0:
print("....................")
for col in range(9):
if col % 3 == 0 and col != 0:
print("|", end=" ")
if col == 8:
print(quiz[row][col])
else:
print(str(quiz[row][col]) + " ", end="")
def main():
st.title('Sudoku Solver')
uploaded_file = st.file_uploader("Upload an image", type=["jpg", "jpeg", "png"])
if uploaded_file is not None:
col1, col2 = st.columns(2)
col1.subheader("Sudoku Puzzle:")
# puzzle = cv2.imread(uploaded_file)
puzzle = Image.open(uploaded_file)
col1.image(puzzle, use_column_width=True)
puzzle = np.asarray(puzzle)
# Resizing puzzle to be solved
puzzle = cv2.resize(puzzle, (450,450))
# Preprocessing Puzzle
su_puzzle = preprocess(puzzle)
# Finding the outline of the sudoku puzzle in the image
su_contour_1= su_puzzle.copy()
su_contour_2= puzzle.copy()
su_contour, hierarchy = cv2.findContours(su_puzzle,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(su_contour_1, su_contour,-1,(0,255,0),3)
black_img = np.zeros((450,450,3), np.uint8)
su_biggest, su_maxArea = main_outline(su_contour)
if su_biggest.size != 0:
su_biggest = reframe(su_biggest)
cv2.drawContours(su_contour_2,su_biggest,-1, (0,255,0),10)
su_pts1 = np.float32(su_biggest)
su_pts2 = np.float32([[0,0],[450,0],[0,450],[450,450]])
su_matrix = cv2.getPerspectiveTransform(su_pts1,su_pts2)
su_imagewrap = cv2.warpPerspective(puzzle,su_matrix,(450,450))
# su_imagewrap =cv2.cvtColor(su_imagewrap, cv2.COLOR_BGR2GRAY)
if len(su_imagewrap.shape) == 2:
su_imagewrap = su_imagewrap # No need to convert, it's already grayscale
else:
# Convert RGB image to grayscale using OpenCV
su_imagewrap = cv2.cvtColor(su_imagewrap, cv2.COLOR_RGB2GRAY)
_, su_imagewrap = cv2.threshold(su_imagewrap, 127, 255, cv2.THRESH_BINARY)
sudoku_cell = splitcells(su_imagewrap)
sudoku_cell_croped= CropCell(sudoku_cell)
grid = read_cells(sudoku_cell_croped, model)
grid = np.asarray(grid)
grid = np.reshape(grid,(9,9))
solve(grid)
# Display the solution or appropriate message
if solve(grid):
col2.subheader("Sudoku Solved:")
col2.table(grid)
else:
st.write("No Solution Found.")
if __name__ == '__main__':
main() |