I was working on a project of Sudoku solver, and i got stuck. At first i have to extract the grid from the image. the image on which i was testing was: the Sudoku image on which i was just testing my code!
to get out the maximum grid from the image, i applied drawcontours, cannyedge detection and houghlines. and after applying houghlines, and from that i got all the lines.
here is the code: import cv2 import numpy as np def get_sudo_rid(name,size):
img=name
original=img.copy()
img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
graymain=cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
ath=cv2.adaptiveThreshold(graymain,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,39,10)
contours,hierarchy=cv2.findContours(ath,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
area=[]
maxarea=0
cnt=contours[0]
for i in contours:
if cv2.contourArea(i)>maxarea:
cnt=i
maxarea=cv2.contourArea(i)
blank= np.zeros(img.shape,np.uint8)
image=cv2.drawContours(blank,[cnt],-1,(255,255,255),5)
edges=cv2.Canny(image,40,150)
lines=cv2.HoughLines(edges,1,np.pi/180,100)
print(len(lines))
print(lines)
createhor=[]
createver=[]
created=[]
anglediff= 800
rhodiff= 800
flag=0
count = 2
for line in lines:
for(rho,theta) in line:
flag=0
for (rho1,theta1) in created:
if(abs(rho-rho1) < rhodiff and abs(theta-theta1)<anglediff):
flag=1
if(flag==0):
a=np.cos(theta)
b=np.sin(theta)
xo=a*rho
yo=b*rho
x1=int( xo + 1000*(-b))
y1=int( yo + 1000*(a))
x2=int( xo + 1000*(-b))
y2=int( yo +1000*(a))
print(x1,x2,y1,y2)
from this i got 11 points: -957 -957 532 532, -956 -956 539 539, -1002 -1002 115 115, -1002 -1002 108 108, 116 116 -1004 -1004, 435 435 -1015 -1015, 428 428 -1015 -1015, 123 123 -1004 -1004, -1000 -1000 138 138, -946 -946 560 560, -1000 -1000 131 131,
after that to get the horizontal and vertical lines i applied basic if-else condition: but it wouldn't work:
d=np.linalg.norm(np.array((x1,y1,0))-np.array((x2,y2,0)))
cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2)
m=abs(1/np.tan(theta))
if(m<1):
createhor.append((rho,theta))
else:
createver.append((rho,theta))
print(len(createhor))
print(len(createver))
points=[]
for (rho,theta) in createhor:
for (rho1,theta1) in createver:
if(rho,theta)!=(rho1,theta1):
a=[[np.cos(theta),np.sin(theta)],[np.cos(theta1),np.sin(theta1)]]
b=[rho,rho1]
cos=np.linalg.solve(a,b)
if list(cos) not in points:
points.append(list(cos))
#print(a,b)
print(len(points))
points.sort()
output - createhor- 7,
createver - 4
i was trying to append the four point in points list of the sudoku in the image: but i didn't get the 4 points, the size of points is: 28
i even tried to eliminate those lines with the anglediff and rhoddiff more than 10, but even after that length of the points still remain 28
can you help me to get only the 4 corner points of the sudoky gird.
Here is one approach using cv2.findContours
, cv2.approxPolyDP
and finally perspective transform:
import cv2
from imutils.perspective import four_point_transform
image = cv2.imread('test_sudoku.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)[:,:,2]
gray = cv2.GaussianBlur(gray, (3, 3), 0)
edged = cv2.Canny(gray, 50, 200)
cnts = cv2.findContours(edged, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:1]
for c in cnts:
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.02 * peri, True)
if len(approx) == 4:
screenCnt = approx
break
warped = four_point_transform(image, screenCnt.reshape(4, 2))
cv2.imshow("Warped", warped)
cv2.waitKey(0)
The output warped grid:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.