-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
146 lines (119 loc) · 4.53 KB
/
main.py
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
from cv2 import cv2
import numpy as np
import os
import sys
from inference import *
from sudoku import *
from time import time
import argparse
from default import IM_NAME
parser = argparse.ArgumentParser()
parser.add_argument("-i", "--image",type=str, help="Show a single image")
args = parser.parse_args()
def distance(pt1, pt2):
return np.sqrt((pt1[0][0] - pt2[0][0])**2 + (pt1[0][1] - pt2[0][1])**2)
def preprocessing(im):
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (11, 11), 0)
thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
inv = cv2.bitwise_not(thresh)
return inv
def biggest_grid(canny):
(contours, _) = cv2.findContours(canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
final_contours = []
for c in contours:
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.015 * peri, True)
if len(approx) == 4:
final_contours.append(c)
final_contours.sort(key=lambda e: cv2.contourArea(e), reverse=True)
return final_contours
def prepare_warp(final_contours):
sorted_add = sorted(((pt, pt[0][0] + pt[0][1]) for pt in final_contours[0]), key=lambda e: e[1])
sorted_diff = sorted(((pt, pt[0][0] - pt[0][1]) for pt in final_contours[0]), key=lambda e: e[1])
top_left = sorted_add[0][0]
top_right = sorted_diff[-1][0]
bottom_right = sorted_add[-1][0]
bottom_left = sorted_diff[0][0]
warp_width = int(max(distance(top_left, top_right), distance(bottom_left, bottom_right)))
warp_height = int(max(distance(top_left, bottom_left), distance(top_right, bottom_right)))
warp_uni = max(warp_height, warp_width)
warp_uni = int(warp_uni + 9/2)
warp_uni -= warp_uni % 9
warp_dim = np.array([[0, 0], [warp_uni - 1, 0], [warp_uni - 1, warp_uni - 1], [0, warp_uni - 1]], dtype="float32")
return np.array([top_left, top_right, bottom_right, bottom_left], dtype="float32"), warp_uni, warp_dim
##################################################################
name = ""
if args.image is None:
name = IM_NAME[:-4]
im = cv2.imread(IM_NAME)
else:
name = args.image[:-4]
im = cv2.imread(args.image)
def splitcells(img):
rows = np.vsplit(img, 9)
res = []
for l in rows:
cols = np.hsplit(l, 9)
for b in cols:
res.append(b)
return res
def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA):
dim = None
(h, w) = image.shape[:2]
if width is None and height is None:
return image
if width is None:
r = height / float(h)
dim = (int(w * r), height)
else:
r = width / float(w)
dim = (width, int(h * r))
resized = cv2.resize(image, dim, interpolation = inter)
return resized
model = load()
def treat(im):
inv = preprocessing(im)
canny = cv2.Canny(inv.copy(), 20, 40)
final_contours = biggest_grid(canny)
ordered_pts, warp_size, warp_dim = prepare_warp(final_contours)
grid = cv2.getPerspectiveTransform(ordered_pts, warp_dim)
perspective = cv2.warpPerspective(inv, grid, (warp_size, warp_size))
cells = splitcells(perspective)
raw_grid = [[0 for j in range(9)] for i in range(9)]
i = 0
j = 0
for c in cells:
reduced = image_resize(c, 28, 28)
middle = reduced[10:18, 10:18]
avg = np.mean(middle)
if avg > 25:
try:
res = int(find_digit(model, reduced))
except:
print("Erreur à la transmission des chiffres au modèle.")
res = 0
raw_grid[i][j] = res
j += 1
if j == 9:
j = 0
i += 1
sol = solve_sudoku(raw_grid)
step = warp_size // 9
coords = [step // 2, step // 2]
blank_image = np.zeros((perspective.shape[0],perspective.shape[1],3), np.uint8)
try:
for i, line in enumerate(sol):
for j, coeff in enumerate(line):
if raw_grid[i][j] == 0:
cv2.putText(blank_image, str(coeff), (coords[0], coords[1]), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 255, 0), 2)
coords[0] += step
coords[0] = step // 2
coords[1] += step
except:
print("La grille n'a pas été détectée correctement. Merci d'essayer avec une meilleure image :)")
h = cv2.getPerspectiveTransform(warp_dim, ordered_pts)
src_warped = cv2.warpPerspective(blank_image, h, (im.shape[1],im.shape[0]))
im = cv2.add(im, src_warped)
cv2.imwrite(f"{name}-result.jpg", im)
treat(im)