Sudoku Solver (Part 1)

Anmol Dua
Anmol Dua
Mar 23 · 7 min read
Camera photo of sudoku

Step1: Read the image using opencv. Here original.jpg refers to my camera photo.

frame = cv2.imread('original.jpg')

Step2: Convert this image into grayscale image.

gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imwrite('gray' , gray)
grayscale image

Step3: Use Adaptive Thresholding

def AdaptiveThresholding(gray):
gray=cv2.adaptiveThreshold(gray,200,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,11,3)
return gray
Adaptive Threshold

Step4 : Opening Operation

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))gray = cv2.morphologyEx(gray, cv2.MORPH_OPEN, kernel)cv2.imwrite('morph.jpg',gray)
After Opening Operation

Step5 : Getting Sudoku

contours,h=cv2.findContours(gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
contour = max(contours, key=cv2.contourArea)
x, y, w, h = cv2.boundingRect(contour)sudoku = gray[y:y + h, x:x + w]side_length = min(sudoku.shape)sudoku = cv2.resize(sudoku, (side_length, side_length))cv2.imwrite('sudoku.jpg' , sudoku)
Getting Sudoku from Image

Step6: Making Sudoku Straight

contours, h = cv2.findContours(sudoku, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key=cv2.contourArea, reverse=True)
largest = None
for cnt in contours[:min(5,len(contours))]:
print ("Length of approx(cnt) : " + str(len(approx(cnt))) )
if (len(approx(cnt)) == 4)
print ("Condition becomes True")
largest = cnt
def approx(cnt):
peri = cv2.arcLength(cnt, True)
app = cv2.approxPolyDP(cnt, 0.01 * peri, True)
return app
def order_points(pts):
pts = pts.reshape(4, 2)
rect = np.zeros((4, 2), dtype = "float32")
s = pts.sum(axis = 1)
rect[0] = pts[np.argmin(s)]
rect[2] = pts[np.argmax(s)]
diff = np.diff(pts, axis = 1)
rect[1] = pts[np.argmin(diff)]
rect[3] = pts[np.argmax(diff)]
return rect
def four_points_transform(image,rect):
(tl,tr,br,bl) = rect
widthBottom = np.sqrt(((br[0] - bl[0])**2) + ((br[1] - bl[1]) ** 2))
widthTop = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1])**2))
maxWidth = max(widthBottom , widthTop)
heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
maxHeight = max(int(heightA), int(heightB))
dst = np.array([
[0,0],
[maxWidth - 1,0],
[maxWidth-1 , maxHeight-1],
[0,maxHeight-1]] , dtype = 'float32')
M = cv2.getPerspectiveTransform(rect,dst)
warped=cv2.warpPerspective(image,M,(int(maxWidth),int(maxHeight)))
return warped
if (largest is not None):
app = approx(largest)
print ("App: " + str(len(app)))
corners = order_points(app)
sudoku = four_points_transform(sudoku,corners)
print ("Done Straighten !!")
cv2.imwrite("FinalSudoku.jpg" ,sudoku)
Final Sudoku

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade